[Freeipa-devel] [PATCH] 0202 support UPNs for trusted domain users

Martin Babinsky mbabinsk at redhat.com
Sat Jun 11 14:13:48 UTC 2016


On 06/09/2016 07:19 PM, Alexander Bokovoy wrote:
> On Thu, 09 Jun 2016, Martin Babinsky wrote:
>> On 06/09/2016 06:46 PM, Alexander Bokovoy wrote:
>>> On Thu, 09 Jun 2016, Martin Babinsky wrote:
>>>> On 06/07/2016 07:35 PM, Alexander Bokovoy wrote:
>>>>> On Tue, 07 Jun 2016, Martin Babinsky wrote:
>>>>>> On 06/07/2016 06:38 PM, Alexander Bokovoy wrote:
>>>>>>> On Tue, 07 Jun 2016, Martin Babinsky wrote:
>>>>>>>> On 06/06/2016 12:34 PM, Alexander Bokovoy wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> Add support for additional user name principal suffixes from
>>>>>>>>> trusted Active Directory forests. UPN suffixes are property
>>>>>>>>> of the forest and as such are associated with the forest root
>>>>>>>>> domain.
>>>>>>>>>
>>>>>>>>> FreeIPA stores UPN suffixes as ipaNTAdditionalSuffixes
>>>>>>>>> multi-valued
>>>>>>>>> attribute of ipaNTTrustedDomain object class.
>>>>>>>>>
>>>>>>>>> In order to look up UPN suffixes,
>>>>>>>>> netr_DsRGetForestTrustInformation
>>>>>>>>> LSA RPC call is used instead of netr_DsrEnumerateDomainTrusts.
>>>>>>>>>
>>>>>>>>> For more details on UPN and naming in Active Directory see
>>>>>>>>> https://technet.microsoft.com/en-us/library/cc739093%28v=ws.10%29.aspx
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> https://fedorahosted.org/freeipa/ticket/5354
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>> Hi Alexander,
>>>>>>>>
>>>>>>>> a few comments:
>>>>>>>>
>>>>>>>> 1.)
>>>>>>>>
>>>>>>>> there are some PEP8 violations in the patch. Not all of them
>>>>>>>> need to
>>>>>>>> be fixed, though (line overhangs < 5 characters are OK by me).
>>>>>>>>
>>>>>>>> """
>>>>>>>> ./ipaserver/dcerpc.py:1199:80: E501 line too long (80 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/dcerpc.py:1200:80: E501 line too long (83 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/dcerpc.py:1258:40: E203 whitespace before ':'
>>>>>>>> ./ipaserver/dcerpc.py:1263:80: E501 line too long (81 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/dcerpc.py:1271:80: E501 line too long (90 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/dcerpc.py:1272:80: E501 line too long (82 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/plugins/trust.py:490:9: E128 continuation line
>>>>>>>> under-indented for visual indent
>>>>>>>> ./ipaserver/plugins/trust.py:490:80: E501 line too long (93 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/plugins/trust.py:490:92: E202 whitespace before ']'
>>>>>>>> ./ipaserver/plugins/trust.py:493:80: E501 line too long (83 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/plugins/trust.py:1461:80: E501 line too long (80 > 79
>>>>>>>> characters)
>>>>>>>> ./ipaserver/plugins/trust.py:1462:59: E202 whitespace before ']'
>>>>>>>> ./ipaserver/plugins/trust.py:1544:1: E302 expected 2 blank lines,
>>>>>>>> found 1
>>>>>>>> ./ipaserver/plugins/trust.py:1638:1: E302 expected 2 blank lines,
>>>>>>>> found 1
>>>>>>>> """
>>>>>>> I've fixed trust.py part, the dcerpc.py fixes in 0201 should be
>>>>>>> enough
>>>>>>> now -- breaking following line is not giving any reasonable benefit:
>>>>>>>
>>>>>>>         res['ipantflatname'] =
>>>>>>> unicode(t.forest_trust_data.netbios_domain_name.string)
>>>>>>>
>>>>>>
>>>>>> Looking at the code, it would be IMHO more readable to directly
>>>>>> append
>>>>>> dict literals to the result like so:
>>>>>>
>>>>>> """
>>>>>> --- a/ipaserver/dcerpc.py
>>>>>> +++ b/ipaserver/dcerpc.py
>>>>>> @@ -1269,18 +1269,20 @@ def fetch_domains(api, mydomain, trustdomain,
>>>>>> creds=None, server=None):
>>>>>>           tname = unicode(t.forest_trust_data.dns_domain_name.string)
>>>>>>           if tname == trustdomain:
>>>>>>               continue
>>>>>> -            res = dict()
>>>>>> -            res['cn'] = tname
>>>>>> -            res['ipantflatname'] =
>>>>>> unicode(t.forest_trust_data.netbios_domain_name.string)
>>>>>> -            res['ipanttrusteddomainsid'] =
>>>>>> unicode(t.forest_trust_data.domain_sid)
>>>>>> -            result['domains'][tname] = res
>>>>>> +
>>>>>> +            result['domains'][tname] = {
>>>>>> +                'cn': tname,
>>>>>> +                'ipantflatname': unicode(
>>>>>> +                    t.forest_trust_data.netbios_domain_name.string),
>>>>>> +                'ipanttrusteddomainsid': unicode(
>>>>>> +                    t.forest_trust_data.domain_sid)
>>>>>> +            }
>>>>>>       elif t.type == lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME:
>>>>>>           tname = unicode(t.forest_trust_data.string)
>>>>>>           if tname == trustdomain:
>>>>>>               continue
>>>>>> -            res = dict()
>>>>>> -            res['cn'] = tname
>>>>>> -            result['suffixes'][tname] = res
>>>>>> +
>>>>>> +            result['suffixes'][tname] = {'cn': tname}
>>>>>>   return result
>>>>>> """
>>>>> Makes sense. Fixed.
>>>>>
>>>>>>
>>>>>> Also there is a whitespace before colon here:
>>>>>> """
>>>>>> +    result = {'domains': {}, 'suffixes' : {}}
>>>>>>                                      ^
>>>>>> """
>>>>>> Please fix that and I will be a happy engineer.
>>>>> Fixed.
>>>>>
>>>>>>
>>>>>>>> 2.)
>>>>>>>>
>>>>>>>> Should the ipaNTAdditionalSuffixes attribute be case
>>>>>>>> insensitive? It
>>>>>>>> makes sense but I'm just asking so that we don't end changing the
>>>>>>>> schema later.
>>>>>>> ipaNTAdditionalSuffixes is defined as
>>>>>>>
>>>>>>> attributeTypes: ( 2.16.840.1.113730.3.8.11.75 NAME
>>>>>>> 'ipaNTAdditionalSuffixes' DESC 'Suffix for the user principal name
>>>>>>> associated with the domain' EQUALITY caseIgnoreMatch SYNTAX
>>>>>>> 1.3.6.1.4.1.1466.115.121.1.15)
>>>>>>>
>>>>>>> There should be no problem with case sensitivity already.
>>>>>>>
>>>>>> OK I presume that the UPN suffixes on AD are also case-insensitive so
>>>>>> everything should be alright.
>>>>> Yes, as everything realm-related on AD side, they are
>>>>> case-insensitive.
>>>>>
>>>>> Updated patch attached.
>>>>
>>>> 1.) there is one unused import that makes pylint choke:
>>>>
>>>> """
>>>> ************* Module com.redhat.idm
>>>> install/oddjob/com.redhat.idm.trust-fetch-domains:6:
>>>> [W0611(unused-import), ] Unused errors imported from ipalib)
>>>> Makefile:137: recipe for target 'lint' failed
>>>> make: *** [lint] Error 1
>>>> """
>>> Fixed, thanks. I wasn't attentive to why it considered that error.
>>
>> We are continuously tighting pylint checks in order to help us improve
>> (or at least not worsen) the code quality.
>>
>>>
>>>> 2.) The UPN suffixes are added during trust establishment and I can
>>>> also kinit as the enterprise principal using one of UPNs, but only
>>>> when using two-way trust. Is this expected? I was not able to find any
>>>> clue in the design page but maybe I was just not looking hard enough.
>>> No, it works just fine for one-way trust as well. The way UPNs used in
>>> AD is a bit awkward -- you define them globally for the whole forest
>>> first and then assign specific UPN suffix for the user account in the
>>> account properties. Only then you can use the suffix for this user:
>>>
>>> [root at f24-master ~]# net ads search -S w12.ad.test -k cn=grumpy |grep
>>> userPrincipalName
>>> userPrincipalName: grumpy at torchwood
>>>
>>> [root at f24-master ~]# KRB5_TRACE=/dev/stderr kinit -E -C grumpy at torchwood
>>> [9135] 1465490159.655327: Resolving unique ccache of type KEYRING
>>> [9135] 1465490159.655408: Getting initial credentials for
>>> grumpy\@torchwood at IPA.AD.TEST
>>> [9135] 1465490159.656798: Sending request (176 bytes) to IPA.AD.TEST
>>> [9135] 1465490159.656994: Initiating TCP connection to stream
>>> 192.168.5.117:88
>>> [9135] 1465490159.657122: Sending TCP request to stream 192.168.5.117:88
>>> [9135] 1465490159.657655: Received answer (169 bytes) from stream
>>> 192.168.5.117:88
>>> [9135] 1465490159.657679: Terminating TCP connection to stream
>>> 192.168.5.117:88
>>> [9135] 1465490159.657715: Response was from master KDC
>>> [9135] 1465490159.657741: Received error from KDC: -1765328316/Realm not
>>> local to KDC
>>> [9135] 1465490159.657756: Following referral to realm AD.TEST
>>> [9135] 1465490159.657783: Sending request (168 bytes) to AD.TEST
>>> [9135] 1465490159.674764: Resolving hostname w12.ad.test.
>>> [9135] 1465490159.679514: Sending initial UDP request to dgram
>>> 192.168.5.111:88
>>> [9135] 1465490159.680158: Received answer (171 bytes) from dgram
>>> 192.168.5.111:88
>>> [9135] 1465490159.688085: Response was not from master KDC
>>> [9135] 1465490159.688141: Received error from KDC:
>>> -1765328359/Additional pre-authentication required
>>> [9135] 1465490159.688203: Processing preauth types: 16, 15, 19, 2
>>> [9135] 1465490159.688252: Selected etype info: etype aes256-cts, salt
>>> "AD.TESTgrumpy", params ""
>>> [9135] 1465490159.688285: PKINIT client has no configured identity;
>>> giving up
>>> [9135] 1465490159.688315: PKINIT client has no configured identity;
>>> giving up
>>> [9135] 1465490159.688342: Preauth module pkinit (16) (real) returned:
>>> 22/Invalid argument
>>> [9135] 1465490159.688368: PKINIT client has no configured identity;
>>> giving up
>>> [9135] 1465490159.688394: Preauth module pkinit (14) (real) returned:
>>> 22/Invalid argument
>>> Password for grumpy\@torchwood at AD.TEST: [9135] 1465490162.317092: AS key
>>> obtained for encrypted timestamp: aes256-cts/C61F
>>> [9135] 1465490162.317176: Encrypted timestamp (for 1465490162.505923):
>>> plain 301AA011180F32303136303630393136333630325AA105020307B843,
>>> encrypted
>>> ADD327ACC03C99C821D9FBBE280866D6342D3CE1BBA2C720CF5A5BEBA586ECD0034CD2C3448F5FD6D66219DB77DC51D81C8C1D6D01A87AC9
>>>
>>>
>>> [9135] 1465490162.317228: Preauth module encrypted_timestamp (2) (real)
>>> returned: 0/Success
>>> [9135] 1465490162.317272: Produced preauth for next request: 2
>>> [9135] 1465490162.317328: Sending request (246 bytes) to AD.TEST
>>> [9135] 1465490162.346793: Resolving hostname w12.ad.test.
>>> [9135] 1465490162.352714: Sending initial UDP request to dgram
>>> 192.168.5.111:88
>>> [9135] 1465490162.353537: Received answer (1442 bytes) from dgram
>>> 192.168.5.111:88
>>> [9135] 1465490162.366042: Response was not from master KDC
>>> [9135] 1465490162.366094: Processing preauth types: 19
>>> [9135] 1465490162.366139: Selected etype info: etype aes256-cts, salt
>>> "AD.TESTgrumpy", params ""
>>> [9135] 1465490162.366190: Produced preauth for next request: (empty)
>>> [9135] 1465490162.366235: AS key determined by preauth: aes256-cts/C61F
>>> [9135] 1465490162.366328: Decrypted AS reply; session key is:
>>> aes256-cts/BD45
>>> [9135] 1465490162.366382: FAST negotiation: unavailable
>>> [9135] 1465490162.366416: Initializing
>>> KEYRING:persistent:0:krb_ccache_dSjqZkD with default princ
>>> grumpy at AD.TEST
>>> [9135] 1465490162.366488: Storing grumpy at AD.TEST ->
>>> krbtgt/AD.TEST at AD.TEST in KEYRING:persistent:0:krb_ccache_dSjqZkD
>>> [9135] 1465490162.366550: Storing config in
>>> KEYRING:persistent:0:krb_ccache_dSjqZkD for krbtgt/AD.TEST at AD.TEST:
>>> pa_type: 2
>>> [9135] 1465490162.366585: Storing grumpy at AD.TEST ->
>>> krb5_ccache_conf_data/pa_type/krbtgt\/AD.TEST\@AD.TEST at X-CACHECONF: in
>>> KEYRING:persistent:0:krb_ccache_dSjqZkD
>>>
>>> As you can see, the realm was considered non-local and a referral to the
>>> correct realm was issued, then kinit followed the referral and finally
>>> we've got the ticket for grumpy at AD.TEST because canonicalization was
>>> asked. If no canonicalization would be asked, the principal would be
>>> enterprise one but, again, from the other realm:
>>>
>>> [root at f24-master ~]# klist
>>> Ticket cache: KEYRING:persistent:0:krb_ccache_lIqrVtl
>>> Default principal: grumpy\@torchwood at AD.TEST
>>>
>>> Valid starting       Expires              Service principal
>>> 06/09/2016 19:45:16  06/10/2016 05:45:16  krbtgt/AD.TEST at AD.TEST
>>>    renew until 06/10/2016 19:45:13
>>>
>>>
>>>
>> Hmmm,
>>
>> when I establish a one-way trust I can kinit with the user having UPN
>> suffix:
>>
>> kinit -E jdoe at crew207
>> Password for jdoe\@crew207 at DOM-207.ADREALM.COM:
>> [root at vm-183 ~]# klist
>> Ticket cache: KEYRING:persistent:0:krb_ccache_gHJAT3H
>> Default principal: jdoe\@crew207 at DOM-207.ADREALM.COM
>>
>> Valid starting       Expires              Service principal
>> 06/09/2016 17:56:31  06/10/2016 03:56:31
>> krbtgt/DOM-207.ADREALM.COM at DOM-207.ADREALM.COM
>>        renew until 06/10/2016 17:56:26
>>
>>
>> However when I issue 'ipa trust-show' I do not see any UPN suffixes
>> associated with the trust because 'ipaNTAdditionalSuffixes' attribute
>> is not populated on the trusted domain object while in the tow-way
>> trust case it is and 'trust-*' commands show the UPNs as expected.
>>
>> ipa trust-show  dom-207.adrealm.com
>>  Domain NetBIOS name: DOM-207
>>  Domain Security Identifier: S-1-5-21-2334637434-2721788842-3715042423
>>  Trust direction: Trusting forest
>>  Trust type: Non-transitive external trust to a domain in another
>> Active Directory forest
>>  Realm name: dom-207.adrealm.com
>>
>> (it doesn't matter if I create external one-way trust or not, the UPNs
>> are not pulled from AD DC in either case)
> Check audit.log, on Fedora 24 selinux policy is broken again due to us
> moving files all around. Try with setenforce 0 to verify it.
>
> We run an equivalent of
> # oddjob_request -i com.redhat.idm.trust.fetch_domains \
>                -s com.redhat.idm.trust -o / \
>                com.redhat.idm.trust.fetch_domains ad.test
>
> when retrieving forest topology information in one-way trust case.
> If SELinux policy prevents oddjobd to launch the helper, no retrieval
> will happen.
>
Yes the code works fine but SELinux blocks 
com.redhat.trust.fetch_domains from running.

I will open appropriate BZs against selinux-policy.

ACK.

-- 
Martin^3 Babinsky




More information about the Freeipa-devel mailing list