2012. szeptember 10., hétfő

OpenLDAP jelszóházirend Ubuntu 12.04-en - ötödik rész

A jelszóházirend megoldása lassan hosszabb, mint egy brazil tévésorozat. A múltkor megbeszéltük, hogy a ppolicy overlay a helyén van és működik, de az smbkrb5pwd és a Windows okoz még gondot.
Ma az smbkrb5pwd problémájának igyekszünk a végére járni. Előrebocsátom, hogy tiszta véletlen, hogy a dolog működik.
Nevezetesen arról van szó, hogy Kerberos-ban is megadható házirend. Ha ugyanazt adjuk meg a jelszóra, mint az OpenLDAP-ban (nálam: 8 karakteres hosszúság, elmúlt három jelszó tárolása), akkor az jó nekünk mert a Kerberos-jelszóházirend akkor is érvényesül, ha az admin változtatja meg a jelszót. (Ellentétben a ppolicy overlay működésével - hiszen a múltkor ott láttuk, hogy csak akkor lép működésbe, ha a saját jelszavunkat változtatjuk meg.) Így viszont az smbkrb5pwd elakad, és nem változtatja meg a másik két jelszót olyankor, amikor a házirend nem teszi lehetővé. A megoldás nekem megfelelő, de aki az smbkrb5pwd-t csak az LDAP-Samba szinkronra használja, annak mást kell kiötlenie.

Szóval teszteljük a módszert.
Van már egy felhasználónk, akit rogyásig teszteltünk. Ő a suser1. Azért pont suser1, mert amikor kialakítottuk a Samba-szervert, ő lett az egyes számú Samba user. Megint vele kezdünk. A kadmin man-oldala szerint:
-policy policy policy used by this principal. If no policy is supplied,
then if the policy "default" exists and the -clearpolicy
is not also specified, then the policy "default" is used;
otherwise, the principal will have no policy, and a
warning message will be printed.
Azaz a későbbi felhasználók létrehozásakor úgyis érdemes volna, ha volna egy default nevű házirendünk. Úgyhogy azt hozzuk létre. Az alábbi házirend többé-kevésbé azt tudja, amit a múltkorjában létrehozott LDAP-házirend:
sudo kadmin.local
kadmin.local:  add_policy -minlength 8 -maxlife "3024000 seconds" -failurecountinterval "600 seconds" -lockoutduration "300 seconds" -maxfailure 3 -history 3  default
Állítsuk be, hogy ez a policy legyen érvényes suser1-re:
kadmin.local:  modprinc -policy default suser1
Principal "suser1@ITTHON.CUCC" modified.
Ha megnézzük a kerberos-cuccot az LDAP-fában, akkor látunk benne egy cn=default részt, ahol a házirend van. suser1 principalján belül pedig lesz egy krbPwdPolicyReference attribútum, ami a default házirendre mutat.
Akkor most:
ldappasswd -D cn=admin,dc=itthon,dc=cucc -w titok -s egy uid=suser1,ou=People,dc=itthon,dc=cucc
Result: Connect error (-11)
Valójában nem connect error van, nézzük a syslog-ot:
smbkrb5pwd conn=1025 op=1 : kadm5_chpass_principal() failed for user suser1@ITTHON.CUCC: Password is too short
Na, eddig jó. Most akkor:
ldappasswd -D cn=admin,dc=itthon,dc=cucc -w titok -s 12345678 uid=suser1,ou=People,dc=itthon,dc=cucc
Result: Connect error (-11)
És a syslog-ban:
smbkrb5pwd conn=1026 op=1 : kadm5_chpass_principal() failed for user suser1@ITTHON.CUCC: Cannot reuse password
Remek. Látjuk, hogy bár az smbkrb5pwd-nek a jelszók körében megfelelő jogosultságot adtunk, most nem megy vele semmire: a házirend megállítja.
Kis próbálkozás után azonban rájön az ember, hogy az előző jelszók tárolása a kerberos-ban nem működik, és az előző üzenet csak azt jelenti, hogy nem adhatjuk meg ugyanazt a jelszót, ami eddig is volt. Na de miért nem működik a jelszótárolás? A man megmondja a tutit:
-history number sets the number of past keys kept for a principal. This
option is not supported for LDAP database
Megette a fene. Akkor mi legyen? Megváltoztatjuk az LDAP default ppolicy-t, hogy csak egy jelszót tároljon, és mindkét helyen beállítjuk, hogy a jelszót leggyakrabban óránként lehet változtatni. Az alapértelmezett LDAP házirendnél ez egy pwdMinAge attribútum felvételét jelenti, 3600-as értékkel. A pwdInHistory legyen 1. A Kerberos esetében a krbMinPwdLife legyen 3600. Akkor most elvileg jó, ennyit tudunk kicsiholni a rendszerből.
Gyakorlatilag viszont nem jó. A jelszó minimális életidejére (is) tojik az smbkrb5pwd. Próbáljuk ki: változtassunk jelszót, majd a kpasswd-vel változtassuk meg közvetlenül a Kerberos-jelszót. Nem fog menni, mert itt figyelünk. Ha azonban ismét a passwd paranccsal próbálkozunk, akkor az userPassword-öt a ppolicy overlay nem engedi megváltoztatni, viszont az smbkrb5pwd a másik két jelszavunkat megváltoztatja.

Érdekes módon viszont a túl rövid jelszón bukik a rendszer, azzal így nincs gond. Azaz lényegében két dolog kényszeríthető ki a házirendekkel:

  • jelszó lejárása
  • jelszó minimális hossza

Hát, elég primitív, de ennyi van.

Már csak egy kisebb probléma maradt: ha még emlékszünk, ha a létrehozott felhasználónak nincs keberos-principalja, az smbkrb5pwd készít neki, az első jelszóváltoztatáskor. Hozzunk létre egy felhasználót, változtassuk meg a jelszavát, például az ldappaswd paranccsal, és figyeljük a syslog-ot. Ilyen lesz benne:
smbkrb5pwd conn=1085 op=1 : created principal for user suser2@ITTHON.CUCC
Egy gyors ellenőrzés:
sudo kadmin.local -q "getprinc suser2"
(pár sorral lejjebb:)
Policy: [none]
Grrr.
Két eset lehetséges:
  1. vagy módosítjuk az smbkrb5pwd kódját,
  2. vagy írunk valami scriptet, ami minden olyan kerberos principalnál létrehozza a megfelelő bejegyzést - akár a kadmin, akár közvetlenül az LDAP használatával, ahol szükség van rá. 
Az a helyzet, hogy pár óra kutakodás után látom, hogy az első megoldáshoz hülye vagyok. Kb. sejtem, hogy mit kéne csinálni, de az kevés. Úgyhogy a második jön.

Az első feladat: kitalálni, hogy kinél kellene házirendet beállítani. Úgy tudom megfogalmazni, hogy azoknál, akiknek a nevében nincs / (per) és krbPrincipal osztályúak és nincs krbPwdPolicyReference attribútumuk. Ez az ldapsearch nyelvén:
ldapsearch -x -LLL -b cn=ITTHON.CUCC,cn=krbcontainer,dc=itthon,dc=cucc -s one "(&(!(krbPrincipalname=*/*))(objectClass=krbPrincipal)(!(krbPwdPolicyReference=*)))" dn
Ugye szép?
Namost, a szutyok ldapsearch töri a hosszú sorokat. A megoldás egy perl-szösszenet (figyeld a vastagot):
ldapsearch -x -LLL -b cn=ITTHON.CUCC,cn=krbcontainer,dc=itthon,dc=cucc -s one "(&(!(krbPrincipalname=*/*))(objectClass=krbPrincipal)(!(krbPwdPolicyReference=*)))" dn|perl -p00e 's/\r?\n //g'
Ebbe nem kellenek az üres sorok:
ldapsearch -x -LLL -b cn=ITTHON.CUCC,cn=krbcontainer,dc=itthon,dc=cucc -s one "(&(!(krbPrincipalname=*/*))(objectClass=krbPrincipal)(!(krbPwdPolicyReference=*)))" dn|perl -p00e 's/\r?\n //g'|grep -v '^$'
Kiharapjuk a principalokat:
ldapsearch -x -LLL -b cn=ITTHON.CUCC,cn=krbcontainer,dc=itthon,dc=cucc -s one "(&(!(krbPrincipalname=*/*))(objectClass=krbPrincipal)(!(krbPwdPolicyReference=*)))" dn|perl -p00e 's/\r?\n //g'|grep -v '^$'|cut -d' ' -f2|cut -d',' -f1|cut -d'=' -f2

És a végső forma (azért így, mert a jó kis formázóm, a tohtml.com megfeküdt tőle):
for pr in $(ldapsearch -Y EXTERNAL -Q -LLL -b cn=ITTHON.CUCC,cn=krbcontainer,dc=itthon,dc=cucc -s one "(&(!(krbPrincipalname=*/*))(objectClass=krbPrincipal)(!(krbPwdPolicyReference=*)))" dn|perl -p00e 's/\r?\n //g'|grep -v '^$'|cut -d' ' -f2|cut -d',' -f1|cut -d'=' -f2); do kadmin.local -q "modprinc -policy default $pr" 2>&1 >/dev/null; done
Na, akkor ebből kell cron-feladatot készíteni.
Legközelebb a Samba-házirenddel igyekszünk dűlőre jutni.

Irodalom:
http://techpubs.spinlocksolutions.com/dklar/kerberos.html#id2500817
http://manpages.ubuntu.com/manpages/precise/man1/kadmin.1.html
http://nemo.its.uiowa.edu/reference/aix-krb5/krb5-app-ref.html#Header_359
http://nullege.com/codes/show/src@c@e@cerebrum-HEAD@cerebrum@clients@ceresync@backend@kerberos@kadm5.py
http://dbocklandt.be/networking/ldapsearch-without-all-the-line-wrapping/

1 megjegyzés:

Unknown írta...

Hello Ráérős rendszergazda,

I"m a big fan of your Howtos, I need your help in regards to openldap password policy

I have followed your password policy steps and it is working fine for the below defined the settings.(minimum length of the passwords, passwords expire, password history = 4)

Now we want to specify a password check module (to check for minimum upper cases, lower cases, digits, etc).

Please help, my email id : sateeshkumar14@gmail.com

Many Thanks
Satish