Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4debfd56c6 | ||
|
|
6139ddd170 | ||
|
|
458dcebd25 | ||
|
|
b6520bef2e | ||
|
|
6c5530c509 | ||
|
|
459b81b196 | ||
|
|
2003eb6b3d | ||
|
|
bfe074ed47 | ||
|
|
7a1e1d9f1c | ||
|
|
a39af6b722 | ||
|
|
eb9f606ffd | ||
|
|
51f1321b9c | ||
|
|
38e5bcf719 | ||
|
|
1bb4ff9ed2 | ||
|
|
c55185d3dc | ||
|
|
e5f7356e7e | ||
|
|
8ff0c1a5ee | ||
|
|
acd1d12793 | ||
|
|
260d6378ec | ||
|
|
499f71729b | ||
|
|
3d827979d2 | ||
|
|
4499c7379b | ||
|
|
02d3fb8266 | ||
|
|
33cd62e0da | ||
|
|
aca97507cd | ||
|
|
cebfb87920 | ||
|
|
e7bee5b668 | ||
|
|
6c6a43c909 | ||
|
|
c9d9fb3a3a | ||
|
|
082ec006f4 |
No files matched your search
@@ -10,5 +10,6 @@ ipaserver == @VERSION@
|
||||
ipatests == @VERSION@
|
||||
|
||||
# keep pylint version in sync with current Fedora release
|
||||
# F37 has 2.15.5
|
||||
pylint ~= 2.15.5
|
||||
# F36 has 2.12.2
|
||||
# https://pagure.io/freeipa/issue/8818 added pylint 2.8 support
|
||||
pylint ~= 2.12.2
|
||||
@@ -153,8 +153,6 @@ aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "krbcanonicalname || krbprincipalname")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Principals";allow (write) groupdn = "ldap:///cn=System: Manage Host Principals,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "memberprincipal || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Resource Delegation";allow (delete,write) groupdn = "ldap:///cn=System: Manage Host Resource Delegation,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "ipasshpubkey")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host SSH Public Keys";allow (write) groupdn = "ldap:///cn=System: Manage Host SSH Public Keys,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "description || ipaassignedidview || krbprincipalauthind || l || macaddress || nshardwareplatform || nshostlocation || nsosversion || userclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Modify Hosts";allow (write) groupdn = "ldap:///cn=System: Modify Hosts,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
@@ -163,7 +161,7 @@ aci: (targetattr = "cn || createtimestamp || entryusn || macaddress || modifytim
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "memberof")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Read Host Membership";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || description || enrolledby || entryusn || fqdn || ipaassignedidview || ipaclientversion || ipakrbauthzdata || ipasshpubkey || ipauniqueid || krbcanonicalname || krblastpwdchange || krbpasswordexpiration || krbprincipalaliases || krbprincipalauthind || krbprincipalexpiration || krbprincipalname || l || macaddress || managedby || memberprincipal || modifytimestamp || nshardwareplatform || nshostlocation || nsosversion || objectclass || serverhostname || usercertificate || userclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Read Hosts";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
aci: (targetattr = "cn || createtimestamp || description || enrolledby || entryusn || fqdn || ipaassignedidview || ipaclientversion || ipakrbauthzdata || ipasshpubkey || ipauniqueid || krbcanonicalname || krblastpwdchange || krbpasswordexpiration || krbprincipalaliases || krbprincipalauthind || krbprincipalexpiration || krbprincipalname || l || macaddress || managedby || modifytimestamp || nshardwareplatform || nshostlocation || nsosversion || objectclass || serverhostname || usercertificate || userclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Read Hosts";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Remove Hosts";allow (delete) groupdn = "ldap:///cn=System: Remove Hosts,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
@@ -224,10 +222,6 @@ dn: cn=ng,cn=alt,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(objectclass=ipanisnetgroup)")(version 3.0;acl "permission:System: Remove Netgroups";allow (delete) groupdn = "ldap:///cn=System: Remove Netgroups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=otp,cn=etc,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || ipatokenhotpauthwindow || ipatokenhotpsyncwindow || ipatokentotpauthwindow || ipatokentotpsyncwindow")(targetfilter = "(objectclass=ipatokenotpconfig)")(version 3.0;acl "permission:System: Read OTP Configuration";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=passkeyconfig,cn=etc,dc=ipa,dc=example
|
||||
aci: (targetattr = "iparequireuserverification")(targetfilter = "(objectclass=ipapasskeyconfigobject)")(version 3.0;acl "permission:System: Modify Passkey Configuration";allow (write) groupdn = "ldap:///cn=System: Modify Passkey Configuration,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=passkeyconfig,cn=etc,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || iparequireuserverification")(targetfilter = "(objectclass=ipapasskeyconfigobject)")(version 3.0;acl "permission:System: Read Passkey Configuration";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=permissions,cn=pbac,dc=ipa,dc=example
|
||||
aci: (targetattr = "member")(targetfilter = "(objectclass=ipapermission)")(version 3.0;acl "permission:System: Modify Privilege Membership";allow (write) groupdn = "ldap:///cn=System: Modify Privilege Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: dc=ipa,dc=example
|
||||
@@ -287,15 +281,11 @@ aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "krbcanonicalname || krbprincipalname")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Principals";allow (write) groupdn = "ldap:///cn=System: Manage Service Principals,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "memberprincipal || objectclass")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Resource Delegation";allow (delete,write) groupdn = "ldap:///cn=System: Manage Service Resource Delegation,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;write_delegation || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Resource Delegation Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Service Resource Delegation Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "krbprincipalauthind || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Modify Services";allow (write) groupdn = "ldap:///cn=System: Modify Services,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || entryusn || gecos || gidnumber || homedirectory || ipantsecurityidentifier || loginshell || modifytimestamp || objectclass || uid || uidnumber")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read POSIX details of SMB services";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalauthind || krbprincipalexpiration || krbprincipalname || managedby || memberof || memberprincipal || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalauthind || krbprincipalexpiration || krbprincipalname || managedby || memberof || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Remove Services";allow (delete) groupdn = "ldap:///cn=System: Remove Services,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||
@@ -387,8 +377,6 @@ aci: (targetattr = "krbpasswordexpiration || krbprincipalkey || passwordhistory
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "krbpasswordexpiration || krbprincipalkey || passwordhistory || sambalmpassword || sambantpassword || userpassword")(targetfilter = "(&(!(memberOf=cn=admins,cn=groups,cn=accounts,dc=ipa,dc=example))(objectclass=posixaccount))")(version 3.0;acl "permission:System: Change User password";allow (write) groupdn = "ldap:///cn=System: Change User password,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "ipapasskey || objectclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage Passkey Mappings";allow (write) groupdn = "ldap:///cn=System: Manage Passkey Mappings,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "ipacertmapdata || objectclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User Certificate Mappings";allow (write) groupdn = "ldap:///cn=System: Manage User Certificate Mappings,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "usercertificate")(targetfilter = "(&(!(memberOf=cn=admins,cn=groups,cn=accounts,dc=ipa,dc=example))(objectclass=posixaccount))")(version 3.0;acl "permission:System: Manage User Certificates";allow (write) groupdn = "ldap:///cn=System: Manage User Certificates,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
@@ -405,7 +393,7 @@ aci: (targetattr = "audio || businesscategory || carlicense || departmentnumber
|
||||
dn: dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || entryusn || gecos || gidnumber || homedirectory || loginshell || modifytimestamp || objectclass || uid || uidnumber")(target = "ldap:///cn=users,cn=compat,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read User Compat Tree";allow (compare,read,search) userdn = "ldap:///anyone";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "ipapasskey || ipasshpubkey || ipauniqueid || ipauserauthtype || userclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User IPA Attributes";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
aci: (targetattr = "ipasshpubkey || ipauniqueid || ipauserauthtype || userclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User IPA Attributes";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "krbcanonicalname || krblastpwdchange || krbpasswordexpiration || krbprincipalaliases || krbprincipalexpiration || krbprincipalname || krbprincipaltype || nsaccountlock")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Read User Kerberos Attributes";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=users,cn=accounts,dc=ipa,dc=example
|
||||
|
||||
@@ -1099,7 +1099,7 @@ option: Int('ipasearchrecordslimit?', autofill=False, cli_name='searchrecordslim
|
||||
option: Int('ipasearchtimelimit?', autofill=False, cli_name='searchtimelimit')
|
||||
option: Str('ipaselinuxusermapdefault?', autofill=False)
|
||||
option: Str('ipaselinuxusermaporder?', autofill=False)
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey', u'disabled'])
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'disabled'])
|
||||
option: Bool('ipauserdefaultsubordinateid?', autofill=False, cli_name='user_default_subid')
|
||||
option: Str('ipauserobjectclasses*', autofill=False, cli_name='userobjectclasses')
|
||||
option: IA5Str('ipausersearchfields?', autofill=False, cli_name='usersearch')
|
||||
@@ -1798,7 +1798,7 @@ option: DNSNameParam('idnssoamname?', cli_name='name_server')
|
||||
option: Int('idnssoarefresh', autofill=True, cli_name='refresh', default=3600)
|
||||
option: Int('idnssoaretry', autofill=True, cli_name='retry', default=900)
|
||||
option: DNSNameParam('idnssoarname', autofill=True, cli_name='admin_email', default=<DNS name hostmaster>)
|
||||
option: Int('idnssoaserial?', cli_name='serial', deprecated=True)
|
||||
option: Int('idnssoaserial', autofill=True, cli_name='serial')
|
||||
option: Str('idnsupdatepolicy?', autofill=True, cli_name='update_policy')
|
||||
option: Str('ip_address?')
|
||||
option: Str('name_from_ip?')
|
||||
@@ -1862,7 +1862,7 @@ option: DNSNameParam('idnssoamname?', autofill=False, cli_name='name_server')
|
||||
option: Int('idnssoarefresh?', autofill=False, cli_name='refresh', default=3600)
|
||||
option: Int('idnssoaretry?', autofill=False, cli_name='retry', default=900)
|
||||
option: DNSNameParam('idnssoarname?', autofill=False, cli_name='admin_email', default=<DNS name hostmaster>)
|
||||
option: Int('idnssoaserial?', autofill=False, cli_name='serial', deprecated=True)
|
||||
option: Int('idnssoaserial?', autofill=False, cli_name='serial')
|
||||
option: Str('idnsupdatepolicy?', autofill=False, cli_name='update_policy')
|
||||
option: Bool('idnszoneactive?', autofill=False, cli_name='zone_active')
|
||||
option: Str('name_from_ip?', autofill=False)
|
||||
@@ -1899,7 +1899,7 @@ option: DNSNameParam('idnssoamname?', autofill=False, cli_name='name_server')
|
||||
option: Int('idnssoarefresh?', autofill=False, cli_name='refresh', default=3600)
|
||||
option: Int('idnssoaretry?', autofill=False, cli_name='retry', default=900)
|
||||
option: DNSNameParam('idnssoarname?', autofill=False, cli_name='admin_email', default=<DNS name hostmaster>)
|
||||
option: Int('idnssoaserial?', autofill=False, cli_name='serial', deprecated=True)
|
||||
option: Int('idnssoaserial?', autofill=False, cli_name='serial')
|
||||
option: Str('idnsupdatepolicy?', autofill=False, cli_name='update_policy')
|
||||
option: Str('name_from_ip?', autofill=False)
|
||||
option: Str('nsec3paramrecord?', autofill=False, cli_name='nsec3param_rec')
|
||||
@@ -2478,7 +2478,7 @@ option: Bool('ipakrbokasdelegate?', cli_name='ok_as_delegate')
|
||||
option: Bool('ipakrboktoauthasdelegate?', cli_name='ok_to_auth_as_delegate')
|
||||
option: Bool('ipakrbrequirespreauth?', cli_name='requires_pre_auth')
|
||||
option: Str('ipasshpubkey*', cli_name='sshpubkey')
|
||||
option: StrEnum('krbprincipalauthind*', cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Str('l?', cli_name='locality')
|
||||
option: Str('macaddress*')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
@@ -2507,17 +2507,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_add_delegation/1
|
||||
args: 2,4,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
arg: Str('memberprincipal+', alwaysask=True, cli_name='principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_add_managedby/1
|
||||
args: 1,5,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
@@ -2540,20 +2529,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_allow_add_delegation/1
|
||||
args: 1,8,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Str('host*', alwaysask=True, cli_name='hosts')
|
||||
option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: host_allow_create_keytab/1
|
||||
args: 1,8,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
@@ -2598,20 +2573,6 @@ option: Str('version?')
|
||||
output: Output('result', type=[<type 'bool'>])
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_disallow_add_delegation/1
|
||||
args: 1,8,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Str('host*', alwaysask=True, cli_name='hosts')
|
||||
option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: host_disallow_create_keytab/1
|
||||
args: 1,8,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
@@ -2653,7 +2614,7 @@ option: Str('in_netgroup*', cli_name='in_netgroups')
|
||||
option: Str('in_role*', cli_name='in_roles')
|
||||
option: Str('in_sudorule*', cli_name='in_sudorules')
|
||||
option: Str('ipaassignedidview?', autofill=False)
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Str('l?', autofill=False, cli_name='locality')
|
||||
option: Str('macaddress*', autofill=False)
|
||||
option: Str('man_by_host*', cli_name='man_by_hosts')
|
||||
@@ -2693,7 +2654,7 @@ option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate')
|
||||
option: Bool('ipakrboktoauthasdelegate?', autofill=False, cli_name='ok_to_auth_as_delegate')
|
||||
option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth')
|
||||
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Principal('krbprincipalname*', autofill=False)
|
||||
option: Str('l?', autofill=False, cli_name='locality')
|
||||
option: Str('macaddress*', autofill=False)
|
||||
@@ -2724,17 +2685,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_remove_delegation/1
|
||||
args: 2,4,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
arg: Str('memberprincipal+', alwaysask=True, cli_name='principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: host_remove_managedby/1
|
||||
args: 1,5,3
|
||||
arg: Str('fqdn', cli_name='hostname')
|
||||
@@ -3377,7 +3327,7 @@ output: Output('result', type=[<type 'bool'>])
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: krbtpolicy_mod/1
|
||||
args: 1,21,3
|
||||
args: 1,19,3
|
||||
arg: Str('uid?', cli_name='user')
|
||||
option: Str('addattr*', cli_name='addattr')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
@@ -3385,13 +3335,11 @@ option: Str('delattr*', cli_name='delattr')
|
||||
option: Int('krbauthindmaxrenewableage_hardened?', autofill=False, cli_name='hardened_maxrenew')
|
||||
option: Int('krbauthindmaxrenewableage_idp?', autofill=False, cli_name='idp_maxrenew')
|
||||
option: Int('krbauthindmaxrenewableage_otp?', autofill=False, cli_name='otp_maxrenew')
|
||||
option: Int('krbauthindmaxrenewableage_passkey?', autofill=False, cli_name='passkey_maxrenew')
|
||||
option: Int('krbauthindmaxrenewableage_pkinit?', autofill=False, cli_name='pkinit_maxrenew')
|
||||
option: Int('krbauthindmaxrenewableage_radius?', autofill=False, cli_name='radius_maxrenew')
|
||||
option: Int('krbauthindmaxticketlife_hardened?', autofill=False, cli_name='hardened_maxlife')
|
||||
option: Int('krbauthindmaxticketlife_idp?', autofill=False, cli_name='idp_maxlife')
|
||||
option: Int('krbauthindmaxticketlife_otp?', autofill=False, cli_name='otp_maxlife')
|
||||
option: Int('krbauthindmaxticketlife_passkey?', autofill=False, cli_name='passkey_maxlife')
|
||||
option: Int('krbauthindmaxticketlife_pkinit?', autofill=False, cli_name='pkinit_maxlife')
|
||||
option: Int('krbauthindmaxticketlife_radius?', autofill=False, cli_name='radius_maxlife')
|
||||
option: Int('krbmaxrenewableage?', autofill=False, cli_name='maxrenew')
|
||||
@@ -3821,28 +3769,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: passkeyconfig_mod/1
|
||||
args: 0,8,3
|
||||
option: Str('addattr*', cli_name='addattr')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('delattr*', cli_name='delattr')
|
||||
option: Bool('iparequireuserverification?', autofill=False, cli_name='require_user_verification')
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Flag('rights', autofill=True, default=False)
|
||||
option: Str('setattr*', cli_name='setattr')
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: passkeyconfig_show/1
|
||||
args: 0,4,3
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Flag('rights', autofill=True, default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: passwd/1
|
||||
args: 3,2,3
|
||||
arg: Principal('principal', autofill=True, cli_name='user')
|
||||
@@ -4150,7 +4076,7 @@ option: Int('krbpwdlockoutduration?', cli_name='lockouttime')
|
||||
option: Int('krbpwdmaxfailure?', cli_name='maxfail')
|
||||
option: Int('krbpwdmindiffchars?', cli_name='minclasses')
|
||||
option: Int('krbpwdminlength?', cli_name='minlength')
|
||||
option: Int('passwordgracelimit?', autofill=True, cli_name='gracelimit', default=-1)
|
||||
option: Int('passwordgracelimit?', cli_name='gracelimit', default=-1)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('setattr*', cli_name='setattr')
|
||||
option: Str('version?')
|
||||
@@ -4758,7 +4684,7 @@ option: StrEnum('ipakrbauthzdata*', cli_name='pac_type', values=[u'MS-PAC', u'PA
|
||||
option: Bool('ipakrbokasdelegate?', cli_name='ok_as_delegate')
|
||||
option: Bool('ipakrboktoauthasdelegate?', cli_name='ok_to_auth_as_delegate')
|
||||
option: Bool('ipakrbrequirespreauth?', cli_name='requires_pre_auth')
|
||||
option: StrEnum('krbprincipalauthind*', cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('setattr*', cli_name='setattr')
|
||||
@@ -4779,17 +4705,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_add_delegation/1
|
||||
args: 2,4,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
arg: Str('memberprincipal+', alwaysask=True, cli_name='principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_add_host/1
|
||||
args: 1,5,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
@@ -4828,20 +4743,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_allow_add_delegation/1
|
||||
args: 1,8,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Str('host*', alwaysask=True, cli_name='hosts')
|
||||
option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: service_allow_create_keytab/1
|
||||
args: 1,8,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
@@ -4885,20 +4786,6 @@ option: Str('version?')
|
||||
output: Output('result', type=[<type 'bool'>])
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_disallow_add_delegation/1
|
||||
args: 1,8,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Str('host*', alwaysask=True, cli_name='hosts')
|
||||
option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: service_disallow_create_keytab/1
|
||||
args: 1,8,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
@@ -4933,7 +4820,7 @@ arg: Str('criteria?')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values=[u'MS-PAC', u'PAD', u'NONE'])
|
||||
option: Principal('krbcanonicalname?', autofill=False, cli_name='canonical_principal')
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
option: Str('man_by_host*', cli_name='man_by_hosts')
|
||||
option: Flag('no_members', autofill=True, default=True)
|
||||
@@ -4957,7 +4844,7 @@ option: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values=
|
||||
option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate')
|
||||
option: Bool('ipakrboktoauthasdelegate?', autofill=False, cli_name='ok_to_auth_as_delegate')
|
||||
option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth')
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('krbprincipalauthind*', autofill=False, cli_name='auth_ind', values=[u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
@@ -4979,17 +4866,6 @@ option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_remove_delegation/1
|
||||
args: 2,4,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
arg: Str('memberprincipal+', alwaysask=True, cli_name='principal')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: service_remove_host/1
|
||||
args: 1,5,3
|
||||
arg: Principal('krbcanonicalname', cli_name='canonical_principal')
|
||||
@@ -5218,7 +5094,7 @@ option: Str('ipaidpsub?', cli_name='idp_user_id')
|
||||
option: Str('ipasshpubkey*', cli_name='sshpubkey')
|
||||
option: Str('ipatokenradiusconfiglink?', cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=True, cli_name='principal')
|
||||
@@ -5284,17 +5160,6 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: stageuser_add_passkey/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
arg: Str('ipapasskey+', alwaysask=True, cli_name='passkey')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: stageuser_add_principal/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
@@ -5344,7 +5209,7 @@ option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
|
||||
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
|
||||
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
@@ -5410,7 +5275,7 @@ option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
|
||||
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
|
||||
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
@@ -5478,17 +5343,6 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: stageuser_remove_passkey/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
arg: Str('ipapasskey+', alwaysask=True, cli_name='passkey')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: stageuser_remove_principal/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
@@ -6425,7 +6279,7 @@ option: Str('ipaidpsub?', cli_name='idp_user_id')
|
||||
option: Str('ipasshpubkey*', cli_name='sshpubkey')
|
||||
option: Str('ipatokenradiusconfiglink?', cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=True, cli_name='principal')
|
||||
@@ -6493,17 +6347,6 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: user_add_passkey/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
arg: Str('ipapasskey+', alwaysask=True, cli_name='passkey')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: user_add_principal/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
@@ -6568,7 +6411,7 @@ option: Str('ipantlogonscript?', autofill=False, cli_name='smb_logon_script')
|
||||
option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
|
||||
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
@@ -6637,7 +6480,7 @@ option: Str('ipantprofilepath?', autofill=False, cli_name='smb_profile_path')
|
||||
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
|
||||
option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
|
||||
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username')
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp', u'passkey'])
|
||||
option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp', u'pkinit', u'hardened', u'idp'])
|
||||
option: DateTime('krbpasswordexpiration?', autofill=False, cli_name='password_expiration')
|
||||
option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
|
||||
option: Principal('krbprincipalname*', autofill=False, cli_name='principal')
|
||||
@@ -6706,17 +6549,6 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: user_remove_passkey/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
arg: Str('ipapasskey+', alwaysask=True, cli_name='passkey')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('version?')
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: user_remove_principal/1
|
||||
args: 2,4,3
|
||||
arg: Str('uid', cli_name='login')
|
||||
@@ -6835,7 +6667,7 @@ option: Flag('shared?', autofill=True, default=False)
|
||||
option: Str('username?', cli_name='user')
|
||||
option: Bytes('vault_data')
|
||||
option: Str('version?')
|
||||
option: StrEnum('wrapping_algo?', autofill=True, default=u'des-ede3-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc'])
|
||||
option: StrEnum('wrapping_algo?', autofill=True, default=u'aes-128-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc'])
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
@@ -6935,7 +6767,7 @@ option: Bytes('session_key')
|
||||
option: Flag('shared?', autofill=True, default=False)
|
||||
option: Str('username?', cli_name='user')
|
||||
option: Str('version?')
|
||||
option: StrEnum('wrapping_algo?', autofill=True, default=u'des-ede3-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc'])
|
||||
option: StrEnum('wrapping_algo?', autofill=True, default=u'aes-128-cbc', values=[u'aes-128-cbc', u'des-ede3-cbc'])
|
||||
output: Entry('result')
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
@@ -7260,21 +7092,17 @@ default: hbactest/1
|
||||
default: host/1
|
||||
default: host_add/1
|
||||
default: host_add_cert/1
|
||||
default: host_add_delegation/1
|
||||
default: host_add_managedby/1
|
||||
default: host_add_principal/1
|
||||
default: host_allow_add_delegation/1
|
||||
default: host_allow_create_keytab/1
|
||||
default: host_allow_retrieve_keytab/1
|
||||
default: host_del/1
|
||||
default: host_disable/1
|
||||
default: host_disallow_add_delegation/1
|
||||
default: host_disallow_create_keytab/1
|
||||
default: host_disallow_retrieve_keytab/1
|
||||
default: host_find/1
|
||||
default: host_mod/1
|
||||
default: host_remove_cert/1
|
||||
default: host_remove_delegation/1
|
||||
default: host_remove_managedby/1
|
||||
default: host_remove_principal/1
|
||||
default: host_show/1
|
||||
@@ -7363,9 +7191,6 @@ default: output_show/1
|
||||
default: param/1
|
||||
default: param_find/1
|
||||
default: param_show/1
|
||||
default: passkeyconfig/1
|
||||
default: passkeyconfig_mod/1
|
||||
default: passkeyconfig_show/1
|
||||
default: passwd/1
|
||||
default: permission/1
|
||||
default: permission_add/1
|
||||
@@ -7447,22 +7272,18 @@ default: server_state/1
|
||||
default: service/1
|
||||
default: service_add/1
|
||||
default: service_add_cert/1
|
||||
default: service_add_delegation/1
|
||||
default: service_add_host/1
|
||||
default: service_add_principal/1
|
||||
default: service_add_smb/1
|
||||
default: service_allow_add_delegation/1
|
||||
default: service_allow_create_keytab/1
|
||||
default: service_allow_retrieve_keytab/1
|
||||
default: service_del/1
|
||||
default: service_disable/1
|
||||
default: service_disallow_add_delegation/1
|
||||
default: service_disallow_create_keytab/1
|
||||
default: service_disallow_retrieve_keytab/1
|
||||
default: service_find/1
|
||||
default: service_mod/1
|
||||
default: service_remove_cert/1
|
||||
default: service_remove_delegation/1
|
||||
default: service_remove_host/1
|
||||
default: service_remove_principal/1
|
||||
default: service_show/1
|
||||
@@ -7491,7 +7312,6 @@ default: stageuser_add/1
|
||||
default: stageuser_add_cert/1
|
||||
default: stageuser_add_certmapdata/1
|
||||
default: stageuser_add_manager/1
|
||||
default: stageuser_add_passkey/1
|
||||
default: stageuser_add_principal/1
|
||||
default: stageuser_del/1
|
||||
default: stageuser_find/1
|
||||
@@ -7499,7 +7319,6 @@ default: stageuser_mod/1
|
||||
default: stageuser_remove_cert/1
|
||||
default: stageuser_remove_certmapdata/1
|
||||
default: stageuser_remove_manager/1
|
||||
default: stageuser_remove_passkey/1
|
||||
default: stageuser_remove_principal/1
|
||||
default: stageuser_show/1
|
||||
default: subid/1
|
||||
@@ -7588,7 +7407,6 @@ default: user_add/1
|
||||
default: user_add_cert/1
|
||||
default: user_add_certmapdata/1
|
||||
default: user_add_manager/1
|
||||
default: user_add_passkey/1
|
||||
default: user_add_principal/1
|
||||
default: user_del/1
|
||||
default: user_disable/1
|
||||
@@ -7598,7 +7416,6 @@ default: user_mod/1
|
||||
default: user_remove_cert/1
|
||||
default: user_remove_certmapdata/1
|
||||
default: user_remove_manager/1
|
||||
default: user_remove_passkey/1
|
||||
default: user_remove_principal/1
|
||||
default: user_show/1
|
||||
default: user_stage/1
|
||||
|
||||
@@ -7,7 +7,7 @@ For more information, see http://www.freeipa.org/page/Build
|
||||
|
||||
The quickest way to get the dependencies needed for building is:
|
||||
|
||||
# dnf builddep -D "with_wheels 1" -D "with_lint 1" -D "with_doc 1" --spec freeipa.spec.in --best --allowerasing --setopt=install_weak_deps=False
|
||||
# dnf builddep -b -D "with_wheels 1" -D "with_lint 1" -D "with_doc 1" --spec freeipa.spec.in --best --allowerasing --setopt=install_weak_deps=False
|
||||
|
||||
TIP: For building with latest dependencies for freeipa master enable copr repo:
|
||||
|
||||
|
||||
@@ -16,10 +16,8 @@ Developers:
|
||||
Alexander Bokovoy
|
||||
Alexander Koksharov
|
||||
Alexander Scheel
|
||||
Alexandra Nikandrova
|
||||
Alexandre Mulatinho
|
||||
Alexey Slaykovsky
|
||||
Alexey Tikhonov
|
||||
Amit Kumar
|
||||
Ana Krivokapić
|
||||
Andika Triwidada
|
||||
@@ -35,7 +33,6 @@ Developers:
|
||||
Brian J. Murrell
|
||||
Brian Turek
|
||||
Carl George
|
||||
Carla Martinez
|
||||
Cédric Jeanneret
|
||||
Changmin Teng
|
||||
Chris Kelley
|
||||
@@ -45,7 +42,6 @@ Developers:
|
||||
David Kreitschmann
|
||||
David Kupka
|
||||
David O'Brien
|
||||
David Pascual
|
||||
David Spångberg
|
||||
Diane Trout
|
||||
Dinesh Prasanth M K
|
||||
@@ -55,11 +51,8 @@ Developers:
|
||||
Drew Erny
|
||||
Emilio Herrera
|
||||
Endi Sukma Dewata
|
||||
Erik
|
||||
Erik Belko
|
||||
Fabiano Fidêncio
|
||||
Felipe Volpone
|
||||
Filip Dvorak
|
||||
Filip Skola
|
||||
Florence Blanc-Renaud
|
||||
Francesco Marella
|
||||
@@ -76,7 +69,6 @@ Developers:
|
||||
Hela Basa
|
||||
Ian Kumlien
|
||||
Ian Pilcher
|
||||
Iker Pedrosa
|
||||
Isaac Boukris
|
||||
Jakub Hrozek
|
||||
James Groffen
|
||||
@@ -85,15 +77,12 @@ Developers:
|
||||
Jan Kuparinen
|
||||
Jan Pazdziora
|
||||
Jan Zelený
|
||||
Jarl Gullberg
|
||||
Jason Gerard DeRose
|
||||
Jason Woods
|
||||
Jayesh
|
||||
Jayesh Garg
|
||||
Jeremy Frasier
|
||||
Jérôme Fenal
|
||||
Jerry James
|
||||
Jesse Sandberg
|
||||
jh23453
|
||||
Jim Meyering
|
||||
Jochen Kellner
|
||||
@@ -113,7 +102,6 @@ Developers:
|
||||
Lars Sjostrom
|
||||
Lenka Doudova
|
||||
Lenka Ryznarova
|
||||
Lenz Grimmer
|
||||
Lewis Eason
|
||||
Lubomír Rintel
|
||||
Ludwig Krispenz
|
||||
@@ -129,7 +117,6 @@ Developers:
|
||||
Martin Nagy
|
||||
Matt Rogers
|
||||
Matthew Davis
|
||||
mbhalodi
|
||||
Michael Simacek
|
||||
Michal Polovka
|
||||
Michal Reznik
|
||||
@@ -145,7 +132,6 @@ Developers:
|
||||
ndehadra
|
||||
Nick Hatch
|
||||
Nikhil Dehadrai
|
||||
Nikola Knazekova
|
||||
Nikolai Kondrashov
|
||||
Niranjan Mallapadi
|
||||
Niranjan MR
|
||||
@@ -173,22 +159,18 @@ Developers:
|
||||
realsobek
|
||||
René Genz
|
||||
Rich Megginson
|
||||
Ricky Tigg
|
||||
Rishabh Dave
|
||||
Rob Crittenden
|
||||
Robbie Harwood
|
||||
Robert Collins
|
||||
Robert Kuska
|
||||
s1341
|
||||
Sam Bristow
|
||||
Sam Morris
|
||||
Scott Poore
|
||||
Sergey Orlov
|
||||
Sergio Oliveira Campos
|
||||
Serhii Tsymbaliuk
|
||||
shanyin
|
||||
Simo Sorce
|
||||
Simon Nussbaum
|
||||
Slava Aseev
|
||||
Spencer E. Olson
|
||||
Stanislav Laznicka
|
||||
@@ -202,20 +184,17 @@ Developers:
|
||||
Sumit Bose
|
||||
Sylvain Baubeau
|
||||
Takeshi MIZUTA
|
||||
Temuri Doghonadze
|
||||
Theodor van Nahl
|
||||
Thierry Bordaz
|
||||
Thomas Woerner
|
||||
Thorsten Scherf
|
||||
Tibor Dudlák
|
||||
Timo Aaltonen
|
||||
Todd Zullinger
|
||||
Tomáš Babej
|
||||
Tomas Halman
|
||||
Tomáš Křížek
|
||||
Troy Dawson
|
||||
Varun Mylaraiah
|
||||
Viacheslav Sychov
|
||||
Viktor Ashirov
|
||||
Vit Mojzis
|
||||
W. Michael Petullo
|
||||
@@ -226,7 +205,6 @@ Developers:
|
||||
Yuri Chornoivan
|
||||
Zdenek Pytela
|
||||
zdover
|
||||
김인수
|
||||
|
||||
Documentation:
|
||||
Gabe Alford
|
||||
|
||||
+2
-2
@@ -244,7 +244,7 @@ fastcodestyle: $(GENERATED_PYTHON_FILES) ipasetup.py
|
||||
| xargs -n1 file 2>/dev/null | grep Python \
|
||||
| cut -d':' -f1; ); \
|
||||
if [ -n "$${PYFILES}" ] && [ -n "$${INFILES}" ]; then \
|
||||
FILES="$$( printf '%s\n' "$${PYFILES}" "$${INFILES}" )" ; \
|
||||
FILES="$$( printf $${PYFILES}\\n$${INFILES} )" ; \
|
||||
elif [ -n "$${PYFILES}" ]; then \
|
||||
FILES="$${PYFILES}" ; \
|
||||
else \
|
||||
@@ -274,7 +274,7 @@ endif
|
||||
| xargs -n1 file 2>/dev/null | grep Python \
|
||||
| cut -d':' -f1; ); \
|
||||
if [ -n "$${PYFILES}" ] && [ -n "$${INFILES}" ]; then \
|
||||
FILES="$$( printf '%s\n' "$${PYFILES}" "$${INFILES}" )" ; \
|
||||
FILES="$$( printf $${PYFILES}\\n$${INFILES} )" ; \
|
||||
elif [ -n "$${PYFILES}" ]; then \
|
||||
FILES="$${PYFILES}" ; \
|
||||
else \
|
||||
|
||||
+5
-11
@@ -20,8 +20,8 @@
|
||||
# -> "1.0.0" #
|
||||
########################################################
|
||||
define(IPA_VERSION_MAJOR, 4)
|
||||
define(IPA_VERSION_MINOR, 11)
|
||||
define(IPA_VERSION_RELEASE, 0)
|
||||
define(IPA_VERSION_MINOR, 10)
|
||||
define(IPA_VERSION_RELEASE, 1)
|
||||
|
||||
########################################################
|
||||
# For 'pre' releases the version will be #
|
||||
@@ -49,7 +49,7 @@ define(IPA_VERSION_PRE_RELEASE, )
|
||||
# This option works only with GNU m4: #
|
||||
# it requires esyscmd m4 macro. #
|
||||
########################################################
|
||||
define(IPA_VERSION_IS_GIT_SNAPSHOT, no)
|
||||
define(IPA_VERSION_IS_GIT_SNAPSHOT, yes)
|
||||
|
||||
########################################################
|
||||
# git development branch: #
|
||||
@@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000)
|
||||
# #
|
||||
########################################################
|
||||
define(IPA_API_VERSION_MAJOR, 2)
|
||||
# Last change: add passkey support
|
||||
define(IPA_API_VERSION_MINOR, 253)
|
||||
# Last change: add Random Serial Numbers v3
|
||||
define(IPA_API_VERSION_MINOR, 249)
|
||||
|
||||
########################################################
|
||||
# Following values are auto-generated from values above
|
||||
@@ -137,11 +137,6 @@ ifelse(IPA_VERSION_IS_GIT_SNAPSHOT, yes,
|
||||
IPA_GIT_VERSION),
|
||||
NEWLINE)) dnl IPA_VERSION end
|
||||
|
||||
########################################################
|
||||
# Version of MIT krb5 used to build IPA
|
||||
########################################################
|
||||
define(IPA_KRB5_BUILD_VERSION, translit(esyscmd(krb5-config --version | awk '{ print $NF }'), NEWLINE))
|
||||
|
||||
dnl DEBUG: uncomment following lines and run command m4 VERSION.m4
|
||||
dnl `IPA_VERSION: ''IPA_VERSION'
|
||||
dnl `IPA_GIT_VERSION: ''IPA_GIT_VERSION'
|
||||
@@ -149,4 +144,3 @@ dnl `IPA_GIT_BRANCH: ''IPA_GIT_BRANCH'
|
||||
dnl `IPA_API_VERSION: ''IPA_API_VERSION'
|
||||
dnl `IPA_DATA_VERSION: ''IPA_DATA_VERSION'
|
||||
dnl `IPA_NUM_VERSION: ''IPA_NUM_VERSION'
|
||||
dnl `IPA_KRB5_BUILD_VERSION: ''IPA_KRB5_BUILD_VERSION'
|
||||
+2
-4
@@ -57,8 +57,6 @@
|
||||
|
||||
char * read_config_file(const char *filename);
|
||||
char * get_config_entry(char * data, const char *section, const char *key);
|
||||
static size_t
|
||||
jsonrpc_handle_response(char *ptr, size_t size, size_t nmemb, void *userdata);
|
||||
|
||||
static int debug = 0;
|
||||
|
||||
@@ -644,7 +642,7 @@ curl_slist_append_log(struct curl_slist *list, char *string, bool quiet) {
|
||||
goto cleanup; \
|
||||
}
|
||||
|
||||
static size_t
|
||||
size_t
|
||||
jsonrpc_handle_response(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||
size_t realsize = size * nmemb;
|
||||
curl_buffer *cb = (curl_buffer *) userdata;
|
||||
@@ -724,7 +722,7 @@ jsonrpc_request(const char *ipaserver, const json_t *json, curl_buffer *response
|
||||
|
||||
CURL_SETOPT(curl, CURLOPT_CAINFO, DEFAULT_CA_CERT_FILE);
|
||||
|
||||
CURL_SETOPT(curl, CURLOPT_WRITEFUNCTION, jsonrpc_handle_response);
|
||||
CURL_SETOPT(curl, CURLOPT_WRITEFUNCTION, &jsonrpc_handle_response);
|
||||
CURL_SETOPT(curl, CURLOPT_WRITEDATA, response);
|
||||
|
||||
CURL_SETOPT(curl, CURLOPT_HTTPAUTH, CURLAUTH_NEGOTIATE);
|
||||
|
||||
@@ -166,9 +166,6 @@ Specifies the mount point that the development server will register. The default
|
||||
.B oidc_child_debug_level <debuglevel>
|
||||
Specifies the debug level of \fBoidc_child\fR, a helper process used by \fBipa-otpd\fR for OIDC/OAuth2 authentication. Level can be between 0 and 10, the higher the more details. If the level is 6 or higher HTTP debug output is added as well.
|
||||
.TP
|
||||
.B passkey_child_debug_level <debuglevel>
|
||||
Specifies the debug level of \fBpasskey_child\fR, a helper process used by \fBipa-otpd\fR for passkey authentication. Level can be between 0 and 10, the higher the more details. If the level is 6 or higher libfido2 debug output is added as well.
|
||||
.TP
|
||||
.B prompt_all <boolean>
|
||||
Specifies that all options should be prompted for in the IPA client, even optional values. Default is False.
|
||||
.TP
|
||||
|
||||
@@ -86,9 +86,6 @@ Time to wait, in milliseconds, between each e-mail sent to try to avoid overload
|
||||
Specifies the From: e-mail address value in the e-mails sent. The default is noreply@ipadefaultemaildomain. This value can be found by running
|
||||
.I ipa config-show
|
||||
.TP
|
||||
.B mail_from_name <name>
|
||||
Specifies the From: name value in the e-mails sent. The default is IPA-EPN.
|
||||
.TP
|
||||
.B notify_ttls <list of days>
|
||||
This is the list of days before a password expiration when ipa-epn should notify a user that their password will soon require a reset. If this value is not specified then the default list will be used: 28, 14, 7, 3, 1.
|
||||
.TP
|
||||
|
||||
@@ -11,7 +11,7 @@ Configures a client machine to use IPA for authentication and identity services.
|
||||
|
||||
By default this configures SSSD to connect to an IPA server for authentication and authorization. Optionally one can instead configure PAM and NSS (Name Switching Service) to work with an IPA server over Kerberos and LDAP.
|
||||
|
||||
An authorized account is required to join a client machine to IPA. This can take the form of a kerberos principal, a one\-time password associated with the machine, or PKINIT identity associated with the machine.
|
||||
An authorized user is required to join a client machine to IPA. This can take the form of a kerberos principal or a one\-time password associated with the machine.
|
||||
|
||||
This same tool is used to unconfigure IPA and attempts to return the machine to its previous state. Part of this process is to unenroll the host from the IPA server. Unenrollment consists of disabling the principal key on the IPA server so that it may be re\-enrolled. The machine principal in /etc/krb5.keytab (host/<fqdn>@REALM) is used to authenticate to the IPA server to unenroll itself. If this principal does not exist then unenrollment will fail and an administrator will need to disable the host principal (ipa host\-disable <fqdn>).
|
||||
|
||||
@@ -229,22 +229,6 @@ first. When this option is not specified, \fBipa\-client\-install\fR will back
|
||||
up SSSD config and create new one. The back up version will be restored during
|
||||
uninstall.
|
||||
|
||||
.SS "PKINIT OPTIONS"
|
||||
.TP
|
||||
\fB\-\-pkinit\-identity=\fIDENTITY\fR
|
||||
Identity string for PKINIT authentication to use to join the IPA realm,
|
||||
for example 'FILE:/path/to/cert.pem,/path/to/key.pem'. See krb5.conf(5)
|
||||
for more information. The option is mutually exclusive with
|
||||
\fB\-\-password\fR and \fB\-\-keytab\fR.
|
||||
.TP
|
||||
\fB\-\-pkinit\-anchor\fR=\fIFILEDIR\fR
|
||||
Trust anchors (root and intermediate CA certs) for PKINIT. \fIFILEDIR\fR is
|
||||
either the absolute path to a PEM bundle (for example
|
||||
'FILE:/etc/pki/tls/cert.pem') or to an OpenSSL hash directory (for example
|
||||
'DIR:/etc/ssl/certs/'). The option can be used multiple times. PKINIT
|
||||
requires the full trust chain of the Kerberos KDC server as well as the full
|
||||
trust chain of the identity certificate.
|
||||
|
||||
.SS "UNINSTALL OPTIONS"
|
||||
.TP
|
||||
\fB\-\-uninstall\fR
|
||||
@@ -253,12 +237,6 @@ Remove the IPA client software and restore the configuration to the pre\-IPA sta
|
||||
\fB\-U\fR, \fB\-\-unattended\fR
|
||||
Unattended uninstallation. The user will not be prompted.
|
||||
|
||||
.SH "DISABLED SERVICES"
|
||||
.TP
|
||||
ipa-client-install will automatically disable the Name Service Caching Daemon (nscd) when configuring the SSSD client. These are competing services and cannot co-exist.
|
||||
.TP
|
||||
If there are other similar services providing nss capabilities they will need to be manually disabled by the user. An example is unscd, a complete replacement for nscd.
|
||||
|
||||
.SH "FILES"
|
||||
.TP
|
||||
Files that will be replaced if SSSD is configured (default):
|
||||
|
||||
@@ -136,10 +136,8 @@ O \- self\-obliterate
|
||||
.TP
|
||||
\fBipa help commands\fR
|
||||
Display a list of available commands
|
||||
.TP
|
||||
\fBipa help topics\fR
|
||||
Display a high\-level list of help topics
|
||||
.TP
|
||||
\fBipa help user\fR
|
||||
Display documentation and list of commands in the "user" topic.
|
||||
.TP
|
||||
|
||||
@@ -60,10 +60,6 @@ smtp_delay = 0
|
||||
# This value can be found by running ipa config-show.
|
||||
# mail_from =
|
||||
|
||||
# Specifies the From: name value in the e-mails-sent.
|
||||
# The default when unset is IPA-EPN.
|
||||
# mail_from_name =
|
||||
|
||||
# The list of days before a password expiration when ipa-epn should notify
|
||||
# a user that their password will soon require a reset.
|
||||
notify_ttls = 28, 14, 7, 3, 1
|
||||
|
||||
@@ -460,7 +460,6 @@ AC_SUBST(VENDOR_SUFFIX)
|
||||
AC_SUBST([VERSION], [IPA_VERSION])
|
||||
AC_SUBST([GIT_VERSION], [IPA_GIT_VERSION])
|
||||
AC_SUBST([GIT_BRANCH], [IPA_GIT_BRANCH])
|
||||
AC_SUBST([KRB5_BUILD_VERSION], [IPA_KRB5_BUILD_VERSION])
|
||||
# used by Makefile.am for files depending on templates
|
||||
AC_SUBST([CONFIG_STATUS])
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
@@ -57,7 +57,7 @@ KEYTAB_FB = paths.IPA_DNSKEYSYNCD_KEYTAB
|
||||
def commenceShutdown(signum, stack):
|
||||
# Declare the needed global variables
|
||||
global watcher_running
|
||||
global ldap_connection
|
||||
global ldap_connection # pylint: disable=global-variable-not-assigned
|
||||
|
||||
logger.info('Signal %s received: Shutting down!', signum)
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ init_with_password(const char *name, const char *password)
|
||||
|
||||
done:
|
||||
if (service_creds != GSS_C_NO_CREDENTIAL)
|
||||
gss_release_cred(&min, &service_creds);
|
||||
gss_release_cred(&min, &client_creds);
|
||||
|
||||
if (client_creds != GSS_C_NO_CREDENTIAL)
|
||||
gss_release_cred(&min, &client_creds);
|
||||
|
||||
@@ -49,11 +49,6 @@ static void ipadb_context_free(krb5_context kcontext,
|
||||
size_t c;
|
||||
|
||||
if (*ctx != NULL) {
|
||||
if ((*ctx)->magic != IPA_CONTEXT_MAGIC) {
|
||||
krb5_klog_syslog(LOG_ERR, "IPA context is corrupted");
|
||||
*ctx = NULL;
|
||||
return;
|
||||
}
|
||||
free((*ctx)->uri);
|
||||
free((*ctx)->base);
|
||||
free((*ctx)->realm_base);
|
||||
@@ -205,7 +200,6 @@ static const struct {
|
||||
{ "pkinit", IPADB_USER_AUTH_PKINIT },
|
||||
{ "hardened", IPADB_USER_AUTH_HARDENED },
|
||||
{ "idp", IPADB_USER_AUTH_IDP },
|
||||
{ "passkey", IPADB_USER_AUTH_PASSKEY },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -621,8 +615,6 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_UNDEFINED;
|
||||
|
||||
ret = ipadb_get_connection(ipactx);
|
||||
if (ret != 0) {
|
||||
/* Not a fatal failure, as the LDAP server may be temporarily down. */
|
||||
@@ -636,7 +628,6 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -807,20 +798,11 @@ kdb_vftabl kdb_function_table = {
|
||||
#endif
|
||||
|
||||
#if (KRB5_KDB_DAL_MAJOR_VERSION == 9)
|
||||
#error DAL version 9 is not supported yet
|
||||
/* Version 9 removes sign_authdata and adds issue_pac method. It is a complete
|
||||
* revamp of how PAC is issued, so we need to implement it differently to previous
|
||||
* versions. */
|
||||
|
||||
krb5_error_code
|
||||
ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_keyblock *replaced_reply_key,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_timestamp authtime, krb5_pac old_pac,
|
||||
krb5_pac new_pac,
|
||||
krb5_data ***auth_indicators);
|
||||
|
||||
kdb_vftabl kdb_function_table = {
|
||||
.maj_ver = KRB5_KDB_DAL_MAJOR_VERSION,
|
||||
.min_ver = 0,
|
||||
@@ -848,8 +830,8 @@ kdb_vftabl kdb_function_table = {
|
||||
.check_allowed_to_delegate = ipadb_check_allowed_to_delegate,
|
||||
.free_principal_e_data = ipadb_free_principal_e_data,
|
||||
.get_s4u_x509_principal = NULL,
|
||||
.allowed_to_delegate_from = ipadb_allowed_to_delegate_from,
|
||||
.issue_pac = ipadb_v9_issue_pac,
|
||||
.allowed_to_delegate_from = NULL,
|
||||
.issue_pac = NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -49,22 +49,6 @@
|
||||
#include "ipa_krb5.h"
|
||||
#include "ipa_pwd.h"
|
||||
|
||||
/* Difference between krb5 1.20 and previous versions. From
|
||||
* krb5 commit a441fbe329ebbd7775eb5d4ccc4a05eef370f08b:
|
||||
* Combine the KRB5_KDB_FLAG_ISSUE_PAC and
|
||||
* KRB5_FLAG_CLIENT_REFERRALS_ONLY flags into KRB5_KDB_FLAG_CLIENT.
|
||||
*
|
||||
* Rename the KRB5_KDB_FLAG_CANONICALIZE flag to
|
||||
* KRB5_KDB_FLAG_REFERRAL_OK, and only pass it to get_principal() for
|
||||
* lookup operations that can use a realm referral.
|
||||
* */
|
||||
#if defined(KRB5_KDB_FLAG_CLIENT)
|
||||
#define CLIENT_REFERRALS_FLAGS (KRB5_KDB_FLAG_REFERRAL_OK)
|
||||
#else
|
||||
#define CLIENT_REFERRALS_FLAGS (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY)
|
||||
#endif
|
||||
|
||||
|
||||
/* easier to copy the defines here than to mess with kadm5/admin.h
|
||||
* for now */
|
||||
#define KMASK_PRINCIPAL 0x000001
|
||||
@@ -106,7 +90,6 @@ enum ipadb_user_auth {
|
||||
IPADB_USER_AUTH_PKINIT = 1 << 4,
|
||||
IPADB_USER_AUTH_HARDENED = 1 << 5,
|
||||
IPADB_USER_AUTH_IDP = 1 << 6,
|
||||
IPADB_USER_AUTH_PASSKEY = 1 << 7,
|
||||
};
|
||||
|
||||
enum ipadb_user_auth_idx {
|
||||
@@ -115,7 +98,6 @@ enum ipadb_user_auth_idx {
|
||||
IPADB_USER_AUTH_IDX_PKINIT,
|
||||
IPADB_USER_AUTH_IDX_HARDENED,
|
||||
IPADB_USER_AUTH_IDX_IDP,
|
||||
IPADB_USER_AUTH_IDX_PASSKEY,
|
||||
IPADB_USER_AUTH_IDX_MAX,
|
||||
};
|
||||
|
||||
@@ -128,12 +110,6 @@ struct ipadb_global_config {
|
||||
bool disable_preauth_for_spns;
|
||||
};
|
||||
|
||||
enum ipadb_tristate_option {
|
||||
IPADB_TRISTATE_FALSE = FALSE,
|
||||
IPADB_TRISTATE_TRUE = TRUE,
|
||||
IPADB_TRISTATE_UNDEFINED,
|
||||
};
|
||||
|
||||
#define IPA_CONTEXT_MAGIC 0x0c027ea7
|
||||
struct ipadb_context {
|
||||
int magic;
|
||||
@@ -151,7 +127,6 @@ struct ipadb_context {
|
||||
krb5_key_salt_tuple *def_encs;
|
||||
int n_def_encs;
|
||||
struct ipadb_mspac *mspac;
|
||||
enum ipadb_tristate_option optional_pac_tkt_chksum;
|
||||
#ifdef HAVE_KRB5_CERTAUTH_PLUGIN
|
||||
krb5_certauth_moddata certauth_moddata;
|
||||
#endif
|
||||
@@ -231,16 +206,6 @@ int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le,
|
||||
int ipadb_ldap_deref_results(LDAP *lcontext, LDAPMessage *le,
|
||||
LDAPDerefRes **results);
|
||||
|
||||
krb5_error_code ipadb_get_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
krb5_octet *data);
|
||||
|
||||
krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
const krb5_octet *data);
|
||||
|
||||
struct ipadb_multires;
|
||||
krb5_error_code ipadb_multires_init(LDAP *lcontext, struct ipadb_multires **r);
|
||||
void ipadb_multires_free(struct ipadb_multires *r);
|
||||
@@ -344,7 +309,6 @@ krb5_error_code ipadb_get_pwd_expiration(krb5_context context,
|
||||
|
||||
/* MS-PAC FUNCTIONS */
|
||||
|
||||
#if (KRB5_KDB_DAL_MAJOR_VERSION < 9)
|
||||
krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_const_principal client_princ,
|
||||
@@ -359,18 +323,6 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||
krb5_authdata **tgt_auth_data,
|
||||
krb5_authdata ***signed_auth_data);
|
||||
|
||||
#else
|
||||
/* DAL 9 or later uses issue_pac */
|
||||
krb5_error_code ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_keyblock *replaced_reply_key,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_timestamp authtime, krb5_pac old_pac,
|
||||
krb5_pac new_pac,
|
||||
krb5_data ***auth_indicators);
|
||||
#endif
|
||||
|
||||
krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit);
|
||||
|
||||
void ipadb_mspac_struct_free(struct ipadb_mspac **mspac);
|
||||
@@ -393,12 +345,6 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
|
||||
const krb5_db_entry *server,
|
||||
krb5_const_principal proxy);
|
||||
|
||||
krb5_error_code ipadb_allowed_to_delegate_from(krb5_context context,
|
||||
krb5_const_principal client,
|
||||
krb5_const_principal server,
|
||||
krb5_pac server_pac,
|
||||
const krb5_db_entry *proxy);
|
||||
|
||||
/* AS AUDIT */
|
||||
|
||||
void ipadb_audit_as_req(krb5_context kcontext,
|
||||
@@ -429,4 +375,4 @@ void ipa_certauth_free_moddata(krb5_certauth_moddata *moddata);
|
||||
int ipadb_string_to_sid(const char *str, struct dom_sid *sid);
|
||||
void alloc_sid(struct dom_sid **sid);
|
||||
void free_sid(struct dom_sid **sid);
|
||||
bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check);
|
||||
bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check);
|
||||
@@ -120,7 +120,6 @@ static krb5_error_code ipa_get_init_data(krb5_context kcontext,
|
||||
char *map_rule = NULL;
|
||||
char *match_rule = NULL;
|
||||
char **domains = NULL;
|
||||
bool rule_added = false;
|
||||
|
||||
const char *certmap_attrs[] = { OBJECTCLASS,
|
||||
IPA_CERTMAP_PRIORITY,
|
||||
@@ -172,7 +171,13 @@ static krb5_error_code ipa_get_init_data(krb5_context kcontext,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (kerr != KRB5_KDB_NOENTRY) {
|
||||
if (kerr == KRB5_KDB_NOENTRY) {
|
||||
ret = sss_certmap_add_rule(ctx, SSS_CERTMAP_MIN_PRIO,
|
||||
NULL, NULL, NULL);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
lc = ipactx->lcontext;
|
||||
|
||||
for (le = ldap_first_entry(lc, result); le;
|
||||
@@ -216,33 +221,8 @@ static krb5_error_code ipa_get_init_data(krb5_context kcontext,
|
||||
ret = sss_certmap_add_rule(ctx, prio, match_rule, map_rule,
|
||||
(const char **) domains);
|
||||
if (ret != 0) {
|
||||
krb5_klog_syslog(LOG_ERR,
|
||||
"Failed to add certificate mapping [%s] and "
|
||||
"matching [%s] rule with error [%d][%s], "
|
||||
"skipping. Please check for typos and if rule "
|
||||
"syntax is supported.", map_rule, match_rule,
|
||||
ret, strerror(ret));
|
||||
continue;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rule_added = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rule_added) {
|
||||
if (kerr == KRB5_KDB_NOENTRY) {
|
||||
krb5_klog_syslog(LOG_INFO,
|
||||
"No certificate mapping and matching rule "
|
||||
"defined, trying to use the default rule.");
|
||||
} else {
|
||||
krb5_klog_syslog(LOG_INFO,
|
||||
"No valid certificate mapping and matching rule "
|
||||
"found, trying to use the default rule.");
|
||||
}
|
||||
ret = sss_certmap_add_rule(ctx, SSS_CERTMAP_MIN_PRIO,
|
||||
NULL, NULL, NULL);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,75 +158,12 @@ static bool ipadb_need_retry(struct ipadb_context *ipactx, int error)
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *no_attrs[] = {
|
||||
LDAP_NO_ATTRS,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
should_support_pac_tkt_sign(struct ipadb_context *ipactx, bool *result)
|
||||
{
|
||||
int ret;
|
||||
LDAPMessage *res = NULL;
|
||||
char *masters_dn = NULL;
|
||||
int count;
|
||||
|
||||
char *kdc_filter = "(&(cn=KDC)(objectClass=ipaConfigObject)"
|
||||
"(!(ipaConfigString=pacTktSignSupported)))";
|
||||
|
||||
if (!ipactx) {
|
||||
ret = KRB5_KDB_DBNOTINITED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
count = asprintf(&masters_dn, "cn=masters,cn=ipa,cn=etc,%s", ipactx->base);
|
||||
if (count < 0) {
|
||||
ret = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ipadb_simple_search(ipactx, masters_dn, LDAP_SCOPE_SUBTREE,
|
||||
kdc_filter, no_attrs, &res);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
count = ldap_count_entries(ipactx->lcontext, res);
|
||||
|
||||
if (result)
|
||||
*result = (count == 0);
|
||||
|
||||
done:
|
||||
free(masters_dn);
|
||||
ldap_msgfree(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipadb_check_connection(struct ipadb_context *ipactx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ipactx->lcontext == NULL) {
|
||||
ret = ipadb_get_connection(ipactx);
|
||||
return ipadb_get_connection(ipactx);
|
||||
}
|
||||
if ((ret == 0) && (ipactx->optional_pac_tkt_chksum == IPADB_TRISTATE_UNDEFINED)) {
|
||||
bool pac_tkt_sign_supported;
|
||||
|
||||
/* Enforce PAC ticket signature verification if supported by all KDCs
|
||||
* To avoid loops as all search functions call into
|
||||
* ipadb_check_connection(), mark that the init is complete at this
|
||||
* point. Default to not issuing PAC to be safe.
|
||||
*/
|
||||
ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_FALSE;
|
||||
ret = should_support_pac_tkt_sign(ipactx,
|
||||
&pac_tkt_sign_supported);
|
||||
if (ret == 0) {
|
||||
ipactx->optional_pac_tkt_chksum = !pac_tkt_sign_supported;
|
||||
} else {
|
||||
ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_UNDEFINED;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_error_code ipadb_simple_search(struct ipadb_context *ipactx,
|
||||
|
||||
@@ -42,7 +42,7 @@ static krb5_error_code ipadb_get_delegation_acl(krb5_context kcontext,
|
||||
{
|
||||
struct ipadb_context *ipactx;
|
||||
krb5_error_code kerr;
|
||||
char *filter = NULL, *basedn = NULL;
|
||||
char *filter = NULL;
|
||||
int ret;
|
||||
|
||||
ipactx = ipadb_get_context(kcontext);
|
||||
@@ -58,20 +58,12 @@ static krb5_error_code ipadb_get_delegation_acl(krb5_context kcontext,
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = asprintf(&basedn,
|
||||
"cn=s4u2proxy,cn=etc,%s", ipactx->base);
|
||||
if (ret == -1) {
|
||||
kerr = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* == Search ACL info == */
|
||||
kerr = ipadb_deref_search(ipactx, basedn,
|
||||
kerr = ipadb_deref_search(ipactx, ipactx->base,
|
||||
LDAP_SCOPE_SUBTREE, filter, acl_attrs,
|
||||
search_attrs, acl_attrs, results);
|
||||
|
||||
done:
|
||||
free(basedn);
|
||||
free(filter);
|
||||
return kerr;
|
||||
}
|
||||
@@ -114,8 +106,6 @@ static krb5_error_code ipadb_match_acl(krb5_context kcontext,
|
||||
bool client_missing;
|
||||
bool client_found;
|
||||
bool target_found;
|
||||
bool is_constraint_delegation = false;
|
||||
size_t nrules = 0;
|
||||
int ret;
|
||||
|
||||
ipactx = ipadb_get_context(kcontext);
|
||||
@@ -123,17 +113,13 @@ static krb5_error_code ipadb_match_acl(krb5_context kcontext,
|
||||
return KRB5_KDB_DBNOTINITED;
|
||||
}
|
||||
|
||||
if ((client != NULL) && (target != NULL)) {
|
||||
kerr = krb5_unparse_name(kcontext, client, &client_princ);
|
||||
if (kerr != 0) {
|
||||
goto done;
|
||||
}
|
||||
kerr = krb5_unparse_name(kcontext, target, &target_princ);
|
||||
if (kerr != 0) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
is_constraint_delegation = true;
|
||||
kerr = krb5_unparse_name(kcontext, client, &client_princ);
|
||||
if (kerr != 0) {
|
||||
goto done;
|
||||
}
|
||||
kerr = krb5_unparse_name(kcontext, target, &target_princ);
|
||||
if (kerr != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
lentry = ldap_first_entry(ipactx->lcontext, results);
|
||||
@@ -156,25 +142,6 @@ static krb5_error_code ipadb_match_acl(krb5_context kcontext,
|
||||
switch (ret) {
|
||||
case 0:
|
||||
for (dres = deref_results; dres; dres = dres->next) {
|
||||
nrules++;
|
||||
if (is_constraint_delegation) {
|
||||
/*
|
||||
Microsoft revised the S4U2Proxy rules for forwardable
|
||||
tickets. All S4U2Proxy operations require forwardable
|
||||
evidence tickets, but S4U2Self should issue a
|
||||
forwardable ticket if the requesting service has no
|
||||
ok-to-auth-as-delegate bit but also no constrained
|
||||
delegation privileges for traditional S4U2Proxy.
|
||||
Implement these rules, extending the
|
||||
check_allowed_to_delegate() DAL method so that the KDC
|
||||
can ask if a principal has any delegation privileges.
|
||||
|
||||
Since target principal is NULL and client principal is
|
||||
NULL in this case, we simply calculate number of rules associated
|
||||
with the server principal to decide whether to deny forwardable bit
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (client_found == false &&
|
||||
strcasecmp(dres->derefAttr, "ipaAllowToImpersonate") == 0) {
|
||||
/* NOTE: client_missing is used to signal that the
|
||||
@@ -208,10 +175,6 @@ static krb5_error_code ipadb_match_acl(krb5_context kcontext,
|
||||
lentry = ldap_next_entry(ipactx->lcontext, lentry);
|
||||
}
|
||||
|
||||
if (nrules > 0) {
|
||||
kerr = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
krb5_free_unparsed_name(kcontext, client_princ);
|
||||
krb5_free_unparsed_name(kcontext, target_princ);
|
||||
@@ -233,35 +196,33 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
|
||||
struct ipadb_e_data *ied_server, *ied_proxy;
|
||||
LDAPMessage *res = NULL;
|
||||
|
||||
if (proxy != NULL) {
|
||||
/* Handle the case where server == proxy, this is allowed in S4U */
|
||||
kerr = ipadb_get_principal(kcontext, proxy,
|
||||
CLIENT_REFERRALS_FLAGS,
|
||||
&proxy_entry);
|
||||
if (kerr) {
|
||||
/* Handle the case where server == proxy, this is allowed in S4U*/
|
||||
kerr = ipadb_get_principal(kcontext, proxy,
|
||||
KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY,
|
||||
&proxy_entry);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ied_server = (struct ipadb_e_data *) server->e_data;
|
||||
ied_proxy = (struct ipadb_e_data *) proxy_entry->e_data;
|
||||
|
||||
/* If we have SIDs for both entries, compare SIDs */
|
||||
if ((ied_server->has_sid && ied_server->sid != NULL) &&
|
||||
(ied_proxy->has_sid && ied_proxy->sid != NULL)) {
|
||||
|
||||
if (dom_sid_check(ied_server->sid, ied_proxy->sid, true)) {
|
||||
kerr = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ied_server = (struct ipadb_e_data *) server->e_data;
|
||||
ied_proxy = (struct ipadb_e_data *) proxy_entry->e_data;
|
||||
|
||||
/* If we have SIDs for both entries, compare SIDs */
|
||||
if ((ied_server->has_sid && ied_server->sid != NULL) &&
|
||||
(ied_proxy->has_sid && ied_proxy->sid != NULL)) {
|
||||
|
||||
if (dom_sid_check(ied_server->sid, ied_proxy->sid, true)) {
|
||||
kerr = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, compare entry DNs */
|
||||
kerr = ulc_casecmp(ied_server->entry_dn, strlen(ied_server->entry_dn),
|
||||
ied_proxy->entry_dn, strlen(ied_proxy->entry_dn),
|
||||
NULL, NULL, &result);
|
||||
if (kerr == 0 && result == 0) {
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise, compare entry DNs */
|
||||
kerr = ulc_casecmp(ied_server->entry_dn, strlen(ied_server->entry_dn),
|
||||
ied_proxy->entry_dn, strlen(ied_proxy->entry_dn),
|
||||
NULL, NULL, &result);
|
||||
if (kerr == 0 && result == 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = krb5_unparse_name(kcontext, server->princ, &srv_principal);
|
||||
@@ -280,56 +241,8 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
|
||||
}
|
||||
|
||||
done:
|
||||
if (kerr) {
|
||||
#if KRB5_KDB_DAL_MAJOR_VERSION < 9
|
||||
kerr = KRB5KDC_ERR_POLICY;
|
||||
#else
|
||||
kerr = KRB5KDC_ERR_BADOPTION;
|
||||
#endif
|
||||
}
|
||||
ipadb_free_principal(kcontext, proxy_entry);
|
||||
krb5_free_unparsed_name(kcontext, srv_principal);
|
||||
ldap_msgfree(res);
|
||||
return kerr;
|
||||
}
|
||||
|
||||
|
||||
krb5_error_code ipadb_allowed_to_delegate_from(krb5_context context,
|
||||
krb5_const_principal client,
|
||||
krb5_const_principal server,
|
||||
krb5_pac server_pac,
|
||||
const krb5_db_entry *proxy)
|
||||
{
|
||||
char **acl_list = NULL;
|
||||
krb5_error_code kerr;
|
||||
size_t i;
|
||||
|
||||
kerr = ipadb_get_tl_data((krb5_db_entry *) proxy, KRB5_TL_CONSTRAINED_DELEGATION_ACL,
|
||||
sizeof(acl_list), (krb5_octet *)&acl_list);
|
||||
|
||||
if (kerr != 0 && kerr != ENOENT) {
|
||||
return KRB5KDC_ERR_BADOPTION;
|
||||
}
|
||||
|
||||
if (kerr == ENOENT) {
|
||||
return KRB5_PLUGIN_OP_NOTSUPP;
|
||||
}
|
||||
|
||||
kerr = KRB5KDC_ERR_BADOPTION;
|
||||
if (acl_list != NULL) {
|
||||
krb5_principal acl;
|
||||
for (i = 0; acl_list[i] != NULL; i++) {
|
||||
if (krb5_parse_name(context, acl_list[i], &acl) != 0)
|
||||
continue;
|
||||
if ((server == NULL) ||
|
||||
(krb5_principal_compare(context, server, acl) == TRUE)) {
|
||||
kerr = 0;
|
||||
krb5_free_principal(context, acl);
|
||||
break;
|
||||
}
|
||||
krb5_free_principal(context, acl);
|
||||
}
|
||||
}
|
||||
|
||||
return kerr;
|
||||
}
|
||||
@@ -143,15 +143,6 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||
goto done;
|
||||
}
|
||||
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_IDP]);
|
||||
} else if (strcmp(auth_indicator, "passkey") == 0) {
|
||||
valid_auth_indicators++;
|
||||
/* Allow hardened even if only password pre-auth is allowed */
|
||||
if (!(ua & IPADB_USER_AUTH_PASSKEY)) {
|
||||
*status = "Passkey pre-authentication not allowed for this user.";
|
||||
kerr = KRB5KDC_ERR_POLICY;
|
||||
goto done;
|
||||
}
|
||||
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PASSKEY]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+140
-193
@@ -401,34 +401,31 @@ static krb5_error_code ipadb_add_asserted_identity(struct ipadb_context *ipactx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
is_master_host(struct ipadb_context *ipactx, const char *fqdn, bool *result)
|
||||
static bool is_master_host(struct ipadb_context *ipactx, const char *fqdn)
|
||||
{
|
||||
int err;
|
||||
int ret;
|
||||
char *master_host_base = NULL;
|
||||
LDAPMessage *ldap_res = NULL;
|
||||
LDAPMessage *result = NULL;
|
||||
krb5_error_code err;
|
||||
|
||||
err = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
|
||||
ret = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
|
||||
fqdn, ipactx->base);
|
||||
if (err == -1)
|
||||
return ENOMEM;
|
||||
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
}
|
||||
err = ipadb_simple_search(ipactx, master_host_base, LDAP_SCOPE_BASE,
|
||||
NULL, NULL, &ldap_res);
|
||||
NULL, NULL, &result);
|
||||
free(master_host_base);
|
||||
ldap_msgfree(ldap_res);
|
||||
if (err != KRB5_KDB_NOENTRY && err != 0)
|
||||
return err;
|
||||
ldap_msgfree(result);
|
||||
if (err == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result)
|
||||
*result = err != KRB5_KDB_NOENTRY;
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||
LDAPMessage *lentry,
|
||||
LDAPMessage *sentry,
|
||||
unsigned int flags,
|
||||
TALLOC_CTX *memctx,
|
||||
krb5_timestamp authtime,
|
||||
@@ -568,20 +565,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||
unix_to_nt_time(&info3->base.last_password_change, timeres);
|
||||
break;
|
||||
case ENOENT:
|
||||
/* If second entry is present, use Kerberos attributes from it */
|
||||
if (sentry != NULL) {
|
||||
ret = ipadb_ldap_attr_to_time_t(ipactx->lcontext, sentry,
|
||||
"krbLastPwdChange", &timeres);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
unix_to_nt_time(&info3->base.last_password_change, timeres);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
info3->base.last_password_change = 0;
|
||||
}
|
||||
info3->base.last_password_change = 0;
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
@@ -694,14 +678,9 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||
if ((is_host || is_service)) {
|
||||
/* it is either host or service, so get the hostname first */
|
||||
char *sep = strchr(info3->base.account_name.string, '/');
|
||||
bool is_master;
|
||||
|
||||
ret = is_master_host(ipactx,
|
||||
sep ? sep + 1 : info3->base.account_name.string,
|
||||
&is_master);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bool is_master = is_master_host(
|
||||
ipactx,
|
||||
sep ? sep + 1 : info3->base.account_name.string);
|
||||
if (is_master) {
|
||||
/* Well known RID of domain controllers group */
|
||||
if (info3->base.rid == 0) {
|
||||
@@ -1004,18 +983,16 @@ static krb5_error_code ipadb_get_pac_attrs_blob(TALLOC_CTX *mem_ctx,
|
||||
#endif
|
||||
|
||||
krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_db_entry *server,
|
||||
krb5_keyblock *replaced_reply_key,
|
||||
unsigned int flags,
|
||||
krb5_timestamp authtime,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
TALLOC_CTX *tmpctx;
|
||||
struct ipadb_e_data *ied;
|
||||
struct ipadb_context *ipactx;
|
||||
LDAPMessage *results = NULL, *sresults = NULL;
|
||||
LDAPMessage *lentry = NULL, *sentry = NULL;
|
||||
LDAPMessage *results = NULL;
|
||||
LDAPMessage *lentry;
|
||||
DATA_BLOB pac_data;
|
||||
krb5_data data;
|
||||
union PAC_INFO pac_info;
|
||||
@@ -1071,40 +1048,9 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
goto done;
|
||||
}
|
||||
|
||||
{
|
||||
bool is_trust_krbtgt;
|
||||
|
||||
/* Trusted domain objects are part of cn=ad,cn=trusts,$BASEDN subtree.
|
||||
* Anchor the search string with ',dc=' to prevent matching anything else.
|
||||
* This is to avoid a string allocation with expanded base DN. */
|
||||
is_trust_krbtgt = strstr(ied->entry_dn, ",cn=ad,cn=trusts,dc=") != NULL;
|
||||
|
||||
if (is_trust_krbtgt) {
|
||||
char *sentry_dn = strchr(ied->entry_dn, ',');
|
||||
if (sentry_dn != NULL) {
|
||||
/* skipped "krbprincipalname=krbtgt/SOME-REALM@AT-REALM," */
|
||||
sentry_dn++;
|
||||
kerr = ipadb_deref_search(ipactx, sentry_dn, LDAP_SCOPE_BASE,
|
||||
"(objectclass=*)", user_pac_attrs,
|
||||
deref_search_attrs, memberof_pac_attrs,
|
||||
&sresults);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
sentry = ldap_first_entry(ipactx->lcontext, sresults);
|
||||
if (!sentry) {
|
||||
kerr = ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* == Fill Info3 == */
|
||||
kerr = ipadb_fill_info3(ipactx, sentry ? sentry : lentry, sentry ? lentry : NULL,
|
||||
flags, tmpctx, authtime, &pac_info.logon_info.info->info3);
|
||||
kerr = ipadb_fill_info3(ipactx, lentry, flags, tmpctx, authtime,
|
||||
&pac_info.logon_info.info->info3);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
@@ -1118,13 +1064,9 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* krb5 1.20+ passes in a pre-created PAC structure but for previous
|
||||
* versions we have to create it ourselves */
|
||||
if (pac != NULL && *pac == NULL) {
|
||||
kerr = krb5_pac_init(kcontext, pac);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
kerr = krb5_pac_init(kcontext, pac);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
data.magic = KV5M_DATA;
|
||||
@@ -1207,7 +1149,7 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
|
||||
#ifdef HAVE_PAC_REQUESTER_SID
|
||||
/* MS-KILE 3.3.5.6.4.8: add PAC_REQUESTER_SID only in TGT case */
|
||||
if (flags & CLIENT_REFERRALS_FLAGS) {
|
||||
if ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0) {
|
||||
union PAC_INFO pac_requester_sid;
|
||||
/* == Package PAC_REQUESTER_SID == */
|
||||
memset(&pac_requester_sid, 0, sizeof(pac_requester_sid));
|
||||
@@ -1235,9 +1177,6 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
|
||||
done:
|
||||
ldap_msgfree(results);
|
||||
if (sresults != NULL) {
|
||||
ldap_msgfree(sresults);
|
||||
}
|
||||
talloc_free(tmpctx);
|
||||
return kerr;
|
||||
}
|
||||
@@ -1614,7 +1553,7 @@ static krb5_error_code save_logon_info(krb5_context context,
|
||||
}
|
||||
|
||||
static struct ipadb_adtrusts *get_domain_from_realm(krb5_context context,
|
||||
krb5_data *realm)
|
||||
krb5_data realm)
|
||||
{
|
||||
struct ipadb_context *ipactx;
|
||||
struct ipadb_adtrusts *domain;
|
||||
@@ -1631,10 +1570,10 @@ static struct ipadb_adtrusts *get_domain_from_realm(krb5_context context,
|
||||
|
||||
for (i = 0; i < ipactx->mspac->num_trusts; i++) {
|
||||
domain = &ipactx->mspac->trusts[i];
|
||||
if (strlen(domain->domain_name) != realm->length) {
|
||||
if (strlen(domain->domain_name) != realm.length) {
|
||||
continue;
|
||||
}
|
||||
if (strncasecmp(domain->domain_name, realm->data, realm->length) == 0) {
|
||||
if (strncasecmp(domain->domain_name, realm.data, realm.length) == 0) {
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
@@ -1643,7 +1582,7 @@ static struct ipadb_adtrusts *get_domain_from_realm(krb5_context context,
|
||||
}
|
||||
|
||||
static struct ipadb_adtrusts *get_domain_from_realm_update(krb5_context context,
|
||||
krb5_data *realm)
|
||||
krb5_data realm)
|
||||
{
|
||||
struct ipadb_context *ipactx;
|
||||
struct ipadb_adtrusts *domain;
|
||||
@@ -1698,7 +1637,7 @@ static void filter_logon_info_log_message_rid(struct dom_sid *sid, uint32_t rid)
|
||||
|
||||
static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||
TALLOC_CTX *memctx,
|
||||
krb5_db_entry *client,
|
||||
krb5_const_principal client_princ,
|
||||
krb5_boolean is_s4u,
|
||||
struct PAC_LOGON_INFO_CTR *info)
|
||||
{
|
||||
@@ -1706,6 +1645,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||
struct ipadb_context *ipactx;
|
||||
bool result;
|
||||
bool is_from_trusted_domain = false;
|
||||
krb5_db_entry *client_actual = NULL;
|
||||
struct ipadb_e_data *ied = NULL;
|
||||
int flags = 0;
|
||||
struct dom_sid client_sid;
|
||||
@@ -1761,12 +1701,18 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||
}
|
||||
}
|
||||
|
||||
if (client == NULL || (is_s4u && is_from_trusted_domain)) {
|
||||
if (is_s4u && is_from_trusted_domain) {
|
||||
/* If the PAC belongs to a user from the trusted domain, we cannot compare SIDs */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ied = (struct ipadb_e_data *)client->e_data;
|
||||
kerr = ipadb_get_principal(context, client_princ, flags, &client_actual);
|
||||
if (kerr != 0) {
|
||||
krb5_klog_syslog(LOG_ERR, "PAC issue: ipadb_get_principal failed.");
|
||||
return KRB5KDC_ERR_TGT_REVOKED;
|
||||
}
|
||||
|
||||
ied = (struct ipadb_e_data *)client_actual->e_data;
|
||||
if (ied == NULL || ied->magic != IPA_E_DATA_MAGIC) {
|
||||
krb5_klog_syslog(LOG_ERR, "PAC issue: client e_data fetching failed.");
|
||||
kerr = EINVAL;
|
||||
@@ -1802,12 +1748,14 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||
}
|
||||
|
||||
done:
|
||||
ipadb_free_principal(context, client_actual);
|
||||
|
||||
return kerr;
|
||||
}
|
||||
|
||||
krb5_error_code filter_logon_info(krb5_context context,
|
||||
TALLOC_CTX *memctx,
|
||||
krb5_data *realm,
|
||||
krb5_data realm,
|
||||
struct PAC_LOGON_INFO_CTR *info)
|
||||
{
|
||||
|
||||
@@ -1834,43 +1782,11 @@ krb5_error_code filter_logon_info(krb5_context context,
|
||||
bool result;
|
||||
char *domstr = NULL;
|
||||
|
||||
ipactx = ipadb_get_context(context);
|
||||
if (!ipactx || !ipactx->mspac) {
|
||||
return KRB5_KDB_DBNOTINITED;
|
||||
}
|
||||
|
||||
domain = get_domain_from_realm_update(context, realm);
|
||||
if (!domain) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* check exact sid */
|
||||
result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
|
||||
if (!result) {
|
||||
struct ipadb_mspac *mspac_ctx = ipactx->mspac;
|
||||
result = FALSE;
|
||||
/* Didn't match but perhaps the original PAC was issued by a child domain's DC? */
|
||||
for (k = 0; k < mspac_ctx->num_trusts; k++) {
|
||||
result = dom_sid_check(&mspac_ctx->trusts[k].domsid,
|
||||
info->info->info3.base.domain_sid, true);
|
||||
if (result) {
|
||||
domain = &mspac_ctx->trusts[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
|
||||
krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
|
||||
"expected domain SID = %s, "
|
||||
"found domain SID = %s",
|
||||
domain->domain_name, domain->domain_sid,
|
||||
domstr ? domstr : "<failed to display>");
|
||||
talloc_free(domstr);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point we may have changed the domain we look at, */
|
||||
/* check netbios/flat name */
|
||||
if (strcasecmp(info->info->info3.base.logon_domain.string,
|
||||
domain->flat_name) != 0) {
|
||||
@@ -1882,6 +1798,21 @@ krb5_error_code filter_logon_info(krb5_context context,
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* check exact sid */
|
||||
result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true);
|
||||
if (!result) {
|
||||
domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid);
|
||||
if (!domstr) {
|
||||
return EINVAL;
|
||||
}
|
||||
krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, "
|
||||
"expected domain SID = %s, "
|
||||
"found domain SID = %s",
|
||||
domain->domain_name, domain->domain_sid, domstr);
|
||||
talloc_free(domstr);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Check if this domain has been filtered out by the trust itself*/
|
||||
if (domain->parent != NULL) {
|
||||
for(k = 0; k < domain->parent->len_sid_blocklist_incoming; k++) {
|
||||
@@ -1968,6 +1899,10 @@ krb5_error_code filter_logon_info(krb5_context context,
|
||||
* should include different possibilities into account
|
||||
* */
|
||||
if (info->info->info3.sidcount != 0) {
|
||||
ipactx = ipadb_get_context(context);
|
||||
if (!ipactx || !ipactx->mspac) {
|
||||
return KRB5_KDB_DBNOTINITED;
|
||||
}
|
||||
count = info->info->info3.sidcount;
|
||||
i = 0;
|
||||
j = 0;
|
||||
@@ -2045,8 +1980,7 @@ krb5_error_code filter_logon_info(krb5_context context,
|
||||
|
||||
|
||||
static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||
krb5_db_entry *client,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_const_principal client_princ,
|
||||
krb5_boolean is_cross_realm,
|
||||
krb5_boolean is_s4u,
|
||||
krb5_data *pac_blob,
|
||||
@@ -2055,7 +1989,7 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||
struct PAC_LOGON_INFO_CTR info;
|
||||
krb5_error_code kerr;
|
||||
TALLOC_CTX *tmpctx;
|
||||
krb5_data origin_realm = {0};
|
||||
krb5_data origin_realm = client_princ->realm;
|
||||
bool result;
|
||||
|
||||
tmpctx = talloc_new(NULL);
|
||||
@@ -2083,12 +2017,12 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||
return KRB5_KDB_DBNOTINITED;
|
||||
}
|
||||
/* In S4U case we might be dealing with the PAC issued by the trusted domain */
|
||||
if ((ipactx->mspac->trusts != NULL)) {
|
||||
if (is_s4u && (ipactx->mspac->trusts != NULL)) {
|
||||
/* Iterate through list of trusts and check if this SID belongs to
|
||||
* one of the domains we trust */
|
||||
for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
|
||||
result = dom_sid_check(&ipactx->mspac->trusts[i].domsid,
|
||||
&client_sid, false);
|
||||
requester_sid, false);
|
||||
if (result) {
|
||||
is_from_trusted_domain = true;
|
||||
break;
|
||||
@@ -2096,7 +2030,7 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_from_trusted_domain && !is_s4u) {
|
||||
if (!is_from_trusted_domain) {
|
||||
/* memctx is freed by the caller */
|
||||
char *pac_sid = dom_sid_string(tmpctx, &client_sid);
|
||||
char *req_sid = dom_sid_string(tmpctx, requester_sid);
|
||||
@@ -2117,17 +2051,11 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||
* is ours but operates on behalf of the cross-realm principal, we will
|
||||
* search through the trusted domains but otherwise skip the exact SID check
|
||||
* as we are not responsible for the principal from the trusted domain */
|
||||
kerr = check_logon_info_consistent(context, tmpctx, client, is_s4u, &info);
|
||||
kerr = check_logon_info_consistent(context, tmpctx, client_princ, is_s4u, &info);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (client != NULL) {
|
||||
origin_realm = client->princ->realm;
|
||||
} else {
|
||||
origin_realm = signing_krbtgt->princ->realm;
|
||||
}
|
||||
|
||||
kerr = filter_logon_info(context, tmpctx, &origin_realm, &info);
|
||||
kerr = filter_logon_info(context, tmpctx, origin_realm, &info);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
@@ -2296,19 +2224,24 @@ done:
|
||||
return kerr;
|
||||
}
|
||||
|
||||
krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_keyblock *krbtgt_key,
|
||||
krb5_timestamp authtime,
|
||||
krb5_pac old_pac,
|
||||
krb5_pac *pac)
|
||||
krb5_error_code ipadb_verify_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_const_principal client_princ,
|
||||
krb5_db_entry *proxy,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *krbtgt,
|
||||
krb5_keyblock *server_key,
|
||||
krb5_keyblock *krbtgt_key,
|
||||
krb5_timestamp authtime,
|
||||
krb5_authdata **authdata,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
krb5_keyblock *srv_key = NULL;
|
||||
krb5_keyblock *priv_key = NULL;
|
||||
krb5_error_code kerr;
|
||||
krb5_ui_4 *types = NULL;
|
||||
size_t num_buffers;
|
||||
krb5_pac old_pac = NULL;
|
||||
krb5_pac new_pac = NULL;
|
||||
krb5_data data;
|
||||
krb5_data pac_blob = { 0 , 0, NULL};
|
||||
@@ -2317,15 +2250,42 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
struct dom_sid *requester_sid = NULL;
|
||||
struct dom_sid req_sid;
|
||||
|
||||
if (signing_krbtgt != NULL &&
|
||||
ipadb_is_cross_realm_krbtgt(signing_krbtgt->princ)) {
|
||||
/* krbtgt from a trusted realm */
|
||||
is_cross_realm = true;
|
||||
kerr = krb5_pac_parse(context,
|
||||
authdata[0]->contents,
|
||||
authdata[0]->length,
|
||||
&old_pac);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* In krb5 1.20+ the PAC signatures are verified prior to call to issue_pac().
|
||||
* In krb5 before 1.20, we do verify PAC signatures before ipadb_common_verify_pac().
|
||||
* Now we can do additional checks.
|
||||
/* for cross realm trusts cases we need to check the right checksum.
|
||||
* when the PAC is signed by our realm, we can always just check it
|
||||
* passing our realm krbtgt key as the kdc checksum key (privsvr).
|
||||
* But when a trusted realm passes us a PAC the kdc checksum is
|
||||
* generated with that realm krbtgt key, so we need to use the cross
|
||||
* realm krbtgt to check the 'server' checksum instead. */
|
||||
if (ipadb_is_cross_realm_krbtgt(krbtgt->princ)) {
|
||||
/* krbtgt from a trusted realm */
|
||||
is_cross_realm = true;
|
||||
|
||||
srv_key = krbtgt_key;
|
||||
|
||||
} else {
|
||||
/* krbtgt from our own realm */
|
||||
priv_key = krbtgt_key;
|
||||
}
|
||||
|
||||
/* only pass with_realm TRUE when it is cross-realm ticket and S4U
|
||||
* extension (S4U2Self or S4U2Proxy (RBCD)) was requested */
|
||||
kerr = krb5_pac_verify_ext(context, old_pac, authtime,
|
||||
client_princ, srv_key, priv_key,
|
||||
(is_cross_realm &&
|
||||
(flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)));
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now that the PAC is verified, do additional checks.
|
||||
* Augment it with additional info if it is coming from a different realm */
|
||||
kerr = krb5_pac_get_buffer(context, old_pac,
|
||||
KRB5_PAC_LOGON_INFO, &pac_blob);
|
||||
@@ -2342,8 +2302,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
#endif
|
||||
|
||||
kerr = ipadb_check_logon_info(context,
|
||||
client,
|
||||
signing_krbtgt,
|
||||
client_princ,
|
||||
is_cross_realm,
|
||||
(flags & KRB5_KDB_FLAGS_S4U),
|
||||
&pac_blob,
|
||||
@@ -2351,19 +2310,12 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
if (kerr != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* krb5 1.20+ passes in a pre-created PAC structure but for previous
|
||||
* versions we have to create it ourselves */
|
||||
if (pac != NULL && *pac == NULL) {
|
||||
/* extract buffers and rebuilt pac from scratch so that when re-signing
|
||||
* with a different cksum type does not cause issues due to mismatching
|
||||
* signature buffer lengths */
|
||||
kerr = krb5_pac_init(context, &new_pac);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
new_pac = *pac;
|
||||
/* extract buffers and rebuilt pac from scratch so that when re-signing
|
||||
* with a different cksum type does not cause issues due to mismatching
|
||||
* signature buffer lengths */
|
||||
kerr = krb5_pac_init(context, &new_pac);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = krb5_pac_get_types(context, old_pac, &num_buffers, &types);
|
||||
@@ -2374,10 +2326,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
for (i = 0; i < num_buffers; i++) {
|
||||
if (types[i] == KRB5_PAC_SERVER_CHECKSUM ||
|
||||
types[i] == KRB5_PAC_PRIVSVR_CHECKSUM ||
|
||||
#ifdef KRB5_PAC_FULL_CHECKSUM
|
||||
types[i] == KRB5_PAC_FULL_CHECKSUM ||
|
||||
#endif
|
||||
types[i] == KRB5_PAC_CLIENT_INFO) {
|
||||
types[i] == KRB5_PAC_CLIENT_INFO) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2385,6 +2334,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
pac_blob.length != 0) {
|
||||
kerr = krb5_pac_add_buffer(context, new_pac, types[i], &pac_blob);
|
||||
if (kerr) {
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2401,18 +2351,21 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
TALLOC_CTX *tmpctx = talloc_new(NULL);
|
||||
if (tmpctx == NULL) {
|
||||
kerr = ENOMEM;
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = ipadb_client_requested_pac(context, old_pac, tmpctx, &pac_requested);
|
||||
if (kerr != 0) {
|
||||
talloc_free(tmpctx);
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = ipadb_get_pac_attrs_blob(tmpctx, &pac_requested, &pac_attrs_data);
|
||||
if (kerr) {
|
||||
talloc_free(tmpctx);
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
data.magic = KV5M_DATA;
|
||||
@@ -2422,6 +2375,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
kerr = krb5_pac_add_buffer(context, new_pac, PAC_TYPE_ATTRIBUTES_INFO, &data);
|
||||
if (kerr) {
|
||||
talloc_free(tmpctx);
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2441,35 +2395,31 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
krb5_free_data_contents(context, &data);
|
||||
}
|
||||
if (kerr) {
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(KRB5_KDB_FLAG_CLIENT)
|
||||
if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
|
||||
if (client == NULL) {
|
||||
if (new_pac != *pac) {
|
||||
krb5_pac_free(context, new_pac);
|
||||
}
|
||||
if (proxy == NULL) {
|
||||
*pac = NULL;
|
||||
kerr = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = ipadb_add_transited_service(context, client, server,
|
||||
kerr = ipadb_add_transited_service(context, proxy, server,
|
||||
old_pac, new_pac);
|
||||
if (kerr) {
|
||||
krb5_pac_free(context, new_pac);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*pac = new_pac;
|
||||
|
||||
done:
|
||||
if (kerr != 0 && (new_pac != *pac)) {
|
||||
krb5_pac_free(context, new_pac);
|
||||
}
|
||||
krb5_free_authdata(context, authdata);
|
||||
krb5_pac_free(context, old_pac);
|
||||
krb5_free_data_contents(context, &pac_blob);
|
||||
free(types);
|
||||
return kerr;
|
||||
@@ -2577,12 +2527,9 @@ void get_authz_data_types(krb5_context context, krb5_db_entry *entry,
|
||||
none_found = true;
|
||||
}
|
||||
} else {
|
||||
/* for out-of-realm entries we suppress warnings in our defaults */
|
||||
if (entry != NULL) {
|
||||
krb5_klog_syslog(LOG_ERR, "Ignoring unsupported " \
|
||||
"authorization data type [%s].",
|
||||
authz_data_list[c]);
|
||||
}
|
||||
krb5_klog_syslog(LOG_ERR, "Ignoring unsupported " \
|
||||
"authorization data type [%s].",
|
||||
authz_data_list[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,24 +53,24 @@ struct ipadb_adtrusts {
|
||||
|
||||
char *dom_sid_string(TALLOC_CTX *memctx, const struct dom_sid *dom_sid);
|
||||
krb5_error_code filter_logon_info(krb5_context context, TALLOC_CTX *memctx,
|
||||
krb5_data *realm, struct PAC_LOGON_INFO_CTR *info);
|
||||
krb5_data realm, struct PAC_LOGON_INFO_CTR *info);
|
||||
void get_authz_data_types(krb5_context context, krb5_db_entry *entry,
|
||||
bool *_with_pac, bool *_with_pad);
|
||||
|
||||
bool ipadb_is_cross_realm_krbtgt(krb5_const_principal princ);
|
||||
krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||
unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_db_entry *server,
|
||||
krb5_keyblock *replaced_reply_key,
|
||||
unsigned int flags,
|
||||
krb5_timestamp authtime,
|
||||
krb5_pac *pac);
|
||||
krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_keyblock *krbtgt_key,
|
||||
krb5_timestamp authtime,
|
||||
krb5_pac old_pac,
|
||||
krb5_pac *pac);
|
||||
krb5_error_code ipadb_verify_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_const_principal client_princ,
|
||||
krb5_db_entry *proxy,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *krbtgt,
|
||||
krb5_keyblock *server_key,
|
||||
krb5_keyblock *krbtgt_key,
|
||||
krb5_timestamp authtime,
|
||||
krb5_authdata **authdata,
|
||||
krb5_pac *pac);
|
||||
@@ -31,68 +31,6 @@
|
||||
|
||||
#include "ipa_kdb_mspac_private.h"
|
||||
|
||||
static
|
||||
krb5_error_code ipadb_verify_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
krb5_const_principal client_princ,
|
||||
krb5_db_entry *proxy,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *krbtgt,
|
||||
krb5_keyblock *server_key,
|
||||
krb5_keyblock *krbtgt_key,
|
||||
krb5_timestamp authtime,
|
||||
krb5_authdata **authdata,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
krb5_error_code kerr;
|
||||
krb5_pac old_pac = NULL;
|
||||
kerr = krb5_pac_parse(context,
|
||||
authdata[0]->contents,
|
||||
authdata[0]->length,
|
||||
&old_pac);
|
||||
if (kerr == 0) {
|
||||
krb5_keyblock *srv_key = NULL;
|
||||
krb5_keyblock *priv_key = NULL;
|
||||
bool is_cross_realm = false;
|
||||
|
||||
/* for cross realm trusts cases we need to check the right checksum.
|
||||
* when the PAC is signed by our realm, we can always just check it
|
||||
* passing our realm krbtgt key as the kdc checksum key (privsvr).
|
||||
* But when a trusted realm passes us a PAC the kdc checksum is
|
||||
* generated with that realm krbtgt key, so we need to use the cross
|
||||
* realm krbtgt to check the 'server' checksum instead. */
|
||||
if (ipadb_is_cross_realm_krbtgt(krbtgt->princ)) {
|
||||
/* krbtgt from a trusted realm */
|
||||
is_cross_realm = true;
|
||||
srv_key = krbtgt_key;
|
||||
} else {
|
||||
/* krbtgt from our own realm */
|
||||
priv_key = krbtgt_key;
|
||||
}
|
||||
|
||||
/* only pass with_realm TRUE when it is cross-realm ticket and S4U
|
||||
* extension (S4U2Self or S4U2Proxy (RBCD)) was requested */
|
||||
kerr = krb5_pac_verify_ext(context, old_pac, authtime,
|
||||
NULL, srv_key, priv_key,
|
||||
(is_cross_realm &&
|
||||
(flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)));
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
kerr = ipadb_common_verify_pac(context, flags,
|
||||
proxy, server, krbtgt,
|
||||
krbtgt_key,
|
||||
authtime, old_pac, pac);
|
||||
}
|
||||
|
||||
done:
|
||||
krb5_free_authdata(context, authdata);
|
||||
krb5_pac_free(context, old_pac);
|
||||
return kerr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static krb5_error_code ipadb_sign_pac(krb5_context context,
|
||||
unsigned int flags,
|
||||
@@ -176,21 +114,11 @@ static krb5_error_code ipadb_sign_pac(krb5_context context,
|
||||
|
||||
/* only pass with_realm TRUE when it is cross-realm ticket and S4U2Self
|
||||
* was requested */
|
||||
#ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||
kerr = krb5_pac_full_sign_compat(
|
||||
context, pac, authtime, client_princ, server->princ, server_key,
|
||||
right_krbtgt_signing_key,
|
||||
(is_issuing_referral && (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)),
|
||||
pac_data
|
||||
);
|
||||
#else
|
||||
/* Use standard function, PAC extended KDC signature not supported */
|
||||
kerr = krb5_pac_sign_ext(context, pac, authtime, client_princ, server_key,
|
||||
right_krbtgt_signing_key,
|
||||
(is_issuing_referral &&
|
||||
(flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION)),
|
||||
pac_data);
|
||||
#endif
|
||||
|
||||
done:
|
||||
free(princ);
|
||||
@@ -311,7 +239,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||
|
||||
(void)ipadb_reinit_mspac(ipactx, force_reinit_mspac);
|
||||
|
||||
kerr = ipadb_get_pac(context, flags, client, server, NULL, authtime, &pac);
|
||||
kerr = ipadb_get_pac(context, client, flags, authtime, &pac);
|
||||
if (kerr != 0 && kerr != ENOENT) {
|
||||
goto done;
|
||||
}
|
||||
@@ -325,7 +253,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||
/* check or generate pac data */
|
||||
if ((pac_auth_data == NULL) || (pac_auth_data[0] == NULL)) {
|
||||
if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
|
||||
kerr = ipadb_get_pac(context, flags, client_entry, server, NULL, authtime, &pac);
|
||||
kerr = ipadb_get_pac(context, client_entry, flags, authtime, &pac);
|
||||
if (kerr != 0 && kerr != ENOENT) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -31,108 +31,4 @@
|
||||
|
||||
#include "ipa_kdb_mspac_private.h"
|
||||
|
||||
krb5_error_code
|
||||
ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||
krb5_db_entry *client,
|
||||
krb5_keyblock *replaced_reply_key,
|
||||
krb5_db_entry *server,
|
||||
krb5_db_entry *signing_krbtgt,
|
||||
krb5_timestamp authtime,
|
||||
krb5_pac old_pac,
|
||||
krb5_pac new_pac,
|
||||
krb5_data ***auth_indicators)
|
||||
{
|
||||
bool with_pac;
|
||||
bool with_pad;
|
||||
krb5_error_code kerr = 0;
|
||||
bool is_as_req = flags & CLIENT_REFERRALS_FLAGS;
|
||||
|
||||
if (is_as_req) {
|
||||
get_authz_data_types(context, client, &with_pac, &with_pad);
|
||||
} else {
|
||||
get_authz_data_types(context, server, &with_pac, &with_pad);
|
||||
}
|
||||
|
||||
if (with_pad) {
|
||||
krb5_klog_syslog(LOG_ERR, "PAD authorization data is requested but " \
|
||||
"currently not supported.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a new PAC for AS-REQ or S4U2Self for our realm.
|
||||
*
|
||||
* For a simple cross-realm S4U2Proxy there will be the following TGS
|
||||
* requests after the client realm is identified:
|
||||
*
|
||||
* 1. server@SREALM to SREALM for krbtgt/CREALM@SREALM -- a regular TGS
|
||||
* request with server's normal TGT and no S4U2Self padata.
|
||||
* 2. server@SREALM to CREALM for server@SREALM (expressed as an
|
||||
* enterprise principal), with the TGT from #1 as header ticket and
|
||||
* S4U2Self padata identifying the client.
|
||||
* 3. server@SREALM to SREALM for server@SREALM with S4U2Self padata,
|
||||
* with the referral TGT from #2 as header ticket
|
||||
*
|
||||
* In request 2 the PROTOCOL_TRANSITION and CROSS_REALM flags are set,
|
||||
* and the request is for a local client (so client != NULL) and we
|
||||
* want to make a new PAC.
|
||||
*
|
||||
* In request 3 the PROTOCOL_TRANSITION and CROSS_REALM flags are also
|
||||
* set, but the request is for a non-local client (so client == NULL)
|
||||
* and we want to copy the subject PAC contained in the referral TGT.
|
||||
*/
|
||||
|
||||
if (old_pac == NULL ||
|
||||
(client != NULL && (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION))) {
|
||||
/* generate initial PAC */
|
||||
if (with_pac) {
|
||||
krb5_boolean force_reinit_mspac = FALSE;
|
||||
struct ipadb_context *ipactx = ipadb_get_context(context);
|
||||
int result = 0;
|
||||
|
||||
if (!ipactx) {
|
||||
kerr = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (client != NULL) {
|
||||
/* Be aggressive here: special case for discovering range type
|
||||
* immediately after establishing the trust by IPA framework. For all
|
||||
* other cases call ipadb_reinit_mspac() with force_reinit_mspac set
|
||||
* to 'false' to make sure the information about trusted domains is
|
||||
* updated on a regular basis for all worker processes. */
|
||||
if ((krb5_princ_size(context, client->princ) == 2) &&
|
||||
(strncmp(krb5_princ_component(context, client->princ, 0)->data, "HTTP",
|
||||
krb5_princ_component(context, client->princ, 0)->length) == 0) &&
|
||||
(ulc_casecmp(krb5_princ_component(context, client->princ, 1)->data,
|
||||
krb5_princ_component(context, client->princ, 1)->length,
|
||||
ipactx->kdc_hostname, strlen(ipactx->kdc_hostname),
|
||||
NULL, NULL, &result) == 0)) {
|
||||
force_reinit_mspac = TRUE;
|
||||
}
|
||||
}
|
||||
(void)ipadb_reinit_mspac(ipactx, force_reinit_mspac);
|
||||
|
||||
/* MS-PAC needs proper configuration and if it is missing, we simply skip issuing one */
|
||||
if (ipactx->mspac->flat_server_name == NULL) {
|
||||
return KRB5_PLUGIN_OP_NOTSUPP;
|
||||
}
|
||||
kerr = ipadb_get_pac(context, flags,
|
||||
client, server, replaced_reply_key,
|
||||
authtime, &new_pac);
|
||||
}
|
||||
} else {
|
||||
kerr = ipadb_common_verify_pac(context, flags,
|
||||
client, server,
|
||||
signing_krbtgt,
|
||||
NULL,
|
||||
authtime,
|
||||
old_pac, &new_pac);
|
||||
if (kerr == ENOENT) {
|
||||
kerr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* in krb5 1.20 no need to sign tickets anymore, KDC does it for us */
|
||||
done:
|
||||
return kerr;
|
||||
}
|
||||
@@ -78,12 +78,10 @@ static char *std_principal_attrs[] = {
|
||||
IPA_USER_AUTH_TYPE,
|
||||
"ipatokenRadiusConfigLink",
|
||||
"ipaIdpConfigLink",
|
||||
"ipaPassKey",
|
||||
"krbAuthIndMaxTicketLife",
|
||||
"krbAuthIndMaxRenewableAge",
|
||||
"ipaNTSecurityIdentifier",
|
||||
"ipaUniqueID",
|
||||
"memberPrincipal",
|
||||
|
||||
"objectClass",
|
||||
NULL
|
||||
@@ -115,14 +113,6 @@ static char *std_principal_obj_classes[] = {
|
||||
|
||||
#define DEFAULT_TL_DATA_CONTENT "\x00\x00\x00\x00principal@UNINITIALIZED"
|
||||
|
||||
#ifndef KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM
|
||||
#define KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM "optional_pac_tkt_chksum"
|
||||
#endif
|
||||
|
||||
#ifndef KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE
|
||||
#define KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE "pac_privsvr_enctype"
|
||||
#endif
|
||||
|
||||
static int ipadb_ldap_attr_to_tl_data(LDAP *lcontext, LDAPMessage *le,
|
||||
char *attrname,
|
||||
krb5_tl_data **result, int *num)
|
||||
@@ -188,56 +178,10 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_tgs_princ(krb5_context kcontext, krb5_const_principal princ)
|
||||
{
|
||||
krb5_data *primary;
|
||||
size_t l_tgs_name;
|
||||
|
||||
if (2 != krb5_princ_size(kcontext, princ))
|
||||
return false;
|
||||
|
||||
primary = krb5_princ_component(kcontext, princ, 0);
|
||||
|
||||
l_tgs_name = strlen(KRB5_TGS_NAME);
|
||||
|
||||
if (l_tgs_name != primary->length)
|
||||
return false;
|
||||
|
||||
return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name);
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
cmp_local_tgs_princ(krb5_context kcontext, const char *local_realm,
|
||||
krb5_const_principal princ, bool *result)
|
||||
{
|
||||
krb5_principal local_tgs_princ;
|
||||
size_t l_local_realm;
|
||||
krb5_error_code kerr;
|
||||
bool res;
|
||||
|
||||
l_local_realm = strlen(local_realm);
|
||||
|
||||
kerr = krb5_build_principal(kcontext, &local_tgs_princ,
|
||||
l_local_realm, local_realm,
|
||||
KRB5_TGS_NAME, local_realm, NULL);
|
||||
if (kerr)
|
||||
goto end;
|
||||
|
||||
res = (bool) krb5_principal_compare(kcontext, local_tgs_princ, princ);
|
||||
|
||||
if (result)
|
||||
*result = res;
|
||||
|
||||
end:
|
||||
krb5_free_principal(kcontext, local_tgs_princ);
|
||||
return kerr;
|
||||
}
|
||||
|
||||
krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
const krb5_octet *data)
|
||||
static krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
const krb5_octet *data)
|
||||
{
|
||||
krb5_error_code kerr;
|
||||
krb5_tl_data *new_td = NULL;
|
||||
@@ -403,25 +347,6 @@ static void ipadb_validate_idp(struct ipadb_context *ipactx,
|
||||
ldap_value_free_len(vals);
|
||||
}
|
||||
|
||||
static void ipadb_validate_passkey(struct ipadb_context *ipactx,
|
||||
LDAPMessage *lentry,
|
||||
enum ipadb_user_auth *ua)
|
||||
{
|
||||
struct berval **vals;
|
||||
|
||||
if (!(*ua & IPADB_USER_AUTH_PASSKEY))
|
||||
return;
|
||||
|
||||
/* Ensure that the user has a link to an IdP config. */
|
||||
vals = ldap_get_values_len(ipactx->lcontext, lentry,
|
||||
"ipaPassKey");
|
||||
if (vals == NULL || vals[0] == NULL)
|
||||
*ua &= ~IPADB_USER_AUTH_PASSKEY;
|
||||
|
||||
if (vals != NULL)
|
||||
ldap_value_free_len(vals);
|
||||
}
|
||||
|
||||
static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
|
||||
LDAPMessage *lentry)
|
||||
{
|
||||
@@ -455,7 +380,6 @@ static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
|
||||
ipadb_validate_otp(ipactx, lentry, &ua);
|
||||
ipadb_validate_radius(ipactx, lentry, &ua);
|
||||
ipadb_validate_idp(ipactx, lentry, &ua);
|
||||
ipadb_validate_passkey(ipactx, lentry, &ua);
|
||||
|
||||
return ua;
|
||||
}
|
||||
@@ -640,8 +564,6 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
|
||||
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
|
||||
{"krbAuthIndMaxTicketLife;idp",
|
||||
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
|
||||
{"krbAuthIndMaxTicketLife;passkey",
|
||||
IPADB_USER_AUTH_PASSKEY, IPADB_USER_AUTH_IDX_PASSKEY},
|
||||
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
|
||||
}, age_authind_map[] = {
|
||||
{"krbAuthIndMaxRenewableAge;otp",
|
||||
@@ -654,8 +576,6 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
|
||||
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
|
||||
{"krbAuthIndMaxRenewableAge;idp",
|
||||
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
|
||||
{"krbAuthIndMaxRenewableAge;passkey",
|
||||
IPADB_USER_AUTH_PASSKEY, IPADB_USER_AUTH_IDX_PASSKEY},
|
||||
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
|
||||
};
|
||||
|
||||
@@ -699,7 +619,6 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
const krb5_octet rad_string[] = "otp\0[{\"indicators\": [\"radius\"]}]";
|
||||
const krb5_octet otp_string[] = "otp\0[{\"indicators\": [\"otp\"]}]";
|
||||
const krb5_octet idp_string[] = "idp\0[{\"type\":\"oauth2\",\"indicators\": [\"idp\"]}]";
|
||||
const krb5_octet passkey_string[] = "passkey\0[{\"indicators\": [\"passkey\"]}]";
|
||||
struct ipadb_context *ipactx;
|
||||
enum ipadb_user_auth ua;
|
||||
LDAP *lcontext;
|
||||
@@ -714,7 +633,6 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
char *uidstring;
|
||||
char **authz_data_list;
|
||||
char *princ_sid;
|
||||
char **acl_list;
|
||||
krb5_timestamp restime;
|
||||
bool resbool;
|
||||
int result;
|
||||
@@ -1084,11 +1002,6 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
sizeof(idp_string), idp_string);
|
||||
if (kerr)
|
||||
goto done;
|
||||
} else if (ua & IPADB_USER_AUTH_PASSKEY) {
|
||||
kerr = ipadb_set_tl_data(entry, KRB5_TL_STRING_ATTRS,
|
||||
sizeof(passkey_string), passkey_string);
|
||||
if (kerr)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ua & ~IPADB_USER_AUTH_NONE) {
|
||||
@@ -1116,30 +1029,6 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
ied->has_sid = true;
|
||||
}
|
||||
|
||||
/* check if it has the serviceDelegation objectclass */
|
||||
ret = ipadb_ldap_attr_has_value(lcontext, lentry,
|
||||
"objectClass", "resourceDelegation");
|
||||
if (ret != 0 && ret != ENOENT) {
|
||||
kerr = ret;
|
||||
goto done;
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = ipadb_ldap_attr_to_strlist(lcontext, lentry,
|
||||
"memberPrincipal", &acl_list);
|
||||
if (ret != 0 && ret != ENOENT) {
|
||||
kerr = KRB5_KDB_INTERNAL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (ret == 0) {
|
||||
kerr = ipadb_set_tl_data(entry, KRB5_TL_CONSTRAINED_DELEGATION_ACL,
|
||||
sizeof(acl_list),
|
||||
(const krb5_octet *) &acl_list);
|
||||
if (kerr) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kerr = 0;
|
||||
|
||||
done:
|
||||
@@ -1473,9 +1362,6 @@ static krb5_boolean is_request_for_us(krb5_context kcontext,
|
||||
{
|
||||
krb5_boolean for_us;
|
||||
|
||||
if (search_for == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
for_us = krb5_realm_compare(kcontext, local_tgs, search_for) ||
|
||||
krb5_principal_compare_any_realm(kcontext,
|
||||
local_tgs, search_for);
|
||||
@@ -1493,17 +1379,11 @@ static krb5_error_code dbget_princ(krb5_context kcontext,
|
||||
LDAPMessage *res = NULL;
|
||||
LDAPMessage *lentry;
|
||||
uint32_t pol;
|
||||
krb5_boolean check = FALSE;
|
||||
|
||||
|
||||
#if defined(KRB5_KDB_FLAG_CLIENT)
|
||||
check = flags & KRB5_KDB_FLAG_CLIENT;
|
||||
#else
|
||||
check = (flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) &&
|
||||
(flags & KRB5_KDB_FLAG_CANONICALIZE);
|
||||
#endif
|
||||
if ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0 &&
|
||||
(flags & KRB5_KDB_FLAG_CANONICALIZE) != 0) {
|
||||
|
||||
if (check) {
|
||||
/* AS_REQ with canonicalization*/
|
||||
krb5_principal norm_princ = NULL;
|
||||
|
||||
@@ -1570,14 +1450,6 @@ done:
|
||||
return kerr;
|
||||
}
|
||||
|
||||
/* For krb5 1.19, there is no KRB5_KDB_FLAG_REFERRAL_OK, emulate it
|
||||
* See krb5 commit a441fbe329ebbd7775eb5d4ccc4a05eef370f08b */
|
||||
#ifndef KRB5_KDB_FLAG_REFERRAL_OK
|
||||
#ifdef KRB5_KDB_FLAG_CANONICALIZE
|
||||
#define KRB5_KDB_FLAG_REFERRAL_OK KRB5_KDB_FLAG_CANONICALIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
struct ipadb_context *ipactx,
|
||||
krb5_const_principal search_for,
|
||||
@@ -1590,40 +1462,18 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
char *trusted_realm = NULL;
|
||||
krb5_db_entry *kentry = NULL;
|
||||
krb5_data *realm;
|
||||
krb5_boolean check = FALSE;
|
||||
/* KRB5_NT_PRINCIPAL must be the last element */
|
||||
krb5_int32 supported_types[] = {
|
||||
[0] = KRB5_NT_ENTERPRISE_PRINCIPAL,
|
||||
[1] = KRB5_NT_PRINCIPAL,
|
||||
-1,
|
||||
};
|
||||
size_t i = 0;
|
||||
|
||||
/* For TGS-REQ server principal lookup, KDC asks with KRB5_KDB_FLAG_REFERRAL_OK
|
||||
* and client usually asks for an KRB5_NT_PRINCIPAL type principal. */
|
||||
if ((flags & KRB5_KDB_FLAG_REFERRAL_OK) == 0) {
|
||||
/* this is *not* TGS-REQ server principal search, remove
|
||||
* KRB5_NT_PRINCIPAL from the supported principal types for this lookup */
|
||||
supported_types[(sizeof(supported_types) / sizeof(supported_types[0])) - 2] = -1;
|
||||
}
|
||||
/* TODO: also support hostbased aliases */
|
||||
|
||||
/* Enterprise principal name type is for potential aliases or principals
|
||||
* from trusted realms. Except for the TGS-REQ server lookup, we only
|
||||
* expect enterprise principals here */
|
||||
for (i = 0; supported_types[i] != -1; i++) {
|
||||
if (krb5_princ_type(kcontext, search_for) == supported_types[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (supported_types[i] == -1) {
|
||||
* from trusted realms. The logic below only applies to this type */
|
||||
if (krb5_princ_type(kcontext, search_for) != KRB5_NT_ENTERPRISE_PRINCIPAL) {
|
||||
return KRB5_KDB_NOENTRY;
|
||||
}
|
||||
|
||||
/* enterprise principal can only have single component in the name
|
||||
* according to RFC6806 section 5. */
|
||||
if ((krb5_princ_type(kcontext, search_for) == KRB5_NT_ENTERPRISE_PRINCIPAL) &&
|
||||
(krb5_princ_size(kcontext, search_for) != 1)) {
|
||||
if (krb5_princ_size(kcontext, search_for) != 1) {
|
||||
return KRB5_KDB_NOENTRY;
|
||||
}
|
||||
|
||||
@@ -1647,12 +1497,6 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
if (krb5_realm_compare(kcontext, ipactx->local_tgs, norm_princ)) {
|
||||
/* In realm alias, try to retrieve it and let the caller handle it. */
|
||||
kerr = dbget_princ(kcontext, ipactx, norm_princ, flags, entry);
|
||||
}
|
||||
|
||||
/* if we haven't found the principal in our realm, it might still
|
||||
* be a referral to a known realm. Otherwise, bail out with the result */
|
||||
if ((kerr != KRB5_KDB_NOENTRY) &&
|
||||
(flags & KRB5_KDB_FLAG_REFERRAL_OK) == 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1663,14 +1507,8 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
* both client and server referrals. But it is more useful to ignore it
|
||||
* like Windows KDC does for client referrals.
|
||||
*/
|
||||
#if defined(KRB5_KDB_FLAG_CLIENT)
|
||||
check = ((flags & KRB5_KDB_FLAG_CLIENT) == 0) &&
|
||||
((flags & KRB5_KDB_FLAG_REFERRAL_OK) == 0);
|
||||
#else
|
||||
check = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) == 0) &&
|
||||
((flags & KRB5_KDB_FLAG_CANONICALIZE) == 0);
|
||||
#endif
|
||||
if (check) {
|
||||
if (((flags & KRB5_KDB_FLAG_CANONICALIZE) == 0) &&
|
||||
((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) == 0)) {
|
||||
kerr = KRB5_KDB_NOENTRY;
|
||||
goto done;
|
||||
}
|
||||
@@ -1696,44 +1534,13 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
&trusted_realm);
|
||||
}
|
||||
|
||||
if (kerr == KRB5_KDB_NOENTRY) {
|
||||
krb5_data *hstname = NULL;
|
||||
int ncomponents = krb5_princ_size(kcontext, norm_princ);
|
||||
|
||||
/* We did not find any alias so far for non-server principal lookups */
|
||||
if ((ncomponents < 2) && ((flags & KRB5_KDB_FLAG_REFERRAL_OK) == 0)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* At this point it is a server principal lookup that might be
|
||||
* referencing a host name in a trusted domain. It might also
|
||||
* have multiple service components so take the last one for the
|
||||
* hostname or the domain name. See MS-ADTS 2.2.21 and MS-DRSR 2.2.4.2.
|
||||
*/
|
||||
hstname = krb5_princ_component(kcontext, norm_princ, ncomponents - 1);
|
||||
|
||||
kerr = ipadb_is_princ_from_trusted_realm(kcontext,
|
||||
hstname->data,
|
||||
hstname->length,
|
||||
&trusted_realm);
|
||||
}
|
||||
|
||||
if (kerr != 0) {
|
||||
kerr = KRB5_KDB_NOENTRY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* This is a known trusted realm. Issue a referral depending on whether this
|
||||
* is client or server referral request */
|
||||
#if defined(KRB5_KDB_FLAG_CLIENT)
|
||||
check = (flags & KRB5_KDB_FLAG_CLIENT) && (flags & KRB5_KDB_FLAG_REFERRAL_OK);
|
||||
#else
|
||||
check = (flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) &&
|
||||
((flags & KRB5_KDB_FLAG_CANONICALIZE) ||
|
||||
search_for->type == KRB5_NT_ENTERPRISE_PRINCIPAL);
|
||||
#endif
|
||||
|
||||
if (check) {
|
||||
if (flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) {
|
||||
/* client referral out of realm, set next realm. */
|
||||
kerr = krb5_set_principal_realm(kcontext, norm_princ, trusted_realm);
|
||||
if (kerr != 0) {
|
||||
@@ -1752,12 +1559,7 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||
goto done;
|
||||
}
|
||||
|
||||
#if defined(KRB5_KDB_FLAG_CLIENT)
|
||||
check = flags & KRB5_KDB_FLAG_CLIENT;
|
||||
#else
|
||||
check = flags & KRB5_KDB_FLAG_INCLUDE_PAC;
|
||||
#endif
|
||||
if (check) {
|
||||
if (flags & KRB5_KDB_FLAG_INCLUDE_PAC) {
|
||||
/* TGS request where KDC wants to generate PAC
|
||||
* but the principal is out of our realm */
|
||||
kerr = KRB5_KDB_NOENTRY;
|
||||
@@ -1801,8 +1603,6 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
|
||||
krb5_db_entry **entry)
|
||||
{
|
||||
struct ipadb_context *ipactx;
|
||||
bool is_local_tgs_princ;
|
||||
const char *opt_pac_tkt_chksum_val;
|
||||
krb5_error_code kerr;
|
||||
|
||||
*entry = NULL;
|
||||
@@ -1818,50 +1618,11 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
|
||||
|
||||
/* Lookup local names and aliases first. */
|
||||
kerr = dbget_princ(kcontext, ipactx, search_for, flags, entry);
|
||||
if (kerr == KRB5_KDB_NOENTRY) {
|
||||
kerr = dbget_alias(kcontext, ipactx, search_for, flags, entry);
|
||||
}
|
||||
if (kerr)
|
||||
if (kerr != KRB5_KDB_NOENTRY) {
|
||||
return kerr;
|
||||
|
||||
/* If TGS principal, some virtual attributes may be added */
|
||||
if (is_tgs_princ(kcontext, (*entry)->princ)) {
|
||||
kerr = cmp_local_tgs_princ(kcontext, ipactx->realm, (*entry)->princ,
|
||||
&is_local_tgs_princ);
|
||||
if (kerr)
|
||||
return kerr;
|
||||
|
||||
/* for trusted AD forests we currently must use SHA-1-based
|
||||
* encryption types. For details, see
|
||||
* https://github.com/krb5/krb5/commit/5af907156f8f502bbe268f0c62274f88a61261e4
|
||||
*/
|
||||
if (!is_local_tgs_princ) {
|
||||
kerr = krb5_dbe_set_string(kcontext, *entry,
|
||||
KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE,
|
||||
"aes256-sha1");
|
||||
if (kerr)
|
||||
return kerr;
|
||||
|
||||
}
|
||||
|
||||
/* We should have been initialized at this point already */
|
||||
if (ipactx->optional_pac_tkt_chksum == IPADB_TRISTATE_UNDEFINED) {
|
||||
return KRB5_KDB_SERVER_INTERNAL_ERR;
|
||||
}
|
||||
/* PAC ticket signature should be optional for foreign realms, and local
|
||||
* realm if not supported by all servers
|
||||
*/
|
||||
if (!is_local_tgs_princ || ipactx->optional_pac_tkt_chksum)
|
||||
opt_pac_tkt_chksum_val = "true";
|
||||
else
|
||||
opt_pac_tkt_chksum_val = "false";
|
||||
|
||||
kerr = krb5_dbe_set_string(kcontext, *entry,
|
||||
KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM,
|
||||
opt_pac_tkt_chksum_val);
|
||||
}
|
||||
|
||||
return kerr;
|
||||
return dbget_alias(kcontext, ipactx, search_for, flags, entry);
|
||||
}
|
||||
|
||||
void ipadb_free_principal_e_data(krb5_context kcontext, krb5_octet *e_data)
|
||||
@@ -1892,20 +1653,12 @@ void ipadb_free_principal_e_data(krb5_context kcontext, krb5_octet *e_data)
|
||||
void ipadb_free_principal(krb5_context kcontext, krb5_db_entry *entry)
|
||||
{
|
||||
krb5_tl_data *prev, *next;
|
||||
size_t i;
|
||||
|
||||
if (entry) {
|
||||
krb5_free_principal(kcontext, entry->princ);
|
||||
prev = entry->tl_data;
|
||||
while(prev) {
|
||||
next = prev->tl_data_next;
|
||||
/* Handle RBCD ACL type */
|
||||
if (prev->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL) {
|
||||
char **acl_list = (char **) prev->tl_data_contents;
|
||||
for (i = 0; (acl_list != NULL) && (acl_list[i] != NULL); i++) {
|
||||
free(acl_list[i]);
|
||||
}
|
||||
}
|
||||
free(prev->tl_data_contents);
|
||||
free(prev);
|
||||
prev = next;
|
||||
@@ -1920,10 +1673,10 @@ void ipadb_free_principal(krb5_context kcontext, krb5_db_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
krb5_error_code ipadb_get_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
krb5_octet *data)
|
||||
static krb5_error_code ipadb_get_tl_data(krb5_db_entry *entry,
|
||||
krb5_int16 type,
|
||||
krb5_ui_2 length,
|
||||
krb5_octet *data)
|
||||
{
|
||||
krb5_tl_data *td;
|
||||
|
||||
@@ -2172,21 +1925,6 @@ done:
|
||||
return kerr;
|
||||
}
|
||||
|
||||
static bool should_filter_out_attr(krb5_tl_data *data)
|
||||
{
|
||||
switch (data->tl_data_type) {
|
||||
case KRB5_TL_CONSTRAINED_DELEGATION_ACL:
|
||||
case KRB5_TL_DB_ARGS:
|
||||
case KRB5_TL_KADM_DATA:
|
||||
case KRB5_TL_LAST_ADMIN_UNLOCK:
|
||||
case KRB5_TL_LAST_PWD_CHANGE:
|
||||
case KRB5_TL_MKVNO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods,
|
||||
krb5_tl_data *tl_data,
|
||||
int mod_op)
|
||||
@@ -2198,8 +1936,13 @@ static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods,
|
||||
int n, i;
|
||||
|
||||
for (n = 0, data = tl_data; data; data = data->tl_data_next) {
|
||||
if (should_filter_out_attr(data))
|
||||
if (data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE ||
|
||||
data->tl_data_type == KRB5_TL_KADM_DATA ||
|
||||
data->tl_data_type == KRB5_TL_DB_ARGS ||
|
||||
data->tl_data_type == KRB5_TL_MKVNO ||
|
||||
data->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) {
|
||||
continue;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
@@ -2215,8 +1958,13 @@ static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods,
|
||||
|
||||
for (i = 0, data = tl_data; data; data = data->tl_data_next) {
|
||||
|
||||
if (should_filter_out_attr(data))
|
||||
if (data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE ||
|
||||
data->tl_data_type == KRB5_TL_KADM_DATA ||
|
||||
data->tl_data_type == KRB5_TL_DB_ARGS ||
|
||||
data->tl_data_type == KRB5_TL_MKVNO ||
|
||||
data->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
be_type = htons(data->tl_data_type);
|
||||
|
||||
@@ -2968,43 +2716,10 @@ done:
|
||||
return kerr;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
remove_virtual_str_attrs(krb5_context kcontext, krb5_db_entry *entry)
|
||||
{
|
||||
char *str_attr_val;
|
||||
krb5_error_code kerr;
|
||||
const char *str_attrs[] = {
|
||||
KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM,
|
||||
KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE,
|
||||
NULL};
|
||||
|
||||
for(int i = 0; str_attrs[i] != NULL; i++) {
|
||||
kerr = krb5_dbe_get_string(kcontext, entry,
|
||||
str_attrs[i],
|
||||
&str_attr_val);
|
||||
if (kerr)
|
||||
return kerr;
|
||||
|
||||
if (str_attr_val)
|
||||
kerr = krb5_dbe_set_string(kcontext, entry,
|
||||
str_attrs[i],
|
||||
NULL);
|
||||
|
||||
krb5_dbe_free_string(kcontext, str_attr_val);
|
||||
}
|
||||
return kerr;
|
||||
}
|
||||
|
||||
krb5_error_code ipadb_put_principal(krb5_context kcontext,
|
||||
krb5_db_entry *entry,
|
||||
char **db_args)
|
||||
{
|
||||
krb5_error_code kerr;
|
||||
|
||||
kerr = remove_virtual_str_attrs(kcontext, entry);
|
||||
if (kerr)
|
||||
return kerr;
|
||||
|
||||
if (entry->mask & KMASK_PRINCIPAL) {
|
||||
return ipadb_add_principal(kcontext, entry);
|
||||
} else {
|
||||
|
||||
@@ -178,7 +178,7 @@ static int teardown(void **state)
|
||||
|
||||
extern krb5_error_code filter_logon_info(krb5_context context,
|
||||
TALLOC_CTX *memctx,
|
||||
krb5_data *realm,
|
||||
krb5_data realm,
|
||||
struct PAC_LOGON_INFO_CTR *info);
|
||||
|
||||
static void test_filter_logon_info(void **state)
|
||||
@@ -204,7 +204,7 @@ static void test_filter_logon_info(void **state)
|
||||
"WRONG");
|
||||
assert_non_null(info->info->info3.base.logon_domain.string);
|
||||
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, realm, info);
|
||||
assert_int_equal(kerr, EINVAL);
|
||||
|
||||
info->info->info3.base.logon_domain.string = talloc_strdup(info->info,
|
||||
@@ -212,7 +212,7 @@ static void test_filter_logon_info(void **state)
|
||||
assert_non_null(info->info->info3.base.logon_domain.string);
|
||||
|
||||
/* missing domain SID */
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, realm, info);
|
||||
assert_int_equal(kerr, EINVAL);
|
||||
|
||||
/* wrong domain SID */
|
||||
@@ -220,7 +220,7 @@ static void test_filter_logon_info(void **state)
|
||||
assert_int_equal(ret, 0);
|
||||
info->info->info3.base.domain_sid = &dom_sid;
|
||||
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, realm, info);
|
||||
assert_int_equal(kerr, EINVAL);
|
||||
|
||||
/* matching domain SID */
|
||||
@@ -228,7 +228,7 @@ static void test_filter_logon_info(void **state)
|
||||
assert_int_equal(ret, 0);
|
||||
info->info->info3.base.domain_sid = &dom_sid;
|
||||
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, test_ctx, realm, info);
|
||||
assert_int_equal(kerr, 0);
|
||||
|
||||
/* empty SIDs */
|
||||
@@ -243,7 +243,7 @@ static void test_filter_logon_info(void **state)
|
||||
assert_non_null(info->info->info3.sids[c].sid);
|
||||
}
|
||||
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, NULL, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, NULL, realm, info);
|
||||
assert_int_equal(kerr, 0);
|
||||
assert_int_equal(info->info->info3.sidcount, 3);
|
||||
|
||||
@@ -297,7 +297,7 @@ static void test_filter_logon_info(void **state)
|
||||
assert_int_equal(ret, 0);
|
||||
}
|
||||
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, NULL, &realm, info);
|
||||
kerr = filter_logon_info(test_ctx->krb5_ctx, NULL, realm, info);
|
||||
assert_int_equal(kerr, 0);
|
||||
assert_int_equal(info->info->info3.sidcount, test_data[c].exp_sidcount);
|
||||
if (test_data[c].exp_sidcount == 0) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
AM_CPPFLAGS := -I$(top_srcdir)/util
|
||||
AM_CFLAGS := @LDAP_CFLAGS@ @LIBVERTO_CFLAGS@ @KRB5_CFLAGS@ @NSPR_CFLAGS@
|
||||
AM_LDFLAGS := @LDAP_LIBS@ @LIBVERTO_LIBS@ @KRAD_LIBS@ @KRB5_LIBS@ @JANSSON_LIBS@
|
||||
AM_LDFLAGS := @LDAP_LIBS@ @LIBVERTO_LIBS@ @KRAD_LIBS@ @KRB5_LIBS@
|
||||
|
||||
noinst_HEADERS = internal.h
|
||||
appdir = $(libexecdir)/ipa/
|
||||
@@ -10,7 +10,7 @@ dist_noinst_DATA = ipa-otpd.socket.in ipa-otpd@.service.in test.py
|
||||
systemdsystemunit_DATA = ipa-otpd.socket ipa-otpd@.service
|
||||
|
||||
ipa_otpd_SOURCES = bind.c forward.c main.c parse.c query.c queue.c stdio.c \
|
||||
oauth2.c passkey.c
|
||||
oauth2.c
|
||||
|
||||
%.socket: %.socket.in
|
||||
@sed -e 's|@krb5rundir[@]|$(krb5rundir)|g' \
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include "krad.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -51,7 +49,6 @@ enum ldap_query {
|
||||
LDAP_QUERY_RADIUS,
|
||||
LDAP_QUERY_RADIUS_USERMAP,
|
||||
LDAP_QUERY_IDP,
|
||||
LDAP_QUERY_PASSKEY,
|
||||
LDAP_QUERY_END
|
||||
};
|
||||
|
||||
@@ -62,8 +59,6 @@ enum oauth2_state {
|
||||
OAUTH2_GET_ACCESS_TOKEN
|
||||
};
|
||||
|
||||
struct otpd_queue_item_passkey;
|
||||
|
||||
struct otpd_queue_item {
|
||||
struct otpd_queue_item *next;
|
||||
krad_packet *req;
|
||||
@@ -79,7 +74,6 @@ struct otpd_queue_item {
|
||||
char *ipatokenRadiusConfigLink;
|
||||
char *ipaidpSub;
|
||||
char *ipaidpConfigLink;
|
||||
char **ipaPassKey;
|
||||
char **ipauserauthtypes;
|
||||
char *other;
|
||||
} user;
|
||||
@@ -113,9 +107,6 @@ struct otpd_queue_item {
|
||||
krb5_data state;
|
||||
} oauth2;
|
||||
|
||||
bool get_passkey_config;
|
||||
struct otpd_queue_item_passkey *passkey;
|
||||
|
||||
int msgid;
|
||||
};
|
||||
|
||||
@@ -170,25 +161,9 @@ void otpd_log_req_(const char * const file, int line, krad_packet *req,
|
||||
void otpd_log_err_(const char * const file, int line, krb5_error_code code,
|
||||
const char * const tmpl, ...);
|
||||
|
||||
int add_krad_attr_to_set(krad_packet *req, krad_attrset *attrset,
|
||||
krb5_data *datap, krad_attr attr, const char *message);
|
||||
|
||||
int get_krad_attr_from_packet(const krad_packet *rres,
|
||||
krad_attr attr, krb5_data *_data);
|
||||
|
||||
int get_string(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char **out);
|
||||
|
||||
int get_string_array(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char ***out);
|
||||
|
||||
bool auth_type_is(char **auth_types, const char *check);
|
||||
|
||||
krb5_error_code otpd_queue_item_new(krad_packet *req,
|
||||
struct otpd_queue_item **item);
|
||||
|
||||
void free_otpd_queue_item_passkey(struct otpd_queue_item *item);
|
||||
|
||||
void otpd_queue_item_free(struct otpd_queue_item *item);
|
||||
|
||||
krb5_error_code otpd_queue_iter_new(const struct otpd_queue * const *queues,
|
||||
@@ -231,10 +206,3 @@ const char *otpd_parse_radius_username(LDAP *ldp, LDAPMessage *entry,
|
||||
struct otpd_queue_item *item);
|
||||
|
||||
int oauth2(struct otpd_queue_item **item, enum oauth2_state);
|
||||
|
||||
const char *otpd_parse_passkey(LDAP *ldp, LDAPMessage *entry,
|
||||
struct otpd_queue_item *item);
|
||||
|
||||
bool is_passkey(struct otpd_queue_item *item);
|
||||
|
||||
int do_passkey(struct otpd_queue_item *item);
|
||||
@@ -7,4 +7,4 @@ EnvironmentFile=@sysconfdir@/ipa/default.conf
|
||||
ExecStart=@libexecdir@/ipa/ipa-otpd $ldap_uri
|
||||
StandardInput=socket
|
||||
StandardOutput=socket
|
||||
StandardError=journal
|
||||
StandardError=syslog
|
||||
@@ -59,12 +59,6 @@ static void free_elts(struct otpd_queue *q)
|
||||
#define otpd_queue_item_free free_elt
|
||||
#define otpd_queue_free_items free_elts
|
||||
|
||||
void free_otpd_queue_item_passkey(struct otpd_queue_item *item)
|
||||
{
|
||||
(void)item; /* Unused */
|
||||
return;
|
||||
}
|
||||
|
||||
static void assert_elt_equal(struct otpd_queue_item *e1,
|
||||
struct otpd_queue_item *e2)
|
||||
{
|
||||
@@ -75,7 +69,7 @@ static void assert_elt_equal(struct otpd_queue_item *e1,
|
||||
assert_int_equal(e1->msgid, e2->msgid);
|
||||
}
|
||||
|
||||
static void test_single_insert(void **state)
|
||||
static void test_single_insert()
|
||||
{
|
||||
struct otpd_queue q = { NULL };
|
||||
struct otpd_queue_item *ein, *eout;
|
||||
@@ -96,7 +90,7 @@ static void test_single_insert(void **state)
|
||||
free_elts(&q);
|
||||
}
|
||||
|
||||
static void test_jump_insert(void **state)
|
||||
static void test_jump_insert()
|
||||
{
|
||||
struct otpd_queue q = { NULL };
|
||||
struct otpd_queue_item *echeck;
|
||||
@@ -112,7 +106,7 @@ static void test_jump_insert(void **state)
|
||||
free_elts(&q);
|
||||
}
|
||||
|
||||
static void test_garbage_insert(void **state)
|
||||
static void test_garbage_insert()
|
||||
{
|
||||
struct otpd_queue q = { NULL };
|
||||
struct otpd_queue_item *e, *g;
|
||||
@@ -127,7 +121,7 @@ static void test_garbage_insert(void **state)
|
||||
free_elts(&q);
|
||||
}
|
||||
|
||||
static void test_removal(void **state)
|
||||
static void test_removal()
|
||||
{
|
||||
struct otpd_queue q = { NULL };
|
||||
|
||||
@@ -155,7 +149,7 @@ static void pick_id(struct otpd_queue *q, int msgid)
|
||||
e = otpd_queue_pop_msgid(q, msgid);
|
||||
assert_ptr_equal(e, NULL);
|
||||
}
|
||||
static void test_pick_removal(void **state)
|
||||
static void test_pick_removal()
|
||||
{
|
||||
struct otpd_queue q = { NULL };
|
||||
|
||||
@@ -172,7 +166,7 @@ static void test_pick_removal(void **state)
|
||||
free_elts(&q);
|
||||
}
|
||||
|
||||
static void test_iter(void **state)
|
||||
static void test_iter()
|
||||
{
|
||||
krb5_error_code ret;
|
||||
struct otpd_queue q = { NULL };
|
||||
|
||||
@@ -88,80 +88,6 @@ void otpd_log_err_(const char * const file, int line, krb5_error_code code,
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
#define min(a,b) ((a) > (b) ? (b) : (a))
|
||||
int add_krad_attr_to_set(krad_packet *req, krad_attrset *attrset,
|
||||
krb5_data *datap, krad_attr attr, const char *message)
|
||||
{
|
||||
krb5_data state = {0};
|
||||
char *p = datap->data;
|
||||
unsigned int len = datap->length;
|
||||
int ret = 0;
|
||||
|
||||
do {
|
||||
state.data = p;
|
||||
state.length = min(MAX_ATTRSIZE - 5, len);
|
||||
p += state.length;
|
||||
|
||||
ret = krad_attrset_add(attrset, attr, &(state));
|
||||
if (ret != 0) {
|
||||
otpd_log_req(req, message);
|
||||
break;
|
||||
}
|
||||
len -= state.length;
|
||||
} while (len > 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Most attributes have limited length (MAX_ATTRSIZE). In order to accept longer
|
||||
* values, we will concatenate all the attribute values to single krb5_data. */
|
||||
int get_krad_attr_from_packet(const krad_packet *rres,
|
||||
krad_attr attr, krb5_data *_data)
|
||||
{
|
||||
const krb5_data *rmsg;
|
||||
krb5_data data = {0};
|
||||
unsigned int memindex;
|
||||
unsigned int i;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
rmsg = krad_packet_get_attr(rres, attr, i);
|
||||
if (rmsg != NULL) {
|
||||
data.length += rmsg->length;
|
||||
}
|
||||
i++;
|
||||
} while (rmsg != NULL);
|
||||
|
||||
if (data.length == 0) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
data.data = malloc(data.length);
|
||||
if (data.data == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
memindex = 0;
|
||||
do {
|
||||
rmsg = krad_packet_get_attr(rres, attr, i);
|
||||
if (rmsg != NULL) {
|
||||
memcpy(&data.data[memindex], rmsg->data, rmsg->length);
|
||||
memindex += rmsg->length;
|
||||
}
|
||||
i++;
|
||||
} while (rmsg != NULL);
|
||||
|
||||
if (memindex != data.length) {
|
||||
free(data.data);
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
*_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void on_ldap_free(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
(void)vctx; /* Unused */
|
||||
|
||||
@@ -135,6 +135,82 @@ static void oauth2_on_child_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
verto_del(ev);
|
||||
}
|
||||
|
||||
#define min(a,b) ((a) > (b) ? (b) : (a))
|
||||
static int add_krad_attr_to_set(struct child_ctx *child_ctx,
|
||||
krad_attrset *attrset,
|
||||
krb5_data *datap,
|
||||
krad_attr attr, const char *message)
|
||||
{
|
||||
krb5_data state = {0};
|
||||
char *p = datap->data;
|
||||
unsigned int len = datap->length;
|
||||
int ret = 0;
|
||||
|
||||
do {
|
||||
state.data = p;
|
||||
state.length = min(MAX_ATTRSIZE - 5, len);
|
||||
p += state.length;
|
||||
|
||||
ret = krad_attrset_add(attrset, attr, &(state));
|
||||
if (ret != 0) {
|
||||
otpd_log_req(child_ctx->item->req, message);
|
||||
break;
|
||||
}
|
||||
len -= state.length;
|
||||
} while (len > 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Most attributes have limited length (MAX_ATTRSIZE). In order to accept longer
|
||||
* values, we will concatenate all the attribute values to single krb5_data. */
|
||||
static int get_krad_attr_from_packet(const krad_packet *rres,
|
||||
krad_attr attr, krb5_data *_data)
|
||||
{
|
||||
const krb5_data *rmsg;
|
||||
krb5_data data = {0};
|
||||
unsigned int memindex;
|
||||
unsigned int i;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
rmsg = krad_packet_get_attr(rres, attr, i);
|
||||
if (rmsg != NULL) {
|
||||
data.length += rmsg->length;
|
||||
}
|
||||
i++;
|
||||
} while (rmsg != NULL);
|
||||
|
||||
if (data.length == 0) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
data.data = malloc(data.length);
|
||||
if (data.data == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
memindex = 0;
|
||||
do {
|
||||
rmsg = krad_packet_get_attr(rres, attr, i);
|
||||
if (rmsg != NULL) {
|
||||
memcpy(&data.data[memindex], rmsg->data, rmsg->length);
|
||||
memindex += rmsg->length;
|
||||
}
|
||||
i++;
|
||||
} while (rmsg != NULL);
|
||||
|
||||
if (memindex != data.length) {
|
||||
free(data.data);
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
*_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* oidc_child will return two lines.
|
||||
* The first is a JSON formatted string containing the device code and other
|
||||
* data needed to get the access token in the second round. This will be
|
||||
@@ -149,7 +225,7 @@ static int handle_device_code_reply(struct child_ctx *child_ctx,
|
||||
krad_attrset *attrset = NULL;
|
||||
int ret;
|
||||
krb5_data data = { 0 };
|
||||
struct otpd_queue_item *state_item = NULL;
|
||||
struct otpd_queue_item *state_item;
|
||||
|
||||
ret = otpd_queue_item_new(NULL, &state_item);
|
||||
if (ret != 0) {
|
||||
@@ -180,8 +256,7 @@ static int handle_device_code_reply(struct child_ctx *child_ctx,
|
||||
}
|
||||
state_item->oauth2.state.length = strlen(dc_reply);
|
||||
|
||||
ret = add_krad_attr_to_set(child_ctx->item->req,
|
||||
attrset, &(state_item->oauth2.state),
|
||||
ret = add_krad_attr_to_set(child_ctx, attrset, &(state_item->oauth2.state),
|
||||
krad_attr_name2num("Proxy-State"),
|
||||
"Failed to serialize state to attribute set");
|
||||
if (ret != 0) {
|
||||
@@ -191,7 +266,7 @@ static int handle_device_code_reply(struct child_ctx *child_ctx,
|
||||
data.magic = 0;
|
||||
data.data = rad_reply;
|
||||
data.length = strlen(rad_reply);
|
||||
ret = add_krad_attr_to_set(child_ctx->item->req, attrset, &data,
|
||||
ret = add_krad_attr_to_set(child_ctx, attrset, &data,
|
||||
krad_attr_name2num("Reply-Message"),
|
||||
"Failed to serialize reply to attribute set");
|
||||
if (ret != 0) {
|
||||
@@ -244,7 +319,7 @@ static int check_access_token_reply(struct child_ctx *child_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void oauth2_on_child_readable(verto_ctx *vctx, verto_ev *ev)
|
||||
static void oauth2_on_child_readable(verto_ctx *, verto_ev *ev)
|
||||
{
|
||||
static char buf[10240];
|
||||
ssize_t io = 0;
|
||||
@@ -253,8 +328,6 @@ static void oauth2_on_child_readable(verto_ctx *vctx, verto_ev *ev)
|
||||
char *rad_reply;
|
||||
char *end;
|
||||
|
||||
(void) vctx; /* Unused */
|
||||
|
||||
child_ctx = (struct child_ctx *) verto_get_private(ev);
|
||||
if (child_ctx == NULL) {
|
||||
otpd_log_err(EINVAL, "Lost child context");
|
||||
@@ -353,7 +426,7 @@ int oauth2(struct otpd_queue_item **item, enum oauth2_state oauth2_state)
|
||||
char *args[50] = {NULL};
|
||||
size_t args_idx = 0;
|
||||
krb5_data data_state = {0};
|
||||
struct otpd_queue_item *saved_item = NULL;
|
||||
struct otpd_queue_item *saved_item;
|
||||
|
||||
if (oauth2_state != OAUTH2_GET_DEVICE_CODE
|
||||
&& oauth2_state != OAUTH2_GET_ACCESS_TOKEN) {
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#define DEFAULT_RETRIES 3
|
||||
|
||||
/* Convert an LDAP entry into an allocated string. */
|
||||
int get_string(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char **out)
|
||||
static int get_string(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char **out)
|
||||
{
|
||||
struct berval **vals;
|
||||
ber_len_t i;
|
||||
@@ -69,12 +69,12 @@ int get_string(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
}
|
||||
|
||||
/* Convert an LDAP entry into an allocated string array. */
|
||||
int get_string_array(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char ***out)
|
||||
static int get_string_array(LDAP *ldp, LDAPMessage *entry, const char *name,
|
||||
char ***out)
|
||||
{
|
||||
struct berval **vals;
|
||||
ber_len_t i;
|
||||
char **buf = NULL;
|
||||
char **buf;
|
||||
int tmp;
|
||||
size_t count;
|
||||
size_t c;
|
||||
@@ -188,11 +188,6 @@ const char *otpd_parse_user(LDAP *ldp, LDAPMessage *entry,
|
||||
if (i != 0 && i != ENOENT)
|
||||
return strerror(i);
|
||||
|
||||
i = get_string_array(ldp, entry, "ipaPassKey",
|
||||
&item->user.ipaPassKey);
|
||||
if (i != 0 && i != ENOENT)
|
||||
return strerror(i);
|
||||
|
||||
i = get_string_array(ldp, entry, "ipauserauthtype",
|
||||
&item->user.ipauserauthtypes);
|
||||
if (i != 0 && i != ENOENT)
|
||||
|
||||
@@ -1,824 +0,0 @@
|
||||
/*
|
||||
* FreeIPA 2FA companion daemon
|
||||
*
|
||||
* Authors: Sumit Bose <sbose@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2022 Sumit Bose, Red Hat
|
||||
* see file 'COPYING' for use and warranty information
|
||||
*
|
||||
* This program is free software you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains various helper functions for the passkey feature.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* for asprintf() */
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <jansson.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
struct passkey_data {
|
||||
int phase;
|
||||
char *state;
|
||||
union {
|
||||
struct passkey_challenge {
|
||||
char *domain;
|
||||
json_t *credential_id_list;
|
||||
int user_verification;
|
||||
unsigned char *cryptographic_challenge;
|
||||
} challenge;
|
||||
|
||||
struct sss_passkey_reply {
|
||||
char *credential_id;
|
||||
char *cryptographic_challenge;
|
||||
char *authenticator_data;
|
||||
char *assertion_signature;
|
||||
char *user_id;
|
||||
} response;
|
||||
} data;
|
||||
json_t *jdata;
|
||||
json_t *jroot;
|
||||
};
|
||||
|
||||
struct otpd_queue_item_passkey {
|
||||
char *domain;
|
||||
char *ipaRequireUserVerification;
|
||||
struct passkey_data *data_in;
|
||||
struct passkey_data *data_out;
|
||||
krb5_data state;
|
||||
char* ipapasskeyDebugLevelStr;
|
||||
krb5_boolean ipapasskeyDebugFido2;
|
||||
};
|
||||
|
||||
static void free_passkey_data(struct passkey_data *p)
|
||||
{
|
||||
if (p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->phase == 1) {
|
||||
free(p->data.challenge.domain);
|
||||
free(p->data.challenge.cryptographic_challenge);
|
||||
}
|
||||
|
||||
json_decref(p->jdata);
|
||||
json_decref(p->jroot);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void free_otpd_queue_item_passkey(struct otpd_queue_item *item)
|
||||
{
|
||||
if (item == NULL || item->passkey == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(item->passkey->domain);
|
||||
free(item->passkey->ipaRequireUserVerification);
|
||||
|
||||
free_passkey_data(item->passkey->data_in);
|
||||
free_passkey_data(item->passkey->data_out);
|
||||
|
||||
free(item->passkey);
|
||||
}
|
||||
|
||||
static struct otpd_queue_item_passkey *get_otpd_queue_item_passkey(void)
|
||||
{
|
||||
struct otpd_queue_item_passkey *p;
|
||||
|
||||
p = calloc(1, sizeof(struct otpd_queue_item_passkey));
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->data_in = calloc(1, sizeof(struct passkey_data));
|
||||
if (p->data_in == NULL) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->data_out = calloc(1, sizeof(struct passkey_data));
|
||||
if (p->data_out == NULL) {
|
||||
free(p->data_in);
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->data_in->phase = -1;
|
||||
p->data_out->phase = -1;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#define PASSKEY_PREFIX "passkey "
|
||||
#define ENV_PASSKEY_CHILD_DEBUG_LEVEL "passkey_child_debug_level"
|
||||
|
||||
/* Parse the passkey configuration */
|
||||
const char *otpd_parse_passkey(LDAP *ldp, LDAPMessage *entry,
|
||||
struct otpd_queue_item *item)
|
||||
{
|
||||
int i;
|
||||
char **objectclasses = NULL;
|
||||
long dbg_lvl = 0;
|
||||
const char *dbg_env = NULL;
|
||||
char *endptr = NULL;
|
||||
|
||||
if (item->passkey == NULL) {
|
||||
otpd_log_req(item->req,
|
||||
"Missing passkey struct to store passkey configuration");
|
||||
return strerror(EINVAL);
|
||||
}
|
||||
|
||||
while (entry != NULL) {
|
||||
i = get_string_array(ldp, entry, "objectclass", &objectclasses);
|
||||
if (i != 0) {
|
||||
return strerror(i);
|
||||
}
|
||||
|
||||
if (auth_type_is(objectclasses, "ipapasskeyconfigobject")) {
|
||||
free(objectclasses);
|
||||
|
||||
i = get_string(ldp, entry, "ipaRequireUserVerification",
|
||||
&item->passkey->ipaRequireUserVerification);
|
||||
if ((i != 0) && (i != ENOENT)) {
|
||||
return strerror(i);
|
||||
}
|
||||
} else if (auth_type_is(objectclasses, "domainRelatedObject")) {
|
||||
free(objectclasses);
|
||||
|
||||
i = get_string(ldp, entry, "associatedDomain",
|
||||
&item->passkey->domain);
|
||||
if ((i != 0) && (i != ENOENT)) {
|
||||
return strerror(i);
|
||||
}
|
||||
}
|
||||
|
||||
entry = ldap_next_entry(ldp, entry);
|
||||
};
|
||||
|
||||
item->passkey->ipapasskeyDebugLevelStr = NULL;
|
||||
item->passkey->ipapasskeyDebugFido2 = FALSE;
|
||||
dbg_env = getenv(ENV_PASSKEY_CHILD_DEBUG_LEVEL);
|
||||
if (dbg_env != NULL && *dbg_env != '\0') {
|
||||
errno = 0;
|
||||
dbg_lvl = strtoul(dbg_env, &endptr, 10);
|
||||
if (errno == 0 && *endptr == '\0') {
|
||||
if (dbg_lvl < 0) {
|
||||
dbg_lvl = 0;
|
||||
} else if (dbg_lvl > 10) {
|
||||
dbg_lvl = 10;
|
||||
}
|
||||
if (asprintf(&item->passkey->ipapasskeyDebugLevelStr, "%ld",
|
||||
dbg_lvl) != -1) {
|
||||
if (dbg_lvl > 5) {
|
||||
item->passkey->ipapasskeyDebugFido2 = TRUE;
|
||||
}
|
||||
} else {
|
||||
otpd_log_req(item->req, "Failed to copy debug level");
|
||||
}
|
||||
} else {
|
||||
otpd_log_req(item->req,
|
||||
"Cannot parse value [%s] from environment variable [%s]",
|
||||
dbg_env, ENV_PASSKEY_CHILD_DEBUG_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int decode_json(const char *inp, size_t size, struct passkey_data *data)
|
||||
{
|
||||
json_error_t jret;
|
||||
int ret;
|
||||
|
||||
data->jroot = json_loadb(inp, size, 0, &jret);
|
||||
if (data->jroot == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
data->jdata = NULL;
|
||||
data->phase = -1;
|
||||
|
||||
ret = json_unpack(data->jroot, "{s:i, s?:s, s?:o}",
|
||||
"phase", &data->phase,
|
||||
"state", &data->state,
|
||||
"data", &data->jdata);
|
||||
if (ret != 0) {
|
||||
ret = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (data->phase) {
|
||||
case 0: /* SSS_PASSKEY_PHASE_INIT */
|
||||
/* no data */
|
||||
if (data->jdata != NULL) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* SSS_PASSKEY_PHASE_REPLY */
|
||||
ret = json_unpack(data->jdata, "{s:s, s:s, s:s, s:s}",
|
||||
"credential_id", &data->data.response.credential_id,
|
||||
"cryptographic_challenge", &data->data.response.cryptographic_challenge,
|
||||
"authenticator_data", &data->data.response.authenticator_data,
|
||||
"assertion_signature", &data->data.response.assertion_signature,
|
||||
"user_id", &data->data.response.user_id);
|
||||
break;
|
||||
default:
|
||||
ret = EINVAL;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ret != 0) {
|
||||
json_decref(data->jdata);
|
||||
data->jdata = NULL;
|
||||
json_decref(data->jroot);
|
||||
data->jroot = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int passkey_parse_data(const char *data, size_t size, struct otpd_queue_item *item)
|
||||
{
|
||||
item->passkey = get_otpd_queue_item_passkey();
|
||||
if (item->passkey == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
return decode_json(data, size, item->passkey->data_in);
|
||||
}
|
||||
|
||||
bool is_passkey(struct otpd_queue_item *item)
|
||||
{
|
||||
const krb5_data *data_pwd;
|
||||
krb5_data data_state = { 0 };
|
||||
int ret;
|
||||
|
||||
if (item->passkey != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
data_pwd = krad_packet_get_attr(item->req,
|
||||
krad_attr_name2num("User-Password"), 0);
|
||||
ret = get_krad_attr_from_packet(item->req,
|
||||
krad_attr_name2num("Proxy-State"),
|
||||
&data_state);
|
||||
|
||||
if (data_pwd == NULL && ret == 0
|
||||
&& data_state.length > strlen(PASSKEY_PREFIX)
|
||||
&& strncmp(data_state.data, PASSKEY_PREFIX,
|
||||
strlen(PASSKEY_PREFIX)) == 0
|
||||
&& (item->user.ipauserauthtypes == NULL
|
||||
|| item->user.ipauserauthtypes[0] == NULL
|
||||
|| *(item->user.ipauserauthtypes[0]) == '\0'
|
||||
|| auth_type_is(item->user.ipauserauthtypes, "passkey"))) {
|
||||
|
||||
ret = passkey_parse_data(data_state.data + strlen(PASSKEY_PREFIX),
|
||||
data_state.length - strlen(PASSKEY_PREFIX) - 1,
|
||||
item);
|
||||
krb5_free_data_contents(NULL, &data_state);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#define PK_PREF "passkey:"
|
||||
|
||||
static json_t *ipa_passkey_to_json_array(char **ipa_passkey)
|
||||
{
|
||||
int ret;
|
||||
const char *sep;
|
||||
char *start;
|
||||
size_t c;
|
||||
json_t *ja = NULL;
|
||||
json_t *js;
|
||||
|
||||
if (ipa_passkey == NULL || *ipa_passkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ja = json_array();
|
||||
if (ja == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (c = 0; ipa_passkey[c] != NULL; c++) {
|
||||
if (strncmp(ipa_passkey[c], PK_PREF, strlen(PK_PREF)) != 0) {
|
||||
otpd_log_err(ret, "Missing prefix in [%s]", ipa_passkey[c]);
|
||||
continue;
|
||||
}
|
||||
start = ipa_passkey[c] + strlen(PK_PREF);
|
||||
sep = strchr(start, ',');
|
||||
if (sep == NULL || sep == start) {
|
||||
otpd_log_err(ret, "Missing seperator in [%s]", ipa_passkey[c]);
|
||||
continue;
|
||||
}
|
||||
|
||||
js = json_stringn(start, sep - start);
|
||||
if (js == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = json_array_append_new(ja, js);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (ret != 0) {
|
||||
json_decref(ja);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ja;
|
||||
}
|
||||
|
||||
/* passkey string:
|
||||
* key_handle,public_key(,optional_user_id)
|
||||
*/
|
||||
static char *ipa_passkey_get_public_key(char **ipa_passkey, const char *key_id)
|
||||
{
|
||||
char *sep;
|
||||
char *sep2;
|
||||
size_t c;
|
||||
char *start;
|
||||
|
||||
if (ipa_passkey == NULL || *ipa_passkey == NULL
|
||||
|| key_id == NULL || *key_id == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (c = 0; ipa_passkey[c] != NULL; c++) {
|
||||
if (strncmp(ipa_passkey[c], PK_PREF, strlen(PK_PREF)) != 0) {
|
||||
otpd_log_err(EINVAL, "Missing prefix in [%s]", ipa_passkey[c]);
|
||||
continue;
|
||||
}
|
||||
start = ipa_passkey[c] + strlen(PK_PREF);
|
||||
|
||||
sep = strchr(start, ',');
|
||||
if (sep == NULL || sep == start) {
|
||||
otpd_log_err(EINVAL, "Missing seperator in [%s]", ipa_passkey[c]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(start, key_id, sep - start) == 0) {
|
||||
sep2 = strchrnul(sep + 1, ',');
|
||||
if (sep2 == sep + 1) {
|
||||
return NULL;
|
||||
}
|
||||
*sep2 = '\0';
|
||||
return (sep + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CHALLENGE_LENGTH 32
|
||||
static unsigned char *get_b64_challenge(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[CHALLENGE_LENGTH];
|
||||
unsigned char *b64;
|
||||
|
||||
ret = RAND_bytes(buf, CHALLENGE_LENGTH);
|
||||
if (ret != 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b64 = calloc(1, 2 * CHALLENGE_LENGTH);
|
||||
if (b64 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = EVP_EncodeBlock(b64, buf, CHALLENGE_LENGTH);
|
||||
if (ret == 0) {
|
||||
free(b64);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return b64;
|
||||
}
|
||||
|
||||
static int prepare_rad_reply(struct otpd_queue_item *item)
|
||||
{
|
||||
krad_attrset *attrset = NULL;
|
||||
int ret;
|
||||
json_t *jtmp = NULL;
|
||||
char *stmp = NULL;
|
||||
krb5_data data = { 0 };
|
||||
|
||||
ret = krad_attrset_new(ctx.kctx, &attrset);
|
||||
if (ret != 0) {
|
||||
otpd_log_err(ret, "Failed to create radius attribute set");
|
||||
goto done;
|
||||
}
|
||||
|
||||
jtmp = json_pack("{s:i, s:s, s:o}", "phase", item->passkey->data_out->phase,
|
||||
"state", item->passkey->data_out->state,
|
||||
"data", item->passkey->data_out->jdata);
|
||||
if (jtmp == NULL) {
|
||||
ret = EIO;
|
||||
otpd_log_err(ret, "Failed to pack JSON reply");
|
||||
goto done;
|
||||
}
|
||||
|
||||
stmp = json_dumps(jtmp, JSON_COMPACT);
|
||||
if (stmp == NULL) {
|
||||
ret = EIO;
|
||||
otpd_log_err(ret, "Failed to dump JSON string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = asprintf(&(data.data), "passkey %s", stmp);
|
||||
if (ret < 0) {
|
||||
ret = ENOMEM;
|
||||
otpd_log_err(ret, "Failed to generate reply string");
|
||||
goto done;
|
||||
}
|
||||
data.length = strlen(data.data);
|
||||
data.magic = 0;
|
||||
|
||||
|
||||
ret = add_krad_attr_to_set(item->req, attrset, &data,
|
||||
krad_attr_name2num("Proxy-State"),
|
||||
"Failed to serialize state to attribute set");
|
||||
if (ret != 0) {
|
||||
otpd_log_err(ret, "Failed to add Proxy-State");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = krad_packet_new_response(ctx.kctx, SECRET,
|
||||
krad_code_name2num("Access-Challenge"),
|
||||
attrset,
|
||||
item->req, &item->rsp);
|
||||
if (ret != 0) {
|
||||
otpd_log_err(ret, "Failed to create radius response");
|
||||
item->rsp = NULL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
krad_attrset_free(attrset);
|
||||
free(stmp);
|
||||
json_decref(jtmp);
|
||||
|
||||
if (ret != 0) {
|
||||
free(data.data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_passkey_challenge(struct otpd_queue_item *item)
|
||||
{
|
||||
unsigned char *challenge = NULL;
|
||||
int ret;
|
||||
struct passkey_data *d;
|
||||
|
||||
d = item->passkey->data_out;
|
||||
|
||||
d->data.challenge.credential_id_list = ipa_passkey_to_json_array(
|
||||
item->user.ipaPassKey);
|
||||
if (d->data.challenge.credential_id_list == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Secure by default, assume user verification is enabled and disable it
|
||||
* only if the option is set to 'false'. */
|
||||
d->data.challenge.user_verification = 1;
|
||||
if (item->passkey->ipaRequireUserVerification != NULL
|
||||
&& strcasecmp(item->passkey->ipaRequireUserVerification,
|
||||
"false") == 0) {
|
||||
d->data.challenge.user_verification = 0;
|
||||
}
|
||||
|
||||
d->data.challenge.cryptographic_challenge = get_b64_challenge();
|
||||
if (d->data.challenge.cryptographic_challenge == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
d->jdata = json_pack("{s:s, s:o, s:i, s:s}",
|
||||
"domain", item->passkey->domain,
|
||||
"credential_id_list",
|
||||
d->data.challenge.credential_id_list,
|
||||
"user_verification",
|
||||
d->data.challenge.user_verification,
|
||||
"cryptographic_challenge",
|
||||
d->data.challenge.cryptographic_challenge);
|
||||
if (d->jdata == NULL) {
|
||||
ret = EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
d->phase = 1; /* SSS_PASSKEY_PHASE_CHALLENGE */
|
||||
d->state = strdup("ipa_otpd state");
|
||||
|
||||
ret = prepare_rad_reply(item);
|
||||
if (ret != 0) {
|
||||
otpd_log_err(ret, "prepare_rad_reply() failed.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
free(challenge);
|
||||
|
||||
otpd_queue_push(&ctx.stdio.responses, item);
|
||||
verto_set_flags(ctx.stdio.writer, VERTO_EV_FLAG_PERSIST |
|
||||
VERTO_EV_FLAG_IO_ERROR |
|
||||
VERTO_EV_FLAG_IO_READ |
|
||||
VERTO_EV_FLAG_IO_WRITE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct child_ctx {
|
||||
int read_from_child;
|
||||
int write_to_child;
|
||||
verto_ev *read_ev;
|
||||
verto_ev *write_ev;
|
||||
verto_ev *child_ev;
|
||||
struct otpd_queue_item *item;
|
||||
};
|
||||
|
||||
static void passkey_on_child_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
(void)vctx; /* Unused */
|
||||
|
||||
/* no input needed */
|
||||
verto_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
static void passkey_on_child_readable(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
(void)vctx; /* Unused */
|
||||
|
||||
/* no output expected */
|
||||
verto_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
static void passkey_on_child_exit(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
(void)vctx; /* Unused */
|
||||
int ret;
|
||||
verto_proc_status st;
|
||||
struct child_ctx *child_ctx = NULL;
|
||||
|
||||
child_ctx = (struct child_ctx *) verto_get_private(ev);
|
||||
if (child_ctx == NULL) {
|
||||
otpd_log_err(EINVAL, "Lost child context");
|
||||
verto_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure ctx.stdio.responses will at least return an error */
|
||||
child_ctx->item->rsp = NULL;
|
||||
child_ctx->item->sent = 0;
|
||||
|
||||
st = verto_get_proc_status(ev);
|
||||
|
||||
if (!WIFEXITED(st)) {
|
||||
otpd_log_err(0, "Child didn't exit normally.");
|
||||
verto_del(ev);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* The krad req might not be available at this stage anymore, so
|
||||
* otpd_log_err() is used. */
|
||||
otpd_log_err(0, "Child finished with status [%d].", WEXITSTATUS(st));
|
||||
|
||||
verto_del(ev);
|
||||
|
||||
if (WEXITSTATUS(st) != 0) {
|
||||
/* verification failed */
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = krad_packet_new_response(ctx.kctx, SECRET,
|
||||
krad_code_name2num("Access-Accept"), NULL,
|
||||
child_ctx->item->req, &child_ctx->item->rsp);
|
||||
if (ret != 0) {
|
||||
otpd_log_err(ret, "Failed to create radius response");
|
||||
child_ctx->item->rsp = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
otpd_queue_push(&ctx.stdio.responses, child_ctx->item);
|
||||
verto_set_flags(ctx.stdio.writer, VERTO_EV_FLAG_PERSIST |
|
||||
VERTO_EV_FLAG_IO_ERROR |
|
||||
VERTO_EV_FLAG_IO_READ |
|
||||
VERTO_EV_FLAG_IO_WRITE);
|
||||
}
|
||||
|
||||
static void free_child_ctx(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
(void)vctx; /* Unused */
|
||||
struct child_ctx *child_ctx;
|
||||
|
||||
child_ctx = verto_get_private(ev);
|
||||
|
||||
free(child_ctx);
|
||||
}
|
||||
|
||||
static int set_fd_nonblocking(int fd)
|
||||
{
|
||||
int flags;
|
||||
int ret;
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags == -1) {
|
||||
ret = errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
ret = errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef PASSKEY_CHILD_PATH
|
||||
#define PASSKEY_CHILD_PATH "/usr/libexec/sssd/passkey_child"
|
||||
#endif
|
||||
|
||||
static int do_passkey_response(struct otpd_queue_item *item)
|
||||
{
|
||||
int ret;
|
||||
pid_t child_pid;
|
||||
int pipefd_to_child[2] = { -1, -1};
|
||||
int pipefd_from_child[2] = { -1, -1};
|
||||
/* Up to 50 arguments to the helper supported. The amount of arguments
|
||||
* is controlled inside this function. Right now max used is below 20 */
|
||||
char *args[50] = {NULL};
|
||||
size_t args_idx = 0;
|
||||
struct child_ctx *child_ctx;
|
||||
char *pk = NULL;
|
||||
|
||||
child_ctx = calloc(sizeof(struct child_ctx), 1);
|
||||
if (child_ctx == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
child_ctx->item = item;
|
||||
|
||||
pk = ipa_passkey_get_public_key(item->user.ipaPassKey,
|
||||
item->passkey->data_in->data.response.credential_id);
|
||||
if (pk == NULL) {
|
||||
ret = EINVAL;
|
||||
otpd_log_err(ret, "No matching public key found for [%s]",
|
||||
item->passkey->data_in->data.response.credential_id);
|
||||
goto done;
|
||||
}
|
||||
|
||||
args[args_idx++] = PASSKEY_CHILD_PATH;
|
||||
args[args_idx++] = "--verify-assert";
|
||||
args[args_idx++] = "--domain";
|
||||
args[args_idx++] = item->passkey->domain;
|
||||
args[args_idx++] = "--key-handle";
|
||||
args[args_idx++] = item->passkey->data_in->data.response.credential_id;
|
||||
args[args_idx++] = "--public-key";
|
||||
args[args_idx++] = pk;
|
||||
args[args_idx++] = "--cryptographic-challenge";
|
||||
args[args_idx++] = item->passkey->data_in->data.response.cryptographic_challenge;
|
||||
args[args_idx++] = "--auth-data";
|
||||
args[args_idx++] = item->passkey->data_in->data.response.authenticator_data;
|
||||
args[args_idx++] = "--signature";
|
||||
args[args_idx++] = item->passkey->data_in->data.response.assertion_signature;
|
||||
if (item->passkey->ipapasskeyDebugLevelStr != NULL) {
|
||||
args[args_idx++] = "--debug-level";
|
||||
args[args_idx++] = item->passkey->ipapasskeyDebugLevelStr;
|
||||
}
|
||||
if (item->passkey->ipapasskeyDebugFido2) {
|
||||
args[args_idx++] = "--debug-libfido2";
|
||||
}
|
||||
|
||||
ret = pipe(pipefd_from_child);
|
||||
if (ret == -1) {
|
||||
ret = errno;
|
||||
goto done;
|
||||
}
|
||||
ret = pipe(pipefd_to_child);
|
||||
if (ret == -1) {
|
||||
ret = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
child_pid = fork();
|
||||
|
||||
if (child_pid == 0) { /* child */
|
||||
close(pipefd_to_child[1]);
|
||||
ret = dup2(pipefd_to_child[0], STDIN_FILENO);
|
||||
if (ret == -1) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(pipefd_from_child[0]);
|
||||
ret = dup2(pipefd_from_child[1], STDOUT_FILENO);
|
||||
if (ret == -1) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
execv(args[0], args);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (child_pid > 0) { /* parent */
|
||||
close(pipefd_to_child[0]);
|
||||
set_fd_nonblocking(pipefd_to_child[1]);
|
||||
child_ctx->write_to_child = pipefd_to_child[1];
|
||||
|
||||
close(pipefd_from_child[1]);
|
||||
set_fd_nonblocking(pipefd_from_child[0]);
|
||||
child_ctx->read_from_child = pipefd_from_child[0];
|
||||
|
||||
child_ctx->write_ev = verto_add_io(ctx.vctx, VERTO_EV_FLAG_PERSIST |
|
||||
VERTO_EV_FLAG_IO_CLOSE_FD |
|
||||
VERTO_EV_FLAG_IO_ERROR |
|
||||
VERTO_EV_FLAG_IO_WRITE,
|
||||
passkey_on_child_writable,
|
||||
child_ctx->write_to_child);
|
||||
if (child_ctx->write_ev == NULL) {
|
||||
ret = ENOMEM;
|
||||
otpd_log_err(ret, "Unable to initialize passkey writer event");
|
||||
goto done;
|
||||
}
|
||||
verto_set_private(child_ctx->write_ev, child_ctx, NULL);
|
||||
|
||||
child_ctx->read_ev = verto_add_io(ctx.vctx, VERTO_EV_FLAG_PERSIST |
|
||||
VERTO_EV_FLAG_IO_CLOSE_FD |
|
||||
VERTO_EV_FLAG_IO_ERROR |
|
||||
VERTO_EV_FLAG_IO_READ,
|
||||
passkey_on_child_readable,
|
||||
child_ctx->read_from_child);
|
||||
if (child_ctx->read_ev == NULL) {
|
||||
ret = ENOMEM;
|
||||
otpd_log_err(ret, "Unable to initialize passkey reader event");
|
||||
goto done;
|
||||
}
|
||||
verto_set_private(child_ctx->read_ev, child_ctx, NULL);
|
||||
|
||||
child_ctx->child_ev = verto_add_child(ctx.vctx, VERTO_EV_FLAG_NONE,
|
||||
passkey_on_child_exit, child_pid);
|
||||
verto_set_private(child_ctx->child_ev, child_ctx, free_child_ctx);
|
||||
|
||||
} else { /* error */
|
||||
ret = errno;
|
||||
otpd_log_err(ret, "Failed to fork passkey_child");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
if (ret != 0) {
|
||||
free(child_ctx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_passkey(struct otpd_queue_item *item)
|
||||
{
|
||||
if (item == NULL || item->passkey == NULL
|
||||
|| item->passkey->data_in == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
switch (item->passkey->data_in->phase) {
|
||||
case 0: /* SSS_PASSKEY_PHASE_INIT */
|
||||
return do_passkey_challenge(item);
|
||||
case 2: /* SSS_PASSKEY_PHASE_REPLY */
|
||||
return do_passkey_response(item);
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,16 +36,6 @@
|
||||
#define DEFAULT_TIMEOUT 15
|
||||
#define DEFAULT_RETRIES 3
|
||||
|
||||
/* To read passkey configuration and attributes from a different server than
|
||||
* FreeIPA you might have to the following two defines of the search filter
|
||||
* for the global configuration data and the attribute name where if passkey
|
||||
* information is stored in the user entry. Additionally otpd_parse_passkey()
|
||||
* might need some updates depending on how the global configuration is stored
|
||||
* in the configuration objects.
|
||||
*/
|
||||
#define PASSKEY_CONFIG_FILTER "(|(objectclass=ipapasskeyconfigobject)(&(objectclass=domain)(objectclass=domainRelatedObject)))"
|
||||
#define PASSKEY_USER_ATTR "ipapasskey"
|
||||
|
||||
static char *user[] = {
|
||||
"uid",
|
||||
"ipatokenRadiusUserName",
|
||||
@@ -53,7 +43,6 @@ static char *user[] = {
|
||||
"ipaidpSub",
|
||||
"ipaidpConfigLink",
|
||||
"ipauserauthtype",
|
||||
PASSKEY_USER_ATTR,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -80,7 +69,7 @@ static char *idp[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
bool auth_type_is(char **auth_types, const char *check)
|
||||
static bool auth_type_is(char **auth_types, const char *check)
|
||||
{
|
||||
size_t c;
|
||||
|
||||
@@ -133,14 +122,6 @@ static void on_query_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
NULL, NULL, 1, &item->msgid);
|
||||
free(filter);
|
||||
|
||||
} else if (item->get_passkey_config) {
|
||||
otpd_log_req(item->req, "passkey config query start:");
|
||||
item->ldap_query = LDAP_QUERY_PASSKEY;
|
||||
|
||||
i = ldap_search_ext(verto_get_private(ev), ctx.query.base,
|
||||
LDAP_SCOPE_SUBTREE, PASSKEY_CONFIG_FILTER, NULL, 0, NULL,
|
||||
NULL, NULL, 0, &item->msgid);
|
||||
|
||||
} else if (auth_type_is(item->user.ipauserauthtypes, "idp")) {
|
||||
otpd_log_req(item->req, "idp query start: %s",
|
||||
item->user.ipaidpConfigLink);
|
||||
@@ -302,9 +283,6 @@ static void on_query_readable(verto_ctx *vctx, verto_ev *ev)
|
||||
case LDAP_QUERY_IDP:
|
||||
err = otpd_parse_idp(ldp, entry, item);
|
||||
break;
|
||||
case LDAP_QUERY_PASSKEY:
|
||||
err = otpd_parse_passkey(ldp, entry, item);
|
||||
break;
|
||||
default:
|
||||
ldap_msgfree(entry);
|
||||
goto egress;
|
||||
@@ -353,35 +331,10 @@ static void on_query_readable(verto_ctx *vctx, verto_ev *ev)
|
||||
goto egress;
|
||||
}
|
||||
break;
|
||||
case LDAP_QUERY_PASSKEY:
|
||||
otpd_log_req(item->req, "passkey query end: %s",
|
||||
item->error == NULL ? "ok" : item->error);
|
||||
if (item->passkey == NULL) {
|
||||
goto egress;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto egress;
|
||||
}
|
||||
|
||||
/* Check for passkey */
|
||||
if (is_passkey(item)) {
|
||||
if (item->ldap_query == LDAP_QUERY_USER) {
|
||||
item->get_passkey_config = true;
|
||||
|
||||
push = &ctx.query.requests;
|
||||
event = ctx.query.io;
|
||||
goto egress;
|
||||
}
|
||||
|
||||
i = do_passkey(item);
|
||||
if (i != 0) {
|
||||
goto egress;
|
||||
}
|
||||
/* do_passkey will call ctx.stdio.writer, so we can return here */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for oauth2 */
|
||||
oauth2_state = get_oauth2_state(item->ldap_query, item);
|
||||
if (oauth2_state == OAUTH2_GET_ISSUER) {
|
||||
|
||||
@@ -87,9 +87,6 @@ void otpd_queue_item_free(struct otpd_queue_item *item)
|
||||
free(item->error);
|
||||
krad_packet_free(item->req);
|
||||
krad_packet_free(item->rsp);
|
||||
|
||||
free_otpd_queue_item_passkey(item);
|
||||
|
||||
free(item);
|
||||
}
|
||||
|
||||
|
||||
@@ -503,8 +503,8 @@ void test_pack_ber_user_timeout(void **state)
|
||||
oldgetgrgid_r = test_data->ctx->nss_ctx->getgrgid_r;
|
||||
test_data->ctx->nss_ctx->getgrgid_r = getgrgid_r_timeout;
|
||||
|
||||
ret = pack_ber_user(test_data->ctx, RESP_USER_GROUPLIST, TEST_DOMAIN_NAME,
|
||||
"member001@"TEST_DOMAIN_NAME, 12345, 54321,
|
||||
ret = pack_ber_user(test_data->ctx, RESP_USER_GROUPLIST,
|
||||
TEST_DOMAIN_NAME, "member001", 12345, 54321,
|
||||
"gecos", "homedir", "shell", NULL, &resp_val);
|
||||
test_data->ctx->nss_ctx->getgrgid_r = oldgetgrgid_r;
|
||||
assert_int_equal(ret, LDAP_TIMELIMIT_EXCEEDED);
|
||||
@@ -548,17 +548,15 @@ void test_encode(void **state)
|
||||
assert_memory_equal(res_nam, resp_val->bv_val, resp_val->bv_len);
|
||||
ber_bvfree(resp_val);
|
||||
|
||||
ret = pack_ber_user(ctx, RESP_USER, TEST_DOMAIN_NAME,
|
||||
"test@"TEST_DOMAIN_NAME, 12345, 54321, NULL, NULL,
|
||||
NULL, NULL, &resp_val);
|
||||
ret = pack_ber_user(ctx, RESP_USER, TEST_DOMAIN_NAME, "test", 12345, 54321,
|
||||
NULL, NULL, NULL, NULL, &resp_val);
|
||||
assert_int_equal(ret, LDAP_SUCCESS);
|
||||
assert_int_equal(sizeof(res_uid), resp_val->bv_len);
|
||||
assert_memory_equal(res_uid, resp_val->bv_val, resp_val->bv_len);
|
||||
ber_bvfree(resp_val);
|
||||
|
||||
ret = pack_ber_group(RESP_GROUP, TEST_DOMAIN_NAME,
|
||||
"test_group@"TEST_DOMAIN_NAME, 54321, NULL, NULL,
|
||||
&resp_val);
|
||||
ret = pack_ber_group(RESP_GROUP, TEST_DOMAIN_NAME, "test_group", 54321,
|
||||
NULL, NULL, &resp_val);
|
||||
assert_int_equal(ret, LDAP_SUCCESS);
|
||||
assert_int_equal(sizeof(res_gid), resp_val->bv_len);
|
||||
assert_memory_equal(res_gid, resp_val->bv_val, resp_val->bv_len);
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#define _GNU_SOURCE 1 /* for asprintf() */
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
@@ -107,7 +106,7 @@ static int inc_buffer(size_t buf_max, size_t *_buf_len, char **_buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __nss_to_err(enum nss_status errcode)
|
||||
int __nss_to_err(enum nss_status errcode)
|
||||
{
|
||||
switch(errcode) {
|
||||
case NSS_STATUS_SUCCESS:
|
||||
@@ -527,30 +526,6 @@ int pack_ber_sid(const char *sid, struct berval **berval)
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static bool verify_domain(const char *fqdn, const char *domain_name)
|
||||
{
|
||||
const char *pos = strrchr(fqdn, SSSD_DOMAIN_SEPARATOR);
|
||||
if (pos == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (strcasecmp(pos + 1, domain_name) == 0);
|
||||
}
|
||||
|
||||
static char *get_short_name(const char *fqdn, const char *domain_name)
|
||||
{
|
||||
const char *pos = strrchr(fqdn, SSSD_DOMAIN_SEPARATOR);
|
||||
if (pos == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcasecmp(pos + 1, domain_name) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strndup(fqdn, pos - fqdn);
|
||||
}
|
||||
|
||||
int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
||||
enum response_types response_type,
|
||||
const char *domain_name, const char *user_name,
|
||||
@@ -567,13 +542,19 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
||||
char *buf = NULL;
|
||||
struct group grp;
|
||||
size_t c;
|
||||
char *locat;
|
||||
char *short_user_name = NULL;
|
||||
|
||||
short_user_name = get_short_name(user_name, domain_name);
|
||||
if (short_user_name == NULL) {
|
||||
/* domain mismatch */
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
short_user_name = strdup(user_name);
|
||||
if ((locat = strrchr(short_user_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
|
||||
if (strcasecmp(locat+1, domain_name) == 0 ) {
|
||||
locat[0] = '\0';
|
||||
} else {
|
||||
/* The found object is from a different domain than requested,
|
||||
* that means it does not exist in the requested domain */
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ber = ber_alloc_t( LBER_USE_DER );
|
||||
@@ -676,13 +657,19 @@ int pack_ber_group(enum response_types response_type,
|
||||
BerElement *ber = NULL;
|
||||
int ret;
|
||||
size_t c;
|
||||
char *locat;
|
||||
char *short_group_name = NULL;
|
||||
|
||||
short_group_name = get_short_name(group_name, domain_name);
|
||||
if (short_group_name == NULL) {
|
||||
/* domain mismatch */
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
short_group_name = strdup(group_name);
|
||||
if ((locat = strrchr(short_group_name, SSSD_DOMAIN_SEPARATOR)) != NULL) {
|
||||
if (strcasecmp(locat+1, domain_name) == 0 ) {
|
||||
locat[0] = '\0';
|
||||
} else {
|
||||
/* The found object is from a different domain than requested,
|
||||
* that means it does not exist in the requested domain */
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ber = ber_alloc_t( LBER_USE_DER );
|
||||
@@ -748,8 +735,8 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pack_ber_name_list(struct extdom_req *req, char **fq_name_list,
|
||||
struct berval **berval)
|
||||
int pack_ber_name_list(struct extdom_req *req, char **fq_name_list,
|
||||
struct berval **berval)
|
||||
{
|
||||
BerElement *ber = NULL;
|
||||
int ret;
|
||||
@@ -905,10 +892,6 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if (!verify_domain(pwd.pw_name, domain_name)) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyusername_timeout(pwd.pw_name, get_timeout(ctx),
|
||||
@@ -988,10 +971,6 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if (!verify_domain(grp.gr_name, domain_name)) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbygroupname_timeout(grp.gr_name, get_timeout(ctx),
|
||||
@@ -1294,10 +1273,6 @@ static int handle_username_request(struct ipa_extdom_ctx *ctx,
|
||||
ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
||||
switch(ret) {
|
||||
case 0:
|
||||
if (!verify_domain(pwd.pw_name, domain_name)) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyusername_timeout(pwd.pw_name,
|
||||
get_timeout(ctx),
|
||||
@@ -1388,10 +1363,6 @@ static int handle_groupname_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if (!verify_domain(grp.gr_name, domain_name)) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbygroupname_timeout(grp.gr_name, get_timeout(ctx),
|
||||
|
||||
@@ -54,7 +54,7 @@ void *ipa_otp_lasttoken_plugin_id;
|
||||
|
||||
static bool entry_is_token(Slapi_Entry *entry)
|
||||
{
|
||||
char **ocls = NULL;
|
||||
char **ocls;
|
||||
|
||||
ocls = slapi_entry_attr_get_charray(entry, SLAPI_ATTR_OBJECTCLASS);
|
||||
for (size_t i = 0; ocls != NULL && ocls[i] != NULL; i++) {
|
||||
@@ -64,7 +64,6 @@ static bool entry_is_token(Slapi_Entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
slapi_ch_array_free(ocls);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,8 +138,7 @@ static bool is_pwd_enabled(const char *user_dn)
|
||||
static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
|
||||
{
|
||||
Slapi_DN *target_sdn = NULL;
|
||||
char *bind_dn;
|
||||
bool rv = false;
|
||||
const char *bind_dn;
|
||||
|
||||
/* Ignore internal operations. */
|
||||
if (slapi_op_internal(pb))
|
||||
@@ -149,35 +147,23 @@ static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
|
||||
/* Load parameters. */
|
||||
(void) slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
|
||||
(void) slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
|
||||
if (bind_dn == NULL) {
|
||||
LOG_FATAL("bind_dn parameter missing!\n");
|
||||
goto done;
|
||||
}
|
||||
if (target_sdn == NULL) {
|
||||
LOG_FATAL("target_sdn parameter missing!\n");
|
||||
goto done;
|
||||
if (target_sdn == NULL || bind_dn == NULL) {
|
||||
LOG_FATAL("Missing parameters!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry != NULL
|
||||
? !entry_is_token(entry)
|
||||
: !sdn_in_otp_container(target_sdn)) {
|
||||
rv = true;
|
||||
goto done;
|
||||
}
|
||||
: !sdn_in_otp_container(target_sdn))
|
||||
return true;
|
||||
|
||||
if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) {
|
||||
rv = true;
|
||||
goto done;
|
||||
}
|
||||
if (!sdn_is_only_enabled_token(target_sdn, bind_dn))
|
||||
return true;
|
||||
|
||||
if (is_pwd_enabled(bind_dn)) {
|
||||
rv = true;
|
||||
goto done;
|
||||
}
|
||||
if (is_pwd_enabled(bind_dn))
|
||||
return true;
|
||||
|
||||
done:
|
||||
slapi_ch_free_string(&bind_dn);
|
||||
return rv;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr)
|
||||
|
||||
@@ -1433,7 +1433,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
Slapi_DN *target_sdn = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
const char *dn = NULL;
|
||||
ber_tag_t method = 0;
|
||||
int method = 0;
|
||||
bool syncreq;
|
||||
bool otpreq;
|
||||
int ret = 0;
|
||||
@@ -1454,10 +1454,8 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
}
|
||||
|
||||
/* We're only interested in simple authentication. */
|
||||
if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0) {
|
||||
LOG("Not handled (not simple bind or NULL dn/credentials)\n");
|
||||
if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Retrieve the user's entry. */
|
||||
sdn = slapi_sdn_dup(target_sdn);
|
||||
@@ -1515,9 +1513,6 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset rc to make sure errors are reported*/
|
||||
rc = LDAP_INVALID_CREDENTIALS;
|
||||
|
||||
/* Authenticate the user. */
|
||||
ret = ipapwd_authenticate(dn, entry, credentials);
|
||||
if (ret) {
|
||||
|
||||
@@ -398,7 +398,6 @@ static struct otp_token **find(const struct otp_config *cfg, const char *user_dn
|
||||
}
|
||||
|
||||
error:
|
||||
slapi_free_search_results_internal(pb);
|
||||
slapi_pblock_destroy(pb);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _A6Record:
|
||||
|
||||
# A6Record
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A6 DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _AAAARecord:
|
||||
|
||||
# AAAARecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
AAAA DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _AFSDBRecord:
|
||||
|
||||
# AFSDBRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
AFSDB DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _APLRecord:
|
||||
|
||||
# APLRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
APL DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _ARecord:
|
||||
|
||||
# ARecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A DNS record.
|
||||
@@ -1,9 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _AccessTime:
|
||||
|
||||
# AccessTime
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Access time parameter type.
|
||||
|
||||
Accepts values conforming to generalizedTime as defined in RFC 4517 section 3.3.13 without time zone information.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Any:
|
||||
|
||||
# Any
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter capable of holding values of any type. For internal use only.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _BinaryFile:
|
||||
|
||||
# BinaryFile
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Binary file parameter type.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Bool:
|
||||
|
||||
# Bool
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for boolean values (stored in the ``bool`` type).
|
||||
@@ -1,11 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Bytes:
|
||||
|
||||
# Bytes
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for binary data (stored in the ``str`` type).
|
||||
This class is named *Bytes* instead of *Str* so it's aligned with the
|
||||
Python v3 ``(str, unicode) => (bytes, str)`` clean-up.
|
||||
See: http://docs.python.org/3.0/whatsnew/3.0.html
|
||||
Also see the `Str` parameter.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _BytesEnum:
|
||||
|
||||
# BytesEnum
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Enumerable for binary data (stored in the ``str`` type).
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _CERTRecord:
|
||||
|
||||
# CERTRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
CERT DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _CNAMERecord:
|
||||
|
||||
# CNAMERecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
CNAME DNS record.
|
||||
@@ -1,5 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Certificate:
|
||||
|
||||
# Certificate
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
@@ -1,5 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _CertificateSigningRequest:
|
||||
|
||||
# CertificateSigningRequest
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DHCIDRecord:
|
||||
|
||||
# DHCIDRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DHCID DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DLVRecord:
|
||||
|
||||
# DLVRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DLV DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DNAMERecord:
|
||||
|
||||
# DNAMERecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DNAME DNS record.
|
||||
@@ -1,9 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DNOrURL:
|
||||
|
||||
# DNOrURL
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DN parameter that allows, and strips, a "ldap:///" prefix on input.
|
||||
|
||||
Used for ``subtree`` to maintain backward compatibility.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DNParam:
|
||||
|
||||
# DNParam
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
LDAP DN.
|
||||
@@ -1,10 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DNSNameParam:
|
||||
|
||||
# DNSNameParam
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Domain name parameter type.
|
||||
|
||||
* `only_absolute`: a domain name has to be absolute (makes it absolute from unicode input)
|
||||
* `only_relative`: a domain name has to be relative
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DNSRecord:
|
||||
|
||||
# DNSRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Base class for DNS records, subclass of `Str`.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DSRecord:
|
||||
|
||||
# DSRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DS DNS record.
|
||||
@@ -1,11 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Data:
|
||||
|
||||
# Data
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Base class for the `Bytes` and `Str` parameters.
|
||||
|
||||
Previously `Str` was as subclass of `Bytes`. Now the common functionality
|
||||
has been split into this base class so that ``isinstance(foo, Bytes)`` wont
|
||||
be ``True`` when ``foo`` is actually an `Str` instance (which is confusing).
|
||||
@@ -1,19 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _DateTime:
|
||||
|
||||
# DateTime
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
DateTime parameter type.
|
||||
|
||||
Accepts LDAP Generalized time without in the following format:
|
||||
'%Y%m%d%H%M%SZ'
|
||||
|
||||
Accepts subset of values defined by ISO 8601:
|
||||
'%Y-%m-%dT%H:%M:%SZ'
|
||||
'%Y-%m-%dT%H:%MZ'
|
||||
'%Y-%m-%dZ'
|
||||
|
||||
Also accepts above formats using ' ' (space) as a separator instead of 'T'.
|
||||
|
||||
Refer to the `man strftime` for the explanations for the %Y,%m,%d,%H.%M,%S.
|
||||
@@ -1,12 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Decimal:
|
||||
|
||||
# Decimal
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for floating-point values (stored in the ``Decimal`` type).
|
||||
|
||||
Python Decimal type helps overcome problems tied to plain "float" type,
|
||||
e.g. problem with representation or value comparison. In order to safely
|
||||
transfer the value over RPC libraries, it is being converted to string
|
||||
which is then converted back to Decimal number.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Dict:
|
||||
|
||||
# Dict
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for dictionary.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Enum:
|
||||
|
||||
# Enum
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Base class for parameters with enumerable values.
|
||||
@@ -1,9 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _File:
|
||||
|
||||
# File
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Text file parameter type.
|
||||
|
||||
Accepts file names and loads their content into the parameter value.
|
||||
@@ -1,37 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Flag:
|
||||
|
||||
# Flag
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A boolean parameter that always gets filled in with a default value.
|
||||
|
||||
This `Bool` subclass forces ``autofill=True`` in `Flag.__init__()`. If no
|
||||
default is provided, it also fills in a default value of ``False``.
|
||||
Lastly, unlike the `Bool` class, the default must be either ``True`` or
|
||||
``False`` and cannot be ``None``.
|
||||
|
||||
For example:
|
||||
```
|
||||
>>> flag = Flag('my_flag')
|
||||
>>> (flag.autofill, flag.default)
|
||||
(True, False)
|
||||
```
|
||||
|
||||
To have a default value of ``True``, create your `Flag` intance with
|
||||
``default=True``. For example:
|
||||
|
||||
```
|
||||
>>> flag = Flag('my_flag', default=True)
|
||||
>>> (flag.autofill, flag.default)
|
||||
(True, True)
|
||||
```
|
||||
|
||||
Also note that creating a `Flag` instance with ``autofill=False`` will have
|
||||
no effect. For example:
|
||||
|
||||
```
|
||||
>>> flag = Flag('my_flag', autofill=False)
|
||||
>>> flag.autofill
|
||||
True
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _ForwardRecord:
|
||||
|
||||
# ForwardRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Forward DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _HINFORecord:
|
||||
|
||||
# HINFORecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
HINFO DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _HIPRecord:
|
||||
|
||||
# HIPRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
HIP DNS record.
|
||||
@@ -1,11 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _HostPassword:
|
||||
|
||||
# HostPassword
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A data type for host passwords to not log password values.
|
||||
|
||||
The `Password` type cannot be used because it disallows
|
||||
setting a password on the command-line which would break
|
||||
backwards compatibility.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _IA5Str:
|
||||
|
||||
# IA5Str
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
An IA5String per RFC 4517.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _IPSECKEYRecord:
|
||||
|
||||
# IPSECKEYRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
IPSECKEY DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Int:
|
||||
|
||||
# Int
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for integer values (stored in the ``int`` type).
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _IntEnum:
|
||||
|
||||
# IntEnum
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Enumerable for integer data (stored in the ``int`` type).
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _KEYRecord:
|
||||
|
||||
# KEYRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
KEY DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _KXRecord:
|
||||
|
||||
# KXRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
KX DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _LOCRecord:
|
||||
|
||||
# LOCRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
LOC DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _MDRecord:
|
||||
|
||||
# MDRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
MD DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _MINFORecord:
|
||||
|
||||
# MINFORecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
MINFO DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _MXRecord:
|
||||
|
||||
# MXRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
MX DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _NAPTRRecord:
|
||||
|
||||
# NAPTRRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
NAPTR DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _NSECRecord:
|
||||
|
||||
# NSECRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
NSEC DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _NSRecord:
|
||||
|
||||
# NSRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
NS DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _NXTRecord:
|
||||
|
||||
# NXTRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
NXT DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Number:
|
||||
|
||||
# Number
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Base class for the `Int` and `Decimal` parameters.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _OTPTokenKey:
|
||||
|
||||
# OTPTokenKey
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A binary password type specified in base32.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _PTRRecord:
|
||||
|
||||
# PTRRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
PTR DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Password:
|
||||
|
||||
# Password
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
A parameter for passwords (stored in the ``unicode`` type).
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _Principal:
|
||||
|
||||
# Principal
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
Kerberos principal name.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _RPRecord:
|
||||
|
||||
# RPRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
RP DNS record.
|
||||
@@ -1,7 +0,0 @@
|
||||
[//]: # (THE CONTENT BELOW IS GENERATED. DO NOT EDIT.)
|
||||
.. _RRSIGRecord:
|
||||
|
||||
# RRSIGRecord
|
||||
[//]: # (ADD YOUR NOTES BELOW. THESE WILL BE PICKED EVERY TIME THE DOCS ARE REGENERATED. //end)
|
||||
|
||||
RRSIG DNS record.
|
||||
Loaded 100 of 940 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user