                   Podklyuchaemye Moduli Autentifikacii (PAM)

  Dag-Erling Smo/rgrav

   Tekst predostavil 
   Izdanie: 43126

   Avtorskie prava (c) 2001-2003 Networks Associates Technology, Inc.

   `Eta stat'ya byla napisana dlya Proekta FreeBSD kompaniyami ThinkSec AS i
   Network Associates Laboratories, Security Research Division of Network
   Associates, Inc. v ramkah rabot po kontraktu N66001-01-C-8035 s
   DARPA/SPAWAR (<<CBOSS>>), kak chast' issledovatel'skoj programmy DARPA
   CHATS.

   FreeBSD `eto zaregistrirovannaya torgovaya marka FreeBSD Foundation.

   Linux `eto zaregistrirovannaya torgovaya marka Linus Torvalds.

   Motif, OSF/1 i UNIX `eto zaregistrirovannye torgovye marki, a IT DialTone
   i The Open Group `eto torgovye marki Open Group v Soedinennyh SHtatah i
   drugih stranah.

   Sun, Sun Microsystems, Java, Java Virtual Machine, JDK, JRE, JSP, JVM,
   Netra, Solaris, StarOffice, SunOS `eto torgovye marki ili
   zaregistrirovannye torgovye marki Sun Microsystems, Inc. v Soedinennyh
   SHtatah i drugih stranah.

   Mnogie iz oboznachenij, ispol'zuemye proizvoditelyami i prodavcami dlya
   oboznacheniya svoih produktov, zayavlyayutsya v kachestve torgovyh marok.
   Kogda takie oboznacheniya poyavlyayutsya v `etom dokumente, i Proektu
   FreeBSD izvestno o torgovoj marke, k oboznacheniyu dobavlyaetsya znak
   <<(TM)>> ili <<(R)>>.

   2013-11-07 gabor.
   Annotaciya

   V `etoj stat'e opisyvayutsya principy i mehanizmy, lezhaschie v osnove
   biblioteki Podklyuchaemyh Modulej Autentifikacii (PAM - Pluggable
   Authentication Modules), i rasskazyvaetsya, kak nastroit' PAM, kak
   integrirovat' PAM v prilozheniya i kak sozdavat' moduli PAM.

     ----------------------------------------------------------------------

   Soderzhanie

   1. Vvedenie

   2. Terminy i soglasheniya

   3. Osnovy PAM

   4. Nastrojka PAM

   5. Moduli PAM vo FreeBSD

   6. Programmirovanie prilozhenij s PAM

   7. Programmirovanie modulya PAM

   A. Primer PAM-prilozheniya

   B. Primer PAM-modulya

   C. Primer funkcii vzaimodejstviya PAM

   Dopolnitel'naya literatura

1. Vvedenie

   Biblioteka Pluggable Authentication Modules (PAM) yavlyaetsya
   obobschionnym API dlya sluzhb, svyazannyh s autentifikaciej, kotorye
   pozvolyayut sistemnomu administratoru dobavlyat' novye metody
   autentifikacii prostoj ustanovkoj novyh modulej PAM, i izmenyat' politiku
   autentifikacii posredstvom redaktirovaniya konfiguracionnyh fajlov.

   PAM opisali i razrabotali Vipin Samar i Charlie Lai iz Sun Microsystems v
   1995 godu, s teh on sil'no ne menyalsya. V 1997 godu Open Group
   opublikovala predvaritel'nye specifikacii na X/Open Single Sign-on (XSSO),
   chto standartizovalo API dlya PAM i dobavilo rasshireniya dlya odnorazovoj
   (ili dostatochno integrirovannoj) podpisi. Na moment napisaniya `etogo
   dokumenta `eta specifikaciya eschio ne byla prinyata za standart.

   Hotya `eta stat'ya posvyaschena v osnovnom FreeBSD 5.x, v kotoroj
   ispol'zuetsya OpenPAM, ona podojdiot dlya FreeBSD 4.x, ispol'zuyuschej
   Linux-PAM, i drugih operacionnyh sistem, takih, kak Linux i Solaris(TM).

2. Terminy i soglasheniya

  2.1. Opredeleniya

   Terminologiya, ispol'zuemaya v PAM, dostatochno zaputana. Ni original'naya
   rabota Samar i Lai, ni specifikaciya XSSO ne delayut nikakih popytok
   formal'no opredelit' terminy dlya razlichnyh ob"ektov i uchastvuyuschih v
   PAM storon, a terminy, kotorye oni ispol'zuyut (no ne opredelyayut) inogda
   neverny i neodnoznachny. Pervoj popytkoj sozdat' nedvusmyslennuyu i
   soglasovannuyu terminologiyu byla rabota, kotoruyu napisal Andrew G.
   Morgan (avtor Linux-PAM) v 1999 godu. Hotya vybor terminologii, kotoruyu
   sdelal Morgan, byl gigantskim skachkom vpered, `eto, po mneniyu avtora
   dannoj stat'i, ne oznachaet ee pravil'nost'. Dalee delaetsya popytka, v
   znachitel'noj stepeni na osnove raboty Morgana, dat' tochnye i
   nedvusmyslennye opredeleniya terminov dlya vseh uchastnikov i ob"ektov
   PAM.

   uchiotnaya zapis' (account)

           Nabor polnomochij, kotorye applikant zaprashivaet ot arbitratora.

   applikant (applicant)

           Pol'zovatel' ili ob"ekt, zaprashivayuschie autentifikaciyu.

   arbitrator (arbitrator)

           Pol'zovatel' ili ob"ekt, imeyuschij privilegii, dostatochnye dlya
           proverki polnomochij applikanta i prava podtverdit' ili otklonit'
           zapros.

   cepochka (chain)

           Posledovatel'nost' modulej, kotorye budut vyzvany v otvet na
           zapros PAM. V cepochku vklyuchena informaciya o posledovatel'nosti
           vyzovov modulej, argumentah, kotorye nuzhno im peredat', i o tom,
           kak interpretirovat' rezul'taty.

   klient (client)

           Prilozhenie, otvechayuschee za iniciirovanie zaprosa na
           autentifikaciyu ot imeni applikanta i poluchayuschee ot nego
           neobhodimuyu dlya autentifikacii informaciyu.

   podsistema (facility)

           Odna iz chetyreh osnovnyh grupp funkcional'nosti, kotorye daet
           PAM: autentifikaciya, upravlenie uchetnymi zapisyami, upravlenie
           seansom i obnovlenie klyuchom autentifikacii.

   modul' (module)

           Nabor iz odnoj ili bol'shego kolichestva svyazannyh funkcij,
           realizuyuschih opredelennuyu podsistemu autentifikacii, sobrannyj
           v odin (obychno dinamicheski zagruzhaemyj) dvoichnyj fajl,
           identificiruemyj po imeni.

   politika (policy)

           Polnyj nabor konfiguracionnyh deklaracij, opisyvayuschih, kak
           obrabatyvat' zaprosy PAM k opredelennoj usluge. Politika obychno
           sostoit iz chetyreh cepochek, po odnoj dlya kazhdoj podsistemy,
           hotya nekotorye sluzhby ispol'zuyut ne vse chetyre podsistemy.

   server (server)

           Prilozhenie, vystupayuschee ot imeni arbitratora dlya obscheniya s
           klientom, zaprashivaniya autentifikacionnoj informacii, proverki
           polnomochij applikanta i podtverzhdayuschee ili otklonyayuschee
           zapros.

   servis (service)

           Klass serverov, predostavlyayuschih pohozhuyu ili svyazannuyu
           funkcional'nost', i trebuyuschuyu podobnuyu autentifikaciyu.
           Politiki PAM zadayutsya na osnove servisov, tak chto ko vsem
           serveram, ob"yavlyayuschim odno i tozhe imya servisa, budet
           primenyat'sya odna i ta zhe politika.

   seans (session)

           Kontekst, v kotorom servis okazyvaetsya applikantu serverom. Odna
           iz chetyreh podsistem PAM, upravlenie seansom, kasaetsya
           isklyuchitel'no nastrojke i ochistke `etogo konteksta.

   klyuch (token)

           Blok informacii, svyazannyj s uchiotnoj zapis'yu, naprimer, parol'
           ili klyuchevaya fraza, kotoruyu applikant dolzhen predostavit'
           dlya svoej identifikacii.

   tranzakciya (transaction)

           Posledovatel'nost' zaprosov ot odnogo i togo zhe applikanta k
           odnomu i tomu zhe `ekzemplyaru togo zhe samogo servera, nachinaya
           s autentifikacii i ustanovleniya seansa i zakanchivaya zakrytiem
           seansa.

  2.2. Primery ispol'zovaniya

   `Etot razdel prednaznachen dlya illyustracii znachenij nekotoryh terminov,
   opredelennyh vyshe, pri pomoschi prostyh primerov.

    2.2.1. Ob"edinennye klient i server

   V `etom prostom primere pokazyvaetsya pol'zovatel' alice, vypolnyayuschij
   komandu su(1) dlya togo, chtoby stat' pol'zovatelem root.

 % whoami
 alice
 % ls -l `which su`
 -r-sr-xr-x  1 root  wheel  10744 Dec  6 19:06 /usr/bin/su
 % su -
 Password: xi3kiune
 # whoami
 root

     * Applikantom yavlyaetsya alice.

     * Uchetnoj zapis'yu yavlyaetsya root.

     * Process su(1) yavlyaetsya kak klientom, tak i serverom.

     * Autentifikacionnym klyuchom yavlyaetsya xi3kiune.

     * Arbitratorom vystupaet root, i imenno po`etomu u komandy su(1)
       vystavlen bit vypolneniya s pravami root.

    2.2.2. Klient i server razdeleny

   V primere nizhe rassmatrivaetsya pol'zovatel' eve, pytayuschijsya
   ustanovit' ssh(1)-soedinenie s login.example.com, i uspeshno vhodya kak
   pol'zovatel' bob. Bob dolzhen byl vybrat' parol' poluchshe!

 % whoami
 eve
 % ssh bob@login.example.com
 bob@login.example.com's password: god
 Last login: Thu Oct 11 09:52:57 2001 from 192.168.0.1
 Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
         The Regents of the University of California.  All rights reserved.
 FreeBSD 4.4-STABLE (LOGIN) #4: Tue Nov 27 18:10:34 PST 2001

 Welcome to FreeBSD!
 %

     * Applikantom yavlyaetsya eve.

     * Klientom yavlyaetsya process ssh(1) pol'zovatelya Eve.

     * Serverom yavlyaetsya process sshd(8) na mashine login.example.com

     * Uchetnoj zapis'yu yavlyaetsya bob.

     * Klyuchom autentifikacii yavlyaetsya god.

     * Hotya `etogo ne vidno v primere, no arbitratorom yavlyaetsya root.

    2.2.3. Primer politiki

   Sleduyuschee yavlyaetsya politikoj, ispol'zuemoj vo FreeBSD po umolchaniyu
   dlya sshd:

 sshd   auth            required        pam_nologin.so  no_warn
 sshd   auth            required        pam_unix.so     no_warn try_first_pass
 sshd   account         required        pam_login_access.so
 sshd   account         required        pam_unix.so
 sshd   session         required        pam_lastlog.so  no_fail
 sshd   password        required        pam_permit.so

     * `Eta politika primenyaetsya k sluzhbe sshd (chto ne obyazatel'no
       ogranicheno serverom sshd(8)).

     * auth, account, session i password yavlyayutsya podsistemami.

     * pam_nologin.so, pam_unix.so, pam_login_access.so, pam_lastlog.so i
       pam_permit.so yavlyayutsya modulyami. Iz `etogo primera vidno, chto
       pam_unix.so realizuet po krajnej mere dve podsistemy (autentifikaciyu
       i upravlenie uchiotnymi zapisyami).

3. Osnovy PAM

  3.1. Podsistemy i primitivy

   API dlya PAM predostavlyaet shest' razlichnyh primitivov dlya
   autentifikacii, sgruppirovannyh v chetyre podsistemy, kazhdaya iz kotoryh
   opisyvaetsya nizhe.

   auth

           Autentifikaciya. `Eta podsistema, sobstvenno govorya, realizuet
           autentifikaciyu applikanta i vyyasnenie polnomochij uchiotnoj
           zapisi. Ona predostavlyaet dva primitiva:

              * Funkciya pam_authenticate(3) autentificiruet applikanta,
                obychno zaprashivaya autentifikacionnyj klyuch i sravnivaya
                ego so znacheniem, hranyaschimsya v baze dannyh ili
                poluchaemym ot servera autentifikacii.

              * Funkciya pam_setcred(3) ustanavlivaet polnomochiya uchiotnoj
                zapisi, takie, kak identifikator pol'zovatelya, chlenstvo v
                gruppah i ogranicheniya na ispol'zovanie resursov.

   account

           Upravlenie uchiotnoj zapis'yu. `Eta podsistema obrabatyvaet
           voprosy dostupnosti uchetnoj zapisi, ne svyazannye s
           autentifikaciej, takie, kak ogranicheniya v dostupe na osnove
           vremeni sutok ili zagruzki servera. On predostavlyaet edinstvennyj
           primitiv:

              * Funkciya pam_acct_mgmt(3) proveryaet, dostupna li
                zaprashivaemaya uchiotnaya zapis'.

   session

           Upravlenie seansom. `Eta podsistema otrabatyvaet zadachi,
           svyazannye s ustanovleniem i zakrytiem seansa, takie, kak uchet
           vhodov pol'zovatelej. Ona predostavlyaet dva primitiva:

              * Funkciya pam_open_session(3) vypolnyaet dejstviya, svyazannye
                s ustanovleniem seansa: dobavlenie zapisej v bazy dannyh utmp
                i wtmp, zapusk agenta SSH i tak dalee.

              * Funkciya pam_close_session(3) vypolnyaet dejstviya,
                svyazannye s zakrytiem seansa: dobavlenie zapisej v bazy
                dannyh utmp i wtmp, zavershenie raboty agenta SSH i tak
                dalee.

   password

           Upravlenie parolem. `Eta podsistema ispol'zuetsya dlya izmeneniya
           klyucha autentifikacii, svyazannogo s uchetnoj zapis'yu, po
           prichine istecheniya ego sroka dejstviya ili zhelaniya
           pol'zovatelya izmenit' ego. Ona predostavlyaet edinstvennyj
           primitiv:

              * Funkciya pam_chauthtok(3) izmenyaet klyuch autentifikacii,
                opcional'no proveryaya, chto on truden dlya podbora, ne
                ispol'zovalsya ranee i tak dalee.

  3.2. Moduli

   Moduli yavlyayutsya central'noj koncepciej v PAM; v konce koncov, im
   sootvetstvuet bukva <<M>> v sokraschenii <<PAM>>. Modul' PAM predstavlyaet
   soboj samodostatochnyj kusok programmnogo koda, kotoryj realizuet
   primitivy odnoj ili bol'shego kolichestva podsistem odnogo konkretnogo
   mehanizma; k vozmozhnym mehanizmam dlya podsistemy autentifikacii, k
   primeru, otnosyatsya bazy dannyh parolej UNIX(R), sistemy NIS, LDAP ili
   Radius.

    3.2.1. Imenovanie modulej

   Vo FreeBSD kazhdyj mehanizm realizuetsya v otdel'nom module s imenem
   pam_mechanism.so (naprimer, pam_unix.so dlya mehanizma UNIX(R).) V drugih
   realizaciyah inogda otdel'nye moduli ispol'zuyutsya dlya raznyh podsistem,
   i v ih imya vklyuchaetsya, krome nazvaniya mehanizma, i imya podsistemy. K
   primeru, v Solaris(TM) imeetsya modul' pam_dial_auth.so.1, kotoryj chasto
   ispol'zuetsya dlya autentifikacii pol'zovatelej, rabotayuschih po
   kommutiruemym kanalam svyazi.

    3.2.2. Versii modulej

   Iznachal'naya realizaciya PAM vo FreeBSD, kotoraya byla osnovana na
   Linux-PAM, ne ispol'zovala nomera versij dlya modulej PAM. `Eto budet
   privodit' k problemam pri rabote unasledovannyh prilozhenij, kotorye mogut
   byt' skomponovany so starymi versiyami sistemnyh bibliotek, tak kak
   sposoba podgruzit' sootvetstvuyuschuyu versiyu trebuemyh modulej net.

   OpenPAM, s drugoj storony, ischet moduli, kotorye imeyut tot zhe samyj
   nomer versii, chto i biblioteka PAM (na dannyj moment 2), i ispol'zuet
   modul' bez versii, tol'ko esli modul' s izvestnoj versiej ne byl
   zagruzhen. Po`etomu dlya staryh prilozhenij mogut predostavlyat'sya starye
   moduli, pri `etom novye (ili zanovo postroennye) prilozheniya budut
   ispol'zovat' vse vozmozhnosti poslednih versij modulej.

   Hotya moduli PAM v Solaris(TM) imeyut nomer versii, po-nastoyaschemu nomer
   versii v nih ne otslezhivaetsya, potomu chto nomer yavlyaetsya chast'yu
   imeni i dolzhen vklyuchat'sya v konfiguraciyu.

  3.3. Cepochki i politiki

   Kogda server iniciiruet PAM-tranzakciyu, biblioteka PAM pytaetsya
   zagruzit' politiku dlya sluzhby, ukazannoj pri vyzove funkcii
   pam_start(3). Politika opredelyaet, kak dolzhny obrabatyvat'sya zaprosy na
   autentifikaciyu, i zadaiotsya v konfiguracionnom fajle. `Eto sostavlyaet
   druguyu osnovopolagayuschuyu koncepciyu PAM: vozmozhnost' administratoru
   nastraivat' politiku bezopasnosti sistemy (v samom shirokom eio ponimanii)
   prostym redaktirovaniem tekstovogo fajla.

   Politika sostoit iz chetyrioh cepochek, po odnoj na kazhdyj iz metodov
   PAM. Kazhdoe zveno predstavlyaet soboj posledovatel'nost' konfiguracionnyh
   utverzhdenij, zadayuschih vyzyvaemyj modul', nekotorye (neobyazatel'nye)
   parametry dlya peredachi v modul', i upravlyayuschij flag, opisyvayuschij,
   kak interpretirovat' vozvraschaemyj iz modulya kod.

   Ponimanie smysla upravlyayuschego flaga neobhodimo dlya ponimaniya
   konfiguracionnyh fajlov PAM. Suschestvuyut chetyre razlichnyh
   upravlyayuschih flaga:

   binding

           Esli modul' otrabotal uspeshno, i ni odin iz predyduschih modulej
           v cepochke ne srabotal otricatel'no, to cepochka preryvaetsya, a
           zapros podtverzhdaetsya. Esli zhe modul' otrabotaet neudachno, to
           vypolnyaetsya ostavshayasya chast' cepochki, odnako zapros
           otvergaetsya.

           `Etot upravlyayuschij flag byl dobavlen kompaniej Sun v
           Solaris(TM) 9 (SunOS(TM) 5.9), i podderzhivaetsya v OpenPAM.

   required

           Esli modul' vozvratil polozhitel'nyj otvet, vypolnyaetsya
           ostavshayasya chast' cepochki, zapros udovletvoryaetsya, esli
           nikakoj drugoj modul' ne otrabotaet otricatel'no. Esli zhe modul'
           vozvratit otricatel'nyj otvet, ostatok cepochki tozhe
           otrabatyvaetsya, no zapros otvergaetsya.

   requisite

           Esli modul' vozvraschaet polozhitel'nyj otvet, vypolnyaetsya
           ostavshayasya chast' cepochki, zapros udovletvoryaetsya, esli
           nikakoj drugoj modul' ne otrabotaet otricatel'no. Esli zhe modul'
           otrabatyvaet otricatel'no, to otrabotka cepochki nemedlenno
           prekraschaetsya, a zapros otvergaetsya.

   sufficient

           Esli modul' vozvratit polozhitel'nyj otvet, i ni odin iz
           predyduschih modulej v cepochke na otrabotal otricatel'no, to
           otrabotka cepochki nemedlenno prekraschaetsya, a zapros
           udovletvoryaetsya. Esli modul' otrabotal otricatel'no, to
           rezul'tat ignoriruetsya i cepochka otrabatyvaetsya dal'she.

           Tak kak semantika `etogo flaga mozhet okazat'sya zaputannoj,
           osobenno pri ego ispol'zovanii s poslednim modulem v cepochke,
           rekomenduetsya vmesto nego ispol'zovat' upravlyayuschij flag
           binding, esli realizaciya ego podderzhivaet.

   optional

           Modul' otrabatyvaetsya, no rezul'tat vypolneniya ignoriruetsya.
           Esli vse moduli v cepochke pomecheny kak optional, to
           udovletvoryat'sya budut vse zaprosy.

   Kogda server vyzyvaet odin iz shesti PAM-primitivov, PAM zaprashivaet
   cepochku podsistemy, k kotoroj prinadlezhit primitiv, i zapuskaet kazhdyj
   modul', perechislennyj v cepochke v poryadke ih perechisleniya, poka
   spisok ne budet ischerpan libo ne budet opredeleno, chto dal'nejshej
   obrabotki ne nuzhno (po prichine dostizhenie modulya, vernuvshego
   polozhitel'nyj otvet pri uslovii binding ili sufficient, libo
   otricatel'nyj s usloviem requisite). Zapros podtverzhdaetsya, esli tol'ko
   byl vyzvan po krajnej mere odin modul', i vse neopcional'nye moduli
   vernuli polozhitel'nyj otvet.

   Zamet'te, chto vozmozhno, hotya `eto ne rasprostraneno, perechislyat' odin
   i tot zhe modul' neskol'ko raz v odnoj cepochke. K primeru, modul',
   prosmatrivayuschij imena i paroli pol'zovatelya v servere kataloga mozhet
   byt' vyzvan neskol'ko raz s razlichnymi parametrami, zadayuschimi
   razlichnye servery katalogov dlya svyazi. PAM schitaet razlichnye
   poyavleniya odnogo modulya v toj zhe samoj cepochke raznymi i ne
   svyazannymi modulyami.

  3.4. Tranzakcii

   ZHiznennyj cikl tipichnoj PAM-tranzakcii opisan nizhe. Zamet'te, chto v
   sluchae, esli lyuboj iz perechislennyh shagov okanchivaetsya neudachno,
   server dolzhen vydat' klientu sootvetstvuyuschee soobschenie ob oshibke i
   prervat' tranzakciyu.

    1. Esli `eto neobhodimo, server poluchaet polnomochiya arbitratora cherez
       nezavisimyj ot PAM mehanizm-chasche vsego po faktu zapuska
       pol'zovatelem root ili s ustanovlennym setuid-bitom root.

    2. Server vyzyvaet funkciyu pam_start(3) dlya inicializacii biblioteki
       PAM i zadaniya imeni servisa i celevoj uchiotnoj zapisi, a takzhe
       registracii podhodyaschego sposoba obscheniya.

    3. Server poluchaet razlichnuyu informaciyu, otnosyaschuyusya k
       tranzakcii (takuyu, kak imya pol'zovatelya applikanta i imya hosta, na
       kotorom zapuschen klient), i otpravlyaet eio v PAM pri pomoschi
       funkcii pam_set_item(3).

    4. Server vyzyvaet funkciyu pam_authenticate(3) dlya autentifikacii
       applikanta.

    5. Server vyzyvaet funkciyu pam_acct_mgmt(3) dlya proverki togo, chto
       zaproshennaya uchiotnaya zapis' dostupna i korrektna. Esli parol'
       veren, no ego srok istiok, pam_acct_mgmt(3) vozvratit rezul'tat
       PAM_NEW_AUTHTOK_REQD, a ne PAM_SUCCESS.

    6. Esli na predyduschem shage byl poluchen rezul'tat
       PAM_NEW_AUTHTOK_REQD, to server vyzyvaet funkciyu pam_chauthtok(3)
       dlya togo, chtoby vynudit' klienta izmenit' klyuch autentifikacii dlya
       zaproshennoj uchiotnoj zapisi.

    7. Teper', kogda applikant polnost'yu autentificirovan, server vyzyvaet
       funkciyu pam_setcred(3) dlya polucheniya polnomochij zaproshennoj
       uchiotnoj zapisi. Sdelat' `eto vozmozhno, potomu chto on rabotaet kak
       arbitrator, i ostavlyaet za soboj polnomochiya arbitratora.

    8. Posle polucheniya neobhodimyh polnomochij, server vyzyvaet funkciyu
       pam_open_session(3) dlya ustanovleniya seansa.

    9. Teper' server vypolnyaet tot servis, kotoryj zatreboval
       klient-naprimer, predostavlyaet applikantu obolochku.

   10. Posle togo, kak server zakonchil obsluzhivanie klienta, on vyzyvaet
       funkciyu pam_close_session(3) dlya zakrytiya seansa.

   11. Nakonec, server vyzyvaet funkciyu pam_end(3) dlya opovescheniya
       biblioteki PAM o tom, chto rabota s nej zavershena i kakie-libo
       vydelennye v techenie seansa resursy mozhno osvobodit'.

4. Nastrojka PAM

  4.1. Fajly politik PAM

    4.1.1. Fajl /etc/pam.conf

   Tradicionno fajlom politik PAM yavlyaetsya /etc/pam.conf. On soderzhit vse
   politiki PAM dlya vashej sistemy. Kazhdaya stroka fajla opisyvaet odin
   shag v cepochke, kak pokazano nizhe:

 login   auth    required        pam_nologin.so  no_warn

   Polya sleduyut v takom poryadke: imya sluzhby, imya podsistemy,
   upravlyayuschij flag, imya modulya i parametry modulya. Lyubye
   dopolnitel'nye polya interpretiruyutsya kak dopolnitel'nye parametry
   modulya.

   Dlya kazhdoj pary servis/podsistema sostavlyaetsya otdel'naya cepochka, i
   togda poluchaetsya, chto, hotya poryadok sledovaniya strok dlya odnoj i
   toj zhe uslugi i podsistemy yavlyaetsya znachimym, poryadok perechisleniya
   otdel'nyh servisov ne znachim. V primerah iz original'noj raboty po PAM
   stroki konfiguracii sgruppirovany po podsistemam, v postavlyaemom s
   Solaris(TM) fajle pam.conf imenno tak i sdelano, no v standartnom
   konfiguracionnom fajle iz postavki FreeBSD stroki nastroek sgruppirovany
   po servisam. Podhodit lyuboj iz `etih sposobov; oni imeyut odin i tot zhe
   smysl.

    4.1.2. Katalog /etc/pam.d

   OpenPAM i Linux-PAM podderzhivayut al'ternativnyj mehanizm nastrojki,
   kotoryj dlya FreeBSD yavlyaetsya predpochtitel'nym. V `etoj sheme kazhdaya
   politika soderzhitsya v otdel'nom fajle s imenem, sootvetstvuyuschem
   servisu, k kotoromu ona primenyaetsya. `Eti fajly razmeschayutsya v
   kataloge /etc/pam.d/.

   Takie fajly politik, orientirovannye na servisy, imeyut tol'ko chetyre
   polya, vmesto pyati polej v fajle pam.conf: pole imeni servisa opuscheno.
   Takim obrazom, vmesto primera stroki fajla pam.conf iz predyduschego
   razdela poluchitsya sleduyuschaya stroka v fajle /etc/pam.d/login:

 auth    required        pam_nologin.so  no_warn

   Kak sledstvie takogo uproschionnogo sintaksisa, vozmozhno ispol'zovanie
   odnih i teh zhe politik dlya neskol'kih servisov, svyazyvaya kazhdoe imya
   servisa s tem zhe samym fajlom politik. K primeru, dlya ispol'zovaniya toj
   zhe samoj politiki dlya servisov su i sudo, mozhno sdelat' sleduyuschee:

 # cd /etc/pam.d
 # ln -s su sudo

   `Eto rabotaet, potomu chto imya servisa opredelyaetsya imenem fajla, a ne
   ego ukazaniem v fajle politiki, tak chto odin i tot zhe fajl mozhet
   ispol'zovat'sya dlya neskol'kih servisov s raznymi nazvaniyami.

   Tak kak politika kazhdogo servisa hranitsya v otdel'nom fajle, to mehanizm
   pam.d delaet ustanovku dopolnitel'nyh politik dlya programmnyh paketov
   storonnih razrabotchikov ochen' liogkoj zadachej.

    4.1.3. Poryadok poiska politik

   Kak vy videli vyshe, politiki PAM mogut nahodit'sya v neskol'kih mestah.
   CHto budet, esli politiki dlya odnogo i togo zhe servisa imeyutsya v
   raznyh mestah?

   Neobhodimo osoznat', chto sistema konfiguracii PAM orientirovana na
   cepochki.

  4.2. Struktura stroki nastrojki

   Kak `eto ob"yasneno v Razdel 4.1, <<Fajly politik PAM>>, kazhdaya stroka
   fajla /etc/pam.conf sostoit iz chetyrioh ili bol'shego kolichestva polej:
   imeni servisa, imeni podsistemy, upravlyayuschego flaga, imeni modulya i
   dopolnitel'nyh parametrov modulya, kotorye mogut otsutstvovat'.

   Imya servisa obychno (hotya ne vsegda) yavlyaetsya imenem prilozheniya,
   kotoroe `etot servis obsluzhivaet. Esli vy ne uvereny, obratites' k
   dokumentacii po konkretnomu prilozheniyu dlya opredeleniya ispol'zuemogo
   imeni servisa.

   Zamet'te, chto esli vy ispol'zuete /etc/pam.d/ vmesto /etc/pam.conf, to
   imya servisa zadaetsya imenem fajla politiki, i opuskaetsya iz strok
   nastrojki, kotorye v takom sluchae nachinayutsya s nazvaniya podsistemy.

   Imya podsistemy predstavlyaet soboj odno iz chetyrioh klyuchevyh slov,
   opisannyh v Razdel 3.1, <<Podsistemy i primitivy>>.

   Tochno takzhe upravlyayuschij flag yavlyaetsya odnim iz chetyrioh
   klyuchevyh slov, opisannyh v Razdel 3.3, <<Cepochki i politiki>>, v
   kotorom rasskazano, kak interpretirovat' vozvraschaemyj iz modulya kod. V
   Linux-PAM podderzhivaetsya al'ternativnyj sintaksis, kotoryj pozvolyaet
   ukazat' dejstvie, svyazannoj s kazhdyj vozmozhnym kodom vozvrata, no
   `etogo sleduet izbegat', tak kak on ne yavlyaetsya standartnym i tesno
   svyazan so sposobom dispetcherizacii vyzovov servisov v Linux-PAM (a on
   znachitel'no otlichaetsya ot sposoba vzaimodejstviya v Solaris(TM) i
   OpenPAM). Ne vyzyvaet udivleniya tot fakt, chto v OpenPAM `etot sintaksis
   ne podderzhivaetsya.

  4.3. Politiki

   Dlya korrektnoj nastrojki PAM neobhodimo ponimat', kak proishodit
   interpretaciya politik.

   V moment, kogda prilozhenie vyzyvaet funkciyu pam_start(3), biblioteka PAM
   zagruzhaet politiku dlya ukazannogo servisa i vystraivaet chetyre cepochki
   modulej (po odnoj dlya kazhdoj podsistemy). Esli odna ili bol'shee
   kolichestvo `etih cepochek yavlyayutsya pustymi, to budut vypolnyat'sya
   podstanovki sootvetstvuyuschih cepochek iz politiki dlya servisa other.

   Kogda zatem prilozhenie vyzyvaet odnu iz shesti primitivov PAM, biblioteka
   PAM vydelyaet iz cepochki nuzhnuyu podsistemu i vyzyvaet funkciyu,
   sootvetstvuyuschuyu servisu, v kazhdom module, perechislennom v cepochke,
   v tom poryadke, v kakom oni perechisleny v konfiguracii. Posle kazhdogo
   obrascheniya k funkcii servisa, tip modulya i vozvraschionnyj iz `etoj
   funkcii kod rezul'tata vypolneniya ispol'zuyutsya dlya togo, chto delat'
   dal'she. Za nekotorymi isklyucheniyami, kotorye budut opisany nizhe,
   primenyaetsya takaya tablica:

   Tablica 1. Svodnaya tablica otrabotki cepochek PAM

   +-------------------------------------------------------------------+
   |            |    PAM_SUCCESS    | PAM_IGNORE |        other        |
   |------------+-------------------+------------+---------------------|
   | binding    | if (!fail) break; | -          | fail = true;        |
   |------------+-------------------+------------+---------------------|
   | required   | -                 | -          | fail = true;        |
   |------------+-------------------+------------+---------------------|
   | requisite  | -                 | -          | fail = true; break; |
   |------------+-------------------+------------+---------------------|
   | sufficient | if (!fail) break; | -          | -                   |
   |------------+-------------------+------------+---------------------|
   | optional   | -                 | -          | -                   |
   +-------------------------------------------------------------------+

   Esli peremennaya fail prinimaet istinnoe znachenie v konce otrabotki
   cepochki, ili kogda dostignut <<break>>, dispetcher vozvraschaet kod
   oshibki, vozvraschionnyj pervym modulem, otrabotavshim neudachno. V
   protivnom sluchae vozvraschaetsya PAM_SUCCESS.

   Pervym isklyucheniem yavlyaetsya to, chto kod oshibki PAM_NEW_AUTHTOK_REQD
   interpretiruetsya kak uspeshnyj rezul'tat, krome sluchaya, kogda modul'
   otrabotal uspeshno, i po krajnej mere odin modul' vozvratil
   PAM_NEW_AUTHTOK_REQD, togda dispetcher vozvratit rezul'tat
   PAM_NEW_AUTHTOK_REQD.

   Vtorym isklyucheniem yavlyaetsya to, chto pam_setcred(3) schitaet, chto
   moduli binding i sufficient yavlyayutsya ravnoznachnymi required.

   Tret'im i poslednim isklyucheniem yavlyaetsya to, chto funkciya
   pam_chauthtok(3) otrabatyvaet polnuyu cepochku dvazhdy (odin raz dlya
   predvaritel'nyh proverok, i eschio raz dlya real'nogo zadaniya parolya), i
   na podgotovitel'noj faze ona schitaet, chto moduli binding i sufficient
   yavlyayutsya ravnoznachnymi required.

5. Moduli PAM vo FreeBSD

  5.1. pam_deny(8)

   Modul' pam_deny(8) yavlyaetsya odnim iz prostejshih dostupnyh modulej; na
   lyuboj zapros on vozvraschaet rezul'tat PAM_AUTH_ERR. On polezen dlya
   bystrogo otklyucheniya servisa (dobav'te ego na verh kazhdoj cepochki) ili
   zaversheniya cepochek modulej sufficient.

  5.2. pam_echo(8)

   Modul' pam_echo(8) prosto peredaiot svoi parametry v funkciyu
   vzaimodejstviya kak soobschenie PAM_TEXT_INFO. V osnovnom polezna dlya
   otladki, no takzhe mozhet ispol'zovat'sya dlya vyvoda soobschenij, takih
   kak <<Unauthorized access will be prosecuted>> do zapuska procedury
   autentifikacii.

  5.3. pam_exec(8)

   Modul' pam_exec(8) vosprinimaet pervyj peredannyj emu parametr kak imya
   programmy dlya vypolneniya, a ostal'nye argumenty peredayutsya `etoj
   programme v kachestve parametrov komandnoj stroki. Odnim iz vozmozhnyh
   primenenij yavlyaetsya ego ispol'zovanie dlya zapuska v moment registracii
   v sisteme programmy montirovaniya domashnego kataloga pol'zovatelya.

  5.4. pam_ftpusers(8)

   Modul' pam_ftpusers(8)

  5.5. pam_group(8)

   Modul' pam_group(8) prinimaet ili otvergaet applikantov v zavisimosti ot
   ih chlenstva v opredelionnoj fajlovoj gruppe (obychno wheel dlya su(1)). V
   pervuyu ochered' prednaznachen dlya sohraneniya tradicionnogo povedeniya
   utility BSD su(1), hotya imeet i mnogo drugih primenenij, takih kak
   otklyuchenie opredelionnyh grupp pol'zovatelej ot nekotorogo servisa.

  5.6. pam_guest(8)

   Modul' pam_guest(8) pozvolyaet osuschestvlyat' gostevye vhody s
   ispol'zovaniem fiksirovannyh imion vhoda v sistemu. Na parol' mogut
   nakladyvat'sya razlichnye ogranicheniya, odnako dejstviem po umolchaniyu
   yavlyaetsya vvod lyubogo parolya pri ispol'zovanii imeni,
   sootvetstvuyuschego gostevomu vhodu. Modul' pam_guest(8) mozhno legko
   ispol'zovat' dlya realizacii anonimnyh vhodov na FTP.

  5.7. pam_krb5(8)

   Modul' pam_krb5(8)

  5.8. pam_ksu(8)

   Modul' pam_ksu(8)

  5.9. pam_lastlog(8)

   Modul' pam_lastlog(8)

  5.10. pam_login_access(8)

   Modul' pam_login_access(8) predostavlyaet realizaciyu primitiva dlya
   upravleniya uchiotnymi zapisyami, kotoryj vvodit v dejstvie ogranicheniya
   na vhod, zadavaemye v tablice login.access(5).

  5.11. pam_nologin(8)

   Modul' pam_nologin(8) otvergaet lyubye vhody ne pol'zovatelem root, esli
   suschestvuet fajl /var/run/nologin. Obychno `etot fajl sozdaiotsya
   utilitoj shutdown(8), kogda do zaplanirovannogo zaversheniya raboty
   sistemy ostaiotsya menee pyati minut.

  5.12. pam_opie(8)

   Modul' pam_opie(8) realizuet metod autentifikacii opie(4). Sistema opie(4)
   yavlyaetsya mehanizmom raboty po sheme zapros-otvet, pri kotorom otvet na
   kazhdyj zapros yavlyaetsya pryamoj funkciej ot zaprosa i klyuchevoj frazy,
   tak chto otvet mozhet byt' legko i <<vovremya>> vychislen lyubym,
   znayuschim klyuchevuyu frazu, chto izbavlyaet ot neobhodimosti peredavat'
   parol'. Krome togo, tak kak v opie(4) nikogda povtorno ne ispol'zuetsya
   zapros, otvet na kotoryj byl korrektno poluchen, `eta shema yavlyaetsya
   ustojchivoj k atakam, osnovannym na povtore dejstvij.

  5.13. pam_opieaccess(8)

   Modul' pam_opieaccess(8) dopolnyaet modul' pam_opie(8). Ego rabota
   zaklyuchaetsya v vypolnenii ogranichenij, zadavaemyh fajlom opieaccess(5),
   kotoryj opredelyaet usloviya, pri kotoryh pol'zovatel', normal'no
   proshedshij autentifikaciyu posredstvom opie(4), mozhet ispol'zovat'
   al'ternativnye metody. CHasche vsego on ispol'zuetsya dlya zapreta
   ispol'zovaniya autentifikacii na osnove parolej s neproverennyh hostov.

   Dlya `effektivnosti modul' pam_opieaccess(8) dolzhen byt' opredelion v
   cepochke auth kak requisite srazu zhe posle zapisi sufficient dlya
   pam_opie(8), no pered lyubymi drugimi modulyami.

  5.14. pam_passwdqc(8)

   Modul' pam_passwdqc(8)

  5.15. pam_permit(8)

   Modul' pam_permit(8) yavlyaetsya odnim iz samyh prostym iz imeyuschihsya;
   na lyuboj zapros on otvechaet PAM_SUCCESS. On polezen v kachestve zameny
   pustogo mesta dlya servisov, kogda odna ili bol'shee kolichestvo cepochek
   v protivnom sluchae ostanutsya pustymi.

  5.16. pam_radius(8)

   Modul' pam_radius(8)

  5.17. pam_rhosts(8)

   Modul' pam_rhosts(8)

  5.18. pam_rootok(8)

   Modul' pam_rootok(8) vozvraschaet polozhitel'nyj rezul'tat v tom i tol'ko
   v tom sluchae, esli real'nyj id pol'zovatelya processa, ego vyzvavshego
   (predpolagaetsya, chto ego zapuskaet applikant) raven 0. `Eto polezno dlya
   nesetevyh servisov, takih kak su(1) ili passwd(1), k kotorym pol'zovatel'
   root dolzhen imet' avtomaticheskij dostup.

  5.19. pam_securetty(8)

   Modul' pam_securetty(8)

  5.20. pam_self(8)

   Modul' pam_self(8) vozvraschaet polozhitel'nyj rezul'tat togda i tol'ko
   togda, kogda imena applikanta sootvetstvuyut celevoj uchiotnoj zapisi.
   Bol'she vsego `eto prigoditsya v nesetevyh servisah, takih kak su(1), v
   kotoryh identifikaciya applikanta mozhet byt' s liogkost'yu proverena.

  5.21. pam_ssh(8)

   Modul' pam_ssh(8) predostavlyaet kak servis autentifikacii, tak i seansa.
   Servis autentifikacii pozvolyaet pol'zovatelyam, imeyuschim sekretnye
   klyuchi SSH, zaschischionnye parolyami, v svoih katalogah ~/.ssh,
   autentificirovat'sya posredstvom `etih parolej. Seansovyj servis zapuskaet
   ssh-agent(1) i zagruzhaet klyuchi, kotorye byli rasshifrovany na faze
   autentifikacii. Takaya vozmozhnost', v chastnosti, polezna dlya lokal'nyh
   vhodov v sistemu, kak v sistemu X (posredstvom xdm(1) ili drugogo
   X-menedzhera vhodov, umeyuschego rabotat' s PAM), tak i na konsol'.

  5.22. pam_tacplus(8)

   Modul' pam_tacplus(8)

  5.23. pam_unix(8)

   Modul' pam_unix(8) realizuet tradicionnuyu autentifikaciyu UNIX(R) na
   osnove parolej, ispol'zuyuschuyu funkciyu getpwnam(3) dlya polucheniya
   parolya celevoj uchiotnoj zapisi i sravnivayuschuyu eio s tem, chto
   predstavil applikant. On takzhe predostavlyaet sredstva upravleniya
   uchiotnymi zapisyami (otslezhivaya vremya dejstviya uchiotnoj zapisi i
   parolya) i smeny parolej. Navernoe, `eto samyj poleznyj modul', tak kak
   podavlyayuschee bol'shinstvo administratorov hotyat sohranit' istoricheski
   slozhivsheesya povedenie po krajnej mere nekotoryh servisov.

6. Programmirovanie prilozhenij s PAM

   `Etot razdel eschio ne napisan.

7. Programmirovanie modulya PAM

   `Etot razdel eschio ne napisan.

A. Primer PAM-prilozheniya

   Dalee sleduet minimal'naya realizaciya programmy su(1) s ispol'zovaniem
   PAM. Zamet'te, chto v nej ispol'zuetsya specifichnaya dlya OpenPAM
   funkciya vzaimodejstviya openpam_ttyconv(3), ob"yavlenie kotoroj
   raspolozheno v fajle security/openpam.h. Esli vy sobiraetes' stroit' `eto
   prilozhenie v sisteme s drugoj bibliotekoj PAM, vam neobhodimo budet
   sozdat' sobstvennuyu funkciyu vzaimodejstviya. Nadiozhnuyu funkciyu
   vzaimodejstviya neozhidanno trudno napisat'; ta, chto nahoditsya v
   Prilozhenie C, Primer funkcii vzaimodejstviya PAM, horosha v kachestve
   otpravnoj tochki, no v real'nyh prilozheniyah ispol'zovat'sya ne mozhet.

 /*-
  * Copyright (c) 2002,2003 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $P4: //depot/projects/openpam/bin/su/su.c#10 $
  * $FreeBSD: head/en_US.ISO8859-1/articles/pam/su.c 38826 2012-05-17 19:12:14Z hrs $
  */

 #include <sys/param.h>
 #include <sys/wait.h>

 #include <err.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>

 #include <security/pam_appl.h>
 #include <security/openpam.h>   /* for openpam_ttyconv() */

 extern char **environ;

 static pam_handle_t *pamh;
 static struct pam_conv pamc;

 static void
 usage(void)
 {

         fprintf(stderr, "Usage: su [login [args]]\n");
         exit(1);
 }

 int
 main(int argc, char *argv[])
 {
         char hostname[MAXHOSTNAMELEN];
         const char *user, *tty;
         char **args, **pam_envlist, **pam_env;
         struct passwd *pwd;
         int o, pam_err, status;
         pid_t pid;

         while ((o = getopt(argc, argv, "h")) != -1)
                 switch (o) {
                 case 'h':
                 default:
                         usage();
                 }

         argc -= optind;
         argv += optind;

         if (argc > 0) {
                 user = *argv;
                 --argc;
                 ++argv;
         } else {
                 user = "root";
         }

         /* initialize PAM */
         pamc.conv = &openpam_ttyconv;
         pam_start("su", user, &pamc, &pamh);

         /* set some items */
         gethostname(hostname, sizeof(hostname));
         if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
                 goto pamerr;
         user = getlogin();
         if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS)
                 goto pamerr;
         tty = ttyname(STDERR_FILENO);
         if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
                 goto pamerr;

         /* authenticate the applicant */
         if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
                 goto pamerr;
         if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
                 pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
         if (pam_err != PAM_SUCCESS)
                 goto pamerr;

         /* establish the requested credentials */
         if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
                 goto pamerr;

         /* authentication succeeded; open a session */
         if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
                 goto pamerr;

         /* get mapped user name; PAM may have changed it */
         pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user);
         if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL)
                 goto pamerr;

         /* export PAM environment */
         if ((pam_envlist = pam_getenvlist(pamh)) != NULL) {
                 for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
                         putenv(*pam_env);
                         free(*pam_env);
                 }
                 free(pam_envlist);
         }

         /* build argument list */
         if ((args = calloc(argc + 2, sizeof *args)) == NULL) {
                 warn("calloc()");
                 goto err;
         }
         *args = pwd->pw_shell;
         memcpy(args + 1, argv, argc * sizeof *args);

         /* fork and exec */
         switch ((pid = fork())) {
         case -1:
                 warn("fork()");
                 goto err;
         case 0:
                 /* child: give up privs and start a shell */

                 /* set uid and groups */
                 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
                         warn("initgroups()");
                         _exit(1);
                 }
                 if (setgid(pwd->pw_gid) == -1) {
                         warn("setgid()");
                         _exit(1);
                 }
                 if (setuid(pwd->pw_uid) == -1) {
                         warn("setuid()");
                         _exit(1);
                 }
                 execve(*args, args, environ);
                 warn("execve()");
                 _exit(1);
         default:
                 /* parent: wait for child to exit */
                 waitpid(pid, &status, 0);

                 /* close the session and release PAM resources */
                 pam_err = pam_close_session(pamh, 0);
                 pam_end(pamh, pam_err);

                 exit(WEXITSTATUS(status));
         }

 pamerr:
         fprintf(stderr, "Sorry\n");
 err:
         pam_end(pamh, pam_err);
         exit(1);
 }

    

B. Primer PAM-modulya

   Dalee privedena minimal'naya realizaciya pam_unix(8), predostavlyayuschaya
   tol'ko servisy autentifikacii. Ona dolzhna stroit'sya i rabotat' s
   bol'shinstvom iz realizacij PAM, no ispol'zuet vozmozhnosti rasshirenij
   OpenPAM, esli oni prisutstvuyut: otmet'te ispol'zovanie funkcii
   pam_get_authtok(3), kotoraya kardinal'no uproschaet organizaciyu vvoda
   parolya pol'zovatelem.

 /*-
  * Copyright (c) 2002 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $P4: //depot/projects/openpam/modules/pam_unix/pam_unix.c#3 $
  * $FreeBSD: head/en_US.ISO8859-1/articles/pam/pam_unix.c 38826 2012-05-17 19:12:14Z hrs $
  */

 #include <sys/param.h>

 #include <pwd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>

 #include <security/pam_modules.h>
 #include <security/pam_appl.h>

 #ifndef _OPENPAM
 static char password_prompt[] = "Password:";
 #endif

 #ifndef PAM_EXTERN
 #define PAM_EXTERN
 #endif

 PAM_EXTERN int
 pam_sm_authenticate(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {
 #ifndef _OPENPAM
         struct pam_conv *conv;
         struct pam_message msg;
         const struct pam_message *msgp;
         struct pam_response *resp;
 #endif
         struct passwd *pwd;
         const char *user;
         char *crypt_password, *password;
         int pam_err, retry;

         /* identify user */
         if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
                 return (pam_err);
         if ((pwd = getpwnam(user)) == NULL)
                 return (PAM_USER_UNKNOWN);

         /* get password */
 #ifndef _OPENPAM
         pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
         if (pam_err != PAM_SUCCESS)
                 return (PAM_SYSTEM_ERR);
         msg.msg_style = PAM_PROMPT_ECHO_OFF;
         msg.msg = password_prompt;
         msgp = &msg;
 #endif
         for (retry = 0; retry < 3; ++retry) {
 #ifdef _OPENPAM
                 pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
                     (const char **)&password, NULL);
 #else
                 resp = NULL;
                 pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
                 if (resp != NULL) {
                         if (pam_err == PAM_SUCCESS)
                                 password = resp->resp;
                         else
                                 free(resp->resp);
                         free(resp);
                 }
 #endif
                 if (pam_err == PAM_SUCCESS)
                         break;
         }
         if (pam_err == PAM_CONV_ERR)
                 return (pam_err);
         if (pam_err != PAM_SUCCESS)
                 return (PAM_AUTH_ERR);

         /* compare passwords */
         if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
             (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
             strcmp(crypt_password, pwd->pw_passwd) != 0)
                 pam_err = PAM_AUTH_ERR;
         else
                 pam_err = PAM_SUCCESS;
 #ifndef _OPENPAM
         free(password);
 #endif
         return (pam_err);
 }

 PAM_EXTERN int
 pam_sm_setcred(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_open_session(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_close_session(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SUCCESS);
 }

 PAM_EXTERN int
 pam_sm_chauthtok(pam_handle_t *pamh, int flags,
         int argc, const char *argv[])
 {

         return (PAM_SERVICE_ERR);
 }

 #ifdef PAM_MODULE_ENTRY
 PAM_MODULE_ENTRY("pam_unix");
 #endif

    

C. Primer funkcii vzaimodejstviya PAM

   Funkciya vzaimodejstviya, privodimaya nizhe, yavlyaetsya znachitel'no
   uproschionnoj versiej funkcii openpam_ttyconv(3) iz OpenPAM. Ona
   polnofunkcional'na, i dolzhna posluzhit' istochnikom idej o tom, kak
   dolzhna sebya vesti funkciya vzaimodejstviya, odnako ona slishkom prosta
   dlya real'nyh prilozhenij. Dazhe esli vy ne ispol'zuete OpenPAM, mozhete
   sgruzit' ishodnyj kod i ispol'zovat' openpam_ttyconv(3) v svoih celyah; my
   nadeemsya, chto ona dostatochno nadiozhna v kachestve funkcii dlya
   vzaimodejstviya s terminal'nymi ustrojstvami.

 /*-
  * Copyright (c) 2002 Networks Associates Technology, Inc.
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
  * Network Associates Laboratories, the Security Research Division of
  * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
  * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior written
  *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD: head/en_US.ISO8859-1/articles/pam/converse.c 38826 2012-05-17 19:12:14Z hrs $
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>

 #include <security/pam_appl.h>

 int
 converse(int n, const struct pam_message **msg,
         struct pam_response **resp, void *data)
 {
         struct pam_response *aresp;
         char buf[PAM_MAX_RESP_SIZE];
         int i;

         data = data;
         if (n <= 0 || n > PAM_MAX_NUM_MSG)
                 return (PAM_CONV_ERR);
         if ((aresp = calloc(n, sizeof *aresp)) == NULL)
                 return (PAM_BUF_ERR);
         for (i = 0; i < n; ++i) {
                 aresp[i].resp_retcode = 0;
                 aresp[i].resp = NULL;
                 switch (msg[i]->msg_style) {
                 case PAM_PROMPT_ECHO_OFF:
                         aresp[i].resp = strdup(getpass(msg[i]->msg));
                         if (aresp[i].resp == NULL)
                                 goto fail;
                         break;
                 case PAM_PROMPT_ECHO_ON:
                         fputs(msg[i]->msg, stderr);
                         if (fgets(buf, sizeof buf, stdin) == NULL)
                                 goto fail;
                         aresp[i].resp = strdup(buf);
                         if (aresp[i].resp == NULL)
                                 goto fail;
                         break;
                 case PAM_ERROR_MSG:
                         fputs(msg[i]->msg, stderr);
                         if (strlen(msg[i]->msg) > 0 &&
                             msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                                 fputc('\n', stderr);
                         break;
                 case PAM_TEXT_INFO:
                         fputs(msg[i]->msg, stdout);
                         if (strlen(msg[i]->msg) > 0 &&
                             msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                                 fputc('\n', stdout);
                         break;
                 default:
                         goto fail;
                 }
         }
         *resp = aresp;
         return (PAM_SUCCESS);
  fail:
         for (i = 0; i < n; ++i) {
                 if (aresp[i].resp != NULL) {
                         memset(aresp[i].resp, 0, strlen(aresp[i].resp));
                         free(aresp[i].resp);
                 }
         }
         memset(aresp, 0, n * sizeof *aresp);
         *resp = NULL;
         return (PAM_CONV_ERR);
 }

    

Dopolnitel'naya literatura

  Raboty

   Making Login Services Independent of Authentication Technologies. Vipin
   Samar Charlie Lai. Sun Microsystems.

   X/Open Single Sign-on Preliminary Specification. The Open Group.
   1-85912-144-6. Iyun' 1997.

   Pluggable Authentication Modules. Andrew G. Morgan. 6 oktyabrya 1999.

  Rukovodstva pol'zovatelya

   PAM Administration. Sun Microsystems.

  Web-stranicy po dannoj tematike

   Domashnyaya stranica OpenPAM. Dag-Erling Smo/rgrav. ThinkSec AS.

   Domashnyaya stranica Linux-PAM. Andrew G. Morgan.

   Domashnyaya stranica Solaris PAM. Sun Microsystems.
