10 Ağustos 2010 Salı

Pardus 2010 Yaz Stajı 7. Gün

Bugün işe PAM'ı iyice araştırarak başladım. Nasıl modül oluşturulacağına kadar bir çok belge okudum ve geliştiricilerden sevgili Bahadır'ın da yardımıyla bu modülü Python ile yazmaya karar verdik.

Bunun için de pamobc gibi paketin de olduğu listeden pam_python'u kurmayı uygun gördük. kaynak kodunu
http://www.stuart.id.au/russell/files/pam_python adresinden indirdikten sonra tar ile açıp
./configure
make
sudo make install
komutları ile sorunsuz kurdum.

Kontrol amaçlı pam_python.so dosyasını /lib/security/ nin içerisine koyup koymadığına baktım ve oradaydı. Yani sıra gerekli modülümüzü yazmaktaydı.

Modülü yazmak için sıradan bir python betiği yazmamız gerekiyordu. Tek farkı bu betik dışarıdan çağırılacağı için, çağırıldığı yere göre belirli metotlara sahip olması gerekiyordu. Bu çağrıldığı yerler ise /etc/pam.d/ dizinin içinden seçilen dosyalar.

Mesela biz system-auth içerisine:

auth sufficient pam_python.so guestlogin.py

satırını ekledik. İlk sırada auth var çünkü kimlik denetimi sırasında çalışmasını istiyoruz. Sufficient ise bunun yeterli olduğunu söylüyor. Diğerleri ise pam_python kullanılacağını ve guestlogin.py betiğinin kullanılacağını söylüyor.

İlk başta merak ettiğiniz soru guestlogin.py dosyası nerede olacak olabilir. Çözümü basit, tahmin edilen ilk yer gibi pam_python.so dosyasıyla aynı yerde yani varsayılan olarak /lib/security/ dizininin içerisinde.

Bu dosyanın içerisinde bulunması gereken metotlar:

def pam_sm_authenticate(pamh, flags, argv):

ve

def pam_sm_setcred(pamh, flags, argv):

metotları. Tabii ki şimdilik bunlar lazım. Çünkü system-auth dosyasında ilk başa auth yazdık. Diğer yazacağımız account, session, password için farklı metotlara ihtiyaç duyuyor pam_python.

Ben şimdilik sadece pam_sm_authenticate metotunda işlem yapıyorum. Öbür metot olan pam_sm_setcred ise pamh.PAM_SUCCESS değerini döndürüyor. Bu da bu aşamadan geçmesini sağlıyor.

İlk iş olarak, pam_sm_authenticate metotunda ilk olarak oturum açıldığında /tmp/ nin içerisinde bir dosya açıp onun içerisine herhangi bir şey yazdırmakla başladım. Sonuç başarısız. Auth.log, syslog ne varsa inceledim bir sonuç elde edemedim. Sorun acaba pam_python da mı diye biraz bakındım ama olma ihtimali da pek yüksek değildi. Kafayı yemeden yemek yemeye gittik.

Dönüşte Bahadır ile beraber debugging yaptık. /etc/pam.d/system-auth dosyasındaki sırayla oynadık. Öncelikle en altta idi. Bir yukarıda da sonuç değişmedi. Sonra pam_unix.so nun üzerine koyduk. Ve çalıştı. Meğersem PAM, pam_unix.so çalıştıktan sonra alttakilere hiç bakmıyormuş.

Bu şekilde bu sorunu çözdükten sonra auth.log dosyasına düşen bir şey yüzünden çalışmadığını ve çalışmayacağını anladım. Sorun /usr/lib/libpython2.6.so.1 dosyasının bulunmamasıydı. pam_python paketi bu dosyayı arıyor ve bulamayınca çalışmıyordu. Bunun için şimdilik bir çözüm olarak orada libpython2.6.so.1.0 a sembolik link olacak şekilde aradığı isimde dosya oluşturdum.

Bu sorunu da hallettikten sonra sırada bizi bambaşka ve çok önemli bir sorun bekliyordu. Şimdi bizim yapmamız gereken eğer kullanıcının ismi guest ise parolasız olarak direk konsola düşmesini sağlamaktı. Bunun için de metotun içerisine kullanıcı adı eğer guest ise pamh.PAM_SUCCESS sonucunu döndürerek konsola düşmesini sağlayacak kod yazdım. Kod çalışıyor lakin konsola düşmüyordu. Ne olabileceğini düşünürken Bahadır'ın aklına gelen nss (nameserverswitch) hayallerimizi biraz yıktı diyebilirim. Login işlemi sırasında nss den alınan ev dizini bilgisi kullanılıyordu ve bizim de buna çok ihtiyacımız vardı çünkü guest adıyla giriş yapmaya çalışan birisine ev dizinini bizi oluşturup tmpfs ile bağlayıp atamamız gerekiyordu. /etc/nsswitch.conf dosyasının içine baktığımızda da işe yarar bir çözüm bulamadık. NSS'ye modül yazma araştırmasından da bir çözüm çıkmayınca bu sorunun etrafından dolaşarak (workaround) bir çözüm bulma çabalarına girdik. Çözüm şu şekildeydi:

eğer girilen kullanıcı adı guest ise pwd yi kullanarak sıradaki ilk guestX (X bir tamsayı)'i buluyor, os.system()'i kullanarak adduser ile guestX adlı kullanıcıyı oluşturuyor ve pam ile bu kullanıcıyı buna atıyorduk. PAM'ın yaptığı girilen kullanıcının ismini (username) guestX yapıp konsola düşmesini sağlıyor. Bu şekilde hem kullanıcı hem de ev dizini yaratıyorduk. Tabi bu şimdilik bir çözümdü, ilerde (belki de bu yazıyı yazdıktan sonra :)) tmpfs ile bir klasörü bağlayıp kullanıcının ev dizini olarak onu belirleyecektik.

Buradaki guestX'in de elde edimini pwd modülünü kullanarak sağlıyorum. Kod parçacığı aşağıdaki şekilde:

users = [x.pw_name for x in pwd.getpwall()]
i = 1
while guest_name + str(i) in users:
i = i + 1

önce users değişkeninin içerisine bütün kullanıcı listesini atıyorum. Sonra da bunun içerisinde guestX var mı diye bakıyorum. Eğer var ise guest1,2,3... diye ilerliyor.

Burada kullanmış olduğum guest_name ise misafir kullanıcının adının tutulduğu değişken (mesela varsayılan olarak "guest" oluyor)

Şimdilik bu çözüm üzerinden giderek guest ile giriş yapılmasını sağladım. Sorun yok gibi gözüküyor. Tabi sıradaki ilk iş kullanıcı çıkış yaptığında da kullanıcının ve ev dizininin silinmesi.

Hiç yorum yok: