11 Ağustos 2010 Çarşamba

Pardus 2010 Yaz Stajı 8. Gün

Hazırlamakta olduğum guestlogin projesinde şimdilik giriş yapılabiliyor ve /home/ dizininin altında guestX şeklinde bir dizini ev dizini olarak gösteriyordu.

Geçici ve parolasız girilen bir hesap için fazlasıyla tehlikeliydi. Bunun için tmpfs ve mktemp komutlarını araştırdım. Tabi bir de kullanıcıyı ev dizini olmadan oluşturmaya baktım.

Öncelikle ev dizini olmadan kullanıcı oluşturmak gayet kolay. Komutumuz:

adduser -M kullanici_adi

şeklinde. -M ev dizini olmadan yarat anlamına geliyor.

mktemp komutu ile /tmp/ dizini içerisinde rasgele bir klasör oluşturuyoruz. Bunu da

mktemp -td guestX.XXXXXX ile yapıyoruz. Buradaki guestX bildiğimiz gibi misafir kullanıcıya vermiş olduğum geçici kullanıcı adı. Noktadan sonraki 6 tane X ise rasgele oluşturacak 6 rakam-harf karışımına denk geliyor. Yani oluşturulan dizin /tmp/guest6.6jHx4f gibi bir şey oluyor.

Buraya kolay bir şekilde gelmiştim fakat önümde biraz araştırmam gereken bir konu vardı. mktemp komutu o XXXXXX leri doldurup stdout a gönderiyordu bunu. Bunu da benim bir şekilde bir değişkene atayıp o dizini tmpfs ile bağlayıp bir de o kullanıcıya atayıp ev dizini yapmam gerekiyordu. Geliştiricilerden Serdar'ın yardımıyla birlikte python ile bunu yapmak için subprocess'leri araştırdım.

Dosyanın başına import subprocess yaptıktan sonra :

procOutput = subprocess.Popen(["mktemp -td %s.XXXXXX" % username], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
homeDir = procOutput.communicate()[0][:-1]

satırları ile çözüme ulaştım. Burda yaptığım iş tam olarak alt bir süreç başlatmak. yanına yazdığım diğer argümanlar sayesinde stdout ve stderr'i okuyabilecektim.

bu Popen fonksiyonunun geri dönüş değerini bir değişkene atadıktan sonra communicate() fonksiyonu ile bakabiliyordum. Aslında bu bile sonucu bir değişkene atamak için yeterliydi fakat sonuç şu şekildeydi:

('/tmp/guest5.d6E3gh\n', None)

bu haliyle benim işimi görmüyordu. Bunun de küçük bir düzenleme yaptım. İlk baştaki lazım olduğu için communicate() den sonra [0] ı kullandım. O değişkenin içinde de en son karakter \n olduğu için [:-1] ile en son karakteri attım. Sonuç olarak elimde sadece

/tmp/guest5.d6E3gh

kaldı ve bu benim için yeterli bir bilgiydi. Bunu homeDir değişkenine atadıktan sonra bunu tmpfs ile bağladım. Bunu da:

os.system("mount -t tmpfs -o mode=700 none %s" % homeDir)

ile sağladım. Sırada ise kullanıcıyı oluşturma, bu dizini kullanıcıya verme ve onun ev dizini haline getirmek vardı. Kullanıcının sistem tarafından verilmiş adını (guestX olan) username değişkenine daha önceden attığım için aşağıdaki komutlar bunlar için yeterli oldu.

os.system("useradd -M %s 2>> /var/log/guestacc.log" % username)
os.system("chown %s:%s %s" % (username, username, homeDir))
os.system("usermod -d %s %s" % (homeDir, username))

Burda dikkatinizi çeken bir şey de 2>> olmalı. Normalde >> komutu ile stdout'u başka bir dosyaya yönlendirebiliyoruz ama stderr yine ekrana düşüyor. stderr'in dosyaya yazılması için 2>> ekliyoruz.

Başlangıç ayarlarını bu şekilde halletmiştim bir de çıkışta da bu dizini umount edip, kullanıcıyı ve ev dizinini sistemden silmem gerekiyordu. İlk olarak /etc/pam.d/system-auth dosyası üzerinde kullanıcı çıkış yaparkan bir metotun çalışması için bir ekleme yapmam gerekiyordu. Bu da:

session sufficient pam_python.so guestlogin.py

satırı idi. Bu satırı:

session required pam_unix.so

satırının hemen üstüne ekledim. Bu satırı eklediğimde ek olarak:

pam_sm_open_session

ve

pam_sm_close_session

metotları çalışıyordu. Benim işime yarayan ise close_session metotuydu.

Bu metot içinden kullanıcı adını pamh.get_user(None) ile aldım fakat burada os.environ['HOME'] komutu işe yaramıyordu. Bunun için de :

homeDir = os.path.expanduser("~%s" % username)

komutunu çözüm olarak buldum.

Diğer umount işlemlerini de normal bir şekilde devam ettirdim. Ve kod daha iyi bir durumdaydı.

Şimdilik yapmam gerekenlerden biri /tmp/ nin içersinde öyle bir dizin olsa bile mktemp komutu guestX.XXXXXX dizinini oluşturmayıp ona bağlamamı sağlıyorsa bu bir güvenlik açığı olur. Bunun bir araştırmasını yapıp, gerekirse oraya bir kontrol koymak olacak.

Hiç yorum yok: