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 plshadow password howto 4 wrjj4xl2rttpywxk645hll3i63bvo7zfmqmiewy wrjj4xl2rttpywxk645hll3i63bvo7zfmqmishadow password howto 5 xwj2yqx7sdr7adin3jsjtftaoqyivxcflwawaqa xwj2yqx7sdr7adin3jsjtftaoqyivxcflwawshadow password howto 2 foxyypsfur2dgvcm757tzpjjjqzxkvhcxqxuazi foxyypsfur2dgvcm757tzpjjjqzxkvhcxqxushadow password howto xaxuxvyqvflgb5m452rbxlszzlk756szuoenxpa xaxuxvyqvflgb5m452rbxlszzlk756szuoenxpshadow password howto 6 wekeaom5hhmqmfgscm4mih3yeed3zer56aqewwa wekeaom5hhmqmfgscm4mih3yeed3zer56aqeshadow password howto 9 rrzkcxlxnah6g6g76dgcjvmvfeeihhseu43rxfi rrzkcxlxnah6g6g76dgcjvmvfeeihhseu43rshadow password howto 1 jvl6nxop7fpn62s67zmft74rytj65xu7oqy4xdi jvl6nxop7fpn62s67zmft74rytj65xu7oqy4więcej podobnych podstron