Shadow Password HOWTO pl 8 (2)


Przesłanianie haseł (Shadow Password): Obsługa przesłanianych haseł w programach w C. Następna strona Poprzednia strona Spis treści 8. Obsługa przesłanianych haseł w programach w C. Dodawanie obsługi haseł przesłanianych do programów jest całkiem proste. Jedynym problemem jest to, że program musi zostać uruchomiony z prawami "root-a", aby mieć dostęp do pliku /etc/shadow. Tutaj pojawia się jeden wielki problem: podczas pisania takich programów należy się trzymać jak najściślej zasad bezpieczeństwa. Na przykład jeśli program posiada wyjście do powłoki, to nie może się to zdarzyć na prawach "root-a". Jeśli program musi mieć dostęp do /etc/shadow i nie potrzebuje więcej praw "root-a", to lepiej uruchomić go z prawami grupy "shadow". Program xlock jest przykładem takiego programu. W przykładzie podanym niżej, pppd-1.2.1d jest już uruchomiony z prawami "root-a", tak więc dodanie obsługi haseł przesłanianych nie powinno zagrozić bezpieczeństwu. 8.1 Pliki nagłówkowe. Pliki te powinny znajdować się w /usr/include/shadow. Powinien tam być także plik /usr/include/shadow.h, ale będzie to symboliczne dołaczenie do /usr/include/shadow/shadow.h. Aby dodać obsługę haseł przesłanianych do programu, musisz dołączyć pliki nagłówkowe: #include <shadow/shadow.h> #include <shadow/pwauth.h> Dobrym pomysłem byłoby użycie dyrektyw kompilatora, aby skompilować warunkowo kod z obsługą haseł przesłanianych. (tak jak w przykładzie poniżej.) 8.2 Biblioteka libshadow.a Biblioteka ta została zainstalowana w /usr/lib jak instalowałeś pakiet Shadow Suite. Kiedy kompilujesz obsługę przesłaniancyh haseł w programie trzeba poinformować "linker-a", aby dołączył bibliotekę libshadow.a. Robi się to tak: gcc program.c -o program -lshadow Chociaż jak zobaczymy w poniższym przykładzie, większość dużych programów używa plików Makefile i ma zwykle zmienną LIBS=..., którą się modyfikuje. 8.3 Struktura Shadow. Biblioteka libshadow.a używa struktury spwd dla informacji, które otrzyma z pliku /etc/shadow. Oto definicja tej struktury wzięta z /usr/include/shadow/shadow.h: struct spwd { char *sp_namp; /* identyfikator */ char *sp_pwdp; /* zakodowane hasło */ sptime sp_lstchg; /* data ostatniej zmiany */ sptime sp_min; /* minimalna ilość dni między zmianami */ sptime sp_max; /* maksymalna ilość dni między zmianami */ sptime sp_warn; /* ilość dni przed wygaśnięciem hasła kiedy będzie wysyłane ostrzeżenie */ sptime sp_inact; /* ilość dni, po jakiej wygasa hasło dopóki konto nie będzie zablokowane */ sptime sp_expire; /* ilość dni od 01.01.1970 dopóki konto nie wygaśnie */ unsigned long sp_flag; /* zarezerwowane na przyszłość */ }; Do pola sp_pwdp można dodatkowo wstawić nawzę programu: identyfikator:Npge08pfz4wuk;@/sbin/extra:9479:0:10000:::: Oznacza to, że oprócz podania hasła będzie wykonany program /sbin/extra, który wykona dalszą autentykację. Wywołany program otrzyma identyfikator i przełącznik, który określi dlaczego został wywołany. Więcej informacji znajdziesz w /usr/include/shadow/pwauth.h i pwauth.c. Oznacza to, że powinniśmy użyć funkcji pwauth do przeprowadzenia poprawnej autentykacji, ponieważ zajmie się ona także drugą autentykacją. Jest to użyte w przykładzie poniżej. Autor pakietu Shadow Suite twierdzi, że odkąd większość programów tego nie stosuje, może to zostać usunięte lub zmienione w przyszłych wersjach pakietu. 8.4 Funkcje pakietu Shadow Suite. Plik shadow.h zawiera deklaracje funkcji zawartych w bibliotece libshadow.a: extern void setspent __P ((void)); extern void endspent __P ((void)); extern struct spwd *sgetspent __P ((__const char *__string)); extern struct spwd *fgetspent __P ((FILE *__fp)); extern struct spwd *getspent __P ((void)); extern struct spwd *getspnam __P ((__const char *__name)); extern int putspent __P ((__const struct spwd *__sp, FILE *__fp)); Funkcja, którą użyjemy w przykładzie to getspnam, która odczyta strukturę spwd dla podanego identyfikatora. 8.5 Przykład. Jest to przykład na dodanie obsługi haseł przesłanianych do programu, który tego potrzebuje, ale nie ma domyślnie włączonego. Przykład ten używa serwera Point-to-Point Protocol (pppd-1.2.1d), który ma tryb do autentykacji PAP używając identyfikatora i hasła z pliku /etc/passwd zamiast z plików PAP czy CHAP. Nie musisz dodawać tego kodu do pppd-2.2.0, ponieważ on już tam jest. Ta właściwość pppd przypuszczalnie nie jest często używana, ale jeśli zainstalowałeś Shadow Suite, to serwer ten nie będzie działał ponieważ hasła nie są już zapisywane w /etc/passwd. Kod do autentykacji użytkowników przez pppd-1.2.1d umieszczony jest w pliku /usr/src/pppd-1.2.1d/pppd/auth.c. Poniższy kod musi zostać dodany na początku pliku gdzie znajdują się wszystkie inne dyrektywy #include. Otoczyliśmy je dyrektywami warunkowymi (czyli skompilują się tylko jeśli kompilujemy z właczoną obsługą haseł przesłanianych). #ifdef HAS_SHADOW #include <shadow.h> #include <shadow/pwauth.h> #endif Następnym krokiem jest modyfikacja właściwiego kodu. Ciągle modyfikujemy plik auth.c. Funkcja auth.c przed modyfikacją: /* * login - Check the user name and password against the system * password database, and login the user if OK. * * returns: * UPAP_AUTHNAK: Login failed. * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ static int login(user, passwd, msg, msglen) char *user; char *passwd; char **msg; int *msglen; { struct passwd *pw; char *epasswd; char *tty; if ((pw = getpwnam(user)) == NULL) { return (UPAP_AUTHNAK); } /* * XXX If no passwd, let them login without one. */ if (pw->pw_passwd == '\0') { return (UPAP_AUTHACK); } epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); } syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ tty = strrchr(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, user, ""); /* Add wtmp login entry */ logged_in = TRUE; return (UPAP_AUTHACK); } Hasło użytkownika jest umieszczane w pw->pw_passwd, tak że wszystko co musimy zrobić, to dodać funkcję getspnam. Umieści to hasło w spwd->sp_pwdp. Dodamy funkcję pwauth, aby przeprowadzić właściwą autentykację. Przeprowadzi to także drugą autentykację jeśli plik shadow jest odpowiednio ustawiony. Funkcja auth.c po modyfikacji do obsługi haseł przesłanianych: /* * login - Check the user name and password against the system * password database, and login the user if OK. * * This function has been modified to support the Linux Shadow Password * Suite if USE_SHADOW is defined. * * returns: * UPAP_AUTHNAK: Login failed. * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ static int login(user, passwd, msg, msglen) char *user; char *passwd; char **msg; int *msglen; { struct passwd *pw; char *epasswd; char *tty; #ifdef USE_SHADOW struct spwd *spwd; struct spwd *getspnam(); #endif if ((pw = getpwnam(user)) == NULL) { return (UPAP_AUTHNAK); } #ifdef USE_SHADOW spwd = getspnam(user); if (spwd) pw->pw_passwd = spwd->sp-pwdp; #endif /* * XXX If no passwd, let NOT them login without one. */ if (pw->pw_passwd == '\0') { return (UPAP_AUTHNAK); } #ifdef HAS_SHADOW if ((pw->pw_passwd && pw->pw_passwd[0] == '@' && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL)) || !valid (passwd, pw)) { return (UPAP_AUTHNAK); } #else epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); } #endif syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ tty = strrchr(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, user, ""); /* Add wtmp login entry */ logged_in = TRUE; return (UPAP_AUTHACK); } Po dokładnym prześledzaniu tego kodu okaże się, że zrobiliśmy jeszcze jedną zmianę. Oryginalna wersja pozwalała na dostęp (zwracała UPAP_AUTHACK) jeśli nie było hasła w pliku /etc/passwd. Nie jest to dobrze, ponieważ popularnym użyciem tej właściwości programu login jest używanie jednego konta, na dostęp do programu PPP, a potem sprawdzenie identyfikatora i hasła dostarczonych przez PAP z tymi w plikach /etc/passwd i /etc/shadow. Tak więc jeśli ustwilibyśmy oryginalną wersję, aby uruchamiała powłokę dla użytkownika np. ppp, to każdy mógłby uzyskać połączenie ppp przez podanie identyfikatora ppp i pustego hasła. Poprawiliśmy to przez zwrócenie UPAP_AUTHNAK zamiast UPAP_AUTHACK jeśli pole z hasłem jest puste. Interesujące jest to, że pppd-2.2.0 ma ten sam problem. Następnie musimy zmodyfikować plik Makefile tak, żeby pojawiły się dwie rzeczy: USE_SHADOW musi być zdefiniowane i libshadow.a musi być dodana w procesie "linkowania". Wyedytuj plik Makefile i dodaj: LIBS = -lshadow Potem znajdź linię: COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t i zmień ją na: COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t -DUSE_SHADOW Teraz kompilacja i instalacja. Następna strona Poprzednia strona Spis treści

Wyszukiwarka

Podobne podstrony:
Shadow Password HOWTO pl 10 (2)
Shadow Password HOWTO pl (3)
Shadow Password HOWTO pl 5 (2)
Shadow Password HOWTO pl (2)
Shadow Password HOWTO pl 6 (2)
Shadow Password HOWTO pl 9 (2)
Shadow Password HOWTO pl 2 (2)
Shadow Password HOWTO pl 7 (2)
Shadow Password HOWTO pl 1 (2)
Shadow Password HOWTO pl 4 (2)
Shadow Password HOWTO pl 3 (2)
Shadow Password HOWTO pl
shadow password howto 4 wrjj4xl2rttpywxk645hll3i63bvo7zfmqmiewy wrjj4xl2rttpywxk645hll3i63bvo7zfmqmi
shadow password howto 5 xwj2yqx7sdr7adin3jsjtftaoqyivxcflwawaqa xwj2yqx7sdr7adin3jsjtftaoqyivxcflwaw
shadow password howto 2 foxyypsfur2dgvcm757tzpjjjqzxkvhcxqxuazi foxyypsfur2dgvcm757tzpjjjqzxkvhcxqxu
shadow password howto xaxuxvyqvflgb5m452rbxlszzlk756szuoenxpa xaxuxvyqvflgb5m452rbxlszzlk756szuoenxp
shadow password howto 6 wekeaom5hhmqmfgscm4mih3yeed3zer56aqewwa wekeaom5hhmqmfgscm4mih3yeed3zer56aqe
shadow password howto 9 rrzkcxlxnah6g6g76dgcjvmvfeeihhseu43rxfi rrzkcxlxnah6g6g76dgcjvmvfeeihhseu43r
shadow password howto 1 jvl6nxop7fpn62s67zmft74rytj65xu7oqy4xdi jvl6nxop7fpn62s67zmft74rytj65xu7oqy4

więcej podobnych podstron