Technologie zapewniające bezpieczeństwo w systemach operacyjnych.
Linux-PAM
Barbara
Domagała
Spis treści
1. Wstęp
2. Krótka charakterystyka.
2.1. Przykład współpracy aplikacji z PAM.
2.2. Zakres usług PAM.
2.3. Schemat komunikacji aplikacji z Linux-PAM.
3. Pisanie aplikacji korzystających z Linux-PAM.
3.1. Wstęp.
3.2. Pliki nagłówkowe i linkowanie.
3.3. Krótka charakterystyka korzystania w aplikacji z Linux-PAM.
3.4. Interfejs Linux-PAM.
3.4.1. Inicjalizacja Linux-PAM - pam_start()
.
3.4.2. Zakończenie korzystania z Linux-PAM - pam_end()
.
3.4.3. Ustawianie danych zawartych w strukturze pamh
- pam_set_item()
.
3.4.4. Czytanie danych zawartych w strukturze pamh
- pam_get_item()
.
3.4.5. Informacja o błędzie - pam_strerror()
.
3.4.6. Odstępy czasowe - pam_fail_delay()
.
3.4.7. Uwierzytelnianie - pam_authenticate()
.
3.4.8. Ustawianie danych o użytkowniku (credentials) - pam_setcred()
.
3.4.9. Zarządzanie kontem- pam_acct_mgmt()
.
3.4.10. Aktualizacja hasła - pam_chauthtok()
.
3.4.11. Otwarcie sesji - pam_open_session()
.
3.4.12. Zamknięcie sesji - pam_close_session()
.
3.4.13. Ustawienie zmiennych środowiskowych dla PAM - pam_putenv()
.
3.4.14. Odczytywanie wartości zmiennej środowiskowej - pam_getenv()
.
3.4.15. Odczytanie środowiska - pam_getenvlist()
.
3.5. Funkcja interakcji.
4. Pisane modułów zgodnych z Linux-PAM.
4.1. Interfejs Linux-PAM dla modułów.
4.1.1. Ustawianie danych - pam_set_data()
.
4.1.2. Odczytywanie danych - pam_get_data()
.
4.1.3. Ustawianie pól - pam_set_item()
.
4.1.4. Odczytywanie pól - pam_get_item()
.
4.1.5. Mechanizm konwersacji.
4.1.6. Czytanie nazwy użytkownika - pam_get_user()
.
4.1.7. Ustawianie zmiennych środowiskowych - pam_putenv()
.
4.1.8. Odczytanie wartości zmiennych środowiskowych - pam_getenv()
.
4.1.9. Odczytanie całego środowiska - pam_getentlist()
.
4.1.10. Notatka o błędzie - pam_strerror()
.
4.1.11. Określanie opóźnienia - pam_fail_delay()
.
4.2. Co musi dostarczać moduł.
4.2.1. Krótka charakterystyka wymagań wobec modułu.
4.2.2. Uwierzytelnianie.
4.2.3. Zarządzanie kontem.
4.2.4. Zarządzanie sesją.
4.2.5. Zarządzanie hasłem.
5. Konfiguracja Linux-PAM.
6. Przykładowy schemat aplikacji korzystającej z Linux-PAM.
7. Przykładowy schemat modułu dla Linux-PAM.
8. Materiały.
1. Wstęp
Linux-PAM (Pluggable Authentication Modules for Linux) to zestaw bibliotek
dzielonych, które umożliwiają administratorowi lokalnego systemu wybranie
dla każdej aplikacji sposobu, w jaki ta aplikacja będzie dokonywać autoryzacji
użytkownika. Innymi słowy, możliwe jest przełączanie pomiędzy rożnymi mechanizmami
uwierzytelniania, bez potrzeby ponownego kompilowania aplikacji, a tym bardziej
ponownego jej programowania. Dodatkowo, można wprowadzać ulepszenia do mechanizmów
autoryzacji bez konieczności wprowadzania jakichkolwiek zmian w aplikacjach
korzystających z tych mechanizmów.
Motywacją do stworzenia PAM jest ciągły postęp w metodach uwierzytelniania,
spowodowany koniecznością zapewniania coraz lepszego bezpieczeństwa.
Celem projektu Linux-PAM jest odseparowanie mechanizmów zapewnienia bezpieczeństwa
od kodu aplikacji korzystających z tych mechanizmów. Osiągnięte to zostało
przez dostarczenie biblioteki funkcji, które aplikacja może użyć do autoryzacji.
Ta byblioteka PAM jest konfigurowana lokalnie w pliku konfiguracyjnym do uwierzytelniania
użytkownika przy użyciu lokalnie dostępnego modułu autoryzacji. Moduły te
zwykle są umieszczone w katalogu /lib/security
i są to dynamicznie
ładowalne pliki obiektowe.
2. Krótka charakterystyka.
2.1. Przykład współpracy aplikacji z PAM.
Login to przykład aplikacji, która wykonuje usługę dla użytkownika. Aplikacja
login robi dwie rzeczy:
- dokonuje uwierzytelnienia użytkownika
- wywołuje żądaną usługę (np. bash).
Z punktu widzenia autora aplikacji login, Linux-PAM przejmuje odpowiedzialność
za wykonanie zadania autoryzacji - weryfikuje wiarygodność użytkownika.
Elastyczność Linux-PAM polega na tym, że administrator może dokonać wyboru
sposobu autoryzacji dla tej aplikacji. Ma możliwość ustawienia mechanizmu
autoryzacji dla każdej aplikacji korzystającej z PAM osobno. Można ustawić
np. autoryzację trywialną, tzn. pustą, autoryzację poprzez hasło, poprzez
głos itp., cokolwiek zostania wymyślone.
Aby użyć PAM należy jego funkcje bezpośrednio zakodować w programie.
2.2. Zakres usług PAM.
Linux-PAM obsługuje cztery odrębne typy zadań:
* autoryzacja
* zarządzania kontem
* zarządzania sesją
* zarządzania hasłem (zmana hasła).
Preferowany dla danej aplikacji mechanizm uwierzytelniania zapisywany jest
w pliku konfiguracyjnym. Mechanizm ten wybierany jest dla aplikacji osobno
dla każdego z czterech wyżej wymienionych typów usług. Funkcje tego mechanizmu
są w modułach, do których ścieżki też umieszczone są w pliku konfiguracyjnym.
2.3. Schemat komunikacji aplikacji z Linux-PAM.
------aplikacja--------
-------------------------- ----------------------
------------------------------
| autoryzacja | <----------------------> | Linux-PAM
| <------------------ | plik konfiguracyjny |
-------------------------- ----------------------
------------------------------
| usługa |
|
-------------------------- |
|
|
----------- autoryzacja
|
----------- zarządzania kontem
|
----------- zarządzanie sesją
|
----------- zarządzanie hasłem
Rys.1. Schemat komunikacji aplikacji z Linux-PAM.
Aplikacja porozumiewa się z biblioteką Linux-PAM poprzez dobrze zdefiniowany
interfejs i nie zna metod autoryzacji ani konfiguracji tych metod. Biblioteka
Linux-PAM komunikuje się z plikiem konfiguracyjnym i ładuje moduły zgodnie
z tym plikiem. Są cztery typy usług autoryzacyjnych i dla każdej z tych usług
może być ładowany inny moduł. Te moduły wykonują zadanie autoryzacji dla aplikacji.
Wymiana komunikatów pomiędzy modułem a aplikacją odbywa się przy pomocy funkcji
konwersacji, która jest dostarczana przez aplikację.
3. Pisanie aplikacji korzystających z Linux-PAM.
3.1. Wstęp.
W tym punkcie zostanie przedstawione, co programista aplikacji powinien
wiedzieć, aby skorzystać z Linux-PAM do autoryzacji użytkownika.
3.2. Pliki nagłówkowe i linkowanie.
Podstawowa biblioteka Linux-PAM.
#include <security/pam_appl.h>
cc -o application .... -lpam -ldl
Pomocnicza biblioteka Linux-PAM.
#include <security/pam_misc.h>
cc -o application .... -lpam -lpam_misc -ldl
3.3. Krótka charakterystyka korzystania w aplikacji z Linux-PAM.
Usługi oferowane przez Linux-PAM są przezroczyste dla aplikacji. Oznacza
to, że gdy aplikacja jest pisana, nie wiadomo jak będzie odbywać się uwierzytelnianie.
Zadanie autoryzacji jest wykonywane przez bibliotekę PAM w funkcji pam_authenticate()
.
Funkcja ta może prowadzić dialog z aplikacją, np. poprosić o hasło. PAM musi
umieć współpracować z aplikacjami niezależnie od tego, w jaki sposób aplikacja
prezentuje użytkownikowi prośbę o hasło. Zostało przyjęte rozwiązanie, w którym
aplikacja dostarcza bibliotece PAM funkcję konwersacji. Funkcja ta
jest wywoływana przez PAM i umożliwia PAM interakcję z użytkownikiem.
Poza uwierzytelnianiem, PAM dostarcza inne formy usług. Zarządzanie sesją
odbywa się przez funkcje pam_open_session()
i pam_close_session()
. To co robią te funkcje zależy
od lokalnego administratora. Może to być zamontowanie i odmontowanie katalogu
domowego. Używa się tych funkcji, jeśli aplikacja oferuje jakiś rodzaj usługi
nieprzerwanie w pewnym odcinku czasu. Wtedy po zalogowaniu i przed zakończeniem
wywołuje się te funkcje.
Zarządzanie kontem odbywa się poprzez funkcję pam_acct_mgmt()
.
Można odczytać stan konta użytkownika, np. czy konto jest zablokowane, czy
aktywne.
Zmiana hasła odbywa się poprzez funkcję pam_chauthtok()
.
PAM ma możliwość zmiany przechowywanych danych o użytkowniku (credentials)
poprzez funkcję pam_setcred()
. Funkcja ta powinna być
wywoływana zawsze po uwierzytelnieniu użytkownika i przed wykonaniem usługi.
Zgodnie z przyjętą konwencją funkcja ta jest ostatnią wywoływaną funkcją
przed otwarciem sesji.
3.4. Interfejs Linux-PAM.
Definicje opisanych w tym punkcie funkcji znajdują się w bibliotece <security/pam_appl.h>
.
Jest to publiczny interfejs Linux-PAM, z którego może korzystać aplikacja.
3.4.1. Inicjalizacja Linux-PAM - pam_start()
.
extern int pam_start (const char *service_name, const char *user,
const struct pam_conv *pam_conversation,
pam_handle_t **pamh);
Pierwsza funkcja Linux-PAM, jaka musi być wywołana przez aplikację. Inicjalizuje
interfejs i czyta plik konfiguracyjny, /etc/pam.conf
. W przypadku
sukcesu zwraca PAM_SUCCESS
. Wtedy *pamh
jest wskaźnikiem,
który należy przekazywać do kolejnych funkcji Linux-PAM. Pobierane zmienne:
* service_name
- nazwa programu/aplikacji
* user
- nazwa użytkownika, który ma zostać uwierzytelniony
* pam_conversation
- wskaźnik do struktury zdefiniowanej w
aplikacji, struktura ta zawiera definicję funkcji konwersacji
* pamh
- zostanie zwrócone przez funkcję, jest to struktura
przekazywana do kolejnych funkcji Linux-PAM. Nie powinna być w żaden sposób
modyfikowana ani odczytywana przez aplikację. W celu zmiany/odczytu danych
znajdujących się w tej strukturze należy użyć funkcji pam_set_item()
i pam_get_item()
.
3.4.2. Zakończenie korzystania z Linux-PAM - pam_end()
.
extern int pam_end (pam_handle_t *pamh, int pam_status);
Ostatnia funkcja Linux-PAM wywoływana przez aplikację. Zwalnia pamięć związaną
ze wskaźnikiem pamh
. Jeśli wcześniejsze funkcje zwracały PAM_SUCCESS
,
to pam_status
też powinien mieć taką wartość. Jeśli jakaś funkcja
zwróciła błąd, to na pam_status
należy wpisać kod tego błędu.
Zależnie od pam_status
zakończenie Linux-PAM może odbywać się
w inny sposób.
3.4.3. Ustawianie danych zawartych w strukturze pamh
-
pam_set_item()
.
extern int pam_set_item (pam_handle_t *pamh, int item_type, const
void *item);
Funkcja ustawia/zmienia wartości następujących typów danych - wartości
przybierane przez item_type
:
PAM_SERVICE
Nazwa usługi.
PAM_USER
Nazwa użytkownika, na konto którego usługa będzie wykonywana
PAM_USER_PROMPT
Napis używany przy proszeniu o nazwę użytkownika. Domyślnie:
"Please enter username:".
PAM_TTY
Nazwa terminala.
PAM_RUSER
Użytkownik, który wywołuje usługi: nazwa użytkownika, który
lokalnie wywołuje usługi lub zdalnie wywołuje usługi.
Administrator ustala poziomy ufności. Gdy równe NULL, nie jest jasne kto żąda
usługi.
PAM_RHOST
Nazwa hosta, z którego użytkownik żąda usługi. Gdy równe
NULL, nie jest jasne skąd użytkownik żąda usługi.
PAM_CONV
Funkcja dialogu.
PAM_FAIL_DELAY
Wskaźnik do funkcji obsługi opóźnień po otrzymaniu błędu.
Wartości zwracane przez pam_set_item()
.
PAM_SUCCESS
Poprawne wykonanie.
PAM_SYSTEM_ERR
Błąd w pamh
.
PAM_PERM_DENIED
Próba wstawienia NULL
na strukturę konwersacji.
PAM_BUF_ERR
Brak dostępnej pamięci.
PAM_BAD_ITEM
Próba zmiany danych niedostępnych lub nieistniejących.
3.4.4. Czytanie danych zawartych w strukturze pamh
- pam_get_item()
.
extern int pam_get_item (const pam_handle_t *pamh, int item_type,
const void **item);
Odczytanie wartości w polu item_type
. W przypadku sukcesu
*item
zawiera wskaźnik do odczytanej wartości. Jest to faktyczna
wartość i nie należy jej modyfikować.
Wartości zwracane.
PAM_SUCCESS
Poprawne wykonanie.
PAM_SYSTEM_ERR
Błąd w pamh
.
PAM_PERM_DENIED
Wartość item była NULL
.
PAM_BAD_ITEM
Niezdefiniowanu lub niedostępny typ danych.
W przypadku błędu wskaźnik item nie jest modyfikowany.
3.4.5. Informacja o błędzie - pam_strerror()
.
extern const char *pam_strerror (pam_handle *pamh, int errnum);
Funkcja zwraca krótką notatkę o błędzie errnum
.
3.4.6. Odstępy czasowe - pam_fail_delay()
.
extern int pam_fail_delay (pam_handle_t *pamh, unsigned int micro_sec);
Ustawia przedziały/odstępy czasowe po powrocie z błędnego wywołania pam_authenticate()
,
a przed przejęciem kontroli przez aplikację.
3.4.7. Uwierzytelnianie - pam_authenticate()
.
extern int pam_authenticate (pam_handle_t *pamh, int flags);
Funkcja pełni rolę intrfejsu do mechanizmu autoryzacji zawartego w załadowanych
modułach. Opcjonalny parametr flags
może mieć jedną wartość.
Wartość ta może zostać logicznie związana poprzez OR z PAM_SILENT
,
które oznacza, że żadne komunikaty nie będą wysyłane do aplikacji.
PAM_DISALLOW_NULL_AUTHTOK
Mówi modułowi autoryzującemu, by zwrócił PAM_AUTH_ERR
jeśli użytkownik nie ma zarejestrowanego hasła, tzn. jego hasło jest NULL
.
Wartości zwracane.
PAM_AUTH_ERR
Użytkownik nie został uwierzytelniony.
PAM_CRED_INSUFFICIENT
Niewystarczające dane o użytkowniku (credentials).
PAM_AUTHINFO_UNAVAIL
Moduł nie uzyskał dostępu do informacji autoryzacyjnych, np.
z powodu błędu sieci lub sprzętu.
PAM_USER_UNKNOWN
Nie ma takiego użytkownika.
PAM_MAXTRIES
Liczba prób autoryzacji została przekroczona.
PAM_ABORT
Nie można załadować jednego lub więcej modułów.
3.4.8. Ustawianie danych o użytkowniku (credentials) - pam_setcred()
.
extern int pam_setcred (pam_handle_t *pamh, int flags)
;
Funkcja używana w celu nadania specyficznych ustawień/danych dla użytkownika.
Zwykle wywoływana po uwierzytelnieniu, ale przed otworzeniem sesji dla tego
użytkownika.
"Dane o użytkowniku" (credentials) to coś, co należy do użytkownika. Pewien
rodzaj posiadłości, jak bilet identyfikujący użytkownika.
Funkcja ta wywołuje funkcje pam_sm_setcred()
znajdujące się
w każdym z załadowanych modułów. Flaga flags
może być logicznie
połączona spójnikiem OR z PAM_SILENT
i ma następujące możliwe
wartości.
PAM_ESTABLISH_CRED
Przydziel i ustaw dane.
PAM_DELETE_CRED
Usuń dane.
PAM_REINITIALIZE_CRED
Zresetuj dane.
PAM_REFRESH_CRED
Przedłuż czas życia danych.
Wartości zwracane.
PAM_SUCCESS
Poprawne wykonanie.
PAM_CRED_UNAVAIL
Dane nie zostały odnalezione przez moduł.
PAM_CRED_EXPIRED
Dane nieaktualne.
PAM_USER_UNKNOWN
Nieznany użytkownik.
PAM_CRED_ERR
Modułowi nie udało się ustawić danych.
3.4.9. Zarządzanie kontem- pam_acct_mgmt()
.
extern int pam_acct_mgmt (pam_handle_t *pamh, int flags);
Zwykle wywoływane po uwierzytelnieniu. Sprawdza stan konta użytkownika.
Może to być sprawdzenie, czy konto jest nadal aktywne, czy użytkownik ma
uprawnienia, by uzyskać dostęp do systemu w tej chwili (pora dnia, data).
Parametr flags
może być logicznie połączony przez OR z PAM_SILENT
i przyjmuje takie wartości jak w pam_authenticate()
.
Funkcja wywołuje odpowiednie funkcje każdego załadowanego modułu zgodnie
z instrukcjami w pliku konfiguracyjnym /etc/pam.conf
.
Wartości zwracane.
PAM_SUCCESS
Poprawne wykonanie.
PAM_AUTHTOKEN_REQD
Hasło nie jest już aktualne. Należy zmienić hasło poprzez pam_chauthtok()
.
PAM_ACCT_EXPIRED
Użytkownik nie ma już dostępu do systemu.
PAM_AUTH_ERR
Błąd przy uwierzytelnianiu.
PAM_PERM_DENIED
Użytkownik nie ma prawa dostępu w tej chwili.
PAM_USER_UNKNOWN
Nieznany użytkownik.
3.4.10. Aktualizacja hasła - pam_chauthtok()
.
extern int pam_authtok (pam_handle_t *pamh, const int flags);
Funkcja używana do zmiany hasła dla użytkownika. Poprzez hasło należy tu
rozumieć nie tylko hasło składające się z ciągu znaków, ale każdy rodzaj hasła
uwierzytelniającego, np. karta z pinem, głos.
Opcjonalny parametr flags
może być połączony poprzez OR z
PAM_SILENT i przyjmuje poniższą wartość.
PAM_CHANGE_EXPIRED_AUTHTOK
Hasło ma być zmienione tylko w przypadku, gdy jest nieaktualne.
Wartości zwracane.
PAM_SUCCESS
Hasło zostało zmienione.
PAM_AUTHTOK_ERR
Moduł nie dostał nowego hasła.
PAM_AUTHTOK_RECOVERY_ERR
Moduł nie dostał starego hasła.
PAM_AUTHTOK_LOCK_BUSY
Jeden lub więcej modułów nie zmieniło hasła, bo jest ono zablokowane.
PAM_AUTHTOK_DISABLE_AGING
PAM_PERM_DENIED
Brak dostępu.
PAM_TRY_AGAIN
Nie wszystkie moduły dokonały zmiany hasła. Hasło nie zostało
zmienione.
PAM_USER_UNKNOWN
Nieznany użytkownik.
3.4.11. Otwarcie sesji - pam_open_session()
.
extern int pam_open_session (pam_handle_t *pamh, int flags);
Poinformowanie modułów, że użytkownik jest w sesji uwierzytelnionej. Powinno
być możliwe otwarcie sesji przez jedną aplikację, a zamknięcie przez inną.
Funkcja ta wywołuje odpowiednie funkcje załadowanych modułów.
Opcjonalna flaga flags
może być PAM_SILENT.
Jeśli jakiś załadowany, a wymagany moduł nie może otworzyć sesji dla tego
użytkownika, funkcja zwraca PAM_SESSION_ERR
.
3.4.12. Zamknięcie sesji - pam_close_session()
.
Informuje moduły, że użytkownik opuszcza sesję.
Woła odpowiednie funkcje modułów.
Flaga flags
jest opcjonalna i może być PAM_SILENT
.
Jeśli jakiś załadowany, a wymagany moduł nie może zamknąć sesji dla tego
użytkownika, funkcja zwraca PAM_SESSION_ERR
.
3.4.13. Ustawienie zmiennych środowiskowych dla PAM - pam_putenv()
.
Wskaźnik pamh ma przypisany zbiór zmiennych środowiskowych.
extern int pam_putenv (pam_handle_t *pamh, const char *name_value);
Funkcja wstawia nową zmienną środowiskową do zbioru, zmienia wartość już
istniejącej zmiennej i usuwa zmienne środowiskowe.
Parametr name_value
jest stringiem o jednej z poniższych form.
"zmienna=wartość"
Zmienna zmienna
zostaje dodana do środowiska o
ile tam jej nie ma. Jeśli jest to jej wartość jest
nadpisywana. W obu przypadkach zmienna
będzie miała
wartość wartość
.
"zmienna"
Usuwa zmienną zmienna
ze środowiska.
Zwracane wartości.
PAM_PERM_DENIED
Parametr name_value
jest NULL
.
PAM_BAD_ITEM
Nie można usunąć zmiennej, bo nie istnieje.
PAM_ABORT
Nieprawidłowy wskaźnik pamh
.
PAM_BUF_ERR
Nie można zaalokować pamięci.
3.4.14. Odczytywanie wartości zmiennej środowiskowej - pam_getenv()
.
extern const char *pam_getenv (pam_handle_t *pamh, const char *name);
Zwraca NULL
gdy błąd.
3.4.15. Odczytanie środowiska - pam_getenvlist()
.
extern const char * const *pam_getenvlist (pam_handle_t *pamh);
Zwraca wskaźnik do pełnej nowej kopii zmiennych, na nowo zaalokowanej.
Jest to kopia listy zmiennych środowiskowych. Ta pamięć nie będzie zwalniana
automatycznie przez Linux-PAM. Za zwolnienie tej pamięci jest odpowiedzialna
aplikacja wołająca funkcję.
Formatem środowiska jest tablica wskaźników do stringów. Ostatni element
tej tablicy to NULL
. Każdy string ma postać "zmienna=wartość"
.
Zarówno tablica wskaźników jak i stringi są na nowo zaalokowane.
3.5. Funkcja interakcji.
Aplikacja musi dostarczyć funkcję do bezpośredniej komunikacji pomiędzi
aplikacją a załadowanym modułem.
struct pam_conv {
int (*conv) (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr);
void *appdata_ptr;
};
Struktura jest inicjalizowana w aplikacji zanim zostanie wysłana do biblioteki.
Zawartość tej struktury jest umieszczana w pamh
.
Aby wspomóc pracę programisy aplikacji dołożono bibliotekę libpam_misc
.
Jedną z funkcji dostarczanych przez tą bibliotekę jest funkcja interakcji
oparta na tekście.
extern int misc_conv (int num_msg, const struct pam_message **msgm,
struct pam_response **response,
void *appdata_ptr);
4. Pisane modułów zgodnych z Linux-PAM.
4.1. Interfejs Linux-PAM dla modułów.
4.1.1. Ustawianie danych - pam_set_data()
.
extern int pam_set_data (pam_handle_t *pamh, const char *module_data_name,
void *data,
void (*cleanup) (pam_handle_t *pamh, void *data,
int error_status));
Modiły mogą być ładowane dynamicznie. Generalnie nie piwinny zawierać zmiannych
statycznych. Ta i inne funkcje dostarczają interfejsu do powiązania wskaźnika
pamh
z danymi. Typowo moduł wywołuje tą funkcję, aby zarejestrować
dane pod unikatową nazwą module_data_name
. Dane mogą być uzywane
przez inne moduły, ale nie przez aplikację.
Funkcja cleanup()
jest wywoływana gdy data
jest
nadpisywane lub po wywołaniu pam_end()
.
4.1.2. Odczytywanie danych - pam_get_data()
.
extern int pam_get_data (const pam_handle_t *pamh, const char *module_data_name,
const void **data);
Po wykonaniu data
wskazuje na dane związane z module_data_name
.
4.1.3. Ustawianie pól - pam_set_item()
.
extern int pam_set_item (pam_handle_t *pamh, int item_type, const
void *item);
Ustawia wartość pola item_type
. Prócz wartości wymienionych
w punkcie 3.4.3 można dodatkowo ustawiać.
PAM_AUTHTOK
Hasło.
PAM_OLDAUTHTOK
Stare hasło.
Oba te pola są resetowane przed powrotem do aplikacji. Resetownie polego
na tym, że wartość jest zerowana, a pamięć zwalniana.
4.1.4. Odczytywanie pól - pam_get_item()
.
extern int pam_get_item (const pam_handle_t *pamh, int item_type,
const void **item);
Prócz wartości wymienionych w punkcie 3.4.4 moduł ma dodatkowo uprawnienia
do czytania pól PAM_AUTHTOK
i PAM_OLDAUTHTOK
.
4.1.5. Mechanizm konwersacji.
Omówiony w punkcie 3.5. Moduł nie powinien narzucać sposobu, w jaki komunikaty
są prezentowane użytkownikowi lub pobierane od użytkownika. Moduł jest odpowiedzialny
za zwalnianie pamięci alokowanych dla struktury pam_conv
.
4.1.6. Czytanie nazwy użytkownika - pam_get_user()
.
extern int pam_get_user (pam_handle_t *pamh, const char **user, const
char *prompt);
Zwraca nazwę użytkownika w *user.
4.1.7. Ustawianie zmiennych środowiskowych - pam_putenv()
.
Omówione w punkcie 3.4.13.
4.1.8. Odczytanie wartości zmiennych środowiskowych - pam_getenv()
.
Omówione w punkcie 3.4.14.
4.1.9. Odczytanie całego środowiska - pam_getentlist()
.
Omówione w punkcie 3.4.15.
4.1.10. Notatka o błędzie - pam_strerror()
.
Omówione w punkcie 3.4.5.
4.1.11. Określanie opóźnienia - pam_fail_delay()
.
Omówione w punkcie 3.4.6.
4.2. Co musi dostarczać moduł.
4.2.1. Krótka charakterystyka wymagań wobec modułu.
Moduł musi definiować podzbiór sześciu funkcji. Grupują się one w cztery
niezależne usługi:
* uwierzytelnianie
* konto
* sesja
* hasło.
Moduł musi definiować wszystkie funkcje z przynajmniej jednej grupy.
Niezależność tych grup usług jakie oferuje moduł oznacz, że moduł powinien
dopuścić możliwość, że jakakolwiek z tych grup usług może być wywołana w dowolnej
kolejności. Stąd autor modułu musi zapewnić poprawność bez założeń, że jakaś
inna część modułu wykona się z sukcesem.
Moduł musi minimalizować problemy administracyjne. Aby uniknąć tych problemów
i nieprawidłowości w /etc/pam.conf
autor modułu może zdefinować
wszystkie sześć funkcji. Dla funkcji które nie będą wołane moduł powinien
zwracać PAM_SERVICE_ERR i wypisać stosowny komunikat do logu systemowego.
Parametr flags
w każdej z poniższych funkcji może być połączony
poprzez OR z PAM_SILENT, co informuje moduł, żeby nie przesyłał żadnego tekstu
do aplikacji.
4.2.2. Uwierzytelnianie.
#define <security/pam_modules.h>
PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags,
int argc, const char **argv);
Wykonuje zadanie uwierzytelniania użytkownika.
PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags, int
argc, const char **argv);
Wykonuje zadanie zmiany danych o użytkowniku zgodnie ze schematem uwierzytelniania.
4.2.3. Zarządzanie kontem.
#include <security/pam_modules.h>
PAM_EXTERN int pam_sm_acct_mgmt (pam_handle_h *pamh, int flags, int
argc, const char **argv);
Wykonuje zadanie ustalenia czy użytkownik ma prawo dostępu w tej chwili.
Nie jest to uwierzytelnianie lecz sprawdzenie takich danych jak: czas dnia,
data, zdalny host, terminal. Funkcja ta również odpowiada za ustalenie końca
ważności hasła i prośby o zmianę hasła.
4.2.4. Zarządzanie sesją.
#include <security/pam_module.h>
PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int
flags, int argc, const char **argv);
PAM_EXTERN int pam_sm_close_session (pam_handle_t *pamh, int
flags, int argc, const char **argv);
4.2.5. Zarządzanie hasłem.
#include <security/pam_module.h>
PAM_EXTERN int pam_sm_chauthtok (pam_handle_t *pamh, int
flags, int argc, const char **argv);
Wykonuje zadanie zmiany hasła.
5. Konfiguracja Linux-PAM.
Konfiguracja Linux-PAM odbywa się poprzez plik konfiguracyjny /etc/pam.conf
.
Rys. 2 przedstawia przykładowy plik konfiguracyjny.
service module_type control_flag module_path
options
------- ----------- ------------ ----------- -------
login auth required pam_unix_auth.so nowarn
login session required pam_unix_session.so
login account required pam_unix_account.so
ftp auth required pam_skey_auth.so debug
ftp session required pam_unix_session.so
telnet session required pam_unix_session.so
login password required pam_unix_passwd.so
passwd password required pam_unix_passwd.so
OTHER auth required pam_unix_auth.so
OTHER session required pam_unix_session.so
OTHER account required pam_unix_account.so
Rys.2. Przykładowy plik konfiguracyjny /etc/pam.conf
.
Login jest wymienione 3 razy, każdy typ usługi PAM dla usługi login znajduje
się w innym module. Wszystkie usługi dokonują autoryzacji w inny sposób, a
sesję obsługują w ten sam sposób.
Pole service
oznacza usługę. OTHER
oznacza wszystkie
usługi nie wymienione nazwą w tym pliku.
Pole module_type
oznacza typ funkcjonalności PAM.
Pole control_flag
wskazuje zachowanie spośród: required,
sufficient, optional
.
Pole module_path
wskazuje na lokalizację modułu.
Pole options
wskazuje na specyficzne opcje dla modułu, np.
przekazanie parametrów innym modułom.
6. Przykładowy schemat aplikacji korzystającej z Linux-PAM.
#include <security/pam_appl.h>
#include <security/pam_misc.h>
static struct pam_conv conv = {
misc_conv, /* Standardowa funkcja konwersacji tekstowej. */
NULL
};
pam_start ("program", "user", &conv, &pamh);
pam_authenticate (pamh, 0); /* Autoryzacja. */
pam_acct_mgmt(pamh, 0); /* Czy w tej chwili ma dostęp do systemu. */
/* Użytkownik został lub nie zostal uwierzytelniony. */
pam_end();
7. Przykładowy schemat modułu dla Linux-PAM.
#include <security/pam_modules.h>
/* AUTORYZACJA */
pam_sm_setcred()
{
/* Alokacja i inicjalizacja danych użytkownika. */
}
pam_sm_authenticate()
{
pam_get_user(user);
pam_set_item(user);
}
/* KONTO */
pam_sm_acct_mgmt()
{
/* Sprawdzenie czy użytkownik ma teraz dostęp. */
}
/* HASŁO */
pam_sm_chauthtok()
{
/* Zmień hasło. */
}
module_init(){}
module_exit(){}
8. Materiały.
* Andrew G. Morgan, The Linux-PAM Module Writers' Guide.
* Andrew G. Morgan, The Linux-PAM System Administrators' Guide.
* Andrew G. Morgan, The Linux-PAM Application Writers' Guide.
* V. Samar, R. Schemers, Unified login with Pluggable Authentication Modules.
Wszystkie na stronie: http://www.kernel.org/pub/linux/libs/pam.