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
1096 changed files with 62096 additions and 85982 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
+1 -1
View File
@@ -120,7 +120,7 @@ extraction:
- lxml
- gssapi
- netaddr
- ifaddr
- netifaces
- polib
- requests
- python-augeas
+3 -2
View File
@@ -10,5 +10,6 @@ ipaserver == @VERSION@
ipatests == @VERSION@
# keep pylint version in sync with current Fedora release
# F39 has 3.0.25
pylint ~= 3.0.2
# F36 has 2.12.2
# https://pagure.io/freeipa/issue/8818 added pylint 2.8 support
pylint ~= 2.12.2
+5 -25
View File
@@ -29,7 +29,7 @@ aci: (targetfilter = "(objectclass=ipaca)")(version 3.0;acl "permission:System:
dn: cn=cas,cn=ca,dc=ipa,dc=example
aci: (targetattr = "cn || description")(targetfilter = "(objectclass=ipaca)")(version 3.0;acl "permission:System: Modify CA";allow (write) groupdn = "ldap:///cn=System: Modify CA,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=cas,cn=ca,dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || description || entryusn || ipacahsmconfiguration || ipacaid || ipacaissuerdn || ipacarandomserialnumberversion || ipacasubjectdn || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaca)")(version 3.0;acl "permission:System: Read CAs";allow (compare,read,search) userdn = "ldap:///all";)
aci: (targetattr = "cn || createtimestamp || description || entryusn || ipacaid || ipacaissuerdn || ipacarandomserialnumberversion || ipacasubjectdn || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaca)")(version 3.0;acl "permission:System: Read CAs";allow (compare,read,search) userdn = "ldap:///all";)
dn: cn=caacls,cn=ca,dc=ipa,dc=example
aci: (targetfilter = "(objectclass=ipacaacl)")(version 3.0;acl "permission:System: Add CA ACL";allow (add) groupdn = "ldap:///cn=System: Add CA ACL,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=caacls,cn=ca,dc=ipa,dc=example
@@ -147,14 +147,12 @@ aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=ipahost)")(ve
dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "userpassword")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Enrollment Password";allow (write) groupdn = "ldap:///cn=System: Manage Host Enrollment Password,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "ipaprotectedoperation;write_keys || krblastpwdchange || krbprincipalkey")(targetfilter = "(&(!(memberOf=cn=ipaservers,cn=hostgroups,cn=accounts,dc=ipa,dc=example))(objectclass=ipahost))")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(&(!(memberOf=cn=ipaservers,cn=hostgroups,cn=accounts,dc=ipa,dc=example))(objectclass=ipahost))")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=computers,cn=accounts,dc=ipa,dc=example
aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Host Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";)
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
@@ -374,14 +364,6 @@ dn: cn=sudorules,cn=sudo,dc=ipa,dc=example
aci: (targetattr = "cmdcategory || cn || createtimestamp || description || entryusn || externalhost || externaluser || hostcategory || hostmask || ipaenabledflag || ipasudoopt || ipasudorunas || ipasudorunasextgroup || ipasudorunasextuser || ipasudorunasextusergroup || ipasudorunasgroup || ipasudorunasgroupcategory || ipasudorunasusercategory || ipauniqueid || member || memberallowcmd || memberdenycmd || memberhost || memberuser || modifytimestamp || objectclass || sudonotafter || sudonotbefore || sudoorder || usercategory")(targetfilter = "(objectclass=ipasudorule)")(version 3.0;acl "permission:System: Read Sudo Rules";allow (compare,read,search) userdn = "ldap:///all";)
dn: dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || description || entryusn || modifytimestamp || objectclass || ou || sudocommand || sudohost || sudonotafter || sudonotbefore || sudooption || sudoorder || sudorunas || sudorunasgroup || sudorunasuser || sudouser")(target = "ldap:///ou=sudoers,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read Sudoers compat tree";allow (compare,read,search) userdn = "ldap:///anyone";)
dn: cn=topology,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetfilter = "(|(objectclass=iparepltopoconf)(objectclass=iparepltoposegment))")(version 3.0;acl "permission:System: Add Topology Segments";allow (add) groupdn = "ldap:///cn=System: Add Topology Segments,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=topology,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetattr = "iparepltoposegmentdirection || iparepltoposegmentleftnode || iparepltoposegmentrightnode || nsds5replicastripattrs || nsds5replicatedattributelist || nsds5replicatedattributelisttotal")(targetfilter = "(|(objectclass=iparepltopoconf)(objectclass=iparepltoposegment))")(version 3.0;acl "permission:System: Modify Topology Segments";allow (write) groupdn = "ldap:///cn=System: Modify Topology Segments,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=topology,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || entryusn || iparepltopoconfroot || iparepltoposegmentdirection || iparepltoposegmentleftnode || iparepltoposegmentrightnode || iparepltoposegmentstatus || modifytimestamp || nsds5replicastripattrs || nsds5replicatedattributelist || nsds5replicatedattributelisttotal || objectclass")(targetfilter = "(|(objectclass=iparepltopoconf)(objectclass=iparepltoposegment))")(version 3.0;acl "permission:System: Read Topology Segments";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Topology Segments,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=topology,cn=ipa,cn=etc,dc=ipa,dc=example
aci: (targetfilter = "(|(objectclass=iparepltopoconf)(objectclass=iparepltoposegment))")(version 3.0;acl "permission:System: Remove Topology Segments";allow (delete) groupdn = "ldap:///cn=System: Remove Topology Segments,cn=permissions,cn=pbac,dc=ipa,dc=example";)
dn: cn=trusts,dc=ipa,dc=example
aci: (targetattr = "cn || createtimestamp || entryusn || ipantadditionalsuffixes || ipantflatname || ipantsecurityidentifier || ipantsidblacklistincoming || ipantsidblacklistoutgoing || ipanttrustdirection || ipanttrusteddomainsid || ipanttrustpartner || modifytimestamp || objectclass")(version 3.0;acl "permission:System: Read Trust Information";allow (compare,read,search) userdn = "ldap:///all";)
dn: cn=trusts,dc=ipa,dc=example
@@ -395,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";)
@@ -413,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
+22 -206
View File
@@ -451,9 +451,8 @@ output: Entry('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
command: batch/1
args: 1,2,2
args: 1,1,2
arg: Dict('methods*')
option: Str('keeponly*')
option: Str('version?')
output: Output('count', type=[<type 'int'>])
output: Output('results', type=[<type 'list'>, <type 'tuple'>])
@@ -1083,7 +1082,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('ca_renewal_master_server?', autofill=False)
option: Str('delattr*', cli_name='delattr')
option: Flag('enable_sid?', autofill=True, default=False)
option: StrEnum('ipaconfigstring*', autofill=False, cli_name='ipaconfigstring', values=[u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs', u'EnforceLDAPOTP'])
option: StrEnum('ipaconfigstring*', autofill=False, cli_name='ipaconfigstring', values=[u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs'])
option: Str('ipadefaultemaildomain?', autofill=False, cli_name='emaildomain')
option: Str('ipadefaultloginshell?', autofill=False, cli_name='defaultshell')
option: Str('ipadefaultprimarygroup?', autofill=False, cli_name='defaultgroup')
@@ -1100,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')
@@ -1799,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?')
@@ -1863,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)
@@ -1900,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')
@@ -2479,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)
@@ -2508,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')
@@ -2541,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')
@@ -2599,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')
@@ -2654,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')
@@ -2694,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)
@@ -2725,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')
@@ -3378,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)
@@ -3386,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')
@@ -3822,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')
@@ -4151,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?')
@@ -4759,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')
@@ -4780,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')
@@ -4829,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')
@@ -4886,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')
@@ -4934,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)
@@ -4958,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)
@@ -4980,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')
@@ -5219,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')
@@ -5285,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')
@@ -5345,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')
@@ -5411,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')
@@ -5479,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')
@@ -6426,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')
@@ -6494,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')
@@ -6569,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')
@@ -6638,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')
@@ -6707,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')
@@ -6836,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')
@@ -6936,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')
@@ -7261,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
@@ -7364,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
@@ -7448,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
@@ -7492,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
@@ -7500,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
@@ -7589,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
@@ -7599,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:
-26
View File
@@ -4,7 +4,6 @@ The following people have contributed to the FreeIPA project.
(Listed in alphabetical order within category)
Developers:
007hacky007
Abhijeet
Abhijeet Kasurde
Adam Misnyovszki
@@ -17,10 +16,8 @@ Developers:
Alexander Bokovoy
Alexander Koksharov
Alexander Scheel
Alexandra Nikandrova
Alexandre Mulatinho
Alexey Slaykovsky
Alexey Tikhonov
Amit Kumar
Ana Krivokapić
Andika Triwidada
@@ -36,7 +33,6 @@ Developers:
Brian J. Murrell
Brian Turek
Carl George
Carla Martinez
Cédric Jeanneret
Changmin Teng
Chris Kelley
@@ -46,7 +42,6 @@ Developers:
David Kreitschmann
David Kupka
David O'Brien
David Pascual
David Spångberg
Diane Trout
Dinesh Prasanth M K
@@ -56,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
@@ -77,7 +69,6 @@ Developers:
Hela Basa
Ian Kumlien
Ian Pilcher
Iker Pedrosa
Isaac Boukris
Jakub Hrozek
James Groffen
@@ -86,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
@@ -114,7 +102,6 @@ Developers:
Lars Sjostrom
Lenka Doudova
Lenka Ryznarova
Lenz Grimmer
Lewis Eason
Lubomír Rintel
Ludwig Krispenz
@@ -128,10 +115,8 @@ Developers:
Martin Bašti
Martin Košek
Martin Nagy
Masahiro Matsuya
Matt Rogers
Matthew Davis
mbhalodi
Michael Simacek
Michal Polovka
Michal Reznik
@@ -147,7 +132,6 @@ Developers:
ndehadra
Nick Hatch
Nikhil Dehadrai
Nikola Knazekova
Nikolai Kondrashov
Niranjan Mallapadi
Niranjan MR
@@ -175,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
@@ -204,33 +184,27 @@ 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
Weblate
Weblate Translation Memory
William Brown
William Jon McCann
Xiao-Long Chen
Yuri Chornoivan
Zdenek Pytela
zdover
zoedong
김인수
Documentation:
Gabe Alford
+4 -13
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
@@ -36,8 +34,6 @@ SUBDIRS = \
po \
pypi \
selinux \
selinux/nfast \
selinux/luna \
$(PYTHON_SUBDIRS) \
$(SERVER_SUBDIRS) \
$(NULL)
@@ -246,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 \
@@ -276,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 \
@@ -340,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="\
@@ -363,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.
#
@@ -398,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,8 +20,8 @@
# -> "1.0.0" #
########################################################
define(IPA_VERSION_MAJOR, 4)
define(IPA_VERSION_MINOR, 12)
define(IPA_VERSION_RELEASE, 2)
define(IPA_VERSION_MINOR, 10)
define(IPA_VERSION_RELEASE, 0)
########################################################
# For 'pre' releases the version will be #
@@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000)
# #
########################################################
define(IPA_API_VERSION_MAJOR, 2)
# Last change: add keeponly option to batch command
define(IPA_API_VERSION_MINOR, 254)
# 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'
-1
View File
@@ -266,7 +266,6 @@ static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *s
error_message(krberr), krberr);
in->result = NULL;
in->len = 0;
krb5_free_context(krbctx);
ret = LDAP_LOCAL_ERROR;
break;
}
+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);
+1 -7
View File
@@ -29,11 +29,6 @@
#include "ipa-client-common.h"
#include "config.h"
int remove_principal(krb5_context context, krb5_keytab ktid,
const char *principal, int debug);
int remove_realm(krb5_context context, krb5_keytab ktid,
const char *realm, int debug);
#define KERBEROS_ERROR 1
#define OOM_ERROR 2
#define KEYTAB_ERROR 3
@@ -176,8 +171,7 @@ remove_realm(krb5_context context, krb5_keytab ktid, const char *realm, int debu
}
done:
krb5_kt_end_seq_get(context, ktid, &kt_cursor);
krb5_free_unparsed_name(context, entry_princ_s);
return rval;
}
-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):
+1 -54
View File
@@ -132,64 +132,12 @@ c \- compare\p
W \- self\-write\p
O \- self\-obliterate
.SH "AUDIT AND LOGGING"
The IPA API logs audit messages to systemd journal about each command executed
through IPA API on the IPA server. These messages can be found by grepping
systemd journal with \fBjournalctl -g IPA.API\fR command. The message includes
following information:
May 21 11:31:33 master1.ipa1.test /usr/bin/ipa[247422]: [IPA.API] [autobind]: user_del: SUCCESS [ldap2_140328582446688] {"uid": ["foobar"], "continue": false, "version": "2.253"}
.TP
\fB/usr/bin/ipa[247422]\fR
executable name and PID (`/mod_wsgi` for HTTP end-point)
.TP
\fB[IPA.API]\fR
marker to allow searches with \fBjournalctl -g IPA.API\R
.TP
\fBusername@REALM\fR
authenticated Kerberos principal or \fB[autobind]\fR marker for LDAP-based operations done as root
.TP
\fBuser_del\fR
name of the command executed
.TP
\fBSUCCESS\fR
result of execution: \fBSUCCESS\fR or an exception name
.TP
\fB[ldap2_140328582446688]\fR
LDAP backend connection instance identifier. The identifier will be the same for all
operations performed under the same request. This allows to identify operations
which were executed using the same LDAP connection. For API operations that
didn't result in LDAP access, there will be \fB[no_connection_id]\fR marker.
.TP
\fB{"uid": ["foobar"], "continue": false, "version": "2.253"}\fR
a list of arguments and options passed to the IPA API command, provided in JSON
format. Credentials are filtered out.
.LP
All explicitly requested operations logged. Internal operations, initiated as
part of execution of the explicitly requested IPA API calls, aren't logged. For
HTTP end-point operations will be logged as performed by the '/mod_wsgi'
executable binary. Remaining details can be inspected through the systemd
journal as journald records execution context. See systemd.journal\-fields(7)
for details.
The details of the individual logged messages can be explained with the help of
'\fBjournalctl -x\fR' command, while full set of logged properties can be
retrieved with '\fBjournalctl -o json-pretty\fR'. See journalctl(1) for details
on the systemd journal viewer.
For the sample message above, an explanation could be requested with '\fBjournalctl -x -g ldap2_140328582446688\fR' where LDAP backend connection instance identifier can be used to uniquely fetch that individual message.
.SH "EXAMPLES"
.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
@@ -256,5 +204,4 @@ IPA default configuration file.
ipa\-client\-install(1), ipa\-compat\-manage(1), ipactl(1), ipa\-dns\-install(1),
ipa\-getcert(1), ipa\-getkeytab(1), ipa\-join(1), ipa\-ldap\-updater(1),
ipa\-nis\-manage(1), ipa\-replica\-install(1), ipa\-replica\-manage(1), ipa\-replica\-prepare(1),
ipa\-rmkeytab(1), ipa\-server\-certinstall(2), ipa\-server\-install(1), ipa\-server\-upgrade(1),
systemd.journal\-fields(7), journalctl(1)
ipa\-rmkeytab(1), ipa\-server\-certinstall(2), ipa\-server\-install(1), ipa\-server\-upgrade(1)
-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 -7
View File
@@ -4,13 +4,7 @@ PubkeyAuthentication yes
${ENABLEPROXY}GlobalKnownHostsFile $KNOWNHOSTS
${VERIFYHOSTKEYDNS}VerifyHostKeyDNS yes
# use sss_ssh_knownhosts if available
# assumes that if a user does not have shell (/sbin/nologin),
# this will return nonzero exit code and proxy command will be ignored
${ENABLEKNOWNHOSTS}Match exec true
${ENABLEKNOWNHOSTS} KnownHostsCommand $KNOWNHOSTSCOMMAND %H
# assumes that if a user does not have shell (/sbin/nologin),
# this will return nonzero exit code and proxy command will be ignored
${ENABLEPROXY}Match exec true
${ENABLEPROXY}Match exec true
${ENABLEPROXY} ProxyCommand $KNOWNHOSTSPROXY -p %p %h
-10
View File
@@ -267,13 +267,6 @@ AC_ARG_WITH([systemdtmpfilesdir],
[systemdtmpfilesdir=$($PKG_CONFIG --define-variable=prefix='${prefix}' --variable=tmpfilesdir systemd)])
AC_SUBST([systemdtmpfilesdir])
AC_ARG_WITH([systemdcatalogdir],
AS_HELP_STRING([--with-systemdcatalogdir=DIR],
[Directory for systemd journal catalog files]),
[systemdcatalogdir=$with_systemdcatalogdir],
[systemdcatalogdir=$($PKG_CONFIG --define-variable=prefix='${prefix}' --variable=catalogdir systemd)])
AC_SUBST([systemdcatalogdir])
dnl ---------------------------------------------------------------------------
dnl - Server-only configuration
dnl ---------------------------------------------------------------------------
@@ -467,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])
@@ -695,8 +687,6 @@ AC_CONFIG_FILES([
po/Makefile.in
po/Makefile.hack
selinux/Makefile
selinux/nfast/Makefile
selinux/luna/Makefile
util/Makefile
])
+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
@@ -116,7 +116,7 @@ ipa_kdb_tests_LDADD = \
$(top_builddir)/util/libutil.la \
-lkdb5 \
-lsss_idmap \
-l$(SAMBA_SECURITY_LIBS)\
-lsamba-security-samba4 \
-lsamba-errors \
$(NULL)
+5 -14
View File
@@ -12,7 +12,9 @@ much more easily managed.
The grouping mechanism has been built so that lookup is highly optimized
and is basically reduced to a single search that uses the derefernce
control.
control. Speed is very important in this case because KDC operations
time out very quickly and unless we add a caching layer in ipa-kdb we
must keep the number of searches down to avoid client timeouts.
The grouping mechanism is very simple a groupOfPrincipals object is
introduced, this Auxiliary class have a single optional attribute called
@@ -110,7 +112,8 @@ kinit -kt /etc/httpd/conf/ipa.keytab HTTP/ipaserver.example.com
kvno -U admin HTTP/ipaserver.example.com
# Perform S4U2Proxy
kvno -U admin -P ldap/ipaserver.example.com
kvno -k /etc/httpd/conf/ipa.keytab -U admin -P HTTP/ipaserver.example.com
ldap/ipaserver.example.com
If this works it means you successfully impersonated the admin user with
@@ -122,18 +125,6 @@ modprinc -ok_to_auth_as_delegate HTTP/ipaserver.example.com
Simo.
If IPA is compiled with krb5 1.20 and newer (KDB DAL >= 9), then the
behavior of S4U2Self changes: S4U2Self TGS-REQs produce forwardable
tickets for all requesters, except if the requester principal is set as
the proxy (impersonating service) in at least one `servicedelegation`
rule. In this case, even if the rule has no target, the KDC will
response to S4U2Self requests with a non-forwardable ticket. Hence,
granting the `ok_to_auth_as_delegate` permission to the proxy service
remains the only way for this service to obtain the evidence ticket
required for general constrained delegation requests if this ticket is
not provided by the client.
[1]
Note that here I use the term proxy in a different way than it is used in
the krb interfaces. It may seem a bit confusing but I think people will
+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);
+20 -81
View File
@@ -26,7 +26,6 @@
#include "ipa_kdb.h"
#include "ipa_krb5.h"
#include "ipa_hostname.h"
#include <kadm5/admin.h>
#define IPADB_GLOBAL_CONFIG_CACHE_TIME 60
@@ -50,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);
@@ -195,9 +189,6 @@ done:
return base;
}
/* In this table all _AUTH_PASSWORD entries will be
* expanded to include _AUTH_HARDENED in ipadb_parse_user_auth()
* which means there is no need to explicitly add it here */
static const struct {
const char *name;
enum ipadb_user_auth flag;
@@ -209,20 +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 },
{ }
},
objclass_table[] = {
{ "ipaservice", IPADB_USER_AUTH_PASSWORD },
{ "ipahost", IPADB_USER_AUTH_PASSWORD },
{ }
},
princname_table[] = {
{ KRB5_TGS_NAME, IPADB_USER_AUTH_PASSWORD },
{ KRB5_KDB_M_NAME, IPADB_USER_AUTH_PASSWORD },
{ KADM5_ADMIN_SERVICE, IPADB_USER_AUTH_PASSWORD },
{ KADM5_CHANGEPW_SERVICE, IPADB_USER_AUTH_PASSWORD },
{ KADM5_HIST_PRINCIPAL, IPADB_USER_AUTH_PASSWORD },
{ }
};
@@ -234,48 +211,16 @@ void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
*userauth = IPADB_USER_AUTH_NONE;
vals = ldap_get_values_len(lcontext, le, IPA_USER_AUTH_TYPE);
if (!vals) {
/* if there is no explicit ipaUserAuthType set, use objectclass */
vals = ldap_get_values_len(lcontext, le, "objectclass");
if (!vals)
return;
if (!vals)
return;
for (i = 0; vals[i]; i++) {
for (j = 0; objclass_table[j].name; j++) {
if (strcasecmp(vals[i]->bv_val, objclass_table[j].name) == 0) {
*userauth |= objclass_table[j].flag;
break;
}
for (i = 0; vals[i]; i++) {
for (j = 0; userauth_table[j].name; j++) {
if (strcasecmp(vals[i]->bv_val, userauth_table[j].name) == 0) {
*userauth |= userauth_table[j].flag;
break;
}
}
} else {
for (i = 0; vals[i]; i++) {
for (j = 0; userauth_table[j].name; j++) {
if (strcasecmp(vals[i]->bv_val, userauth_table[j].name) == 0) {
*userauth |= userauth_table[j].flag;
break;
}
}
}
}
/* If neither ipaUserAuthType nor objectClass were definitive,
* check the krbPrincipalName to see if it is krbtgt/ or K/M one */
if (*userauth == IPADB_USER_AUTH_NONE) {
ldap_value_free_len(vals);
vals = ldap_get_values_len(lcontext, le, "krbprincipalname");
if (!vals)
return;
for (i = 0; vals[i]; i++) {
for (j = 0; princname_table[j].name; j++) {
if (strncmp(vals[i]->bv_val, princname_table[j].name,
strlen(princname_table[j].name)) == 0) {
*userauth |= princname_table[j].flag;
break;
}
}
}
}
/* If password auth is enabled, enable hardened policy too. */
if (*userauth & IPADB_USER_AUTH_PASSWORD) {
@@ -449,7 +394,6 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
struct timeval tv = { 5, 0 };
LDAPMessage *res = NULL;
LDAPMessage *first;
const char *stmsg;
int ret;
int v3;
@@ -529,9 +473,16 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
}
/* get adtrust options using default refresh interval */
ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
if (ret && stmsg)
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
ret = ipadb_reinit_mspac(ipactx, false);
if (ret && ret != ENOENT) {
/* TODO: log that there is an issue with adtrust settings */
if (ipactx->lcontext == NULL) {
/* for some reason ldap connection was reset in ipadb_reinit_mspac
* and is no longer established => failure of ipadb_get_connection
*/
goto done;
}
}
ret = 0;
@@ -664,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. */
@@ -679,7 +628,6 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
goto fail;
}
return 0;
fail:
@@ -850,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,
@@ -891,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
+2 -101
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
@@ -94,34 +78,6 @@
#define IPA_KRB_AUTHZ_DATA_ATTR "ipaKrbAuthzData"
#define IPA_USER_AUTH_TYPE "ipaUserAuthType"
/* Virtual managed ticket flags like "-allow_tix", are always controlled by the
* "nsAccountLock" attribute, such flags should never be set in the database.
* The following expression combine all of them, and is used to filter them
* out. */
#define IPA_KDB_TKTFLAGS_VIRTUAL_MANAGED_ALL (KRB5_KDB_DISALLOW_ALL_TIX)
/* Virtual static ticket flags are hard-coded in the KDB driver. */
/* Virtual static mandatory flags are set systematically and implicitly for all
* principals. They are filtered out from database ticket flags updates.
* (However, "KRB5_KDB_REQUIRES_PRE_AUTH" can still be unset by the
* "KDC:Disable Default Preauth for SPNs" global setting) */
#define IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_MANDATORY (KRB5_KDB_REQUIRES_PRE_AUTH)
/* Virtual static default ticket flags are implicitly set for user and non-user
* (SPN) principals, and not stored in the database.
* (Except if the "IPA_KDB_STRATTR_FINAL_TKTFLAGS" string attribute is "true"
* the principal) */
/* Virtual static default user ticket flags are set for users only. The
* "-allow_svr" flag is set to protect them from CVE-2024-3183. */
#define IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_DEFAULTS_USER (KRB5_KDB_DISALLOW_SVR)
#define IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_DEFAULTS_SPN (0)
/* If this string attribute is set to "true", then only the virtual managed and
* virtual static mandatory ticket flags are applied and filtered out from
* database read and write operations for the concerned user principal.
* Configurable principal ticket flags are applied, but not the configurable
* global ticket policy flags. */
#define IPA_KDB_STRATTR_FINAL_USER_TKTFLAGS "final_user_tkt_flags"
struct ipadb_mspac;
struct dom_sid;
@@ -134,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 {
@@ -143,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,
};
@@ -156,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;
@@ -179,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
@@ -215,21 +162,6 @@ struct ipadb_e_data {
struct dom_sid *sid;
};
inline static krb5_error_code
ipadb_get_edata(krb5_db_entry *entry, struct ipadb_e_data **ied)
{
struct ipadb_e_data *in_ied;
in_ied = (struct ipadb_e_data *)entry->e_data;
if (!in_ied || in_ied->magic != IPA_E_DATA_MAGIC)
return EINVAL;
if (ied)
*ied = in_ied;
return 0;
}
struct ipadb_context *ipadb_get_context(krb5_context kcontext);
int ipadb_get_connection(struct ipadb_context *ipactx);
@@ -274,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);
@@ -387,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,
@@ -402,21 +323,7 @@ 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,
const char **stmsg);
krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit);
void ipadb_mspac_struct_free(struct ipadb_mspac **mspac);
krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
@@ -438,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,
@@ -474,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,
+80 -184
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;
}
@@ -99,110 +91,91 @@ static bool ipadb_match_member(char *princ, LDAPDerefRes *dres)
return false;
}
#if KRB5_KDB_DAL_MAJOR_VERSION >= 9
static krb5_error_code
ipadb_has_acl(krb5_context kcontext, LDAPMessage *ldap_acl, bool *res)
static krb5_error_code ipadb_match_acl(krb5_context kcontext,
LDAPMessage *results,
krb5_const_principal client,
krb5_const_principal target)
{
struct ipadb_context *ipactx;
bool in_res = false;
krb5_error_code kerr = 0;
krb5_error_code kerr;
LDAPMessage *lentry;
LDAPDerefRes *deref_results;
LDAPDerefRes *dres;
char *client_princ = NULL;
char *target_princ = NULL;
bool client_missing;
bool client_found;
bool target_found;
int ret;
ipactx = ipadb_get_context(kcontext);
if (!ipactx)
if (!ipactx) {
return KRB5_KDB_DBNOTINITED;
switch (ldap_count_entries(ipactx->lcontext, ldap_acl)) {
case 0:
break;
case -1:
kerr = EINVAL;
goto end;
default:
in_res = true;
goto end;
}
end:
if (res)
*res = in_res;
return kerr;
}
#endif
static krb5_error_code
ipadb_match_acl(krb5_context kcontext, LDAPMessage *ldap_acl,
krb5_const_principal client, krb5_const_principal target)
{
struct ipadb_context *ipactx;
LDAPMessage *rule;
LDAPDerefRes *acis, *aci;
char *client_princ = NULL, *target_princ= NULL;
bool client_missing, client_found, target_found;
int lerr;
krb5_error_code kerr;
ipactx = ipadb_get_context(kcontext);
if (!ipactx)
return KRB5_KDB_DBNOTINITED;
kerr = krb5_unparse_name(kcontext, client, &client_princ);
if (kerr)
goto end;
if (kerr != 0) {
goto done;
}
kerr = krb5_unparse_name(kcontext, target, &target_princ);
if (kerr)
goto end;
if (kerr != 0) {
goto done;
}
lentry = ldap_first_entry(ipactx->lcontext, results);
if (!lentry) {
kerr = ENOENT;
goto done;
}
/* the default is that we fail */
kerr = KRB5KDC_ERR_BADOPTION;
kerr = ENOENT;
for (rule = ldap_first_entry(ipactx->lcontext, ldap_acl);
rule;
rule = ldap_next_entry(ipactx->lcontext, rule))
{
while (lentry) {
/* both client and target must be found in the same ACI */
client_missing = true;
client_found = false;
target_found = false;
lerr = ipadb_ldap_deref_results(ipactx->lcontext, rule, &acis);
switch (lerr) {
ret = ipadb_ldap_deref_results(ipactx->lcontext, lentry,
&deref_results);
switch (ret) {
case 0:
for (aci = acis; aci; aci = aci->next) {
if (!client_found &&
0 == strcasecmp(aci->derefAttr, "ipaAllowToImpersonate"))
{
for (dres = deref_results; dres; dres = dres->next) {
if (client_found == false &&
strcasecmp(dres->derefAttr, "ipaAllowToImpersonate") == 0) {
/* NOTE: client_missing is used to signal that the
* attribute was completely missing. This signals that
* ANY client is allowed to be impersonated.
* This logic is valid only for clients, not for targets */
client_missing = false;
client_found = ipadb_match_member(client_princ, aci);
client_found = ipadb_match_member(client_princ, dres);
}
if (!target_found &&
0 == strcasecmp(aci->derefAttr, "ipaAllowedTarget"))
{
target_found = ipadb_match_member(target_princ, aci);
if (target_found == false &&
strcasecmp(dres->derefAttr, "ipaAllowedTarget") == 0) {
target_found = ipadb_match_member(target_princ, dres);
}
}
ldap_derefresponse_free(acis);
ldap_derefresponse_free(deref_results);
break;
case ENOENT:
break;
default:
kerr = lerr;
goto end;
kerr = ret;
goto done;
}
if ((client_found || client_missing) && target_found) {
if ((client_found == true || client_missing == true) &&
target_found == true) {
kerr = 0;
goto end;
goto done;
}
lentry = ldap_next_entry(ipactx->lcontext, lentry);
}
end:
done:
krb5_free_unparsed_name(kcontext, client_princ);
krb5_free_unparsed_name(kcontext, target_princ);
return kerr;
@@ -221,37 +194,35 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
char *srv_principal = NULL;
krb5_db_entry *proxy_entry = NULL;
struct ipadb_e_data *ied_server, *ied_proxy;
LDAPMessage *ldap_gcd_acl = NULL;
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);
@@ -259,94 +230,19 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
goto done;
}
/* Load general constrained delegation rules */
kerr = ipadb_get_delegation_acl(kcontext, srv_principal, &ldap_gcd_acl);
kerr = ipadb_get_delegation_acl(kcontext, srv_principal, &res);
if (kerr) {
goto done;
}
#if KRB5_KDB_DAL_MAJOR_VERSION >= 9
/*
* 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.
*
* If target service principal is NULL, and the impersonating service has
* at least one GCD rule, then succeed.
*/
if (!proxy) {
bool has_gcd_rules;
kerr = ipadb_has_acl(kcontext, ldap_gcd_acl, &has_gcd_rules);
if (!kerr)
kerr = has_gcd_rules ? 0 : KRB5KDC_ERR_BADOPTION;
} else if (client) {
#else
if (client && proxy) {
#endif
kerr = ipadb_match_acl(kcontext, ldap_gcd_acl, client, proxy);
} else {
/* client and/or proxy is missing */
kerr = KRB5KDC_ERR_BADOPTION;
}
if (kerr)
kerr = ipadb_match_acl(kcontext, res, client, proxy);
if (kerr) {
goto done;
}
done:
if (kerr) {
#if KRB5_KDB_DAL_MAJOR_VERSION >= 9
kerr = KRB5KDC_ERR_BADOPTION;
#else
kerr = KRB5KDC_ERR_POLICY;
#endif
}
ipadb_free_principal(kcontext, proxy_entry);
krb5_free_unparsed_name(kcontext, srv_principal);
ldap_msgfree(ldap_gcd_acl);
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);
}
}
ldap_msgfree(res);
return kerr;
}
+5 -11
View File
@@ -119,8 +119,11 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_RADIUS]);
} else if (strcmp(auth_indicator, "pkinit") == 0) {
valid_auth_indicators++;
/* allow PKINIT unconditionally -- it has passed already at this
* point so some certificate was useful, only apply the limits */
if (!(ua & IPADB_USER_AUTH_PKINIT)) {
*status = "PKINIT pre-authentication not allowed for this user.";
kerr = KRB5KDC_ERR_POLICY;
goto done;
}
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PKINIT]);
} else if (strcmp(auth_indicator, "hardened") == 0) {
valid_auth_indicators++;
@@ -140,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]);
}
}
File diff suppressed because it is too large. Load diff
+14 -14
View File
@@ -31,7 +31,7 @@ struct ipadb_mspac {
char *fallback_group;
uint32_t fallback_rid;
size_t num_trusts;
int num_trusts;
struct ipadb_adtrusts *trusts;
time_t last_update;
};
@@ -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);
+3 -78
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);
@@ -233,7 +161,6 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
krb5_db_entry *client_entry = NULL;
krb5_boolean is_equal;
bool force_reinit_mspac = false;
const char *stmsg = NULL;
is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
@@ -310,11 +237,9 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
force_reinit_mspac = true;
}
kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg);
if (kerr && stmsg)
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
(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;
}
@@ -328,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;
}
-112
View File
@@ -31,116 +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;
const char *stmsg = NULL;
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;
}
}
/* MS-PAC generator has to be initalized */
kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg);
if (kerr && stmsg)
krb5_klog_syslog(LOG_ERR, "MS-PAC generator: %s", stmsg);
/* Continue even if initilization of PAC generator failed.
* It may caused by the trust objects part only. */
/* At least the core part of the PAC generator is required. */
if (!ipactx->mspac)
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;
}
+86 -623
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;
@@ -765,12 +683,9 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
"krbTicketFlags", &result);
if (ret == 0) {
entry->attributes = result;
}
/* Since principal, global policy, and virtual ticket flags are combined,
* they must always be resolved, except if we are in IPA setup mode (because
* ticket policies and virtual ticket flags are irrelevant in this case). */
if (!ipactx->override_restrictions)
} else {
*polmask |= TKTFLAGS_BIT;
}
ret = ipadb_ldap_attr_to_int(lcontext, lentry,
"krbMaxTicketLife", &result);
@@ -974,12 +889,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
if (ret == 0) {
if (1 == krb5_princ_size(kcontext, entry->princ)) {
/* A principal must be a POSIX account AND have only one element to
* be considered a user (this is to filter out CIFS principals). */
ied->ipa_user = true;
}
ied->ipa_user = true;
ret = ipadb_ldap_attr_to_str(lcontext, lentry,
"uid", &uidstring);
if (ret != 0 && ret != ENOENT) {
@@ -1092,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) {
@@ -1124,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:
@@ -1347,150 +1228,23 @@ done:
return ret;
}
static krb5_error_code
are_final_tktflags(struct ipadb_context *ipactx, krb5_db_entry *entry,
bool *final_tktflags)
static krb5_flags maybe_require_preauth(struct ipadb_context *ipactx,
krb5_db_entry *entry)
{
krb5_error_code kerr;
struct ipadb_e_data *ied;
char *str = NULL;
bool in_final_tktflags = false;
kerr = ipadb_get_edata(entry, &ied);
if (kerr)
goto end;
if (!ied->ipa_user) {
kerr = 0;
goto end;
}
kerr = krb5_dbe_get_string(ipactx->kcontext, entry,
IPA_KDB_STRATTR_FINAL_USER_TKTFLAGS, &str);
if (kerr)
goto end;
in_final_tktflags = str && ipa_krb5_parse_bool(str);
end:
if (final_tktflags)
*final_tktflags = in_final_tktflags;
krb5_dbe_free_string(ipactx->kcontext, str);
return kerr;
}
static krb5_error_code
add_virtual_static_tktflags(struct ipadb_context *ipactx, krb5_db_entry *entry,
krb5_flags *tktflags)
{
krb5_error_code kerr;
krb5_flags vsflg;
bool final_tktflags;
const struct ipadb_global_config *gcfg;
const struct ipadb_global_config *config;
struct ipadb_e_data *ied;
vsflg = IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_MANDATORY;
kerr = ipadb_get_edata(entry, &ied);
if (kerr)
goto end;
kerr = are_final_tktflags(ipactx, entry, &final_tktflags);
if (kerr)
goto end;
/* In practice, principal ticket flags cannot be final for SPNs. */
if (!final_tktflags)
vsflg |= ied->ipa_user ? IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_DEFAULTS_USER
: IPA_KDB_TKTFLAGS_VIRTUAL_STATIC_DEFAULTS_SPN;
if (!ied->ipa_user) {
gcfg = ipadb_get_global_config(ipactx);
if (gcfg && gcfg->disable_preauth_for_spns)
vsflg &= ~KRB5_KDB_REQUIRES_PRE_AUTH;
config = ipadb_get_global_config(ipactx);
if (config && config->disable_preauth_for_spns) {
ied = (struct ipadb_e_data *)entry->e_data;
if (ied && ied->ipa_user != true) {
/* not a user, assume SPN */
return 0;
}
}
if (tktflags)
*tktflags |= vsflg;
end:
return kerr;
}
static krb5_error_code
get_virtual_static_tktflags_mask(struct ipadb_context *ipactx,
krb5_db_entry *entry, krb5_flags *mask)
{
krb5_error_code kerr;
krb5_flags flags = IPA_KDB_TKTFLAGS_VIRTUAL_MANAGED_ALL;
kerr = add_virtual_static_tktflags(ipactx, entry, &flags);
if (kerr)
goto end;
if (mask)
*mask = ~flags;
kerr = 0;
end:
return kerr;
}
/* Add ticket flags from the global ticket policy if it exists, otherwise
* succeed. If the global ticket policy is set, the "exists" parameter is set to
* true. */
static krb5_error_code
add_global_ticket_policy_flags(struct ipadb_context *ipactx,
bool *gtpol_exists, krb5_flags *tktflags)
{
krb5_error_code kerr;
char *policy_dn;
char *tktflags_attr[] = { "krbticketflags", NULL };
LDAPMessage *res = NULL, *first;
int ec, ldap_tktflags;
bool in_gtpol_exists = false;
ec = asprintf(&policy_dn, "cn=%s,cn=kerberos,%s", ipactx->realm,
ipactx->base);
if (-1 == ec) {
kerr = ENOMEM;
goto end;
}
kerr = ipadb_simple_search(ipactx, policy_dn, LDAP_SCOPE_BASE,
"(objectclass=krbticketpolicyaux)",
tktflags_attr, &res);
if (kerr) {
if (KRB5_KDB_NOENTRY == kerr)
kerr = 0;
goto end;
}
first = ldap_first_entry(ipactx->lcontext, res);
if (!first) {
kerr = 0;
goto end;
}
in_gtpol_exists = true;
ec = ipadb_ldap_attr_to_int(ipactx->lcontext, first, "krbticketflags",
&ldap_tktflags);
if (0 == ec && tktflags) {
*tktflags |= (krb5_flags)ldap_tktflags;
}
kerr = 0;
end:
if (gtpol_exists)
*gtpol_exists = in_gtpol_exists;
ldap_msgfree(res);
free(policy_dn);
return kerr;
/* By default require preauth for all principals */
return KRB5_KDB_REQUIRES_PRE_AUTH;
}
static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext,
@@ -1503,7 +1257,6 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext,
char *policy_dn = NULL;
LDAPMessage *res = NULL;
LDAPMessage *first;
bool final_tktflags, has_local_tktpolicy = true;
int result;
int ret;
@@ -1512,18 +1265,12 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext,
return KRB5_KDB_DBNOTINITED;
}
kerr = are_final_tktflags(ipactx, entry, &final_tktflags);
if (kerr)
goto done;
ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
"krbticketpolicyreference", &policy_dn);
switch (ret) {
case 0:
break;
case ENOENT:
/* If no principal ticket policy, fallback to the global one. */
has_local_tktpolicy = false;
ret = asprintf(&policy_dn, "cn=%s,cn=kerberos,%s",
ipactx->realm, ipactx->base);
if (ret == -1) {
@@ -1567,13 +1314,12 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext,
}
}
if (polmask & TKTFLAGS_BIT) {
/* If global ticket policy is being applied, set flags only if
* user principal ticket flags are not final. */
if (has_local_tktpolicy || !final_tktflags) {
ret = ipadb_ldap_attr_to_int(ipactx->lcontext, first,
"krbticketflags", &result);
if (ret == 0)
entry->attributes |= result;
ret = ipadb_ldap_attr_to_int(ipactx->lcontext, first,
"krbticketflags", &result);
if (ret == 0) {
entry->attributes |= result;
} else {
entry->attributes |= maybe_require_preauth(ipactx, entry);
}
}
@@ -1597,25 +1343,11 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext,
if (polmask & MAXRENEWABLEAGE_BIT) {
entry->max_renewable_life = 604800;
}
kerr = 0;
}
if (polmask & TKTFLAGS_BIT) {
/* If the principal ticket flags were applied, then flags from the
* global ticket policy has to be applied atop of them if user principal
* ticket flags are not final. */
if (has_local_tktpolicy && !final_tktflags) {
kerr = add_global_ticket_policy_flags(ipactx, NULL,
&entry->attributes);
if (kerr)
goto done;
if (polmask & TKTFLAGS_BIT) {
entry->attributes |= maybe_require_preauth(ipactx, entry);
}
/* Virtual static ticket flags are set regardless of database content */
kerr = add_virtual_static_tktflags(ipactx, entry, &entry->attributes);
if (kerr)
goto done;
kerr = 0;
}
done:
@@ -1630,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);
@@ -1650,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;
@@ -1727,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,
@@ -1747,41 +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;
const char *stmsg = NULL;
/* 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;
}
@@ -1805,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;
}
@@ -1821,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;
}
@@ -1843,11 +1523,8 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
if (kerr == KRB5_KDB_NOENTRY) {
/* If no trusted realm found, refresh trusted domain data and try again
* because it might be a freshly added trust to AD */
kerr = ipadb_reinit_mspac(ipactx, false, &stmsg);
kerr = ipadb_reinit_mspac(ipactx, false);
if (kerr != 0) {
if (stmsg)
krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s",
stmsg);
kerr = KRB5_KDB_NOENTRY;
goto done;
}
@@ -1857,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) {
@@ -1913,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;
@@ -1962,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;
@@ -1979,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)
@@ -2053,21 +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(acl_list);
}
free(prev->tl_data_contents);
free(prev);
prev = next;
@@ -2082,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;
@@ -2206,36 +1797,6 @@ static void ipadb_mods_free_tip(struct ipadb_mods *imods)
imods->tip--;
}
/* Use LDAP REPLACE operation to remove an attribute.
* Contrary to the DELETE operation, it will not fail if the attribute does not
* exist. */
static krb5_error_code
ipadb_ldap_replace_remove(struct ipadb_mods *imods, char *attribute)
{
krb5_error_code kerr;
LDAPMod *m = NULL;
kerr = ipadb_mods_new(imods, &m);
if (kerr)
return kerr;
m->mod_op = LDAP_MOD_REPLACE;
m->mod_type = strdup(attribute);
if (!m->mod_type) {
kerr = ENOMEM;
goto end;
}
m->mod_values = NULL;
kerr = 0;
end:
if (kerr)
ipadb_mods_free_tip(imods);
return kerr;
}
static krb5_error_code ipadb_get_ldap_mod_str(struct ipadb_mods *imods,
char *attribute, char *value,
int mod_op)
@@ -2364,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)
@@ -2390,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++;
}
@@ -2407,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);
@@ -2652,93 +2208,6 @@ static krb5_error_code ipadb_get_ldap_mod_auth_ind(krb5_context kcontext,
return ret;
}
static krb5_error_code
update_tktflags(krb5_context kcontext, struct ipadb_mods *imods,
krb5_db_entry *entry, int mod_op)
{
krb5_error_code kerr;
struct ipadb_context *ipactx;
struct ipadb_e_data *ied;
bool final_tktflags;
krb5_flags tktflags_mask;
int tktflags;
ipactx = ipadb_get_context(kcontext);
if (!ipactx) {
kerr = KRB5_KDB_DBNOTINITED;
goto end;
}
if (ipactx->override_restrictions) {
/* In IPA setup mode, IPA edata might not be available. In this mode,
* ticket flags are written as they are provided. */
tktflags = (int)entry->attributes;
} else {
kerr = ipadb_get_edata(entry, &ied);
if (kerr)
goto end;
kerr = get_virtual_static_tktflags_mask(ipactx, entry, &tktflags_mask);
if (kerr)
goto end;
kerr = are_final_tktflags(ipactx, entry, &final_tktflags);
if (kerr)
goto end;
/* Flags from the global ticket policy are filtered out only if the user
* principal flags are not final. */
if (!final_tktflags) {
krb5_flags gbl_tktflags = 0;
kerr = add_global_ticket_policy_flags(ipactx, NULL, &gbl_tktflags);
if (kerr)
goto end;
tktflags_mask &= ~gbl_tktflags;
}
tktflags = (int)(entry->attributes & tktflags_mask);
if (LDAP_MOD_REPLACE == mod_op && ied && !ied->has_tktpolaux) {
if (0 == tktflags) {
/* No point initializing principal ticket policy if there are no
* flags left after filtering out virtual and global ticket
* policy ones. */
kerr = 0;
goto end;
}
/* if the object does not have the krbTicketPolicyAux class
* we need to add it or this will fail, only for modifications.
* We always add this objectclass by default when doing an add
* from scratch. */
kerr = ipadb_get_ldap_mod_str(imods, "objectclass",
"krbTicketPolicyAux", LDAP_MOD_ADD);
if (kerr)
goto end;
}
}
if (tktflags != 0) {
kerr = ipadb_get_ldap_mod_int(imods, "krbTicketFlags", tktflags,
mod_op);
if (kerr)
goto end;
} else if (LDAP_MOD_REPLACE == mod_op) {
/* If the principal is not being created, and there are no custom ticket
* flags to be set, remove the "krbTicketFlags" attribute. */
kerr = ipadb_ldap_replace_remove(imods, "krbTicketFlags");
if (kerr)
goto end;
}
kerr = 0;
end:
return kerr;
}
static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext,
struct ipadb_mods *imods,
krb5_db_entry *entry,
@@ -2814,9 +2283,36 @@ static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext,
/* KADM5_ATTRIBUTES */
if (entry->mask & KMASK_ATTRIBUTES) {
kerr = update_tktflags(kcontext, imods, entry, mod_op);
if (kerr)
/* if the object does not have the krbTicketPolicyAux class
* we need to add it or this will fail, only for modifications.
* We always add this objectclass by default when doing an add
* from scratch. */
if ((mod_op == LDAP_MOD_REPLACE) && entry->e_data) {
struct ipadb_e_data *ied;
ied = (struct ipadb_e_data *)entry->e_data;
if (ied->magic != IPA_E_DATA_MAGIC) {
kerr = EINVAL;
goto done;
}
if (!ied->has_tktpolaux) {
kerr = ipadb_get_ldap_mod_str(imods, "objectclass",
"krbTicketPolicyAux",
LDAP_MOD_ADD);
if (kerr) {
goto done;
}
}
}
kerr = ipadb_get_ldap_mod_int(imods,
"krbTicketFlags",
(int)entry->attributes,
mod_op);
if (kerr) {
goto done;
}
}
/* KADM5_MAX_LIFE */
@@ -3220,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' \
-6
View File
@@ -79,7 +79,6 @@ static void on_bind_readable(verto_ctx *vctx, verto_ev *ev)
struct otpd_queue_item *item = NULL;
int i, rslt;
(void)vctx;
int kerr = 0;
rslt = ldap_result(verto_get_private(ev), LDAP_RES_ANY, 0, NULL, &results);
if (rslt != LDAP_RES_BIND) {
@@ -119,7 +118,6 @@ static void on_bind_readable(verto_ctx *vctx, verto_ev *ev)
krad_code_name2num("Access-Accept"),
NULL, item->req, &item->rsp);
if (i != 0) {
kerr = 1;
errstr = krb5_get_error_message(ctx.kctx, i);
goto error;
}
@@ -129,10 +127,6 @@ error:
otpd_log_req(item->req, "bind end: %s",
item->rsp != NULL ? "success" : errstr);
if (kerr) {
krb5_free_error_message(ctx.kctx, errstr);
}
ldap_msgfree(results);
otpd_queue_push(&ctx.stdio.responses, item);
verto_set_flags(ctx.stdio.writer, VERTO_EV_FLAG_PERSIST |
+7 -13
View File
@@ -43,14 +43,10 @@ static void forward_cb(krb5_error_code retval, const krad_packet *request,
NULL, item->req, &item->rsp);
}
if (retval == 0) {
otpd_log_req(item->req, "forward end: %s", krad_code_num2name(code));
} else {
const char *err_msg = krb5_get_error_message(ctx.kctx, retval);
otpd_log_req(item->req, "forward end: %s",
krb5_get_error_message(ctx.kctx, retval));
krb5_free_error_message(ctx.kctx, err_msg);
}
otpd_log_req(item->req, "forward end: %s",
retval == 0
? krad_code_num2name(code)
: krb5_get_error_message(ctx.kctx, retval));
otpd_queue_push(&ctx.stdio.responses, item);
verto_set_flags(ctx.stdio.writer, VERTO_EV_FLAG_PERSIST |
@@ -121,10 +117,8 @@ krb5_error_code otpd_forward(struct otpd_queue_item **item)
*item = NULL;
error:
if (retval != 0) {
const char *err_msg = krb5_get_error_message(ctx.kctx, retval);
otpd_log_req((*item)->req, "forward end: %s", err_msg);
krb5_free_error_message(ctx.kctx, err_msg);
}
if (retval != 0)
otpd_log_req((*item)->req, "forward end: %s",
krb5_get_error_message(ctx.kctx, retval));
return retval;
}
-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);
}
+6 -7
View File
@@ -2165,17 +2165,17 @@ static bool handle_cross_realm_princs(struct ipasam_private *ipasam_state,
princ_l = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
remote_realm, ipasam_state->realm);
l_tdo_alias = talloc_asprintf(tmp_ctx, "%s$@%s",
princ_l_tdo = talloc_asprintf(tmp_ctx, "%s$@%s",
flat_name, ipasam_state->realm);
princ_l_tdo = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
l_tdo_alias = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
flat_name, ipasam_state->realm);
princ_r = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
ipasam_state->realm, remote_realm);
r_tdo_alias = talloc_asprintf(tmp_ctx, "%s$@%s",
princ_r_tdo = talloc_asprintf(tmp_ctx, "%s$@%s",
ipasam_state->flat_name, remote_realm);
princ_r_tdo = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
r_tdo_alias = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s",
ipasam_state->flat_name, remote_realm);
if (trusted_dn == NULL || princ_l == NULL || princ_l_tdo == NULL ||
@@ -2212,7 +2212,7 @@ static bool handle_cross_realm_princs(struct ipasam_private *ipasam_state,
* only used to retrieve trusted domain credentials by
* AD Trust Agents across the IPA topology */
failed += !set_krb_princ(ipasam_state, tmp_ctx,
princ_r_tdo, r_tdo_alias,
r_tdo_alias, princ_r_tdo,
pwd_incoming, trusted_dn,
(KRB_PRINC_CREATE_DISABLED |
KRB_PRINC_CREATE_AGENT_PERMISSION));
@@ -2232,9 +2232,8 @@ static bool handle_cross_realm_princs(struct ipasam_private *ipasam_state,
pwd_outgoing, trusted_dn,
KRB_PRINC_CREATE_DEFAULT);
/* Second: <krbtgt/REMOTE FLAT NAME>@<OUR REALM>, enabled by default
/* Second: <REMOTE FLAT NAME>$@<OUR REALM>, enabled by default
* as it is used for a remote DC to authenticate against IPA Samba
* Uses <REMOTE FLAT NAME$>@<OUR REALM> as an alias.
*
* A local account for the outbound trust must have
* POSIX and SMB identities associated with our domain but we associate
+1 -5
View File
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2010-2023 Red Hat, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -67,10 +67,6 @@
"[file %s, line %d]: " fmt, \
__FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_PWDPOLICY(fmt, ...) \
slapi_log_error(SLAPI_LOG_PWDPOLICY, log_func, fmt, ##__VA_ARGS__)
/* "Trace" logging is very expensive and should be avoided/replaced. TBD */
#define LOG_TRACE(fmt, ...) \
slapi_log_error(SLAPI_LOG_TRACE, log_func, fmt, ##__VA_ARGS__)
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2005-2023 Red Hat, Inc.
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -132,8 +132,7 @@ ipa_join(Slapi_PBlock *pb)
Slapi_DN *sdn;
Slapi_Backend *be;
Slapi_Entry **es = NULL;
int rc=0, ret=0, res;
size_t i;
int rc=0, ret=0, res, i;
int is_root=0;
char *krbLastPwdChange = NULL;
char *fqdn = NULL;
@@ -205,7 +204,7 @@ ipa_join(Slapi_PBlock *pb)
/* if there is none or more than one, freak out */
if (i != 1) {
LOG_TRACE("Too many entries, or entry no found (%lu)\n", i);
LOG_TRACE("Too many entries, or entry no found (%d)", i);
if (i == 0)
errMesg = "Host not found.\n";
else
@@ -218,7 +217,7 @@ ipa_join(Slapi_PBlock *pb)
/* Is this host already enrolled? */
krbLastPwdChange = slapi_entry_attr_get_charptr(targetEntry, "krbLastPwdChange");
if (NULL != krbLastPwdChange) {
LOG_TRACE("Host already enrolled\n");
LOG_TRACE("Host already enrolled");
errMesg = "Host already enrolled.\n";
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
@@ -314,8 +313,8 @@ done:
ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, JOIN_OID);
if (!ret) ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, &retbval);
if (ret) {
errMesg = "Could not set return values\n";
LOG("%s", errMesg);
errMesg = "Could not set return values";
LOG("%s\n", errMesg);
rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
}
@@ -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),
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2022-2023 Red Hat, Inc.
* Copyright (C) 2022 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -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,
@@ -447,7 +441,7 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb)
LOG_TRACE("grace limit disabled, skipping\n");
goto done;
} else if (grace_limit < -1) {
LOG_FATAL("Invalid passwordGraceLimit value %ld\n", grace_limit);
LOG_FATAL("Invalid passwordGraceLimit value %d\n", grace_limit);
return LDAP_OPERATIONS_ERROR;
}
@@ -479,8 +473,8 @@ 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) {
LOG_PWDPOLICY("%s password is expired and out of grace limit\n", dn);
} 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;
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2010-2023 Red Hat, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -823,15 +823,13 @@ static int ipalockout_preop(Slapi_PBlock *pb)
if (failedcount >= max_fail) {
if (lockout_duration == 0) {
errstr = "Entry permanently locked.\n";
LOG_PWDPOLICY("Entry '%s' is permanently locked.\n", dn);
ret = LDAP_UNWILLING_TO_PERFORM;
goto done;
}
if (time_now < last_failed + lockout_duration) {
/* Too many failures */
LOG_PWDPOLICY("Too many failed logins for '%s'. %lu out of %d\n",
dn, failedcount, max_fail);
LOG_TRACE("Too many failed logins. %lu out of %d\n", failedcount, max_fail);
errstr = "Too many failed logins.\n";
ret = LDAP_UNWILLING_TO_PERFORM;
}
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2010-2023 Red Hat, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -350,6 +350,7 @@ ipamodrdn_load_plugin_config(void)
{
int status = EOK;
int result;
int i;
Slapi_PBlock *search_pb;
Slapi_Entry **entries = NULL;
@@ -378,7 +379,7 @@ ipamodrdn_load_plugin_config(void)
goto cleanup;
}
for (size_t i = 0; (entries[i] != NULL); i++) {
for (i = 0; (entries[i] != NULL); i++) {
/* We don't care about the status here because we may have
* some invalid config entries, but we just want to continue
* looking for valid ones. */
@@ -679,8 +680,7 @@ ipamodrdn_change_attr(struct configEntry *cfgentry,
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("Failed to change attribute '%s' in '%s' with error %d\n",
cfgentry->tattr, targetdn, ret);
LOG_FATAL("Failed to change attribute with error %d\n", ret);
ret = EFAIL;
}
ret = EOK;
@@ -33,7 +33,7 @@
* Authors:
* Nathaniel McCallum <npmccallum@redhat.com>
*
* Copyright (C) 2014-2023 Red Hat, Inc.
* Copyright (C) 2014 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -295,16 +295,14 @@ preop_mod(Slapi_PBlock *pb)
}
if (!simulate(mods, attr, cpre, &cpost) && repl == 0) {
msg = slapi_ch_smprintf("Invalid operation sequence on %s (%s)",
attr, slapi_entry_get_dn_const(epre));
msg = slapi_ch_smprintf("Invalid operation sequence on %s", attr);
goto error;
}
if (cpost < cpre) {
if (repl == 0) {
msg = slapi_ch_smprintf("Will not %s %s (%s)",
cpost == COUNTER_UNSET ? "delete" : "decrement",
attr, slapi_entry_get_dn_const(epre));
msg = slapi_ch_smprintf("Will not %s %s",
cpost == COUNTER_UNSET ? "delete" : "decrement", attr);
goto error;
}
@@ -323,9 +321,6 @@ preop_mod(Slapi_PBlock *pb)
error:
rc = LDAP_UNWILLING_TO_PERFORM;
if (msg) {
LOG("%s - error %d\n", msg, rc);
}
slapi_send_ldap_result(pb, rc, NULL, msg, 0, NULL);
if (slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc)) {
LOG_FATAL("slapi_pblock_set failed!\n");
@@ -33,7 +33,7 @@
* Authors:
* Nathaniel McCallum <npmccallum@redhat.com>
*
* Copyright (C) 2014-2023 Red Hat, Inc.
* Copyright (C) 2014 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -41,8 +41,6 @@
#include <slapi-plugin.h>
#define IPA_PLUGIN_NAME "ipa-otp-counter"
long long
ldapmod_get_value(const LDAPMod *mod, long long def);
@@ -33,7 +33,7 @@
* Authors:
* Nathaniel McCallum <npmccallum@redhat.com>
*
* Copyright (C) 2013-2023 Red Hat, Inc.
* Copyright (C) 2013 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -46,7 +46,7 @@
#include "util.h"
#define IPA_PLUGIN_NAME "ipa-otp-lasttoken"
#define PLUGIN_NAME "ipa-otp-lasttoken"
#define OTP_CONTAINER "cn=otp,%s"
static struct otp_config *otp_config;
@@ -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)
@@ -191,14 +177,9 @@ static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr)
static int preop_del(Slapi_PBlock *pb)
{
char *dn = NULL;
if (is_allowed(pb, NULL))
return 0;
slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
LOG("Can't delete last active token (%s)", dn);
return send_error(pb, LDAP_UNWILLING_TO_PERFORM,
"Can't delete last active token");
}
@@ -226,12 +207,10 @@ static int preop_mod(Slapi_PBlock *pb)
return 0;
/* If a protected attribute is modified, deny. */
for (size_t i = 0; mods != NULL && mods[i] != NULL; i++) {
for (size_t j = 0; errors[j].attr != NULL; j++) {
if (strcasecmp(mods[i]->mod_type, errors[j].attr) == 0) {
LOG("%s (%s)", errors[j].msg, slapi_entry_get_dn_const(entry));
for (int i = 0; mods != NULL && mods[i] != NULL; i++) {
for (int j = 0; errors[j].attr != NULL; j++) {
if (strcasecmp(mods[i]->mod_type, errors[j].attr) == 0)
return send_error(pb, LDAP_UNWILLING_TO_PERFORM, errors[j].msg);
}
}
}
@@ -291,7 +270,7 @@ static int ipa_otp_lasttoken_start(Slapi_PBlock *pb)
int ipa_otp_lasttoken_init(Slapi_PBlock *pb)
{
static const Slapi_PluginDesc preop_desc = {
IPA_PLUGIN_NAME,
PLUGIN_NAME,
"FreeIPA",
"FreeIPA/1.0",
"Protect the user's last active token"
@@ -304,14 +283,14 @@ int ipa_otp_lasttoken_init(Slapi_PBlock *pb)
ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &preop_desc);
ret |= slapi_register_plugin("betxnpreoperation", 1, __func__, preop_init,
IPA_PLUGIN_NAME " betxnpreoperation", NULL,
PLUGIN_NAME " betxnpreoperation", NULL,
ipa_otp_lasttoken_plugin_id);
ret |= slapi_register_plugin("postoperation", 1, __func__, postop_init,
IPA_PLUGIN_NAME " postoperation", NULL,
PLUGIN_NAME " postoperation", NULL,
ipa_otp_lasttoken_plugin_id);
ret |= slapi_register_plugin("internalpostoperation", 1, __func__,
intpostop_init,
IPA_PLUGIN_NAME " internalpostoperation", NULL,
PLUGIN_NAME " internalpostoperation", NULL,
ipa_otp_lasttoken_plugin_id);
ret |= slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
(void *)ipa_otp_lasttoken_start);
@@ -33,7 +33,7 @@
* Authors:
* Simo Sorce <ssorce@redhat.com>
*
* Copyright (C) 2007-2023 Red Hat, Inc.
* Copyright (C) 2007-2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -81,9 +81,7 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
char **encsalts;
char **tmparray;
char *tmpstr;
int ret;
size_t i;
bool fips_enabled = false;
int i, ret;
config = calloc(1, sizeof(struct ipapwd_krbcfg));
if (!config) {
@@ -242,34 +240,27 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
config->allow_nt_hash = false;
if (ipapwd_fips_enabled()) {
LOG("FIPS mode is enabled, NT hashes are not allowed.\n");
fips_enabled = true;
}
sdn = slapi_sdn_new_dn_byval(ipa_etc_config_dn);
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
slapi_sdn_free(&sdn);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("No config Entry?\n");
goto free_and_error;
} else {
tmparray = slapi_entry_attr_get_charray(config_entry,
"ipaConfigString");
for (i = 0; tmparray && tmparray[i]; i++) {
if (strcasecmp(tmparray[i], "EnforceLDAPOTP") == 0) {
config->enforce_ldap_otp = true;
continue;
}
if (!fips_enabled) {
sdn = slapi_sdn_new_dn_byval(ipa_etc_config_dn);
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
slapi_sdn_free(&sdn);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("No config Entry?\n");
goto free_and_error;
} else {
tmparray = slapi_entry_attr_get_charray(config_entry,
"ipaConfigString");
for (i = 0; tmparray && tmparray[i]; i++) {
if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
config->allow_nt_hash = true;
continue;
}
}
if (tmparray) slapi_ch_array_free(tmparray);
}
if (tmparray) slapi_ch_array_free(tmparray);
}
slapi_entry_free(config_entry);
slapi_entry_free(config_entry);
}
return config;
@@ -336,8 +327,7 @@ int ipapwd_getPolicy(const char *dn,
"ipaPwdUserCheck", NULL};
Slapi_Entry **es = NULL;
Slapi_Entry *pe = NULL;
int ret, res, scope;
size_t i;
int ret, res, scope, i;
int buffer_flags=0;
Slapi_ValueSet* results = NULL;
char *actual_type_name = NULL;
@@ -555,7 +545,7 @@ int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
}
sdn = slapi_sdn_new_dn_byref(dn);
if (!sdn) {
LOG_FATAL("Unable to convert dn to sdn %s\n", dn ? dn : "<NULL>");
LOG_FATAL("Unable to convert dn to sdn %s", dn ? dn : "<NULL>");
*errMesg = "Internal Error";
rc = LDAP_OPERATIONS_ERROR;
goto done;
@@ -574,18 +564,11 @@ int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
/* get the kerberos context and master key */
*config = ipapwd_getConfig();
if (NULL == *config) {
LOG_FATAL("Error Retrieving Master Key\n");
LOG_FATAL("Error Retrieving Master Key");
*errMesg = "Fatal Internal Error";
rc = LDAP_OPERATIONS_ERROR;
}
/* do not return the master key if asked */
if (check_flags & IPAPWD_CHECK_ONLY_CONFIG) {
free((*config)->kmkey->contents);
free((*config)->kmkey);
(*config)->kmkey = NULL;
}
done:
return rc;
}
@@ -611,7 +594,7 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
/* Find the entry with the password policy */
ret = ipapwd_getPolicy(data->dn, data->target, &pol);
if (ret) {
LOG_TRACE("No password policy, use defaults\n");
LOG_TRACE("No password policy, use defaults");
}
break;
case IPA_CHANGETYPE_ADMIN:
@@ -637,14 +620,14 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
*/
ret = ipapwd_getPolicy(data->dn, data->target, &tmppol);
if (ret) {
LOG_TRACE("No password policy, use defaults\n");
LOG_TRACE("No password policy, use defaults");
} else {
pol.max_pwd_life = tmppol.max_pwd_life;
pol.history_length = tmppol.history_length;
}
break;
default:
LOG_TRACE("Unknown password change type, use defaults\n");
LOG_TRACE("Unknown password change type, use defaults");
break;
}
@@ -877,7 +860,7 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
case IPA_CHANGETYPE_DSMGR:
case IPA_CHANGETYPE_ADMIN:
/* Mark as administratively reset which will unlock acct */
ret = ipapwd_setdate(data->target, smods,
ret = ipapwd_setdate(data->target, smods,
"krbLastAdminUnlock",
data->timeNow, false);
if (ret != LDAP_SUCCESS)
@@ -968,7 +951,7 @@ Slapi_Value **ipapwd_setPasswordHistory(Slapi_Mods *smods,
char **new_pwd_history = NULL;
int n = 0;
int ret;
size_t i;
int i;
pwd_history = slapi_entry_attr_get_charray(data->target,
"passwordHistory");
@@ -1100,9 +1083,10 @@ int ipapwd_set_extradata(const char *dn,
void ipapwd_free_slapi_value_array(Slapi_Value ***svals)
{
Slapi_Value **sv = *svals;
int i;
if (sv) {
for (size_t i = 0; sv[i]; i++) {
for (i = 0; sv[i]; i++) {
slapi_value_free(&sv[i]);
}
}
@@ -1118,10 +1102,8 @@ void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
krb5_free_default_realm(c->krbctx, c->realm);
krb5_free_context(c->krbctx);
if (c->kmkey) {
free(c->kmkey->contents);
free(c->kmkey);
}
free(c->kmkey->contents);
free(c->kmkey);
free(c->supp_encsalts);
free(c->pref_encsalts);
slapi_ch_array_free(c->passsync_mgrs);
@@ -33,7 +33,7 @@
* Authors:
* Simo Sorce <ssorce@redhat.com>
*
* Copyright (C) 2007-2023 Red Hat, Inc.
* Copyright (C) 2007-2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -231,7 +231,7 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
if (!*svals) {
/* errMesg should have been set in encrypt_encode_key() */
LOG_FATAL("key encryption/encoding failed (%s)\n", *errMesg);
LOG_FATAL("key encryption/encoding failed\n");
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
@@ -267,7 +267,6 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
}
(*ntvals)[0] = slapi_value_new();
if (slapi_value_set((*ntvals)[0], nt_key, 16) == NULL) {
LOG("Failed to set value for nt_key");
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
@@ -33,7 +33,7 @@
* Authors:
* Simo Sorce <ssorce@redhat.com>
*
* Copyright (C) 2007-2023 Red Hat, Inc.
* Copyright (C) 2007-2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -108,7 +108,7 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
struct ipapwd_keyset *kset,
bool allow_nthash)
{
size_t i, j;
int i, j;
for (i = 0; i < kset->num_keys; i++) {
for (j = 0; j < krbcfg->num_supp_encsalts; j++) {
@@ -151,11 +151,11 @@ static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
bool allow_nthash)
{
/* first filter for duplicates */
for (size_t i = 0; i + 1 < *num_kenctypes; i++) {
for (size_t j = i + 1; j < *num_kenctypes; j++) {
for (int i = 0; i + 1 < *num_kenctypes; i++) {
for (int j = i + 1; j < *num_kenctypes; j++) {
if (kenctypes[i].ks_enctype == kenctypes[j].ks_enctype) {
/* duplicate, filter out */
for (size_t k = j; k + 1 < *num_kenctypes; k++) {
for (int k = j; k + 1 < *num_kenctypes; k++) {
kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
}
@@ -166,8 +166,8 @@ static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
}
/* then filter for supported */
for (size_t i = 0; i < *num_kenctypes; i++) {
size_t j;
for (int i = 0; i < *num_kenctypes; i++) {
int j;
/* Check if supported */
for (j = 0; j < krbcfg->num_supp_encsalts; j++) {
@@ -184,7 +184,7 @@ static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
}
if (j == krbcfg->num_supp_encsalts) {
/* Unsupported, filter out */
for (size_t k = i; k + 1 < *num_kenctypes; k++) {
for (int k = i; k + 1 < *num_kenctypes; k++) {
kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
}
@@ -344,8 +344,6 @@ parse_req_done:
rc = ipapwd_check_max_pwd_len(strlen(newPasswd), &errMesg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
bindDN, errMesg);
goto free_and_return;
}
@@ -458,7 +456,7 @@ parse_req_done:
char *cur_pw;
if (oldPasswd == NULL || *oldPasswd == '\0') {
LOG_FATAL("Old password was not provided for '%s'!\n", dn);
LOG_FATAL("Old password was not provided!\n");
rc = LDAP_INVALID_CREDENTIALS;
goto free_and_return;
}
@@ -468,7 +466,7 @@ parse_req_done:
cur_pw = slapi_entry_attr_get_charptr(targetEntry,
"userPassword");
if (!cur_pw) {
LOG_FATAL("User '%s' does not have a current password?\n", dn);
LOG_FATAL("User has no current password?\n");
rc = LDAP_UNWILLING_TO_PERFORM;
goto free_and_return;
}
@@ -487,7 +485,7 @@ parse_req_done:
slapi_value_free(&pw);
if (ret != 0) {
LOG_TRACE("Invalid password for '%s'!\n", dn);
LOG_TRACE("Invalid password!\n");
rc = LDAP_INVALID_CREDENTIALS;
goto free_and_return;
}
@@ -581,9 +579,11 @@ parse_req_done:
/* special cases */
if ((strcasecmp(dn, bindDN) != 0) &&
(strcasecmp(ipa_changepw_principal_dn, bindDN) != 0)) {
int i;
pwdata.changetype = IPA_CHANGETYPE_ADMIN;
for (size_t i = 0; i < krbcfg->num_passsync_mgrs; i++) {
for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
if (strcasecmp(krbcfg->passsync_mgrs[i], bindDN) == 0) {
pwdata.changetype = IPA_CHANGETYPE_DSMGR;
break;
@@ -606,8 +606,6 @@ parse_req_done:
errMesg = ipapwd_error2string(ret);
ret = ipapwd_to_ldap_pwpolicy_error(ret);
slapi_pwpolicy_make_response_control(pb, -1, -1, ret);
LOG_PWDPOLICY("Failed to set password credentials for"
" '%s': %s\n", dn, errMesg);
rc = LDAP_CONSTRAINT_VIOLATION;
goto free_and_return;
}
@@ -668,7 +666,7 @@ free_and_return:
if (targetEntry) slapi_entry_free(targetEntry);
if (ber) ber_free(ber, 1);
LOG("%s\n", errMesg ? errMesg : "success");
LOG("%s", errMesg ? errMesg : "success");
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
@@ -734,8 +732,7 @@ static Slapi_Entry *get_entry_by_principal(const char *principal)
"krbCanonicalName",
"enrolledBy", NULL };
Slapi_Entry **es = NULL;
int res, ret;
size_t i;
int res, ret, i;
Slapi_Entry *entry = NULL;
/* Find ancestor base DN */
@@ -777,7 +774,7 @@ static Slapi_Entry *get_entry_by_principal(const char *principal)
/* if there is none or more than one, freak out */
if (i != 1) {
LOG_TRACE("Too many entries, or entry no found (%ld)\n", i);
LOG_TRACE("Too many entries, or entry no found (%d)", i);
goto free_and_return;
}
entry = slapi_entry_dup(es[0]);
@@ -812,7 +809,7 @@ static bool is_allowed_to_access_attr(Slapi_PBlock *pb, char *bindDN,
*/
be = get_realm_backend();
if (!be) {
LOG_FATAL("Could not fetch REALM backend!\n");
LOG_FATAL("Could not fetch REALM backend!");
return false;
}
if (slapi_pblock_set(pb, SLAPI_BACKEND, be)) {
@@ -871,8 +868,7 @@ static void remove_user_password(Slapi_Mods *smods,
if ((NULL != pw) && (NULL == krbLastPwdChange)) {
slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE,
"userPassword", NULL);
LOG_TRACE("Removing userPassword from host entry '%s'\n",
slapi_entry_get_dn_const(targetEntry));
LOG_TRACE("Removing userPassword from host entry\n");
}
}
if (krbLastPwdChange) slapi_ch_free_string(&krbLastPwdChange);
@@ -895,9 +891,8 @@ static int store_new_keys(Slapi_Entry *target, char *svcname, char *bind_dn,
rc = set_krbLastPwdChange(smods, time_now);
if (rc) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to set krbLastPwdChange for target '%s'\n",
slapi_entry_get_dn_const(target));
err_msg = "Internal error while storing keytab data";
LOG_FATAL("Failed to set krbLastPwdChange");
err_msg = "Internal error while storing keytab data\n";
goto done;
}
@@ -910,9 +905,8 @@ static int store_new_keys(Slapi_Entry *target, char *svcname, char *bind_dn,
rc = ipapwd_apply_mods(slapi_entry_get_dn_const(target), smods);
if (rc != LDAP_SUCCESS) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to apply mods to target '%s'\n",
slapi_entry_get_dn_const(target));
err_msg = "Internal error while saving keys";
LOG_FATAL("Failed to apply mods");
err_msg = "Internal error while saving keys\n";
goto done;
}
@@ -920,9 +914,8 @@ static int store_new_keys(Slapi_Entry *target, char *svcname, char *bind_dn,
svcname, time_now);
if (rc != LDAP_SUCCESS) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to set extradata for target '%s'\n",
slapi_entry_get_dn_const(target));
err_msg = "Internal error while saving keytab extradata";
LOG_FATAL("Failed to set extradata");
err_msg = "Internal error while saving keytab extradata\n";
goto done;
}
@@ -1010,7 +1003,7 @@ static int decode_setkeytab_request(krb5_context krbctx,
kset->mkvno = mkvno;
rtag = ber_peek_tag(ber, &tlen);
for (size_t i = 0; rtag == LBER_SEQUENCE; i++) {
for (int i = 0; rtag == LBER_SEQUENCE; i++) {
krb5_key_data *newset;
ber_tag_t ctag;
ber_int_t type;
@@ -1188,29 +1181,29 @@ static int encode_setkeytab_reply(struct ipapwd_keyset *kset,
rc = ber_printf(ber, "{i{", (ber_int_t)kset->keys[0].key_data_kvno);
if (rc == -1) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to ber_printf the kvno\n");
LOG_FATAL("Failed to ber_printf the kvno");
goto done;
}
for (size_t i = 0; i < kset->num_keys; i++) {
for (int i = 0; i < kset->num_keys; i++) {
rc = ber_printf(ber, "{i}", (ber_int_t)kset->keys[i].key_data_type[0]);
if (rc == -1) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to ber_printf the enctype\n");
LOG_FATAL("Failed to ber_printf the enctype");
goto done;
}
}
rc = ber_printf(ber, "}}");
if (rc == -1) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to ber_printf the termination\n");
LOG_FATAL("Failed to ber_printf the termination");
goto done;
}
rc = ber_flatten(ber, &bvp);
if (rc == -1) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("Failed to ber_flatten the buffer\n");
LOG_FATAL("Failed to ber_flatten the buffer");
goto done;
}
@@ -1313,7 +1306,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
/* get next kvno for entry (will be 1 if this is new) and fix keyset */
kvno = ipapwd_get_cur_kvno(targetEntry) + 1;
for (size_t i = 0; i < kset->num_keys; i++) {
for (int i = 0; i < kset->num_keys; i++) {
kset->keys[i].key_data_kvno = kvno;
}
@@ -1359,7 +1352,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
rc = encode_setkeytab_reply(kset, &bvp);
if (rc) {
errMesg = "Internal Error.";
errMesg = "Internal Error.\n";
goto free_and_return;
}
@@ -1379,7 +1372,7 @@ free_and_return:
if (targetEntry) slapi_entry_free(targetEntry);
if (svals) {
for (size_t i = 0; svals[i]; i++) {
for (int i = 0; svals[i]; i++) {
slapi_value_free(&svals[i]);
}
free(svals);
@@ -1389,7 +1382,7 @@ free_and_return:
if (rc == LDAP_SUCCESS)
errMesg = NULL;
LOG("%s\n", errMesg ? errMesg : "success");
LOG("%s", errMesg ? errMesg : "success");
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
@@ -1410,6 +1403,7 @@ static int decode_getkeytab_request(struct berval *extop, bool *wantold,
krb5_key_salt_tuple *enctypes = NULL;
bool newkt;
bool ret;
int i;
ret = ipaasn1_dec_getkt(extop->bv_val, extop->bv_len, &newkt,
&svcname, &password, &etypes, &numtypes);
@@ -1429,7 +1423,7 @@ static int decode_getkeytab_request(struct berval *extop, bool *wantold,
goto done;
}
for (size_t i = 0; i < numtypes; i++) {
for (i = 0; i < numtypes; i++) {
enctypes[i].ks_enctype = etypes[i];
enctypes[i].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
}
@@ -1472,7 +1466,7 @@ static int encode_getkeytab_reply(krb5_context krbctx,
/* uses last key kvno */
kvno = keys[num_keys-1].key_data_kvno;
for (size_t i = 0; i < num_keys; i++) {
for (int i = 0; i < num_keys; i++) {
krb5_enc_data cipher = { 0 };
krb5_data plain = { 0 };
krb5_int16 plen;
@@ -1522,7 +1516,7 @@ static int encode_getkeytab_reply(krb5_context krbctx,
rc = LDAP_SUCCESS;
done:
for (size_t i = 0; i < ksc.nkeys; i++) {
for (int i = 0; i < ksc.nkeys; i ++) {
free(ksc.ksdata[i].key.contents);
}
if (rc != LDAP_SUCCESS) {
@@ -1638,7 +1632,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
* this operation. */
if (bind_dn == NULL || *bind_dn == '\0') {
/* Refuse the operation because they're bound anonymously */
err_msg = "Anonymous Binds are not allowed.";
err_msg = "Anonymous Binds are not allowed.\n";
rc = LDAP_INSUFFICIENT_ACCESS;
goto free_and_return;
}
@@ -1654,7 +1648,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
if (!extop_value) {
LOG_FATAL("Failed to retrieve extended op value from pblock\n");
err_msg = "Failed to retrieve extended operation value";
err_msg = "Failed to retrieve extended operation value\n";
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
}
@@ -1680,7 +1674,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
/* get Entry by krbPrincipalName */
target_entry = get_entry_by_principal(service_name);
if (!target_entry) {
err_msg = "PrincipalName not found.";
err_msg = "PrincipalName not found.\n";
rc = LDAP_NO_SUCH_OBJECT;
goto free_and_return;
}
@@ -1696,7 +1690,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
if (!acl_ok) {
LOG_FATAL("Not allowed to retrieve keytab on [%s] as user [%s]!\n",
service_name, bind_dn);
err_msg = "Insufficient access rights";
err_msg = "Insufficient access rights\n";
rc = LDAP_INSUFFICIENT_ACCESS;
goto free_and_return;
}
@@ -1707,8 +1701,6 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
/* if password was passed-in, check its length */
rc = ipapwd_check_max_pwd_len(strlen(password), &err_msg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
bind_dn, err_msg);
goto free_and_return;
}
}
@@ -1720,7 +1712,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
if (!acl_ok) {
LOG_FATAL("Not allowed to set keytab on [%s]!\n",
service_name);
err_msg = "Insufficient access rights";
err_msg = "Insufficient access rights\n";
rc = LDAP_INSUFFICIENT_ACCESS;
goto free_and_return;
}
@@ -1753,7 +1745,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
if (!svals) {
rc = LDAP_OPERATIONS_ERROR;
LOG_FATAL("encrypt_encode_keys failed!\n");
err_msg = "Internal error while encrypting keys";
err_msg = "Internal error while encrypting keys\n";
goto free_and_return;
}
@@ -1773,7 +1765,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
rc = encode_getkeytab_reply(krbctx, krbcfg->kmkey, mkvno,
keys, num_keys, &bvp);
if (rc != LDAP_SUCCESS) {
err_msg = "Internal Error.";
err_msg = "Internal Error.\n";
goto free_and_return;
}
@@ -1784,7 +1776,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
free_and_return:
if (rc == LDAP_SUCCESS) err_msg = NULL;
LOG("%s\n", err_msg ? err_msg : "success");
LOG("%s", err_msg ? err_msg : "success");
slapi_send_ldap_result(pb, rc, NULL, err_msg, 0, NULL);
/* Free anything that we allocated above */
@@ -1795,7 +1787,7 @@ free_and_return:
if (target_entry) slapi_entry_free(target_entry);
if (keys) ipa_krb5_free_key_data(keys, num_keys);
if (svals) {
for (size_t i = 0; svals[i]; i++) {
for (int i = 0; svals[i]; i++) {
slapi_value_free(&svals[i]);
}
free(svals);
@@ -2039,7 +2031,7 @@ int ipapwd_init( Slapi_PBlock *pb )
"ipapwd_post_init_betxn", ipapwd_post_init_betxn,
"IPA pwd post ops betxn", NULL,
ipapwd_plugin_id);
}
}
slapi_register_plugin("preoperation", 1,
"ipapwd_pre_init", ipapwd_pre_init,
@@ -70,7 +70,6 @@
#define IPAPWD_CHECK_CONN_SECURE 0x00000001
#define IPAPWD_CHECK_DN 0x00000002
#define IPAPWD_CHECK_ONLY_CONFIG 0x00000004
#define IPA_CHANGETYPE_NORMAL 0
#define IPA_CHANGETYPE_ADMIN 1
@@ -110,7 +109,6 @@ struct ipapwd_krbcfg {
char **passsync_mgrs;
int num_passsync_mgrs;
bool allow_nt_hash;
bool enforce_ldap_otp;
};
int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
@@ -33,7 +33,7 @@
* Authors:
* Simo Sorce <ssorce@redhat.com>
*
* Copyright (C) 2007-2023 Red Hat, Inc.
* Copyright (C) 2007-2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -248,13 +248,6 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
return 0;
}
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
/* Ok this is interesting,
* Check this is a clear text password, or refuse operation */
if ('{' == userpw[0]) {
@@ -287,8 +280,6 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
} else {
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
slapi_sdn_get_dn(sdn), errMesg);
goto done;
}
userpw = slapi_ch_strdup(userpw_clear);
@@ -338,6 +329,13 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
goto done;
}
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
/* time to get the operation handler */
ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
if (ret != 0) {
@@ -361,6 +359,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
} else {
char *binddn;
int i;
pwdop->pwdata.changetype = IPA_CHANGETYPE_ADMIN;
@@ -368,7 +367,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
/* if it is a passsync manager we also need to skip resets */
for (size_t i = 0; i < krbcfg->num_passsync_mgrs; i++) {
for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
if (strcasecmp(krbcfg->passsync_mgrs[i], binddn) == 0) {
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
break;
@@ -386,8 +385,6 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
(ret != 0) ) {
errMesg = ipapwd_error2string(ret);
LOG_PWDPOLICY("Failed to add password credentials for '%s': %s\n",
slapi_sdn_get_dn(sdn), errMesg);
rc = LDAP_CONSTRAINT_VIOLATION;
goto done;
}
@@ -510,13 +507,6 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
goto done;
}
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
/* grab the mods - we'll put them back later with
* our modifications appended
*/
@@ -578,8 +568,6 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
rc = ipapwd_check_max_pwd_len(bv->bv_len, &errMesg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
slapi_sdn_get_dn(sdn), errMesg);
goto done;
}
slapi_ch_free_string(&unhashedpw);
@@ -603,6 +591,14 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
/* OK we have something interesting here, start checking for
* pre-requisites */
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
tmp_sdn = slapi_sdn_dup(sdn);
if (tmp_sdn) {
/* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
@@ -799,8 +795,6 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
const char *userpw_clear = &userpw[strlen("{CLEAR}")];
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
slapi_sdn_get_dn(sdn), errMesg);
goto done;
}
unhashedpw = slapi_ch_strdup(userpw_clear);
@@ -812,8 +806,9 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
slapi_ch_free_string(&userpw);
} else if (slapi_is_encoded(userpw)) {
errMesg = "Pre-Encoded passwords are not valid";
LOG("%s (%s)\n", errMesg, slapi_sdn_get_dn(sdn));
LOG("Pre-Encoded passwords are not valid\n");
errMesg = "Pre-Encoded passwords are not valid\n";
rc = LDAP_CONSTRAINT_VIOLATION;
goto done;
}
@@ -848,6 +843,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
} else {
char *binddn;
Slapi_DN *bdn, *tdn;
int i;
/* Check Bind DN */
slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
@@ -861,16 +857,18 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
pwdop->pwdata.changetype = IPA_CHANGETYPE_ADMIN;
/* if it is a passsync manager we also need to skip resets */
for (size_t i = 0; i < krbcfg->num_passsync_mgrs; i++) {
for (i = 0; i < krbcfg->num_passsync_mgrs; i++) {
if (strcasecmp(krbcfg->passsync_mgrs[i], binddn) == 0) {
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
break;
}
}
}
slapi_sdn_free(&bdn);
slapi_sdn_free(&tdn);
}
pwdop->pwdata.dn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
@@ -886,8 +884,6 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
(ret != 0)) {
errMesg = ipapwd_error2string(ret);
LOG_PWDPOLICY("Check Password Policy failed for (%s) - %s/n",
pwdop->pwdata.dn, errMesg);
rc = LDAP_CONSTRAINT_VIOLATION;
goto done;
}
@@ -980,6 +976,7 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
int num_keys;
int mkvno;
int ret;
int i;
ret = slapi_entry_attr_find(entry, "ipaNTHash", &attr);
if (ret == 0) {
@@ -1011,7 +1008,7 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
ret = LDAP_UNWILLING_TO_PERFORM;
for (size_t i = 0; i < num_keys; i++) {
for (i = 0; i < num_keys; i++) {
char nthash[16];
krb5_enc_data cipher;
krb5_data plain;
@@ -1212,20 +1209,13 @@ done:
* value at the end. This leaves only the password in creds for later
* validation.
*/
typedef enum {
OTP_IS_NOT_REQUIRED = 0,
OTP_IS_REQUIRED_EXPLICITLY,
OTP_IS_REQUIRED_IMPLICITLY
} otp_req_enum;
static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
struct berval *creds, otp_req_enum otpreq,
bool *notokens)
struct berval *creds, bool otpreq)
{
uint32_t auth_types;
/* Get the configured authentication types. */
auth_types = otp_config_auth_types(otp_config, entry);
*notokens = false;
/*
* IMPORTANT SECTION!
@@ -1255,11 +1245,7 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
/* With no tokens, succeed if tokens aren't required. */
if (tokens[0] == NULL) {
otp_token_free_array(tokens);
*notokens = true;
if (otpreq != OTP_IS_NOT_REQUIRED)
/* DENY: OTP is required, either explicitly or implicitly */
return false;
return true;
return !otpreq;
}
if (otp_token_validate_berval(tokens, creds, NULL)) {
@@ -1270,8 +1256,7 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
otp_token_free_array(tokens);
}
return (auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD) &&
(otpreq == OTP_IS_NOT_REQUIRED);
return (auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD) && !otpreq;
}
static int ipapwd_authenticate(const char *dn, Slapi_Entry *entry,
@@ -1426,11 +1411,6 @@ done:
}
#ifdef USE_OP_NOTE_MFA_AUTH
/* defined in ldap/servers/slapd/pblock.c in 389-ds but not exposed via slapi-plugin.h */
extern void slapi_pblock_set_flag_operation_notes(Slapi_PBlock *pb, uint32_t opflag);
#endif
/* PRE BIND Operation
*
* Used for:
@@ -1448,13 +1428,12 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
"krbPasswordExpiration", "krblastpwchange",
NULL
};
struct ipapwd_krbcfg *krbcfg = NULL;
struct berval *credentials = NULL;
Slapi_Entry *entry = NULL;
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;
@@ -1464,7 +1443,6 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
struct tm expire_tm;
int rc = LDAP_INVALID_CREDENTIALS;
char *errMesg = NULL;
bool notokens = false;
/* get BIND parameters */
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &target_sdn);
@@ -1476,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);
@@ -1523,28 +1499,9 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
/* Try to do OTP first. */
syncreq = otpctrl_present(pb, OTP_SYNC_REQUEST_OID);
otpreq = otpctrl_present(pb, OTP_REQUIRED_OID) ?
OTP_IS_REQUIRED_EXPLICITLY : OTP_IS_NOT_REQUIRED;
if (!syncreq && (otpreq == OTP_IS_NOT_REQUIRED)) {
ret = ipapwd_gen_checks(pb, &errMesg, &krbcfg, IPAPWD_CHECK_ONLY_CONFIG);
if (ret != 0) {
LOG_FATAL("ipapwd_gen_checks failed!?\n");
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
return 0;
}
if (krbcfg->enforce_ldap_otp) {
otpreq = OTP_IS_REQUIRED_IMPLICITLY;
}
}
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry,
credentials, otpreq, &notokens)) {
/* We got here because ipapwd_pre_bind_otp() returned false,
* it means that either token verification failed or
* a rule for empty tokens failed current policy. */
if (!(notokens || (otpreq == OTP_IS_NOT_REQUIRED)))
goto invalid_creds;
}
otpreq = otpctrl_present(pb, OTP_REQUIRED_OID);
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials, otpreq))
goto invalid_creds;
/* Ensure that there is a password. */
if (credentials->bv_len == 0) {
@@ -1552,15 +1509,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
} else {
rc = ipapwd_check_max_pwd_len(credentials->bv_len, &errMesg);
if (rc) {
LOG_PWDPOLICY("Failed to set password credentials for '%s': %s\n",
slapi_sdn_get_dn(sdn), errMesg);
goto invalid_creds;
}
}
/* Reset rc to make sure errors are reported*/
rc = LDAP_INVALID_CREDENTIALS;
/* Authenticate the user. */
ret = ipapwd_authenticate(dn, entry, credentials);
if (ret) {
@@ -1576,23 +1528,11 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
/* Attempt to write out kerberos keys for the user. */
ipapwd_write_krb_keys(pb, discard_const(dn), entry, credentials);
#ifdef USE_OP_NOTE_MFA_AUTH
/* If it was a successful authentication with OTP required, mark it
* for access log to notice multi-factor authentication has happened
* https://www.port389.org/docs/389ds/design/mfa-operation-note-design.html
*/
if (!syncreq &&
((otpreq != OTP_IS_NOT_REQUIRED) && !notokens)) {
slapi_pblock_set_flag_operation_notes(pb, SLAPI_OP_NOTE_MFA_AUTH);
}
#endif
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
return 0;
invalid_creds:
free_ipapwd_krbcfg(&krbcfg);
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
@@ -45,8 +45,6 @@
#define UID_NUMBER "uidnumber"
#define GID_NUMBER "gidnumber"
#define IPA_SID "ipantsecurityidentifier"
#define IPA_UNIQUEID "ipauniqueid"
#define IPA_UNIQUEID_AUTOGENERATE "autogenerate"
#define DOM_ATTRS_FILTER OBJECTCLASS"=ipantdomainattrs"
#define DOMAIN_ID_RANGE_FILTER OBJECTCLASS"=ipadomainidrange"
#define POSIX_ACCOUNT "posixaccount"
@@ -106,6 +104,3 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
const char *base_dn,
const char *dom_sid,
struct range_info **ranges);
int sidgen_task_init(Slapi_PBlock *pb);
int ipa_sidgen_init(Slapi_PBlock *pb);
@@ -454,7 +454,6 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
uint32_t id;
char *sid = NULL;
char **objectclasses = NULL;
char *uniqueid = NULL;
Slapi_PBlock *mod_pb = NULL;
Slapi_Mods *smods = NULL;
int result;
@@ -480,18 +479,8 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
goto done;
}
uniqueid = slapi_entry_attr_get_charptr(entry, IPA_UNIQUEID);
if (uniqueid != NULL &&
strncmp(IPA_UNIQUEID_AUTOGENERATE, uniqueid,
sizeof(IPA_UNIQUEID_AUTOGENERATE)) == 0) {
LOG("Staged entry [%s] does not have Posix IDs, nothing to do.\n",
dn_str);
ret = 0;
goto done;
}
if (uid_number >= UINT32_MAX || gid_number >= UINT32_MAX) {
LOG_FATAL("ID value too large on entry [%s].\n", dn_str);
LOG_FATAL("ID value too large.\n");
ret = LDAP_CONSTRAINT_VIOLATION;
goto done;
}
@@ -508,7 +497,7 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
&has_posix_group,
&has_ipa_id_object);
if (ret != 0) {
LOG_FATAL("Cannot determine objectclasses on entry [%s].\n", dn_str);
LOG_FATAL("Cannot determine objectclasses.\n");
goto done;
}
@@ -522,16 +511,15 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
id = (uid_number != 0) ? uid_number : gid_number;
objectclass_to_add = NULL;
} else {
LOG_FATAL("Inconsistent objectclasses and attributes on entry "
"[%s], nothing to do.\n", dn_str);
LOG_FATAL("Inconsistent objectclasses and attributes, nothing to do.\n");
ret = 0;
goto done;
}
ret = find_sid_for_id(id, plugin_id, base_dn, dom_sid, ranges, &sid);
if (ret != 0) {
LOG_FATAL("Cannot convert Posix ID [%lu] into an unused SID on "
"entry [%s].\n", (unsigned long) id, dn_str);
LOG_FATAL("Cannot convert Posix ID [%lu] into an unused SID.\n",
(unsigned long) id);
goto done;
}
@@ -566,7 +554,6 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
}
done:
slapi_ch_free_string(&uniqueid);
slapi_ch_free_string(&sid);
slapi_pblock_destroy(mod_pb);
slapi_mods_free(&smods);
@@ -89,7 +89,7 @@ static void free_pblock(void *arg)
static int do_work(struct worker_ctx *worker_ctx)
{
Slapi_PBlock *pb;
int ret, failures = 0;
int ret;
size_t c;
char *filter = NULL;
char *attrs[] = { OBJECTCLASS, UID_NUMBER, GID_NUMBER, NULL };
@@ -151,7 +151,8 @@ static int do_work(struct worker_ctx *worker_ctx)
worker_ctx->base_dn, worker_ctx->dom_sid,
worker_ctx->ranges);
if (ret != 0) {
failures++;
LOG_FATAL("Cannot add SID to existing entry.\n");
goto done;
}
if (worker_ctx->delay != 0) {
@@ -161,12 +162,6 @@ static int do_work(struct worker_ctx *worker_ctx)
}
};
ret = failures;
if (ret > 0) {
LOG_FATAL("Finished with %d failures, please check the log.\n",
failures);
}
done:
slapi_ch_free_string(&filter);
pthread_cleanup_pop(1);
@@ -30,7 +30,7 @@
* Program may make changes or additions to the list of Approved
* Interfaces.
*
* Copyright (C) 2010-2023 Red Hat, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
@@ -1185,7 +1185,7 @@ static int ipauuid_pre_op(Slapi_PBlock *pb, int modtype)
* enforce is enabled. */
errstr = slapi_ch_smprintf("Only the Directory Manager "
"can set arbitrary values "
"for %s", cfgentry->attr);
"for %s\n", cfgentry->attr);
ret = LDAP_INSUFFICIENT_ACCESS;
goto done;
}
@@ -1221,7 +1221,7 @@ done:
}
if (ret) {
LOG("operation failure [%d] - %s\n", ret, errstr);
LOG("operation failure [%d]\n", ret);
slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
slapi_ch_free((void **)&errstr);
ret = EFAIL;
@@ -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;
}
+2 -3
View File
@@ -5,7 +5,7 @@
# from the environment for the first two.
PYTHON ?= python3
VENVDIR = ./.venv
SPHINXOPTS ?= -W --keep-going -j 1
SPHINXOPTS ?= -W --keep-going -j auto
SPHINXBUILD ?= PATH=$(VENVDIR)/bin:$$PATH sphinx-build
SOURCEDIR = .
BUILDDIR = _build
@@ -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.
Loaded 100 of 1096 files, more files were not shown because too many files have changed in this diff. Show more