[Freeipa-devel] Search global catalog for trusted domain SIDs

2012-10-18 Thread Alexander Bokovoy

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

2012-10-18 Thread Simo Sorce
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

2012-10-18 Thread Alexander Bokovoy

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

2012-10-18 Thread Sumit Bose
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

2012-10-18 Thread Alexander Bokovoy

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