Ppolicy
Installare ppolicy
Aggiungere il modulo ppolicy
Se lo openldap e' configurato con i moduli dinamici (tipo lo slapd pacchettizzato con debian squeeze), bisogna aggiungere il modulo di ppolicy con lo ldif:
dn: cn=module{1},cn=config objectClass: olcModuleList cn: module{1} olcModulePath: /usr/lib/ldap olcModuleLoad: ppolicy
Aggiungere lo schema ppolicy
Lo overlay ppolicy non si carica in openldap se prima non si include lo schema ppolicy. L'errore che lamenta al momento dell'insert e' che non riesce a trovare la definizione per l'attributo pwdAttribute.
Per inserire uno schema openldap con configuazione in slapd.d seguire le istruzioni ubuntu.
Il file ldif nel caso che sia il decimo schema e':
dn: cn={10}ppolicy,cn=schema,cn=config objectClass: olcSchemaConfig cn: {10}ppolicy olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.8.1.1 NAME 'pwdAttribute' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 ) olcAttributeTypes: {1}( 1.3.6.1.4.1.42.2.27.8.1.2 NAME 'pwdMinAge' EQUALITY in tegerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {2}( 1.3.6.1.4.1.42.2.27.8.1.3 NAME 'pwdMaxAge' EQUALITY in tegerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {3}( 1.3.6.1.4.1.42.2.27.8.1.4 NAME 'pwdInHistory' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {4}( 1.3.6.1.4.1.42.2.27.8.1.5 NAME 'pwdCheckQuality' EQUAL ITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {5}( 1.3.6.1.4.1.42.2.27.8.1.6 NAME 'pwdMinLength' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {6}( 1.3.6.1.4.1.42.2.27.8.1.7 NAME 'pwdExpireWarning' EQUA LITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {7}( 1.3.6.1.4.1.42.2.27.8.1.8 NAME 'pwdGraceAuthNLimit' EQ UALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {8}( 1.3.6.1.4.1.42.2.27.8.1.9 NAME 'pwdLockout' EQUALITY b ooleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) olcAttributeTypes: {9}( 1.3.6.1.4.1.42.2.27.8.1.10 NAME 'pwdLockoutDuration' E QUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {10}( 1.3.6.1.4.1.42.2.27.8.1.11 NAME 'pwdMaxFailure' EQUAL ITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {11}( 1.3.6.1.4.1.42.2.27.8.1.12 NAME 'pwdFailureCountInter val' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: {12}( 1.3.6.1.4.1.42.2.27.8.1.13 NAME 'pwdMustChange' EQUAL ITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) olcAttributeTypes: {13}( 1.3.6.1.4.1.42.2.27.8.1.14 NAME 'pwdAllowUserChange' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) olcAttributeTypes: {14}( 1.3.6.1.4.1.42.2.27.8.1.15 NAME 'pwdSafeModify' EQUAL ITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) olcAttributeTypes: {15}( 1.3.6.1.4.1.4754.1.99.1 NAME 'pwdCheckModule' DESC 'L oadable module that instantiates "check_password() function' EQUALITY caseExa ctIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcObjectClasses: {0}( 1.3.6.1.4.1.4754.2.99.1 NAME 'pwdPolicyChecker' SUP top AUXILIARY MAY pwdCheckModule ) olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.8.2.1 NAME 'pwdPolicy' SUP top AUXI LIARY MUST pwdAttribute MAY ( pwdMinAge $ pwdMaxAge $ pwdInHistory $ pwdCheck Quality $ pwdMinLength $ pwdExpireWarning $ pwdGraceAuthNLimit $ pwdLockout $ pwdLockoutDuration $ pwdMaxFailure $ pwdFailureCountInterval $ pwdMustChange $ pwdAllowUserChange $ pwdSafeModify ) )
Aggiungere lo overlay ppolicy
In questo caso lo aggiungo al secondo database, perche' il primo e' quello in replica.
dn: olcOverlay=ppolicy,olcDatabase={2}hdb,cn=config changetype: add objectClass: olcOverlayConfig objectClass: olcPPolicyConfig olcOverlay: ppolicy olcPPolicyDefault: cn=default,ou=policies,dc=unimore,dc=it
Aggiungere la entry di policy
dn: ou=policies,dc=unimore,dc=it ou: policies objectClass: top objectClass: organizationalUnit dn: cn=default,ou=policies,dc=unimore,dc=it cn: default objectClass: pwdPolicy objectClass: person objectClass: top pwdAllowUserChange: TRUE pwdAttribute: userPassword pwdCheckQuality: 2 pwdExpireWarning: 600 pwdFailureCountInterval: 30 pwdGraceAuthNLimit: 5 pwdInHistory: 5 pwdLockout: TRUE pwdLockoutDuration: 0 pwdMaxAge: 86400 pwdMaxFailure: 5 pwdMinAge: 0 pwdMinLength: 5 pwdMustChange: FALSE pwdSafeModify: FALSE sn: dummy value
Provare ppolicy
Chi usa ldapsearch deve usare il controllo esteso "-e ppolicy", ad esempio:
ldapsearch -x -h localhost -e ppolicy -D uid=ospite1,ou=users,dc=unimore,dc=it -w test_2 'uid=ospite1' ldap_bind: Invalid credentials (49); Password expired
mentre i log sono piu' chiari:
Nov 12 10:09:33 ldap4 slapd[2572]: conn=1018 op=60 SEARCH RESULT tag=101 err=0 nentries=1 text= Nov 12 10:09:42 ldap4 slapd[2572]: conn=1063 fd=38 ACCEPT from IP=127.0.0.1:59825 (IP=0.0.0.0:389) Nov 12 10:09:42 ldap4 slapd[2572]: conn=1063 op=0 BIND dn="uid=ospite1,ou=users,dc=unimore,dc=it" method=128 Nov 12 10:09:42 ldap4 slapd[2572]: conn=1063 op=0 BIND dn="uid=ospite1,ou=users,dc=unimore,dc=it" mech=SIMPLE ssf=0 Nov 12 10:09:42 ldap4 slapd[2572]: ppolicy_bind: Entry uid=ospite1,ou=users,dc=unimore,dc=it has an expired password: 0 grace logins Nov 12 10:09:42 ldap4 slapd[2572]: conn=1063 op=0 RESULT tag=97 err=49 text= Nov 12 10:09:42 ldap4 slapd[2572]: conn=1063 fd=38 closed (connection lost)
Con il comando esteso "-e ppolicy" appare in testa agli ldapsearch autenticati il numero di secondi prima della scadenza della password.
Con un linguaggio di programmazione: php (non funziona)
La chiave e' mandare un control type esteso dal valore:
1.3.6.1.4.1.42.2.27.8.5.1
in php questo sembra si faccia con
$ppolicy = array("oid" => "1.3.6.1.4.1.42.2.27.8.5.1", "iscritical" => true); if (!ldap_set_option($ds, LDAP_OPT_CLIENT_CONTROLS, array($ppolicy))) { echo "Failed to set server controls"; }
I risultati possibili sono elencati nella sezione 6.2. Response Control documento ietf
Quello che non funziona e' che non si riesce a leggere PasswordPolicyResponseValue, anche se nei log di openldap viene registrata.
Con un linguaggio di programmazione: ruby-ldap (non funziona)
Qui il problema e' che non riesce a mandare un comando esteso con il bind (manca la funzione), solo sulla connessione o sulle operazioni tipo add, search e modify. Se poi ci si riuscisse, non si sa se si riuscirebbe e leggere la PasswordPolicyResponseValue.
Associare una policy diversa a un certo utente
Creare la policy, e modificare la entry dell'utente con lo ldif:
dn: uid=ospite1,ou=users,dc=unimore,dc=it changetype: modify replace: pwdPolicySubentry pwdPolicySubentry: cn=policy0,ou=policies,dc=unimore,dc=it
Associare una policy diversa a un certo gruppo
Pare non si faccia (messaggio privato di Luca Scamoni).
Obbligare un soggetto a cambiare la password
E' necessario che all'utente sia associata una policy che abbia
pwdMustChange: TRUE
poi si modifica la entry e si aggiunge l'attributo esteso pwdReset: TRUE, ad esempio:
dn: cn=cinecaugov,ou=agents,dc=unimore,dc=it changetype: modify replace: pwdReset pwdReset: TRUE
Se l'utente tenta un bind riceve un errore di insufficient access: text: Operations are restricted to bind/unbind/abandon/StartTLS/modify password
Problemi con ppolicy
preseed delle policy
Un utente non segue la ppolicy di default se ha cambiato la password prima dell'entrata in funzione dell'overlay. Cioe': sono soggetti a ppolicy solo coloro che cambiano la password dopo l'abilitazione di una certa policy.
Il workaround è settare pwdChangedTime.
Però si tratta di un attributo operazionale che richiede il contollo RELAX per essere modificato:
dn: uid=user,ou=people,dc=unimore,dc=it control: 1.3.6.1.4.1.4203.666.5.12 changetype: modify replace: pwdChangedTime pwdChangedTime: 20140811071845Z
replica delle policy
Se si desidera che le ppolicy siano replicate, bisogna che siano nell'albero di replica.
Esempio: replica di ou=people,dc=unimore,dc=it.
Funziona se le policies sono definite in ou=policies,ou=people,dc=unimore,dc=it
Non funziona se le policies dono definite in ou=policies,dc=unimore,dc=it, anche se nel consumer c'e' un ramo ou=policies popolato.