30 Ağustos 2010 Pazartesi

ptsp_installer ve guestlogin projeleri çalışmaları

ptsp_installer projesi ile ilgili, daha önce de yapacağım dediğim, dosyaları düzenlerken girdilerin varlığı kontrolünü ekledim.

Şimdilik hosts ve exports dosyasındakilere bakıyor, dhcpd.conf dosyasında eskisi gibi kalıyor. Bu kontrolü ilk başta:

for line in file_pointer.readlines()

şeklinde yapıyordum. Fakat bu şekilde yapmanın bir açık/sorun yaratabileceğine karar verdim ve bu döngülerden önce:

orig_exports = file_pointer.readlines()

ya da

orig_hosts = file_pointer.readlines()

yapıyor ve ondan hemen sonra da:

file_pointer.close()

yaparak dosya ile işimi bitiriyorum.

Bundan sonra da for döngüsü ile satır satır okuyarak içinde IP'leri arıyorum. Eğer yok ise bunları bir string'e aktarıyorum. En son ise dosyayı "w" modunda oluşturarak (yok ise yarat var ise üzerine yaz) hepsini:

file_pointer.writelines(new_hosts)

veya

file_pointer.writelines(new_exports)

ile yazıyordum. Şimdilik bunlar sorunsuz çalışıyor. Bir sonraki iş olarak dhcpd.conf dosyasını da bu şekilde düzenlemek var.

Guestlogin projesinde de en son Onur'un fikri olan girişte parola sorma fikrini nasıl uygularız diyordum ve aklıma daha önce de gelmiş olan başka birisinin o kullanıcı adı ile giriş yapmasını nasıl engelleriz diye düşündüm. Ben, guestlogin.py üzerinden eğer kullanıcı adı guestX şeklinde ise reddet desem bile bir sonraki modül olan pam_unix burdan giriş yapılmasına izin verecektir.

Şimdilik aklıma bununla ilgili bir çözüm gelmiyor ama bunun bir sorun olacağı kanaatindeyim çünkü bu kullanıcı çıkış yaparken bütün verileri de silinecek ve öbür oturumdaki kullanıcının oturumu muhtemelen kilitlenecek. Bunu önlemenin bir yolunu bulmak lazım.

28 Ağustos 2010 Cumartesi

Pardus Yaz Stajı

Son olarak kısa bir kaç şey yazmak istedim.

Bence bir bilgisayar mühendisinin ve ya Linux ile ilgilenen, kendini geliştirmek isteyen herhangi birisinin kesinlikle gelip görmesi/staj yapması/çalışması gereken bir yer. Ben 20 iş günlük staj süresi boyunca bir çok şey öğrendim. Geliştiriciler hakikatten çok iyi insanlar. Yani kelimeler ile anlatmak gerçekten mümkün mü bilmiyorum ama süper diyelim şimdilik. (bir kelime bulursam ya da bulunursa yazacağım bunu :) )

Buradan herkese tek tek teşekkür ediyorum. Bana bu staj süresinin çok zevkli geçmesini sağladılar. Her gün yeni bir şeyler öğrenme heyecanı gerçekten çok güzel bir şey. (zaten böyleydi ama burada ve Necdet Hoca'nın yanında gerçekten bir başka oluyor bu)

Süper ya :)

27 Ağustos 2010 Cuma

Pardus 2010 Yaz Stajı 20. (Son) Gün

Eveeeet, işte geldik stajın son gününe. Bugün ayrıca yaptığımız projeler ile ilgili bir sunum yapacaktık. Sunumlarımızı yaptık ve stajlarımızı tamamladık.

Sunumlara geçmeden önce yaptıklarımdan bahsedeyim. Öncelikle kdm için yapmış olduğum yamadaki ufak bir hata (aslında blog'a doğru yazmış olduğum ama yamaya yanlış geçirdiğim) sorunu çözmemi biraz geciktirdi. Bugün Fatih'in göstermesi sayesinde SVN'deki yamayı düzelttim. Son yama, Pardus 2009 için hem guestlogin'in hem de AutoLogin'in sorunsuz çalışmasını sağladı.

Yamanın eski hali şu şekilde idi

if (!curuser || psrv != "kde4-np" )

burda psrv'nin tipi char'a pointer olduğu için bir adres döndürüyordu ve "kde4-np" dizgisi (string) de bir adres döndürüyordu ve doğal olarak bunlar aynı olmuyordu. Bu yüzden yama yüzünden AutoLogin çalışmıyordu. Fakat bunu denemek için yazılan ufak C kodu çalışabilir çünkü psrv = "kde4-np" dediğinizde sanırım bir eniyileştirme (optimizasyon) yapılarak adresler eşitleniyor böylece yukarıdaki if sorunsuz çalışıyor. Ama kesinlikle yanlış. Demek ki dikkat etmek gerekiyormuş, dalgınlığa gelmiyor :)

Yamanın sondan bir önceki hali şu şekilde idi: (sadece if kısmı, zaten sadece burası değişiyor)

if (!curuser || strcmp(psrv, "kde4-np") ) {

Fakat sunum sırasında Onur bunun yerine strncmp kullanmamın daha güvenli olduğunu söyledi, anladığım kadarıyla strncmp ile strcmp arasındaki fark da strncmp yaparken ikinci verdiğimiz parametrenin uzunluğu kadar karşılaştırma yapıyor. Yamada bu olay daha iyi anlaşılıyor. Yamanın son hali:

if (!curuser || strncmp(psrv, "kde4-np", strlen("kde4-np"))) {

yani burda karşılaştırma "kde4-np" nin boyutu kadar olacak. Tabiki de bu yamayı da upstream'a yolladım. Upstream'a bizim yama haricinde KDM'deki bug'un çözümü olan yamayı da yolladım. Aradaki tek fark || yerine && kullanıyor olmam. Bunun sebebi de bizde PluginsLogin=generic iken curuser NULL olması gerekirken bir değer atanıyor. (kullanıcı adı) Bu yüzden OR kullanıyorum. KDM'deki bugda da buraya girmesini engellemek gerekiyor. (AutoLogin aktif iken) Bunun için de AND ile "kde4-np" ye eşit olup olmadığını kontrol ediyorum.

Ayrıca bugün bir de bu projeyi Pardus 2011'de de denedim. İlk olarak pam_python paketini oluşturmam gerekiyordu. Zaten review'de olan paketin inşa dosyalarını SVN ile çektikten paketini yapmaya çalıştım fakat henüz python-sphinx paketi daha depoya girmediği için hata veriyordu. Makefile içerisinde dökümantasyonu kapatıp bunu bir yama ile inşa dosyalarına koydum ve paket sorunsuz oluştu. Kurulum da sorunsuz tamamlandı. Guestlogin ile ilgili yapılandırma ve betik dosyalarını gerekli yerlere koyduktan sonra /etc/pam.d/system-auth dosyasında gerekli eklemeleri yaptım. Konsolda sorunsuz çalışıyordu. Sırada KDM vardı. KDM'de çalışabilmesi için kendi yamamı 2011'deki kdebase-workspace'in içine koyup derlemem gerekiyordu. Derleme sırasındaki bir kaç bağımlılıkla ilgili olan sorun sebebiyle (derleme zamanı bağımlılığı eksikliği: akonadi-devel ve docbooc-xml4_2) derlenmiyordu. Bunları Fatih'in yardımıyla hallettim. Aynı zamanda da bu eksiklikleri paket sorumlusuna da bildirdim. İkilik dosyalar oluştuktan sonra KDM'yi sistemden kaldırıp yeni oluşturduğum halini kurdum ve sorunsuz çalıştı. Yani projem Pardus 2011'de de çalışıyordu.

Bir de Onur'dan gelen bir istek olan, misafir kullanıcı giriş yaptığında kullanacağı parolanın sorulmasını araştıracağım. Mesela KDE'de oturup kilitlendiği zaman kullanıcının parolası soruluyor. Aslında misafir kullanıcı sırasında bu kapatılabilir ama parola işlemi mantıklı gözüküyor. Bunu araştırıp uygulamaya çalışacağım.

Şimdilik aklıma gelenler böyle, tabi ki de Pardus'a vereceğim desteğe her zaman devam edeceğim. Bu zaten staj ile sınırlı değildi (daha öncesinden) ve bundan sonrasında da devam edecek.

Ayrıca yapmış olduğum sunumu SVN'e koyacağım. Koyduktan sonra buraya yine adresi vereceğim.

Staj boyunca bana her konuda yardımcı olan herkese, bütün Pardus çalışanlarına çok teşekkür ediyorum.

Staj bitti diye de yazmayı bırakmayacağım tabi ki. Araştırmaya, kendimi geliştirmeye, bir şeyler öğrenmeye devam edeceğim. Ve bunları da buradan aktarmaya çalışacağım.

26 Ağustos 2010 Perşembe

Pardus 2010 Yaz Stajı 19. Gün

Artık Pardus 2010 Yaz stajında son günlere geldik. Proje ile ilgili son sorunlardan birisi olan KDM'ye giriş yapamama ile ilgili başka gelişmeler oldu. Aslında dün hallettim dediğim KDM hallolmamıştı. Başka sorunlar çıktı.

Daha önceden Oswald ile konuştuğum kadarıyla PluginsLogin'i generic yaptığımda istediğim gibi çalışması gerekiyordu. Fakat bizim depoya aldığımız KDM'nin 2 yaması:

same-pam-generic-classic.diff

ve

kdm-fix-generic-greeter.diff

PluginsLogin generic olsa bile classic'miş gibi davranmasına sebep oluyor. Yani kdm/backend/client.c dosyasındaki curuser değişkenine bir şey atamaması gerekirken bir şeyler atıyor. Bununla ilgili nasıl bir çözüm bulabileceğimizi Oswald'a sordum ve haftasonundan sonra halledebileceğimizden bahsetti.

Şimdilik kendi eklediğim yama ile sorunsuz çalışıyor. Biraz daha düzeltme yapmam gerekecek tabi. Tam olarak çalıştığına karar verdiğim halini yine buraya yazmayı düşünüyorum.

Bir de KDM'nin açılış ekranında ek bir menü mü yoksa buton mu koysak konusunda kararsız kalıyorum. Eğer buton koyar isek görünür olup olmamasını kdmrc dosyasına koyacağımız

guestlogin

değişkeni ile sağlayabiliriz. Yani eğer guestlogin true ise buton görünecek, değil ise görünmeyecek. Tabi hem bunun için hem de PluginsLogin için pardus-air temasının xml dosyasını buna göre düzenlemem gerekecek.

Ya da başka bir fikir olarak kdmrc dosyasının içine herhangi bir değişken koymadan, xml dosyasından 2 tane oluşturup biri guestlogin'li diğeri ise guestlogin'siz yapabilirim. Guestlogin'lide buton olur.

Bugün Pardus 2011'in Alpha'sı çıktı. Bunu test etmek için sanal makina'ya bunu kurdum. Öncelikle X'in açılabilmesi için sistem açılırken (ve kurulurken) kernel'e (grub sırasında)

xorg=driver:fbdev

parametresini giriyorum. Bu parametre sayesinde kurulumu tamamladıktan sonra yeniden başlatınca sistem açılmadı. Onur'un ve Gökçen'in çalışmaları sonucu sorunu çözüldü. Anladığım kadarıyla sorun, YALI'da sistem saatinin değiştirilmesinden kaynaklanıyor. YALI saati yanlış ayarladığı için onu düzeltmiştim.

Ayrıca bugün bir şey daha oldu. Serdar'ın uğraştığı ve configure işlemi tamamlandıktan sonra make sırasında tekrar configure dosyasını çağırması sonucu make işlemi patlayan bir paket var, libmpcdec.

En sonunda hatayı çözmüşler ama bana söylemeden hadi bu kodu derle dedi Onur. :). Hmmm diyerek başladım uğraşmaya, sorun aslında basit gibi görünüyordu ilk configure'de sorun olmadığına göre ikinci kez yapılan configure'ü bir şekilde kapatırsam sorun çözülecekti. Configure'ün çağırıldığı yerdeki yazan yazıyı grep'leyip kaynak kodda araştırdım. config.status'de çağırılıyor. Ve düzeltmek için ./configure sırasında oluşturulan "config.status" dosyası içinde ufak bir değişiklik yaptım. Sorunsuz derleniyordu ama neden configure'u tekrar çağırıyordu? Tam olarak bir çözüm bulamıyordum. Onur geldi ve benim bunun neden olabileceği konusunda düşünmeme yardımcı oldu. Sonuç olarak sorun configure.ac dosyasının configure'den yeni olmasıymış. Yani makefile bir yerde bu dosyanın tarihini kontrol ediyor ve tarihi yeni olduğu için bu dosyanın değiştirildiğine kanaat getirip tekrar configure'ü çalıştırıyor.

Bana yukarıda yazdığım deneyimi yaşattığı için buradan tekrar Onur'a teşekkür ediyorum. Ayrıca sabahki yapmış olduğu disk kurtarma operasyonu ile kendisinin bu konulardaki (Linux vb.) bilgisine olan +sonsuzdaki saygımı yine +sonsuz ekleyerek +sonsuza götürmüştür.

25 Ağustos 2010 Çarşamba

Pardus 2010 Yaz Stajı 18. Gün

Artık Pardus 2010 Yaz Stajının son günlerine yaklaştık. Elimde bir adet sorun vardı. Ve yeterince büyüktü. KDM üzerinden giriş yapamıyordum.

Daha önce düşündüğüm gibi

if (!curuser)

yazan yere şimdilik

if (!curuser || strcmp(curuser, "guest") )

olarak değiştirdim ve çalışacak mı diye denedim. Çalıştı. Fakat bu biraz kötü bir çözüm yoluydu. Bununla ilgili upstream ile konuştum.(Oswald Buddenhagen) Bunun yanlış bir yöntem olduğunu ve kdmrc dosyasında

PluginsLogin=generic

yaparsam zaten curuser ataması yapılmadığı için o bloğa girileceğinden bahsetti. Denediğimde çalışmadı çünkü bizim (Pardus) varsayılan temamız "pardus-air" bu kimlik doğrulama metodunu kabul etmiyordu. Değiştirip "oxygen-air" yaptığımda sorunsuz çalıştı. Ama bu sefer de AutoLogin aktif iken çalışmıyordu.

Bununla ilgili hata mesajlarını Oswald'a yolladım ve bunun bir bug olduğuna karar verdik.

Bu hata mesajlarını incelerken dikkatimi çeken şey ise AutoLogin aktif iken PAM doğrulama metodu "kde4-np" yani nopassword girişi. Bu "kde4-np" değerini tutan değişken ise psrv değişkeni. Bunun pam dosyasına baktığımda ise:

#%PAM-1.0

auth required pam_nologin.so
auth required pam_permit.so

satırlarını görüyorum auth bölümünde. Sadece bunlar olduğu için ve bu modüller de kullanıcı adını pek önemsemeden girişe izin verdiği için pam_get_item() fonksiyonunda çakılıyor KDM.

AutoLogin kapalı iken PAM doğrulama metodu "kde4" olarak seçili. Bunun üzerine bir başka yama daha yaptım.

Bu yama

if (!curuser) {

satırını

if (!curuser && psrv != "kde4-np" ) {

olarak değiştiriyor. Bu şekilde denediğimde sorunsuz olarak çalıştı. Bunu upstream'a da yolladım. Aslında doğru bir yöntem değil ama en azından çözüm yolundan bahsetmek açısından yaptım bunu. Bunun yerine de eğer AutoLogin aktif ise curuser in boş olmaması gibi değişiklikler yapılırsa sorunun halledilebileceğinden de bahsettim.

Son aldığımız başka bir karar da KDM ekranında alttaki menüler gibi ayrı bir menü olsun ve simgesi anahtar olsun. (girişi simgelemek adına)

Bu menünün içine bir yandaki kapat, x i yeniden başlat'ın olduğu yerin ordaki konsol girişi ve uzaktan girişi alıp bir de misafir girişini ekleyecektim.

Bu misafir girişi temel olarak kullanıcı adını /etc/security/guestlogin.conf dan alıcak ve kullanıcı adına yazacak sonra da giriş yapacak.

Şimdilik bunun üzerine araştırmalar yapıyorum. Oswald'ın da yardımları sayesinde sanırım menü ekleme işi gayet kolay olacak.

24 Ağustos 2010 Salı

Pardus 2010 Yaz Stajı 17. Gün

Bugün ptsp_installer projesine ufak bir ekleme yaptım. Bu ekleme her adım çalışmadan önce çalıştırılsın mı diye sormak. Henüz bunun kesinlikle kalıp kalmaması konusunda emin değilim ama bence böyle olması daha iyi çünkü bazı dosyaları güncellemek istemeyebilir. (daha önceden güncellenmişi olabilir)

Bunu yaptıktan sonra Pardus Bugzilla'sında benim eklemiş olduğum yamadan sonra oluşan hatayı inceledim. Kendim hatayı tekrarlayamıyordum. Hatayı alan arkadaşın kdmrc dosyasını incelediğimde "AutoLogin" özelliğinin aktif hale getirildiğini fark ettim. Bunun için kendi kdmrc dosyamda da bunu açtım. Fakat yine hata ile karşılaşamadım. Biraz daha araştırdıktan sonra AutoLoginDelay=0 olduğunu gördüm. Bunu uyguladığımda hakikatten kdm'nin çöktüğünü fark ettim. Kdm yi tekrar:

kdm -debug 1

ile açtıktan sonra "/var/log/syslog" dosyasını inceledim. Benim kaldırdığım if bloğu her zaman çalıştığı için orada çakılıyor.

Yaptığım yamayı kaldırdığımda ise bu sorun düzeliyor. Bunun için çözüm arayışlarındayım.

AutoLoginDelay aslında 0 haricinde bir değer olsa sorunsuz çalışıyor ve kdmrc dosyasında '#' lı halinde AutoLoginDelay=10 olarak verilmiş ve varsayılan da 0 gözüküyor. Bunu kullanıcının elle mi oluşturduğunu araştırırken YALI'da eğer otomatik giriş seçilirse bunun 0 olarak ayarlandığını fark ettim.

Öncelikle tahminime göre AutoLoginDelay=0 ise KDM, PAM'i ya çağırmıyor ya da başka bir şekilde çağırıyor ki pam_get_item() fonkisoyunda sorun çıkıyor.

Bunu önlemek için de aklıma bir kaç yöntem geldi.

Başlangıç olarak kdmrc ye

guestlogin=true

satırını ekleyip buna göre o if bloğunu çalıştırmak olabilirdi

if(!curuser || guestLogin)

şeklide mesela. Ama burada da hem guestlogin aktif olup hem de AutoLoginDelay=0 olduğunda sorun olurdu ki bu da istenebilecek bir şey bir şey.

İlk olarak sorunu anlamamıştım ama o if bloğu ile ilgili bir şey olduğunu düşünüp oraya girip girmemesini kontrol etmek adına kullanıcı adını pam_get_item() ile çekiyor ve daha önce çekilmiş olan kullanıcı ismi olan curuser ile karşılaştırıyordum. Fakat bu kodda da kullanıcı adını çekerken sorun olduğunu fark ettim ve sorunun yukarıda da dediğim gibi PAM'ın çağrımı ile ilgili olduğunu düşündüm.

Şimdilik aklımda 2 çözüm var, bunları uygulayacağım.

1. si eğer kdmrc dosyasında

guestlogin=true

ise ve PAM'dan gelen kullanıcı adı eğer

/etc/security/guestlogin.conf (aslında burayı da kdmrc ye koyabiliriz, sonuçta günün birinde bunu değiştirmek istediğimizde kodda tekrar değişiklik yapmamız gerekecek) dosyasındaki

guestname=

satırındaki eşitliğin sağ tarafına eşit ise if bloğu çalışsın diyebilirim. Ya da

yine kdmrc dosyasında

guestlogin=true

ise bir şekilde PAM'in çalışıp çalışmadığını kontrol edip (pamh değişkeninden olabilir belki) ona göre if bloğu çalıştırılabilir.

Bunlar ile ilgili araştırma ve uygulamayı yarın yapmayı düşünüyorum.

23 Ağustos 2010 Pazartesi

Pardus 2010 Yaz Stajı 16. Gün

Eklemem gereken fonksiyonların tamamını ekledim. Şimdilik ptsp_installer projesi de temel hatlarıyla tamamlandı diyebilirim sanırım.

Tabi ki bunun üzerine iyileştirmeler yapmam gerekecek. Şimdilik iyice test ettikten sonra bunlara bakmayı düşünüyorum. Ağ profili oluşturma işi biraz uğraştırdı ama MÜDÜR'ün network.py betiğine bakarak hallettim.

Ayrıca Ağ Profili oluştururken, durumu değiştirme(up/down), ağ kartını listeleme, profilleri listeleme gibi işlemleri fonksiyon fonksiyon yapmanın da bayağı faydasını gördüm. Mesela hem yeni profil oluştururken hem de var olanı aktif ederken durum değiştirme fonksiyonunu kullanıyorum. İleride başka şeyler lazım olduğunda da çok fazla uğraşmadan ekleyebileceğim. Bunların yanı sıra kodun okunabilirliği de artıyor.

Daha önceden de yazmış olduğum yapılandırma dosyasındaki boşluk sebebiyle oluşturmuş olduğum set_key_with_spaces ile set_key fonksiyonlarını birleştirdim.

En sonuna da white_spaces == true ise ona göre işlem yap dedim.

Bir önceki proje olan guestlogin'de sevgili Gökçen ve Koray ile ufak bir şeyler ekleme kararı aldık.

KDM ekranındaki kapat ikonunu açıldığı listeye Misafir Girişi diye bir şey ekleyip, orada tıklandığında giriş yapılmasını sağlamak.

Bunun için bir de kdmrc dosyasına:

guestlogin = true

gibi bir satır eklenerek o listede Misafir Girişinin olup olmayacağı ve KDM için Misafir Girişinin sağlanıp sağlanamayacağını kontrol edeceğim.

Bu arada da ptsp_installer projesinin iyileştirme çalışmaları devam edecek.

ptsp_installer projesi çalışmaları

Ptsp_installer projesinin çalışmaları iyiye gidiyor diyebilirim.

Hafta sonunda bir kaç fonksiyon daha ekledim. Şimdilik en önemli ihtiyacım olan ağ profili oluşturma ve gerekli bilgileri alma fonksiyonunu sonraya bıraktım. Yeni eklediğim fonksiyonlar:

hosts dosyası güncelleme
exports dosyası güncelleme
pts-client.conf dosyası güncelleme

fonksiyonları. Bu dosyaları güncelleyebilmem için sunucu adresi (ip address), ağ maskesi adresi (netmask), ağ geçidi adresi (gateway) gibi adreslere ihtiyacım var. Bunları ilerde ÇOMAR ile alacağım ama şimdilik elle verdim.

Bir de hosts dosyasını düzenlerken kullandığım bir yöntem var. IP adresini aldıktan sonra onun en sonunu alıyorum ve ona istemci sayısına gelene kadar o anki istemciyi ekliyorum.

10.0.0.1(+1)
10.0.0.1(+2)

gibi. IP den maskelerken bunu int() in içinde yapıyorum. Yoksa onu da string olarak algılıyor ve ekleme yapamıyorum.

Karşılaştığım bir sorun ise pts-client.conf dosyasındaydı. Kdmrc dosyasını düzenlemek için kullandığım fonksiyon bunda pek işe yaramıyor çünkü bunda eşittir('=')'den önce ve sonra birer boşluk var. Bunu çözmek için şimdilik set_key fonksiyonunun yanına bir de set_key_with_spaces diye bir fonksiyon daha yarattım. Daha iyi bir çözümü olabilir ona da bakacağım. Bunlardan biri mesela set_key fonksiyonuna bir tane daha değişken alıp oradan dosya ismi pts-client.conf ise ona göre boşluklu atama yap ya da boşluksuz atama yap derim.

Şimdilik durum böyle. Eklemem gereken sanırım 3 tane fonksiyon kaldı. Çalışmaya devam.

21 Ağustos 2010 Cumartesi

Pardus 2010 Yaz Stajı 15. Gün

PTSP installer projesinde, paketlerin kurulu olup olmadığını kontrol ettikten sonra sıradaki iş olarak "kdmrc" dosyasını güncellemeyi yaptım.

Bunu yaparken ilk başta aklıma ConfigParser ile o dosyayı okuyup, gerekli değişikliği de set() fonksiyonu ile sağlamaktı. Fakat bu komut tam olarak istediğim işi yapmıyor. Ben, verdiğim parametrelere uyan değişkeni dosyanın içinde bulup değiştireceğini düşünüyordum fakat yanılmışım.

Bununla ilgili araştırmaya devam ettim. Sonuç olarak, Gökçen'in YALI için yazmış olduğu kdmrc düzenleme fonksiyonunu kullandım. Tam olarak işimi görüyor bu fonksiyon. Bu fonksiyon, YALI'nın kaynak kodundaki users.py betiğinin içindeki setKey fonksiyonu.

Bunu da hallettikten sonra sıradaki iş olarak servisleri başlatmayı yazmaya başladım. Bunun için ÇOMAR API'si kullanacağımı biliyordum.

ÇOMAR API'si ayrıca bana ağ profilinde de lazım olacaktı. Temel olarak bunu kullanabilmek için:

link = comar.Link()

satırını ekledikten sonra,

link.System.Service["servisadi"]

şeklinde erişebiliyordum. info() ile gerekli bilgilere erişiyordum, bununla çalışıp çalışmadığını kontrol edip eğer çalışıyorsa stop() ile durdurup sonra da start() ile başlatıyordum.

Yani:

link.System.Service["dhcp"].info()[2].find("on") veya .find("started") ile çalışıp çalışmadığını kontrol ediyor. Eğer çalışıyorsa:

link.System.Service["dhcp"].stop() ve sonra da

link.System.Service["dhcp"].start() satırlarını ekleyerek, servis başlatma fonksiyonunu tamamlıyorum. Tabi ki de bu servis işlemlerini bir try-except bloğu içerisinde yapıyorum ki herhangi bir servis başlatılamadığı zaman onunla ilgili uyarı verdirip betiği sonlandırabileyim.

Bunu da tamamladıktan sonra sırada ağ profili oluşturma var. Bu sefer de yine ÇOMAR API'sini kullanacağım.

Henüz bunu bitirmedim ama uygularken MÜDÜR'ün network.py adlı betiğinden ve iptables paketinin firewall.py betiğinden de yararlanıyorum.

Şimdilik bütün ağ aygıtlarını listeleyip (kablosuz ağ aygıtları şimdilik desteklenmediği için onları listelemiyorum) o aygıtı seçtirebiliyorum. Sıradaki iş ise o aygıt üzerinde var olan profilleri listelemek olacak.

Bir de servisleri ve gerekli paketleri en yukarıya bir listede tutmamın bana büyük faydası oldu. Öncelikle "for x in y" şeklinde hepsini sırayla gezebiliyorum, bu kolaylığı sağladı hem de ilerde bir gün bir paket ekleneceği zaman en yukarıya sadece eklemek yeterli olacak. Tek tek nerede bakıyor buna diye aramaya gerek olmayacak.

19 Ağustos 2010 Perşembe

Pardus 2010 Yaz Stajı 14. Gün

Yapmaya karar vermiş olduğum /etc/pam.d/ içerisindeki dosyaları düzenleme projesinin epostalaşmış olduğum Debian geliştiricisi tarafından Perl ile yazıldığını öğrendikten sonra bu projeden vazgeçtim.

Var olan projeye "http://bazaar.launchpad.net/~ubuntu-core-dev/pam/ubuntu/files/head%3A/debian/local/" adresinden ulaşabilirsiniz.

Bu adresteki pam-auth-update adlı betik bu işi yapıyor. Ayrıca pam-auth-update.8 isminde bir man dosyası var.

Bunun üzerine başka proje arayışlarına geçtim ve Bahadır ile PTSP kurulum betiği hazırlamaya karar verdim.

Öncelikle PTSP nedir ile başlayayım.

PTSP, ince istemciler için bir çözümdür. Yani bir tane sunucu üzerinde PTSP sunucu çalışacak ve diğer istemciler ağ kablosu üzerinden ona bağlanacak. Bu bağlantı ile X üzerinden de işlemler yapmak mümkün, yani bildiğiniz Pardus kullanıyor olacaksınız ama bir sunucu üzerinde. Aynı zamanda da benim hazırlamış olduğum Misafir Kullanıcı projesi de PTSP ile çalışması çok faydalı olacak.

Bununla ilgili bir belge pardus wikisinde var.

Adresi: http://tr.pardus-wiki.org/NASIL:PTSP

İlk iş olarak ben bu adres üzerindeki işlemleri yapıp PTSP sunucu yaratıp, hem nasıl çalıştığını anladım hem de PTSP ile beraber Misafir Kullanıcı'yı deneme fırsatı buldum.

Sonuç güzel, gördüğüm kadarıyla sorunsuz çalışıyor. Hem sunucudan hem de istemciden "guest" ismi ile bağlandım. İkisine de ayrı isimler ve ev dizinleri belirleyip sorunsuzca çalıştırdım.

Şimdi ise sırada bu yaptığım işlemleri yapacak bir betik hazırlamak.

Hazırlıklara başladım. http://svn.pardus.org.tr/uludag/trunk/playground/intern/ptsp-installer içerisindeki TODO dosyasındaki işlemleri sırasıyla yapacağım. Bu TODO dosyasını yukarıda vermiş olduğum Pardus wikisindeki belgeden yararlanarak oluşturdum.

Şimdilik gerekli olan paketler kurulu mu diye kontrol eden bir metot yazdım. Bu metotta PiSi'nin API'sini kullandım.

Yapılandırma dosyalarını düzenlerken dikkatli olmam gerekiyor. Diğer ihtimalleri göz önünde bulundurarak bunu yaptıktan sonra geriye kalan işlemler pek de zor gözükmüyor.

18 Ağustos 2010 Çarşamba

Pardus 2010 Yaz Stajı 13. Gün

Bugün halihazırda tamamlamış olduğum kod üzerinde bir kaç iyileştirme yaptım. README, AUTHORS ve COPYING dosyalarını düzenledim.

Yaptığım iyileştirmeler, eğer yapılandırma dosyasında değer atanmamış ise varsayılan değerleri kullanacak. Başlangıçta eğer sistemde guest_name isminde bir kullanıcı var ise modülü çalıştırmayacak, guest_group isminde bir grup yok ise bunu oluşturacak ve en önemlilerinden birisi ise ev dizinini bağlarken noexec özelliği ile bağlamak.

noexec bize önemli derecede güvenlik sağlıyor. Bu özellik sayesinde kullanıcı bağlandığı ev dizini içerisinde ikilik dosya çalıştıramayacak. Aynı zamanda da kendisi de ikilik dosya yazıp bunu çalıştıramayacak.

Varsayılan değerleri kullanma kısmını da, yapılandırma dosyasını okurken bir hata oluşursa except bloğuna geçip aktarıyor ve hata ayıklama (debug) modunda ekrana dosya okunamadı diye hata veriyor ya da değerleri okurken boş çıkar ise onun varsayılan değerlerini aktarıyorum.

Kullanıcının varlığını ise pwd.getpwnam() ile sorguluyorum. Bunu try-except bloğu içerisinde yapıyorum. try içerisinde bu başarılı olur ise geriye başarısız diye değer döndürüyor, eğer başarısız olur ise except bloğuna geçiyor ve burada da hiç bir şey yapmadan normal koda devam ediyor.

Grubun varlığını da grp.getgrnam() ile sorguluyorum. Yok ise yine hata ayıklama modunda ekrana grup bulunamadı, grup oluşturulacak yazıyor ve grubu "groupadd %s" % guest_group ile oluşturuyorum.

Ayrıca daha önceden /etc/pam.d/ içerisindeki dosyalardaki control yerine uzun uzun yazılar yazıyorduk. Sadece sufficient yazmak yeterli şu an. Daha önceden de yazdığım yazıda bunu düzelteceğim.

Bahadır'ın aklındaki bir proje olan /etc/pam.d/ içerisindeki yapılandırma dosyalarını düzenleme projesini biraz araştırdım ve bunu Ubuntu'da yapmakta olan birileri olduğunu öğrendim.

İstek ise şu adreste: https://blueprints.launchpad.net/ubuntu/+spec/pam-config-framework

Ayrıca 2003 yılında da http://www.mail-archive.com/debian-wnpp@lists.debian.org/msg18384.html adresinde belirtildiği gibi istenmiş fakat zaman aşımından kapanmış.

Ubuntu'daki bu projeyi hazırlayan arkadaşa eposta yolladım. Bana bu paketin Ubuntu ve Debian için pam içerisine koyduklarını söyledi. Bunu biraz daha araştırıp Pardus'a uygulanabilirliğini araştırmayı düşünüyorum.

Sırada bir de PiSi paketi yapmak var. Daha önceden almaya karar verip paketini yaptığım paketleri düzenleyip ve yeni alacağım paketleri belirleyip bunlar üzerine çalışmalar yapacağım.

Yani Pardus 2010 Yaz Stajı, benim için tam hızıyla, zevkli, heyecanlı, öğretici yani her şeyiyle çok güzel devam ediyor.

17 Ağustos 2010 Salı

Pardus 2010 Yaz Stajı 12. Gün

Bugün içerisinde iyi gelişmeler oldu. KDM sorununu hallettim. Oswald ile epostalaşma sonucunda bir çözüme ulaşamınca kendim KDM'nin kaynak kodunu inceleyerek bir çözüme ulaşmaya çalıştım.

Ve aşağıdaki gibi bir çözüme ulaştım, aşağıdaki yama dosyası tam olarak PAM'dan bir kez daha PAM_USER'i alıyor. Bu şekilde hem 2 kez kontrol edilmiş oluyor hem de misafir kullanıcı hesabı çalışmış olur.

yama dosyası:

--- kdm/backend/client.c.old 2010-08-17 11:43:02.775903757 +0300
+++ kdm/backend/client.c 2010-08-17 11:43:19.548533659 +0300
@@ -474,14 +474,13 @@
* the module needs an own conversation plugin which does not cause
* curuser being set.
*/
- if (!curuser) {
- debug( " asking PAM for user ...\n" );
- pam_get_item( pamh, PAM_USER, &pitem );
- reInitErrorLog();
- strDup( &curuser, (const char *)pitem );
- gSendInt( V_PUT_USER );
- gSendStr( curuser );
- }
+ /* Always check username from PAM */
+ debug( " asking PAM for user ...\n" );
+ pam_get_item( pamh, PAM_USER, &pitem );
+ reInitErrorLog();
+ strDup( &curuser, (const char *)pitem );
+ gSendInt( V_PUT_USER );
+ gSendStr( curuser );
if (pretc != PAM_SUCCESS) {
/* Log the failed login attempt */
log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED);


Bu yamayı kaynak koda uygulayıp, derleyip kurduğumuzda Misafir Kullanıcı sorunsuz olarak çalışıyor.

Şimdilik projede sadece ssh ile bağlantı sorunu kaldı, o da önemli bir sorun olarak görülmüyor.

Ayrıca PAM yapılandırma (/etc/pam.d/ içerisindeki) dosyaları düzenleme aracı yazmak gibi bir plan var. README dosyasını düzenledikten sonra burada yayınlamayı düşünüyorum.

Yama ise Pardus SVN depolarında mevcut. KDM nin de bir parçası olduğu "kdebase-workspace" paketinin bakımcısı olan Gökçen ile bu durumu konuştuktan sonra yamayı ona yolladım.

Paket Adresi: http://svn.pardus.org.tr/pardus/2009/devel/desktop/kde/base/kdebase-workspace/
Yama Adresi: http://svn.pardus.org.tr/pardus/2009/devel/desktop/kde/base/kdebase-workspace/files/pardus/kdm-pam-fix-for-guest-account.patch

16 Ağustos 2010 Pazartesi

Pardus 2010 Yaz Stajı 11. Gün

Bugün pam_python'u geliştiren kişiye yani Russell Stuart'a eposta yolladım. Bu epostada kısaca yazdığım modülün ne işe yaradığını, nerelerde sorunsuz çalıştığını, nerelerde sorun yarattığını, sorunların nerelerden kaynaklandığını, gerekli yapılandırma dosyalarının içeriklerini yazdım.

Kendisi gayet yardımcı olacak bir şekilde epostalarımı yanıtladı. Sorunun benim kodumda değil de KDM'nin kendi kodunda olduğundan bahsetti. Yani KDM, eğer PAM modülü içerisinde kullanıcı adı değişiyorsa değişen kullanıcı adını yok sayıp eski girilen ile devam ediyor.

Bunu denemek için, sistemde var olan iki kullanıcı arasında PAM modülü yardımıyla kullanıcı adlarını değiştirdim. Yani "pars" ve "parsik" sistemde var olan iki kullanıcı olsun. PAM modülünü eğer kullanıcı adı "pars" ise onu "parsik" olarak değiştirip PAM_SUCCESS geri döndürdüm.

Sonuç olarak kde ye ilk girdiğim kullanıcı adı olan "pars" ile giriş yaptım. Yani KDM, PAM modülü içerisinde yapılan değişikliği yok sayıyor.

Bunun üzerine açılışta kdm yerine xdm ile deneyeyim dedim. Bunun için /etc/default/xdm içerisinde:

DISPLAY_MANAGER="kdm"

satırını

DISPLAY_MANAGER="xdm"

olarak değiştirdim. Ekran açıldığında kullanıcı adına "guest" yazıp entere bastıktan sonra kde açıldı. Yani sorun KDM'deymiş. Bunun üzerine ofiste önce Bahadır ile sorunu nasıl çözebiliriz diye konuştuk sonra Ozan ile bunun üzerine önce bunu başka türlü nasıl çözebiliriz, acaba böyle bir çözüm uygun bir çözüm değil mi üzerine konuştuk sonra da kısa bir süre kodları inceledik. Tam olarak bir çözüme ulaşamadık, biraz daha fazla incelememiz gerekiyor.

Bu blog girdimi girmeden yaklaşık 1 saat önce de KDE KDM geliştiricisi olan Oswald Buddenhagen'a eposta attım. Ona da yazdığım modülü ve karşılaştığım hatalar ile ilgili bilgi içeren bir eposta attım. Onun cevabını bekleyene kadar da KDM'nin kaynak kodunu inceleyip Russell Stuart'ın dediği gibi PAM_USER ile ilgili olan yerleri inceleyeceğim.

Herhangi bir gelişmeyi yine buraya yazacağım.

15 Ağustos 2010 Pazar

Guestlogin projesi gelişmeleri

Haftasonumu projedeki sıkıntıları araştırmakla geçirdim diyebilirim. 2 tane sorun var şimdilik bilinen. Bunlardan biri ssh bağlantı sağlanamaması, öteki ise kdm den bağlantı sağlanamaması.

Ssh'daki sorun da şu şekilde: Eğer normal bağlanmaya çalışırsam kesinlikle bağlanmıyor ve

Connection closed by ::1

Şeklinde hata alıyorum. Sanırım bunun sebebi var olmayan bir kullanıcı ile bağlanmaya çalıştığım için oluyor dedim ve "/etc/ssh/sshd_config" dosyasında bununla ilgili bir şeyler aradım. Sonuç olarak yapılandırma dosyasında 3 tane değişken ile oynamak gerekiyormuş. Bunlar:

UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication no

Bunları bu şekilde düzelttikten sonra (kimisinin başında # vardı kimisi yes idi no yaptım) tekrar denedim. Bu sefer de:

Permission denied (publickey).

Hatası aldım. Bunu da araştırdığımda openssh'ın PAM'daki kullanıcı ismi değişikliğini kabul etmemesinin buna sebep olabileceğini öğrendim. Bununla ilgili bir yama buldum ve Pazartesi günü (16.08.2010) bunu uyguladıktan sonra sonuçları ile birlikte buraya yazacağım.

XDM sorununun çözümünü bulmak için başta google'da ayrıntılı bir arama yaptım, fakat hala bir çözüm yoktu. Sonra xdm/kdm'de kullanılan benim projeme benzer modülleri araştırdım. Zaten benimki gibi bir proje bulmak çok zordu ama parmak izi gibi kimlik doğrulama modülleri kullananlara baktım. Kaynak kodunu indirip inceledim, bir kaç şey gözüme çarptı.

Kaynak kod içerisinde $XAUTHORITY ortam değişkenine "$HOME/.Xauthority" değerini atıyorlar ve $DISPLAY ortam değişkenine de pam_tty değerini atıyorlar(pam_python'daki karşılığı pamh.tty oluyor). Ben de bunları gördükten sonra. os.environ[]'u kullanarak bu ortam değişkenlerine gerekli değerleri atadım ama hala sorun çözülmemişti.

Sonra sorun acaba kullanıcıyı PAM modülü üzerinden oluşturduğum için mi oluyor diye şüphelendim. Bunun için yarattığım kullanıcı adını da girilen kullanıcı adıyla aynı yaptım (yani guest adında kullanıcı oluşturdum guestX değil) ve sorunsuz bir şekilde çalıştı.

Kullanıcıyı PAM modülü içerisinde yaratmanın da bir sıkıntı yaratmadığını anladıktan sonra aklıma acaba kullanıcı adı değiştirmenin bir sorun yaratıp yaratmadığı geldi. Bunun için de kullanıcı adını varolan bir kullanıcı adına yönlendirdim. Yani:

pamh.user = sistemde_varolan_bir_kullanici

şeklinde atadım. Ve bunda da sorunsuz bir şekilde açıldı. Benim aklıma gelenler arasında geriye tek bir seçenek kalmıştı. Bu da girilen kullanıcı adı ile PAM tarafından verilen kullanıcı adının aynı olmamasıydı. Yani bir şekilde KDM, girilen kullanıcı adını alıyor bir yerlere yazıyor ya da onunla ilgili kimlik doğrulaması yapmaya çalışıyordu.

KDM nin de kendi kimlik doğrulamaları vb. şeyler var mı diye bir araştırma yaptım. Xauth'u biraz inceledim. Burada cevap bulamayınca "/etc/X11/kdm/" içerisindeki yapılandırma dosyalarında işime yarayacak herhangi bir şey aradım ama nafile. Sanırım şimdi yapmam gereken şey KDM nin kendi kimlik doğrulamasını kapatmak veya bunu PAM dan sonra yapmasını sağlamak. Bunun için de KDM nin kaynak kodunu indirdim ve incelemeye başladım. Şimdilik kodu inceleyip anlama kısmındayım. Gerçi daha yeni başladım KDM nin kaynak kodunu incelemeye ama yarın Pardus ofisinde bu incelemeyi hızlandırıp bu KDM sorununu da çözmeyi düşünüyorum.

14 Ağustos 2010 Cumartesi

Pardus 2010 Yaz Stajı 10. Gün

Bugün, Misafir kullanıcı modülüne eğer işlemlerde bir sorun varsa ona göre işlemleri geri alıp geri değer döndürme fonksiyonu hazırladım.

Bu fonksiyon ayrıca sadece geri değer döndürme işine de yarıyor. Aldığı integer tipindeki değere göre işlem yapıyor. Böylece geri döndürülen değer sırasında bir işlem yapma veya diğer işlemlerde büyük esneklik kazandırmış oldu.

İşlemleri geri alma da şu şekilde oluyor. Her adım sırasında yapılan işlemi kontrol ediyor ve bir önceki adımların zıttını uyguluyorum. Mesela eğer klasör oluşturulup bağlama sırasında bir sorun olursa dizini silip, bir hata kodu gönderiyorum. Bu şekilde bütün kodda kontroller var artık.

Ayrıca tüm komutları subprocess ile kullanamamak gibi bir sorunla karşılaştım demiştim. Aslında o öyle değilmiş, o işlemin bitmesini beklemek gerekiyormuş yani

a = subprocess.Popen([..........])

a.wait()

buradaki wait komutu bütün işi halletti. Yani koddaki bütün os.system leri Popen ile hallettim.

Ayrıca sistem politikaları gereği chown, usermod ile değişiklik yapmak yerine kullanıcı oluştururken ev dizinini belirlemenin daha uygun olduğunu düşündük. Bunun için bunları kaldırıp, rastgele isim üreten bir fonksiyon oluşturup kullanıcıya bu dizini vermek gibi bir plan yaptık.

Fakat burada bir güvenlik açığı oluşuyordu. O dizini kullanıcıya verene kadar bir şey olup olmayacağını bilmiyorduk. flock vb. komutları incelememize rağmen bir çözüme ulaşamıyorduk çünkü flock ile kilitlesek bile useradd komutu sırasında bir şeyler olabilirdi ve useradd komutu eğer ev dizini varsa bile 0 değerini geri döndürüyor. Bunun için başka bir çözüm arayışına girdik.

Sonuç olarak yine mktemp ile rasgele dizin oluşturup onun içerisinde home diye bir dizini o kullanıcıya vermek kararına vardık.

Kod ise aşağıdaki şekilde:

"mktemp -td %s.XXXXXX" % username

"mount -t tmpfs -o size=%sm -o mode=711 none %s" % (guest_home_dir_size, home_dir)

useradd -m -d %s/home -g %s %s" % (home_dir, guest_group_name, username)

Burada mode=711 sayesinde useradd ile ev dizinini oluşturabiliyoruz.
guest_home_dir_size -> ev dizin boyutu, home_dir -> ev dizininin konumu, username -> kullanıcı adı (guestX şeklindeki)

bu şekilde bu sorunun da üstesinden geldik. Pardus 2010 Yaz Stajının 2. haftası da bitti. Her şey çok güzel gidiyor. Burada çalışmak gerçekten çok zevkli ve çok güzel.

Şimdilik çözülmesi gereken sorunlar:

ssh üzerinden bağlantı sağlanmıyor.

kdm ile de bağlanılamıyor.

12 Ağustos 2010 Perşembe

Pardus 2010 Yaz Stajı 9. Gün

Misafir kullanıcı çalışmaları son hızda devam ederken öbür yandan da pam_python'un PiSi paketini oluşturdum. Kurarken karşılaştığım bir sorun olan libpython2.6.so.1'in bulunamaması için de bir yama yaptım.

Bu yama kaynak koddaki src/setup.py dosyasında libpython2.6.so.1 yerine libpython2.6.so.1.0 yapıyor. (aslında versiyonu sistemden alıyor)

Bu paket üzerinden kurulduğu zaman herhangi bir sorun olmadan pam_python'u kullanabiliyorsunuz.

Paketi oluşturduktan sonra yapılacak işlerden olan hata çözümleme modu yaratmakla başladım. Bunun için argv değişkeninin içerisinde debug var ise debugging değişkenini True yapmak en mantıklısı olacak diye düşünüp bu şekilde uyguladım.

Kod içerisinde de if(debugging) ile kontrol ederek eğer doğru ise hazırlamış olduğum log fonksiyonuna bir çıktı gönderiyor.

log fonksiyonu ise bu şekilde

def log(text):
sys.stdout.write(text)
sys.stdout.flush()

burda sys.stdout.write şeklinde yazmak en mantıklısı olacak çünkü eğer X açıkken yapılacak olursa bu işlemler print ya da başka fonksiyonlar işe yaramayabilir. Stdout ise her durumda işimize yarayacak bir şey. Tabi bu işlemler için de sys modülünü kullandığım için yukarıda import sys yapıyorum.

İçeride de loglama şu şekilde:

if(debugging):
log("Yazı")

kodda aşama aşama ilerlemeler bu şekilde yapılıyor.

Debugging işlemini hallettikten sonra da bir sonraki iş olarak os.system yerine subprocess.popen ile yapabileceklerimi belirleyip onları değiştirdim.

Bir de girilecek kullanıcı adı, ev dizini boyutu ve girebilecek en fazla kullanıcı sayısını tutmak için bir yapılandırma dosyası oluşturdum. Bunu da /etc/security/ nin içerisine koydum.

Dosya adı guestlogin.conf. Üzerinden değişkenleri almak için ConfigParser modülünü kullanıyorum. Kod ise aşağıdaki şekilde:

try:
config = ConfigParser.ConfigParser()
config.read('/etc/security/guestlogin.conf')
guest_name = config.get('guest', 'guestname')
guest_limit = config.getint('guest', 'guestlimit')
guest_home_dir_size = config.getint('guest', 'homedirsize')

except:
return pamh.PAM_AUTHINFO_UNAVAIL
guestlogin.conf dosyası ise aşağıdaki gibi:

[guest]
guestname = guest
guestlimit = 50
homedirsize = 100

Bu şekilde biraz daha esneklik kazandırmış olduk.

Şimdilik aklıma gelenler bunlar fakat projeye eklemeler yapılacak.

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.

10 Ağustos 2010 Salı

Guest Account düzenlemeler

NOT: Bu güvenlik açığını başka şekilde hallettiğim için buradaki control kısmına sadece sufficient yazmam yeterli oldu. Ama yine de aşağıdaki yazıyı bırakıyorum.


Biraz önce yazdığım yazıdaki kodu kontrol ederken akıl almaz bir güvenlik açığı ile karşı karşıya geldiğimi öğrendim. Açık şu: Sistemdeki herhangi bir kullanıcı parola yazmadan giriş yapabiliyor. Bunun sebebi yazdığım metot her türlü SUCCESS döndürmesi. Bunun yerine hata döndürse bu sefer başka sorunlar ortaya çıkacak.

Bu şekilde aklıma /etc/pam.d/ nin içerisinde bir şeyleri değiştirmek geldi. man pam.d yaparak kolları sıvadım. Ve çözüm:

auth [user_unknown=ok success=done new_authtok_reqd=done default=ignore] pam_python.so guestlogin.py

İkinci yazdığımız sufficient yerine bunları yazıyorum. Şu an daha iyi durumda.

Şimdilik aklıma gelen düzeltme yapılması gereken yerlerden birisi de bu durumda her bilinmeyen/kayıtlı olmayan kullanıcı için SUCCESS döndürmesi. Bunun kontrolünü python betiğinin içerisinde uygulamam gerekiyor.

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.

9 Ağustos 2010 Pazartesi

Pardus 2010 Yaz Stajı 6. Gün

Bugün diğerlerine nazaran daha heyecanlı başladı. Bugünün başlarında daha çok bize verilen projeler listesindeki projeler üzerinde genel bir araştırma yaptık. Herkes kafasında bir proje belirledi ve onlar üzerinde yoğunlaştı.

Biraz daha araştırma yaptıktan sonra Staj Koordinatörümüz Renan Çakırerk geldi ve herkes projelerini belirledi.

Ben de Pardus'a Misafir Kullanıcı Ekleme projesini aldım.

Bu projeyi geliştirirken PAM (Pluggable Authentication Modules) ve Shell Script kullanacağım.

Bugün içerisinde şimdilik Misafir Kullanıcısında olması gerekenler, olmaması gerekenler üzerinde bir araştırma yaptım. Bir de PAM nedir onu araştırdım.

Biraz da Kabuk Programlama (Shell Scripting) araştırdım.

Bugünlük böyle.

8 Ağustos 2010 Pazar

Pardus 2010 Yaz Stajı İlk Haftası

Pardus 2010 Yaz stajının Ağustos ayı döneminde staja kabul edildim.

Zaten heyecanlı olan staj başvuru ve sonuç açıklanma süresinden sonra staja gitmek için olan heyecanlı bekleme sona erdi.

İlk gün staj yapacağımız yer olan Tübitak MAM'a kendi imkanlarımızla ulaştık ki bu da benim oturduğum yer olan Kanarya Mah./Küçükçekmece'den yaklaşık olarak 2 Saat 30 Dakika sürdü. Yerleşke kesinlikle çok güzel bir yer. Üniversite kampüsü gibi. Staj yapacağım ofisi oradan sonra bulmak pek vakit almadı ama oranın güzelliğini incelemek bile çok güzel. İçeriye girdikten sonra Fotoğraf çekimi de yapmak yasak. Zaten UEKAE binasıının içerisine girerken Cep Telefonu, Ses kayıt cihazı, Taşınabilir bellek ve Mp3 çalar sokmak yasak.

Staja geldiğimde Staj Koordinatörümüz ve eski bir stajyer olan Renan Çakırerk bize, hem orada uymamız gereken kurallar ile ilgili bir belge hem de stajyerin el kılavuzu adında ilk hafta araştırmamız gereken ve yapmamız gerekenlere ilgili bir belge verdi.

Verdiği belge içerisinde öncelikle Linux'u, Pardus'u, Pardus Teknolojileri ve Mimarileri, kullanacağımız geliştirme araçları, PiSi paket yapımı ve yama yapımı gibi bilgiler barındırıyor. İlk hafta içerisinde de bunları okuyup bunlar üzerinde araştırmalar yaptık. Bilgisayarlar üzerinde de uygulayabileceklerimizi uyguladık. İlk haftanın son gününde , bize, yapabileceğimiz projeler ile ilgili bir kağıt dağıtıldı. Hafta sonu da bu projeler üzerinde genel olarak bir araştırma yapıp pazartesi günü eğer bir sorun çıkmaz ise bunlardan bir tanesini seçip başlayacağımız söylendi.

İlk hafta genel olarak böyle geçti. Pardus ekibiyle tanışıp kaynaşma, Pardus'u, Linux'u ve diğer teknolojileri araştırma.

Haftaya daha dolu dolu ve yoğun geçeceğe benziyor.

Bize kolay gelsin.