[Freeipa-devel] Search global catalog for trusted domain SIDs
Hi, this is work in progress, shared mostly to get comments. Simo, Sumit, this is an attempt to resolve external group members from trusted domains using their Global Catalog services. The code quickly became complex because it needs to do a lot of additional activity. A rough sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace an external member name by SID in the group-add-member command Right now I'm failing at SASL interactive bind as Global Catalog does not accept the credentials in DomainValidator.__resolve_against_gc(), perhaps because I'm using LDAP SASL interactive bind wrongly. It is late here so I might simply be blind already. [Thu Oct 18 21:42:08.924696 2012] [:error] [pid 7831] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} Note that ccache is successfully created and populated and is usable from command line via ldapsearch: # klist -c /tmp/systemd-private-eBLWxO/krb5cc_TRUSTEDDOMAIN Ticket cache: FILE:/tmp/systemd-private-eBLWxO/krb5cc_TRUSTEDDOMAIN Default principal: IPATEAM$@AD.LOCAL Valid starting ExpiresService principal 10/18/12 21:42:06 10/19/12 07:42:06 krbtgt/AD.LOCAL@AD.LOCAL renew until 10/19/12 21:42:08 10/18/12 21:42:06 10/19/12 07:42:06 ldap/winda.ad.local@AD.LOCAL renew until 10/19/12 21:42:08 # KRB5CCNAME=/tmp/systemd-private-eBLWxO/krb5cc_TRUSTEDDOMAIN ldapsearch -Y GSSAPI -H ldap://winda.ad.local:3268 -b dc=ad,dc=local '((sAMAccountName=ipateam$)(objectClass=*))' SASL/GSSAPI authentication started SASL username: IPATEAM$@AD.LOCAL SASL SSF: 56 SASL data security layer installed. # extended LDIF # # LDAPv3 # base dc=ad,dc=local with scope subtree # filter: ((sAMAccountName=ipateam$)(objectClass=*)) # requesting: ALL # # IPATEAM$, Users, ad.local dn: CN=IPATEAM$,CN=Users,DC=ad,DC=local objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user cn: IPATEAM$ distinguishedName: CN=IPATEAM$,CN=Users,DC=ad,DC=local instanceType: 4 whenCreated: 20121018132513.0Z whenChanged: 20121018174020.0Z uSNCreated: 209080 uSNChanged: 209106 name: IPATEAM$ objectGUID:: 43oH5Pepm0CCvJ8VGxLEnA== userAccountControl: 2080 primaryGroupID: 513 objectSid:: AQUAAAUVze8BAQQy1QhmzheAyAUAAA== sAMAccountName: IPATEAM$ sAMAccountType: 805306370 objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=local dSCorePropagationData: 1601010100.0Z lastLogonTimestamp: 129950556201332000 # search result search: 4 result: 0 Success # numResponses: 2 # numEntries: 1 -- / Alexander Bokovoy From 960277985935169490ca1c550bb8e0e3cd382001 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy aboko...@redhat.com Date: Thu, 18 Oct 2012 21:46:35 +0300 Subject: [PATCH 4/4] WIP: Resolve external members from trusted domain via Global Catalog A sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace external member name by SID --- ipalib/plugins/group.py | 6 +- ipaserver/dcerpc.py | 162 +++- 2 files changed, 164 insertions(+), 4 deletions(-) diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py index a174ba62cc32a7fb83474f52e2621521553889af..c4ecd6299d6111a389565e53f3a3e09a5c3f2f89 100644 --- a/ipalib/plugins/group.py +++ b/ipalib/plugins/group.py @@ -382,7 +382,11 @@ class group_add_member(LDAPAddMember): if domain_validator.is_trusted_sid_valid(sid): sids.append(sid) else: -failed_sids.append((sid, 'Not a trusted domain SID')) +actual_sid = domain_validator.get_sid_trusted_domain_object(sid) +if actual_sid: +sids.append(actual_sid) +else: +failed_sids.append((sid, 'Not a trusted domain SID')) if len(sids) == 0: raise errors.ValidationError(name=_('external member'), error=_('values are not recognized as valid SIDs from trusted domain')) diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index 80e6b7c87511e1d206df4d1de28574cc7b8410f7..1b5b77661aec20366f37f3a3d1f5e6e48de0cbff 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -29,6 +29,7 @@ from ipalib import
Re: [Freeipa-devel] Search global catalog for trusted domain SIDs
On Thu, 2012-10-18 at 22:00 +0300, Alexander Bokovoy wrote: Hi, this is work in progress, shared mostly to get comments. Simo, Sumit, this is an attempt to resolve external group members from trusted domains using their Global Catalog services. The code quickly became complex because it needs to do a lot of additional activity. A rough sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace an external member name by SID in the group-add-member command Right now I'm failing at SASL interactive bind as Global Catalog does not accept the credentials in DomainValidator.__resolve_against_gc(), perhaps because I'm using LDAP SASL interactive bind wrongly. It is late here so I might simply be blind already. [Thu Oct 18 21:42:08.924696 2012] [:error] [pid 7831] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} I do not see anything clearly wrong in the patch, I guess wireshark may help to understand if there is a difference between your code and ldapsearch ? Simo. -- Simo Sorce * Red Hat, Inc * New York ___ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel
Re: [Freeipa-devel] Search global catalog for trusted domain SIDs
On Thu, 18 Oct 2012, Sumit Bose wrote: On Thu, Oct 18, 2012 at 10:00:54PM +0300, Alexander Bokovoy wrote: Hi, this is work in progress, shared mostly to get comments. Simo, Sumit, this is an attempt to resolve external group members from trusted domains using their Global Catalog services. The code quickly became complex because it needs to do a lot of additional activity. A rough sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace an external member name by SID in the group-add-member command Right now I'm failing at SASL interactive bind as Global Catalog does not accept the credentials in DomainValidator.__resolve_against_gc(), perhaps because I'm using LDAP SASL interactive bind wrongly. It is late here so I might simply be blind already. [Thu Oct 18 21:42:08.924696 2012] [:error] [pid 7831] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} Note that ccache is successfully created and populated and is usable from command line via ldapsearch: ... + +def __resolve_against_gc(self, info, name): +conn = IPAdmin(host=info['dc'], port=3268) +auth = self.__extract_trusted_auth(info) +if auth: +(ccache_name, principal) = self.__kinit_as_trusted_account(info, auth) +if ccache_name: +cb_info = dict() +(CB_USER, CB_GETREALM) = (0x4001, 0x4008) +cb_info[CB_USER] = principal +cb_info[CB_GETREALM] = info['dns_domain'].upper() +sasl_auth = _ldap.sasl.sasl(cb_info,'GSSAPI') +old_ccache = os.environ.get('KRB5CCNAME') +os.environ[KRB5CCNAME] = ccache_name +conn.sasl_interactive_bind_s(None, sasl_auth) +os.environ[KRB5CCNAME] = old_ccache Are you sure the bind is already finished here? I haven't looked at the implementation, but if it does a lazy bind, i.e. only bind when the first request is made, it will see the wrong ccache. Can you try to set KRB5CCNAME to the old value after calling conn.getEntry()? Yes, I'm sure because it raises exception from within sasl_interactive_bind_s() call, it never ever gets to the next line. [Thu Oct 18 23:28:12.421356 2012] [:error] [pid 8183] [client 192.168.111.206:0] conn.sasl_interactive_bind_s(None, sasl_auth) [Thu Oct 18 23:28:12.421412 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib/python2.7/site-packages/ipaserver/plugins/ldap2.py, line 556, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.421832 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self.conn.sasl_interactive_bind_s(who, auth, serverctrls, clientctrls, sasl_flags) [Thu Oct 18 23:28:12.421854 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 229, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.422086 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self._ldap_call(self._l.sasl_interactive_bind_s,who,auth,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls),sasl_flags) [Thu Oct 18 23:28:12.422108 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 99, in _ldap_call [Thu Oct 18 23:28:12.422134 2012] [:error] [pid 8183] [client 192.168.111.206:0] result = func(*args,**kwargs) [Thu Oct 18 23:28:12.422196 2012] [:error] [pid 8183] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} -- / Alexander Bokovoy ___ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel
Re: [Freeipa-devel] Search global catalog for trusted domain SIDs
On Thu, Oct 18, 2012 at 11:42:34PM +0300, Alexander Bokovoy wrote: On Thu, 18 Oct 2012, Sumit Bose wrote: On Thu, Oct 18, 2012 at 10:00:54PM +0300, Alexander Bokovoy wrote: Hi, this is work in progress, shared mostly to get comments. Simo, Sumit, this is an attempt to resolve external group members from trusted domains using their Global Catalog services. The code quickly became complex because it needs to do a lot of additional activity. A rough sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace an external member name by SID in the group-add-member command Right now I'm failing at SASL interactive bind as Global Catalog does not accept the credentials in DomainValidator.__resolve_against_gc(), perhaps because I'm using LDAP SASL interactive bind wrongly. It is late here so I might simply be blind already. [Thu Oct 18 21:42:08.924696 2012] [:error] [pid 7831] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} Note that ccache is successfully created and populated and is usable from command line via ldapsearch: ... + +def __resolve_against_gc(self, info, name): +conn = IPAdmin(host=info['dc'], port=3268) +auth = self.__extract_trusted_auth(info) +if auth: +(ccache_name, principal) = self.__kinit_as_trusted_account(info, auth) +if ccache_name: +cb_info = dict() +(CB_USER, CB_GETREALM) = (0x4001, 0x4008) +cb_info[CB_USER] = principal +cb_info[CB_GETREALM] = info['dns_domain'].upper() +sasl_auth = _ldap.sasl.sasl(cb_info,'GSSAPI') +old_ccache = os.environ.get('KRB5CCNAME') +os.environ[KRB5CCNAME] = ccache_name +conn.sasl_interactive_bind_s(None, sasl_auth) +os.environ[KRB5CCNAME] = old_ccache Are you sure the bind is already finished here? I haven't looked at the implementation, but if it does a lazy bind, i.e. only bind when the first request is made, it will see the wrong ccache. Can you try to set KRB5CCNAME to the old value after calling conn.getEntry()? Yes, I'm sure because it raises exception from within sasl_interactive_bind_s() call, it never ever gets to the next line. [Thu Oct 18 23:28:12.421356 2012] [:error] [pid 8183] [client 192.168.111.206:0] conn.sasl_interactive_bind_s(None, sasl_auth) [Thu Oct 18 23:28:12.421412 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib/python2.7/site-packages/ipaserver/plugins/ldap2.py, line 556, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.421832 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self.conn.sasl_interactive_bind_s(who, auth, serverctrls, clientctrls, sasl_flags) [Thu Oct 18 23:28:12.421854 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 229, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.422086 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self._ldap_call(self._l.sasl_interactive_bind_s,who,auth,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls),sasl_flags) [Thu Oct 18 23:28:12.422108 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 99, in _ldap_call [Thu Oct 18 23:28:12.422134 2012] [:error] [pid 8183] [client 192.168.111.206:0] result = func(*args,**kwargs) [Thu Oct 18 23:28:12.422196 2012] [:error] [pid 8183] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} ok another guess. In the python docs it is said the Such changes to the environment affect subprocesses started with os.system(), popen() or fork() and execv(). So I guess os.environ[KRB5CCNAME]=something does not change the environment of the running process, but only python data. If I try to set a new env var in the python interpreter and look at /proc/PID/environ from a different shell, I see no changes. bye, Sumit -- / Alexander Bokovoy ___ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel
Re: [Freeipa-devel] Search global catalog for trusted domain SIDs
On Thu, 18 Oct 2012, Sumit Bose wrote: On Thu, Oct 18, 2012 at 11:42:34PM +0300, Alexander Bokovoy wrote: On Thu, 18 Oct 2012, Sumit Bose wrote: On Thu, Oct 18, 2012 at 10:00:54PM +0300, Alexander Bokovoy wrote: Hi, this is work in progress, shared mostly to get comments. Simo, Sumit, this is an attempt to resolve external group members from trusted domains using their Global Catalog services. The code quickly became complex because it needs to do a lot of additional activity. A rough sequence is following: 1. Match external member against existing trusted domain 2. Find trusted domain's domain controller 3. Fetch trusted domain account auth info 4. Set up ccache in /tmp/krb5cc_TRUSTEDDOMAIN with principal ourdomain$@trusted.domain 5. Do LDAP SASL interactive bind using the ccache 6. Search for the member's SID 7. Decode SID 8. Replace an external member name by SID in the group-add-member command Right now I'm failing at SASL interactive bind as Global Catalog does not accept the credentials in DomainValidator.__resolve_against_gc(), perhaps because I'm using LDAP SASL interactive bind wrongly. It is late here so I might simply be blind already. [Thu Oct 18 21:42:08.924696 2012] [:error] [pid 7831] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} Note that ccache is successfully created and populated and is usable from command line via ldapsearch: ... + +def __resolve_against_gc(self, info, name): +conn = IPAdmin(host=info['dc'], port=3268) +auth = self.__extract_trusted_auth(info) +if auth: +(ccache_name, principal) = self.__kinit_as_trusted_account(info, auth) +if ccache_name: +cb_info = dict() +(CB_USER, CB_GETREALM) = (0x4001, 0x4008) +cb_info[CB_USER] = principal +cb_info[CB_GETREALM] = info['dns_domain'].upper() +sasl_auth = _ldap.sasl.sasl(cb_info,'GSSAPI') +old_ccache = os.environ.get('KRB5CCNAME') +os.environ[KRB5CCNAME] = ccache_name +conn.sasl_interactive_bind_s(None, sasl_auth) +os.environ[KRB5CCNAME] = old_ccache Are you sure the bind is already finished here? I haven't looked at the implementation, but if it does a lazy bind, i.e. only bind when the first request is made, it will see the wrong ccache. Can you try to set KRB5CCNAME to the old value after calling conn.getEntry()? Yes, I'm sure because it raises exception from within sasl_interactive_bind_s() call, it never ever gets to the next line. [Thu Oct 18 23:28:12.421356 2012] [:error] [pid 8183] [client 192.168.111.206:0] conn.sasl_interactive_bind_s(None, sasl_auth) [Thu Oct 18 23:28:12.421412 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib/python2.7/site-packages/ipaserver/plugins/ldap2.py, line 556, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.421832 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self.conn.sasl_interactive_bind_s(who, auth, serverctrls, clientctrls, sasl_flags) [Thu Oct 18 23:28:12.421854 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 229, in sasl_interactive_bind_s [Thu Oct 18 23:28:12.422086 2012] [:error] [pid 8183] [client 192.168.111.206:0] return self._ldap_call(self._l.sasl_interactive_bind_s,who,auth,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls),sasl_flags) [Thu Oct 18 23:28:12.422108 2012] [:error] [pid 8183] [client 192.168.111.206:0] File /usr/lib64/python2.7/site-packages/ldap/ldapobject.py, line 99, in _ldap_call [Thu Oct 18 23:28:12.422134 2012] [:error] [pid 8183] [client 192.168.111.206:0] result = func(*args,**kwargs) [Thu Oct 18 23:28:12.422196 2012] [:error] [pid 8183] [client 192.168.111.206:0] INVALID_CREDENTIALS: {'info': '8009030B: LdapErr: DSID-0C0904DC, comment: AcceptSecurityContext error, data 0, v1db1', 'desc': 'Invalid credentials'} ok another guess. In the python docs it is said the Such changes to the environment affect subprocesses started with os.system(), popen() or fork() and execv(). So I guess os.environ[KRB5CCNAME]=something does not change the environment of the running process, but only python data. If I try to set a new env var in the python interpreter and look at /proc/PID/environ from a different shell, I see no changes. No, this does not matter. I'm reproducing the same error with a standalone app that does not modify environment: http://cpaste.org/1370/raw/ We do modify environment in the framework code (ipaserver/rpcserver.py) already and it works just fine. -- / Alexander Bokovoy ___ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel