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.