On Wed, 10 Jul 2013, Alexander Bokovoy wrote:
On Wed, 10 Jul 2013, Simo Sorce wrote:
On Tue, 2013-07-09 at 22:39 +0200, Jakub Hrozek wrote:
On Tue, Jul 09, 2013 at 02:12:33PM +0300, Alexander Bokovoy wrote:
> On Tue, 09 Jul 2013, Jakub Hrozek wrote:
> >On Wed, Jul 03, 2013 at 02:53:55PM +0200, Sumit Bose wrote:
> >>On Wed, Jul 03, 2013 at 01:00:43PM +0300, Alexander Bokovoy wrote:
> >>> On Mon, 01 Jul 2013, Sumit Bose wrote:
> >>> >Hi,
> >>> >
> >>> >this patch fixes https://fedorahosted.org/freeipa/ticket/3651 but only
> >>> >to allow SSSD running on a FreeIPA server to access the AD LDAP server.
> >>> >In the ticket a more generic solution is described but since there is no
> >>> >other use case so far I think this patch is sufficient for the time
> >>> >being.
> >>> >
> >>> >bye,
> >>> >Sumit
> >>>
> >>> >From a707d8f9d771dfe4fb8487e051519dba0ef72449 Mon Sep 17 00:00:00 2001
> >>> >From: Sumit Bose <sb...@redhat.com>
> >>> >Date: Mon, 1 Jul 2013 13:47:22 +0200
> >>> >Subject: [PATCH] Add PAC to master host TGTs
> >>> >
> >>> >For a proper SALS bind with GSSAPI against an AD LDAP server a PAC is
> >>> >needed. To allow SSSD in ipa_server_mode to access the LDAP or GC server
> >>> >of a trusted domain with the credentials of a FreeIPA server host a
> >>> >PAC must be added to the TGT for the host.
> >>> s/SALS/SASL/
> >>
> >>Thank you for the review, I've fixed the typo and added the numerical
> >>values for the well-known RIDs to the commit message.
> >>
> >>>
> >>>
> >>> >To determine if a host is a FreeIPA server or not it is checked if there
> >>> >is an entry for the host in cn=master,cn=ipa,cn=etc,$base. Unfortunately
> >>> >this requires an additional LDAP lookup. But since TGS-REQs for hosts
> >>> >should be rare I think it is acceptable for the time being.
> >>> I think it is better to change this lookup to
> >>> "cn=ADTRUST,cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX", it would
> >>> explicitly limit us to the IPA masters running AD trusts.
> >>
> >>I'm not sure if this restriction is needed. With SSSD's ipa_server_mode
> >>any IPA master (which networkwise can access an AD server of the trusted
> >>domain) can read AD user and group data, no running smbd or winbind is
> >>required. So it would be possible to run the extdom plugin or the compat
> >>plugin for the legacy clients on any IPA server which would allow a much
> >>better load balancing.
> >>
> >>If there are other concerns I'm happy to add the restriction.
> >>
> >>bye,
> >>Sumit
> >
> >I don't think I know the code good enough to provide a full review, but
> >the patch enables the lookups from an IPA master without any additional
> >hacks. So ack on functionality at least.
> Ok.
>
> I've extended this functionality to generate MS-PAC also for services
> running on IPA masters. Patch attached.
>
> This is needed to finally get rid of access to trust auth material for
> IPA python code. HTTP/fqdn@REALM will now be able to authenticate
> against AD LDAP server and look up needed information directly, without
> elevating privileges to trust admins.
>
> This should also help for AD range discovery Tomas is working on.
>

Hi,

The patch looks good to me so I'm giving my +1. I would appreciate other
review too before a full ack, though.

I've nacked the approach, although the results are as expected.
Alexander will send a simplified patch that avoids the extra search and
use of managedby which is not ok.
New patch attached.
After discussion with Simo on IRC, I decided to use krb5_parse_name() to
properly parse krbPrincipalName attribute for the service and veto it
against pre-defined set of services we support generating MS-PAC for on
the IPA master.

The list currently includes only cifs/ipa.master@REALM and
HTTP/ipa.master@REALM as host/ipa.master@REALM is handled by the is_host
case.

I verified it by initializing ccache with /etc/httpd/conf/ipa.keytab and
accessing AD over LDAP, it worked well (same result for host/):
---------------------------------------------------------------------
# kinit -kt /etc/httpd/conf/ipa.keytab HTTP/ipa.example....@example.com
# ldapsearch -Y GSSAPI -h altai.ad.lan -b dc=ad,dc=lan '(cn=IPAX$)'
SASL/GSSAPI authentication started
SASL username: HTTP/ipa.example....@example.com
SASL SSF: 56
SASL data security layer installed.
# extended LDIF
#
# LDAPv3
# base <dc=ad,dc=lan> with scope subtree
# filter: (cn=IPAX$)
# requesting: ALL
#

# IPAX$, Users, ad.lan
dn: CN=IPAX$,CN=Users,DC=ad,DC=lan
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: IPAX$
distinguishedName: CN=IPAX$,CN=Users,DC=ad,DC=lan
instanceType: 4
whenCreated: 20130708091622.0Z
whenChanged: 20130710123914.0Z
uSNCreated: 98603
uSNChanged: 102524
name: IPAX$
objectGUID:: FxL42tGLnEOfKkuMw6sVVw==
userAccountControl: 2080
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 130179335549552172
pwdLastSet: 130177485824178582
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAAzl3L0KYmgQdG8ZPbeQQAAA==
accountExpires: 9223372036854775807
logonCount: 1
sAMAccountName: IPAX$
sAMAccountType: 805306370
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=lan
isCriticalSystemObject: TRUE
dSCorePropagationData: 16010101000000.0Z
lastLogonTimestamp: 130179335549552172

# search reference
ref: ldap://ForestDnsZones.ad.lan/DC=ForestDnsZones,DC=ad,DC=lan

# search reference
ref: ldap://DomainDnsZones.ad.lan/DC=DomainDnsZones,DC=ad,DC=lan

# search reference
ref: ldap://ad.lan/CN=Configuration,DC=ad,DC=lan

# search result
search: 4
result: 0 Success

# numResponses: 5
# numEntries: 1
# numReferences: 3
---------------------------------------------------------------------

When I tried to initialize ccache with /etc/dirsrv/ds.keytab, I've got:
---------------------------------------------------------------------
# kinit -kt /etc/dirsrv/ds.keytab ldap/ipa.example....@example.com
# ldapsearch -Y GSSAPI -h altai.ad.lan -b dc=ad,dc=lan '(cn=IPAX$)'
SASL/GSSAPI authentication started
SASL username: ldap/ipa.example....@example.com
SASL SSF: 56
SASL data security layer installed.
# extended LDIF
#
# LDAPv3
# base <dc=ad,dc=lan> with scope subtree
# filter: (cn=IPAX$)
# requesting: ALL
#

# search result
search: 4
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090724, comment: In order to perform
this operation a successful bind must be completed on the connection., data 0,
v23f0

# numResponses: 1
---------------------------------------------------------------------



--
/ Alexander Bokovoy
>From 124e6ed79c69d486b9d9bf69d9bfef354b40840b Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <aboko...@redhat.com>
Date: Tue, 9 Jul 2013 14:05:02 +0300
Subject: [PATCH 15/15] Generate syntethic MS-PAC for all services running on
 IPA master

MS-PAC is required to be present in TGT if one wants to connect to
AD services using this TGT. Users get MS-PAC by default, SSSD in
ipa_server_mode uses host/fqdn@REALM principal to talk to AD LDAP.

This patch enables other services running on IPA master to connect
to AD services. This is required for IPA python code doing discovery
of remote AD domain settings shortly after IPA-AD trust has been
established.
---
 daemons/ipa-kdb/ipa_kdb_mspac.c | 79 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 92dc8dd..96eac6f 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -93,9 +93,21 @@ static char *memberof_pac_attrs[] = {
     NULL
 };
 
+
+static struct {
+    char *service;
+    int length;
+} supported_services[] = {
+    {"cifs", sizeof("cifs")},
+    {"HTTP", sizeof("HTTP")},
+    {NULL, 0}
+};
+
+
 #define SID_ID_AUTHS 6
 #define SID_SUB_AUTHS 15
 #define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN(a,b) (((a)<(b))?(a):(b))
 
 #define AUTHZ_DATA_TYPE_PAC "MS-PAC"
 #define AUTHZ_DATA_TYPE_PAD "PAD"
@@ -395,10 +407,14 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
     char *strres;
     int intres;
     int ret;
+    int i;
     char **objectclasses = NULL;
     size_t c;
     bool is_host = false;
     bool is_user = false;
+    bool is_service = false;
+    krb5_principal princ;
+    krb5_data *data;
 
     ret = ipadb_ldap_attr_to_strlist(lcontext, lentry, "objectClass",
                                      &objectclasses);
@@ -407,6 +423,9 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
             if (strcasecmp(objectclasses[c], "ipaHost") == 0) {
                 is_host = true;
             }
+            if (strcasecmp(objectclasses[c], "ipaService") == 0) {
+                is_service = true;
+            }
             if (strcasecmp(objectclasses[c], "ipaNTUserAttrs") == 0) {
                 is_user = true;
             }
@@ -415,8 +434,8 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
     }
     free(objectclasses);
 
-    if (!is_host && !is_user) {
-        /* We only handle users and hosts */
+    if (!is_host && !is_user && !is_service) {
+        /* We only handle users and hosts, and services */
         return ENOENT;
     }
 
@@ -433,6 +452,54 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
             free(strres);
             return ENOENT;
         }
+    } else if (is_service) {
+        ret = ipadb_ldap_attr_to_str(lcontext, lentry, "krbPrincipalName", 
&strres);
+        if (ret) {
+            /* krbPrincipalName is mandatory for services */
+            return ret;
+        }
+
+        ret = krb5_parse_name(ipactx->kcontext, strres, &princ);
+
+        free(strres);
+        if (ret) {
+            return ENOENT;
+        }
+
+        if (krb5_princ_size(ipactx->kcontext, princ) != 2) {
+            krb5_free_principal(ipactx->kcontext, princ);
+            return ENOENT;
+        }
+
+        data = krb5_princ_component(ipactx->context, princ, 0);
+        for (i = 0; supported_services[i].service; i++) {
+            if (0 == memcmp(data->data, supported_services[i].service,
+                            MIN(supported_services[i].length, data->length))) {
+                break;
+            }
+        }
+
+        if (supported_services[i].service == NULL) {
+            krb5_free_principal(ipactx->kcontext, princ);
+            return ENOENT;
+        }
+
+        data = krb5_princ_component(ipactx->context, princ, 1);
+        strres = malloc(data->length);
+        if (strres == NULL) {
+            krb5_free_principal(ipactx->kcontext, princ);
+            return ENOENT;
+        }
+
+        memcpy(strres, data->data, data->length);
+        krb5_free_principal(ipactx->kcontext, princ);
+
+        /* Only add PAC to TGT to services on IPA masters to allow querying
+         * AD LDAP server */
+        if (!is_master_host(ipactx, strres)) {
+            free(strres);
+            return ENOENT;
+        }
     } else {
         ret = ipadb_ldap_attr_to_str(lcontext, lentry, "uid", &strres);
         if (ret) {
@@ -444,7 +511,7 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
     info3->base.account_name.string = talloc_strdup(memctx, strres);
     free(strres);
 
-    if (is_host) {
+    if (is_host || is_service) {
         prigid = 515; /* Well known RID for domain computers group */
     } else {
         ret = ipadb_ldap_attr_to_int(lcontext, lentry, "gidNumber", &intres);
@@ -567,7 +634,7 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
     info3->base.logon_count = 0; /* we do not have this info yet */
     info3->base.bad_password_count = 0; /* we do not have this info yet */
 
-    if (is_host) {
+    if (is_host || is_service) {
         /* Well know RID of domain controllers group */
         info3->base.rid = 516;
     } else {
@@ -658,7 +725,7 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
     }
 
     if (info3->base.primary_gid == 0) {
-        if (is_host) {
+        if (is_host || is_service) {
             info3->base.primary_gid = 515;  /* Well known RID for domain 
computers group */
         } else {
             if (ipactx->mspac->fallback_rid) {
@@ -698,7 +765,7 @@ static krb5_error_code ipadb_fill_info3(struct 
ipadb_context *ipactx,
         return ENOENT;
     }
 
-    if (is_host) {
+    if (is_host || is_service) {
         info3->base.domain_sid = talloc_memdup(memctx, &ipactx->mspac->domsid,
                                                sizeof(ipactx->mspac->domsid));
     } else {
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to