3 Commits
Author SHA1 Message Date
zpericic 63c4b387a6 ipaserver: Move /etc/httpd/ipa to /etc/ipa/httpd 2022-08-17 08:35:52 +02:00
zpericic e3fa19dfde ipaserver: Use apache VirtualHost for IPA UI 2022-08-17 08:35:52 +02:00
Antonio Torres 082ec006f4 Become IPA 4.10.0 2022-06-29 16:52:09 +02:00
967 changed files with 40300 additions and 56644 deletions

No files matched your search

-1
View File
@@ -155,7 +155,6 @@ install/custodia/ipa-custodia-dmldap
install/custodia/ipa-custodia-pki-tomcat
install/custodia/ipa-custodia-pki-tomcat-wrapped
install/custodia/ipa-custodia-ra-agent
install/oddjob/org.freeipa.server.config-enable-sid
install/oddjob/org.freeipa.server.trust-enable-agent
install/oddjob/com.redhat.idm.trust-fetch-domains
install/oddjob/etc/oddjobd.conf.d/ipa-server.conf
+3 -2
View File
@@ -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
+3 -15
View File
@@ -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
+20 -203
View File
@@ -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
+1 -1
View File
@@ -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:
-22
View File
@@ -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
+4 -11
View File
@@ -23,8 +23,6 @@ PYTHON_SCRIPT_SUBDIRS = \
$(top_builddir)/install/tools \
$(NULL)
PRCI_DEFINITIONS_DIR = $(top_srcdir)/ipatests/prci_definitions
AZURE_PYTHON_SCRIPT_SUBDIR = $(top_builddir)/ipatests/azure
IPA_PLACEHOLDERS = freeipa ipa ipaserver ipatests
@@ -244,7 +242,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 +272,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 \
@@ -338,8 +336,6 @@ endif # WITH_RPMLINT
# There are Jinja yaml templates, which differ from reqular ones. These
# files should be placed on skip list (YAML_TEMPLATE_FILES), otherwise
# safe_load fails.
# Also check PRCI definitions yaml files jobs format and content with
# prci_checker script
.PHONY: yamllint
yamllint:
YAML_TEMPLATE_FILES="\
@@ -361,10 +357,7 @@ yamllint:
echo $${YAML}; \
$(PYTHON) -c "import yaml; f = open('$${YAML}'); yaml.safe_load(f); f.close()" || { echo Your YAML file: $${YAML} has a wrong syntax or this is a Jinja template. In the latter clause, consider to add your YAML file to the YAML_TEMPLATE_FILES list in Makefile.am.; exit 1; } \
done; \
echo -e "\nCheck PRCI definitions";
@echo "-----------"
$(PYTHON) $(PRCI_DEFINITIONS_DIR)/prci_checker.py -d $(PRCI_DEFINITIONS_DIR) -s $(PRCI_DEFINITIONS_DIR)/prci_jobs_spec.yaml;
@echo "-----------"
echo "-----------"
# Build & lint documentation.
#
@@ -396,7 +389,7 @@ pylint: $(GENERATED_PYTHON_FILES) ipasetup.py python_scripts
-name '*~' -o \
-name '*.py' -print -o \
-type f -exec grep -qsm1 '^#!.*\bpython' '{}' \; -print`; \
FILES=`echo -e "$${FILES}\n$(AZURE_PYTHON_SCRIPT_SUBDIR)\n$(PRCI_DEFINITIONS_DIR)"`; \
FILES=`echo -e "$${FILES}\n$(AZURE_PYTHON_SCRIPT_SUBDIR)"`; \
echo -e "Pylint on $(PYTHON) is running over files:\n$${FILES}\nPlease wait ...\n"; \
$(PYTHON) -m pylint --version; \
PYTHONPATH=$(top_srcdir) $(PYTHON) -m pylint \
+4 -10
View File
@@ -20,7 +20,7 @@
# -> "1.0.0" #
########################################################
define(IPA_VERSION_MAJOR, 4)
define(IPA_VERSION_MINOR, 12)
define(IPA_VERSION_MINOR, 10)
define(IPA_VERSION_RELEASE, 0)
########################################################
@@ -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, yes)
define(IPA_VERSION_IS_GIT_SNAPSHOT, no)
########################################################
# 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
View File
@@ -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);
-3
View File
@@ -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
-3
View File
@@ -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
+1 -23
View File
@@ -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):
-2
View File
@@ -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
-4
View File
@@ -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
-1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
#
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
#
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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);
+3 -21
View File
@@ -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
+1 -55
View File
@@ -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);
+8 -28
View File
@@ -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;
}
}
+2 -65
View File
@@ -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,
+33 -120
View File
@@ -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;
}
-9
View File
@@ -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
View File
@@ -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]);
}
}
+13 -13
View File
@@ -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);
+2 -74
View File
@@ -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;
}
-104
View File
@@ -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;
}
+32 -317
View File
@@ -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 {
+7 -7
View File
@@ -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) {
+2 -2
View File
@@ -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' \
-32
View File
@@ -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);
+1 -1
View File
@@ -7,4 +7,4 @@ EnvironmentFile=@sysconfdir@/ipa/default.conf
ExecStart=@libexecdir@/ipa/ipa-otpd $ldap_uri
StandardInput=socket
StandardOutput=socket
StandardError=journal
StandardError=syslog
+6 -12
View File
@@ -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 };
-74
View File
@@ -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 */
+81 -8
View File
@@ -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) {
+5 -10
View File
@@ -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)
-824
View File
@@ -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;
}
}
+1 -48
View File
@@ -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) {
-3
View File
@@ -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),
@@ -359,8 +359,7 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb)
Slapi_ValueSet *values = NULL;
long grace_limit = 0;
int grace_user_time;
char *tmpstr = NULL;
time_t pwd_expiration;
char *pwd_expiration = NULL;
int pwresponse_requested = 0;
Slapi_PBlock *pbtm = NULL;
Slapi_Mods *smods = NULL;
@@ -415,17 +414,12 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb)
}
slapi_value_free(&objectclass);
tmpstr = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration");
if (tmpstr == NULL) {
pwd_expiration = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration");
if (pwd_expiration == NULL) {
/* No expiration means nothing to do */
LOG_TRACE("No krbPasswordExpiration for %s, nothing to do\n", dn);
goto done;
}
pwd_expiration = ipapwd_gentime_to_time_t(tmpstr);
if (pwd_expiration > time(NULL)) {
/* Not expired, nothing to see here */
goto done;
}
ldrc = ipagraceperiod_getpolicy(target_entry, &policy_entry,
&values, &actual_type_name,
@@ -479,7 +473,7 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb)
if (pwresponse_requested) {
slapi_pwpolicy_make_response_control(pb, -1, grace_limit - grace_user_time , -1);
}
} else if (grace_user_time >= grace_limit) {
} else if ((grace_limit > 0) && (grace_user_time >= grace_limit)) {
LOG_TRACE("%s password is expired and out of grace limit\n", dn);
errstr = "Password is expired.\n";
ret = LDAP_INVALID_CREDENTIALS;
@@ -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 -2
View File
@@ -35,5 +35,4 @@ distclean: clean
venv:
$(PYTHON) -m venv $(VENVDIR)
$(VENVDIR)/bin/python3 -m pip install -U pip setuptools
$(VENVDIR)/bin/python3 -m pip install -U -r ./requirements.txt \
-c constraints.txt
$(VENVDIR)/bin/python3 -m pip install -U -r ./requirements.txt
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-9
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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).
-11
View File
@@ -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.
-7
View File
@@ -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).
-7
View File
@@ -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.
-7
View File
@@ -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.
-5
View File
@@ -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)
-5
View File
@@ -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)
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-9
View File
@@ -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.
-7
View File
@@ -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.
-10
View File
@@ -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
-7
View File
@@ -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`.
-7
View File
@@ -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.
-11
View File
@@ -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).
-19
View File
@@ -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.
-12
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-9
View File
@@ -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.
-37
View File
@@ -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
```
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-11
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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).
-7
View File
@@ -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).
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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.
-7
View File
@@ -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).
Loaded 100 of 967 files, more files were not shown because too many files have changed in this diff. Show more