1: **Contents**
2:
3: [[!toc levels=3]]
4:
5: # Pluggable Authentication Modules (PAM)
6:
7: ## About
8:
9: This article describes the underlying principles and mechanisms of the
10: *Pluggable Authentication Modules (PAM)* library, and explains how to configure
11: PAM, how to integrate PAM into applications, and how to write PAM modules.
12:
13: See on the bottom of the page for the license of this text.
14:
15: ## Introduction
16:
17: The Pluggable Authentication Modules (PAM) library is a generalized API for
18: authentication-related services which allows a system administrator to add new
19: authentication methods simply by installing new PAM modules, and to modify
20: authentication policies by editing configuration files.
21:
22: PAM was defined and developed in 1995 by Vipin Samar and Charlie Lai of Sun
23: Microsystems, and has not changed much since. In 1997, the Open Group published
24: the X/Open Single Sign-on (XSSO) preliminary specification, which standardized
25: the PAM API and added extensions for single (or rather integrated) sign-on. At
26: the time of this writing, this specification has not yet been adopted as a
27: standard.
28:
29: Although this article focuses primarily on FreeBSD 5.x and NetBSD 3.x, which
30: both use OpenPAM, it should be equally applicable to FreeBSD 4.x, which uses
31: Linux-PAM, and other operating systems such as Linux and Solaris.
32:
33: ## Terms and conventions
34:
35: ### Definitions
36:
37: The terminology surrounding PAM is rather confused. Neither Samar and Lai's
38: original paper nor the XSSO specification made any attempt at formally defining
39: terms for the various actors and entities involved in PAM, and the terms that
40: they do use (but do not define) are sometimes misleading and ambiguous. The
41: first attempt at establishing a consistent and unambiguous terminology was a
42: whitepaper written by Andrew G. Morgan (author of Linux-PAM) in 1999. While
43: Morgan's choice of terminology was a huge leap forward, it is in this author's
44: opinion by no means perfect. What follows is an attempt, heavily inspired by
45: Morgan, to define precise and unambiguous terms for all actors and entities
46: involved in PAM.
47:
48: * *account* -- The set of credentials the applicant is requesting from the
49: arbitrator.
50:
51: * *applicant* -- The user or entity requesting authentication.
52:
53: * *arbitrator* -- The user or entity who has the privileges necessary to verify
54: the applicant's credentials and the authority to grant or deny the request.
55:
56: * *chain* -- A sequence of modules that will be invoked in response to a PAM
57: request. The chain includes information about the order in which to invoke
58: the modules, what arguments to pass to them, and how to interpret the
59: results.
60:
61: * *client* -- The application responsible for initiating an authentication
62: request on behalf of the applicant and for obtaining the necessary
63: authentication information from him.
64:
65: * *facility* -- One of the four basic groups of functionality provided by PAM:
66: authentication, account management, session management and authentication
67: token update.
68:
69: * *module* -- A collection of one or more related functions implementing a
70: particular authentication facility, gathered into a single (normally
71: dynamically loadable) binary file and identified by a single name.
72:
73: * *policy* -- The complete set of configuration statements describing how to
74: handle PAM requests for a particular service. A policy normally consists of
75: four chains, one for each facility, though some services do not use all four
76: facilities.
77:
78: * *server* -- The application acting on behalf of the arbitrator to converse
79: with the client, retrieve authentication information, verify the applicant's
80: credentials and grant or deny requests.
81:
82: * *service* -- A class of servers providing similar or related functionality
83: and requiring similar authentication. PAM policies are defined on a
84: per-service basis, so all servers that claim the same service name will be
85: subject to the same policy.
86:
87: * *session* -- The context within which service is rendered to the applicant by
88: the server. One of PAM's four facilities, session management, is concerned
89: exclusively with setting up and tearing down this context.
90:
91: * *token* -- A chunk of information associated with the account, such as a
92: password or passphrase, which the applicant must provide to prove his
93: identity.
94:
95: * *transaction* -- A sequence of requests from the same applicant to the same
96: instance of the same server, beginning with authentication and session set-up
97: and ending with session tear-down.
98:
99: ### Usage examples
100:
101: This section aims to illustrate the meanings of some of the terms defined above
102: by way of a handful of simple examples.
103:
104: #### Client and server are one
105:
106: This simple example shows `alice`
107: [[!template id=man name="su" section="1"]]'ing to
108: `root`:
109:
110: $ whoami
111: alice
112: $ ls -l `which su`
113: -r-sr-xr-x 1 root wheel 10744 Dec 6 19:06 /usr/bin/su
114: $ su -
115: Password: xi3kiune
116: # whoami
117: root
118:
119: * The applicant is `alice`.
120: * The account is `root`.
121: * The [[!template id=man name="su" section="1"]]
122: process is both client and server.
123: * The authentication token is `xi3kiune`.
124: * The arbitrator is `root`, which is why
125: [[!template id=man name="su" section="1"]] is
126: setuid `root`.
127:
128: #### Client and server are separate
129:
130: The example below shows `eve` try to initiate an
131: [[!template id=man name="ssh" section="1"]]
132: connection to `login.example.com`, ask to log in as `bob`, and succeed. Bob
133: should have chosen a better password!
134:
135: $ whoami
136: eve
137: $ ssh bob@login.example.com
138: bob@login.example.com's password: god
139: Last login: Thu Oct 11 09:52:57 2001 from 192.168.0.1
140: NetBSD 3.0 (LOGIN) #1: Thu Mar 10 18:22:36 WET 2005
141:
142: Welcome to NetBSD!
143: $
144:
145: * The applicant is `eve`.
146: * The client is Eve's
147: [[!template id=man name="ssh" section="1"]]
148: process.
149: * The server is the
150: [[!template id=man name="sshd" section="8"]]
151: process on `login.example.com`
152: * The account is `bob`.
153: * The authentication token is `god`.
154: * Although this is not shown in this example, the arbitrator is `root`.
155:
156: #### Sample policy
157:
158: The following is FreeBSD's default policy for `sshd`:
159:
160: sshd auth required pam_nologin.so no_warn
161: sshd auth required pam_unix.so no_warn try_first_pass
162: sshd account required pam_login_access.so
163: sshd account required pam_unix.so
164: sshd session required pam_lastlog.so no_fail
165: sshd password required pam_permit.so
166:
167: * This policy applies to the `sshd` service (which is not necessarily
168: restricted to the
169: [[!template id=man name="sshd" section="8"]]
170: server.)
171:
172: * `auth`, `account`, `session` and `password` are facilities.
173:
174: * `pam_nologin.so`, `pam_unix.so`, `pam_login_access.so`, `pam_lastlog.so` and
175: `pam_permit.so` are modules. It is clear from this example that `pam_unix.so`
176: provides at least two facilities (authentication and account management.)
177:
178: There are some differences between FreeBSD and NetBSD PAM policies:
179:
180: * By default, every configuration is done under `/etc/pam.d`.
181:
182: * If configuration is non-existent, you will not have access to the system, in
183: contrast with FreeBSD that has a default policy of allowing authentication.
184:
185: * For authentication, NetBSD forces at least one `required`, `requisite` or
186: `binding` module to be present.
187:
188: ## PAM Essentials
189:
190: ### Facilities and primitives
191:
192: The PAM API offers six different authentication primitives grouped in four
193: facilities, which are described below.
194:
195: * `auth` -- *Authentication.* This facility concerns itself with authenticating
196: the applicant and establishing the account credentials. It provides two
197: primitives:
198:
199: * [[!template id=man name="pam\_authenticate" section="3"]]
200: authenticates the applicant, usually by requesting an authentication token
201: and comparing it with a value stored in a database or obtained from an
202: authentication server.
203:
204: * [[!template id=man name="pam\_setcred" section="3"]]
205: establishes account credentials such as user ID, group membership and
206: resource limits.
207:
208: * `account` -- *Account management.* This facility handles
209: non-authentication-related issues of account availability, such as access
210: restrictions based on the time of day or the server's work load. It provides
211: a single primitive:
212:
213: * [[!template id=man name="pam\_acct\_mgmt" section="3"]]
214: verifies that the requested account is available.
215:
216: * `session` -- *Session management.* This facility handles tasks associated
217: with session set-up and tear-down, such as login accounting. It provides two
218: primitives:
219:
220: * [[!template id=man name="pam\_open\_session" section="3"]]
221: performs tasks associated with session set-up: add an entry in the `utmp`
222: and `wtmp` databases, start an SSH agent, etc.
223:
224: * [[!template id=man name="pam\_close\_session" section="3"]]
225: performs tasks associated with session tear-down: add an entry in the
226: `utmp` and `wtmp` databases, stop the SSH agent, etc.
227:
228: * `password` -- *Password management.* This facility is used to change the
229: authentication token associated with an account, either because it has
230: expired or because the user wishes to change it. It provides a single
231: primitive:
232:
233: * [[!template id=man name="pam\_chauthtok" section="3"]]
234: changes the authentication token, optionally verifying that it is
235: sufficiently hard to guess, has not been used previously, etc.
236:
237: ### Modules
238:
239: Modules are a very central concept in PAM; after all, they are the *M* in *PAM*.
240: A PAM module is a self-contained piece of program code that implements the
241: primitives in one or more facilities for one particular mechanism; possible
242: mechanisms for the authentication facility, for instance, include the UNIX®
243: password database, NIS, LDAP and Radius.
244:
245: #### Module Naming
246:
247: FreeBSD and NetBSD implement each mechanism in a single module, named
248: `pam_mechanism`.so (for instance, `pam_unix.so` for the UNIX mechanism.) Other
249: implementations sometimes have separate modules for separate facilities, and
250: include the facility name as well as the mechanism name in the module name. To
251: name one example, Solaris has a `pam_dial_auth.so.1` module which is commonly
252: used to authenticate dialup users. Also, almost every module has a man page with
253: the same name, i.e.:
254: [[!template id=man name="pam\_unix" section="8"]]
255: explains how the `pam_unix.so` module works.
256:
257: #### Module Versioning
258:
259: FreeBSD's original PAM implementation, based on Linux-PAM, did not use version
260: numbers for PAM modules. This would commonly cause problems with legacy
261: applications, which might be linked against older versions of the system
262: libraries, as there was no way to load a matching version of the required
263: modules.
264:
265: OpenPAM, on the other hand, looks for modules that have the same version number
266: as the PAM library (currently 2 in FreeBSD and 0 in NetBSD), and only falls back
267: to an unversioned module if no versioned module could be loaded. Thus legacy
268: modules can be provided for legacy applications, while allowing new (or newly
269: built) applications to take advantage of the most recent modules.
270:
271: Although Solaris PAM modules commonly have a version number, they're not truly
272: versioned, because the number is a part of the module name and must be included
273: in the configuration.
274:
275: #### Module Path
276:
277: There isn't a common directory for storing PAM modules. Under FreeBSD, they are
278: located at `/usr/lib` and, under NetBSD, you can find them in
279: `/usr/lib/security`.
280:
281: ### Chains and policies
282:
283: When a server initiates a PAM transaction, the PAM library tries to load a
284: policy for the service specified in the
285: [[!template id=man name="pam\_start" section="3"]]
286: call. The policy specifies how authentication requests should be processed, and
287: is defined in a configuration file. This is the other central concept in PAM:
288: the possibility for the admin to tune the system security policy (in the wider
289: sense of the word) simply by editing a text file.
290:
291: A policy consists of four chains, one for each of the four PAM facilities. Each
292: chain is a sequence of configuration statements, each specifying a module to
293: invoke, some (optional) parameters to pass to the module, and a control flag
294: that describes how to interpret the return code from the module.
295:
296: Understanding the control flags is essential to understanding PAM configuration
297: files. There are a number of different control flags:
298:
299: * `binding` -- If the module succeeds and no earlier module in the chain has
300: failed, the chain is immediately terminated and the request is granted. If
301: the module fails, the rest of the chain is executed, but the request is
302: ultimately denied.
303:
304: This control flag was introduced by Sun in Solaris 9 (SunOS 5.9), and is also
305: supported by OpenPAM.
306:
307: * `required` -- If the module succeeds, the rest of the chain is executed, and
308: the request is granted unless some other module fails. If the module fails,
309: the rest of the chain is also executed, but the request is ultimately denied.
310:
311: * `requisite` -- If the module succeeds, the rest of the chain is executed, and
312: the request is granted unless some other module fails. If the module fails,
313: the chain is immediately terminated and the request is denied.
314:
315: * `sufficient` -- If the module succeeds and no earlier module in the chain has
316: failed, the chain is immediately terminated and the request is granted. If
317: the module fails, the module is ignored and the rest of the chain is
318: executed.
319:
320: As the semantics of this flag may be somewhat confusing, especially when it
321: is used for the last module in a chain, it is recommended that the `binding`
322: control flag be used instead if the implementation supports it.
323:
324: * `optional` -- The module is executed, but its result is ignored. If all
325: modules in a chain are marked `optional`, all requests will always be
326: granted.
327:
328: When a server invokes one of the six PAM primitives, PAM retrieves the chain for
329: the facility the primitive belongs to, and invokes each of the modules listed in
330: the chain, in the order they are listed, until it reaches the end, or determines
331: that no further processing is necessary (either because a `binding` or
332: `sufficient` module succeeded, or because a `requisite` module failed.) The
333: request is granted if and only if at least one module was invoked, and all
334: non-optional modules succeeded.
335:
336: Note that it is possible, though not very common, to have the same module listed
337: several times in the same chain. For instance, a module that looks up user names
338: and passwords in a directory server could be invoked multiple times with
339: different parameters specifying different directory servers to contact. PAM
340: treat different occurrences of the same module in the same chain as different,
341: unrelated modules.
342:
343: ### Transactions
344:
345: The lifecycle of a typical PAM transaction is described below. Note that if any
346: of these steps fails, the server should report a suitable error message to the
347: client and abort the transaction.
348:
349: 1. If necessary, the server obtains arbitrator credentials through a mechanism
350: independent of PAM -- most commonly by virtue of having been started by `root`,
351: or of being setuid `root`.
352:
353: 2. The server calls
354: [[!template id=man name="pam\_start" section="3"]]
355: to initialize the PAM library and specify its service name and the target
356: account, and register a suitable conversation function.
357:
358: 3. The server obtains various information relating to the transaction (such as
359: the applicant's user name and the name of the host the client runs on) and
360: submits it to PAM using
361: [[!template id=man name="pam\_set\_item" section="3"]].
362:
363: 4. The server calls
364: [[!template id=man name="pam\_authenticate" section="3"]]
365: to authenticate the applicant.
366:
367: 5. The server calls
368: [[!template id=man name="pam\_acct\_mgmt" section="3"]]
369: to verify that the requested account is available and valid. If the password is
370: correct but has expired,
371: [[!template id=man name="pam\_acct\_mgmt" section="3"]]
372: will return `PAM_NEW_AUTHTOK_REQD` instead of `PAM_SUCCESS`.
373:
374: 6. If the previous step returned `PAM_NEW_AUTHTOK_REQD`, the server now calls
375: [[!template id=man name="pam\_chauthtok" section="3"]]
376: to force the client to change the authentication token for the requested
377: account.
378:
379: 7. Now that the applicant has been properly authenticated, the server calls
380: [[!template id=man name="pam\_setcred" section="3"]]
381: to establish the credentials of the requested account. It is able to do this
382: because it acts on behalf of the arbitrator, and holds the arbitrator's
383: credentials.
384:
385: 8. Once the correct credentials have been established, the server calls
386: [[!template id=man name="pam\_open\_session" section="3"]]
387: to set up the session.
388:
389: 9. The server now performs whatever service the client requested -- for
390: instance, provide the applicant with a shell.
391:
392: 10. Once the server is done serving the client, it calls
393: [[!template id=man name="pam\_close\_session" section="3"]]
394: to tear down the session.
395:
396: 11. Finally, the server calls
397: [[!template id=man name="pam\_end" section="3"]]
398: to notify the PAM library that it is done and that it can release whatever
399: resources it has allocated in the course of the transaction.
400:
401: ## PAM Configuration
402:
403: ### PAM policy files
404:
405: #### The `/etc/pam.conf` file
406:
407: The traditional PAM policy file is `/etc/pam.conf`. This file contains all the
408: PAM policies for your system. Each line of the file describes one step in a
409: chain, as shown below:
410:
411: login auth required pam_nologin.so no_warn
412:
413: The fields are, in order: service name, facility name, control flag, module
414: name, and module arguments. Any additional fields are interpreted as additional
415: module arguments.
416:
417: A separate chain is constructed for each service / facility pair, so while the
418: order in which lines for the same service and facility appear is significant,
419: the order in which the individual services and facilities are listed is not. The
420: examples in the original PAM paper grouped configuration lines by facility, and
421: the Solaris stock `pam.conf` still does that, but FreeBSD's stock configuration
422: groups configuration lines by service. Either way is fine; either way makes
423: equal sense.
424:
425: #### The `/etc/pam.d` directory
426:
427: OpenPAM and Linux-PAM support an alternate configuration mechanism, which is the
428: preferred mechanism in FreeBSD and NetBSD. In this scheme, each policy is
429: contained in a separate file bearing the name of the service it applies to.
430: These files are stored in `/etc/pam.d/`.
431:
432: These per-service policy files have only four fields instead of `pam.conf`'s
433: five: the service name field is omitted. Thus, instead of the sample `pam.conf`
434: line from the previous section, one would have the following line in
435: `/etc/pam.d/login`:
436:
437: auth required pam_nologin.so no_warn
438:
439: As a consequence of this simplified syntax, it is possible to use the same
440: policy for multiple services by linking each service name to a same policy file.
441: For instance, to use the same policy for the `su` and `sudo` services, one could
442: do as follows:
443:
444: # cd /etc/pam.d
445: # ln -s su sudo
446:
447: This works because the service name is determined from the file name rather than
448: specified in the policy file, so the same file can be used for multiple
449: differently-named services.
450:
451: Since each service's policy is stored in a separate file, the `pam.d` mechanism
452: also makes it very easy to install additional policies for third-party software
453: packages.
454:
455: #### The policy search order
456:
457: As we have seen above, PAM policies can be found in a number of places. If no
458: configuration file is found for a particular service, the `/etc/pam.d/other` is
459: used instead. If that file does not exist, `/etc/pam.conf` is searched for
460: entries matching he specified service or, failing that, the "other" service.
461:
462: It is essential to understand that PAM's configuration system is centered on
463: chains.
464:
465: ### Breakdown of a configuration line
466:
467: As explained in the [PAM policy files](chap-pam.html#pam-config-file "18.5.1.
468: PAM policy files") section, each line in `/etc/pam.conf` consists of four or
469: more fields: the service name, the facility name, the control flag, the module
470: name, and zero or more module arguments.
471:
472: The service name is generally (though not always) the name of the application
473: the statement applies to. If you are unsure, refer to the individual
474: application's documentation to determine what service name it uses.
475:
476: Note that if you use `/etc/pam.d/` instead of `/etc/pam.conf`, the service name
477: is specified by the name of the policy file, and omitted from the actual
478: configuration lines, which then start with the facility name.
479:
480: The facility is one of the four facility keywords described in the
481: [[Facilities and primitives|guide/pam#facilities-primitives]]] section.
482:
483: Likewise, the control flag is one of the four keywords described in the [[Chains
484: and policies|guide/pam#chains-policies]] section, describing how to interpret
485: the return code from the module. Linux-PAM supports an alternate syntax that
486: lets you specify the action to associate with each possible return code, but
487: this should be avoided as it is non-standard and closely tied in with the way
488: Linux-PAM dispatches service calls (which differs greatly from the way Solaris
489: and OpenPAM do it.) Unsurprisingly, OpenPAM does not support this syntax.
490:
491: ### Policies
492:
493: To configure PAM correctly, it is essential to understand how policies are
494: interpreted.
495:
496: When an application calls
497: [[!template id=man name="pam\_start" section="3"]],
498: the PAM library loads the policy for the specified service and constructs four
499: module chains (one for each facility.) If one or more of these chains are empty,
500: the corresponding chains from the policy for the `other` service are
501: substituted.
502:
503: When the application later calls one of the six PAM primitives, the PAM library
504: retrieves the chain for the corresponding facility and calls the appropriate
505: service function in each module listed in the chain, in the order in which they
506: were listed in the configuration. After each call to a service function, the
507: module type and the error code returned by the service function are used to
508: determine what happens next. With a few exceptions, which we discuss below, the
509: following table applies:
510:
511: [[!table data="""
512: | `PAM_SUCCESS` | `PAM_IGNORE` | `other`
513: binding | if (!fail) break; | - | fail = true;
514: required | - | - | fail = true;
515: requisite | - | - | fail = true; break;
516: sufficient | if (!fail) break; | - | -
517: optional | - | - | -
518: """]]
519:
520: If `fail` is true at the end of a chain, or when a `break` is reached, the
521: dispatcher returns the error code returned by the first module that failed.
522: Otherwise, it returns `PAM_SUCCESS`.
523:
524: The first exception of note is that the error code `PAM_NEW_AUTHTOK_REQD` is
525: treated like a success, except that if no module failed, and at least one module
526: returned `PAM_NEW_AUTHTOK_REQD`, the dispatcher will return
527: `PAM_NEW_AUTHTOK_REQD`.
528:
529: The second exception is that
530: [[!template id=man name="pam\_setcred" section="3"]]
531: treats `binding` and `sufficient` modules as if they were `required`.
532:
533: The third and final exception is that
534: [[!template id=man name="pam\_chauthtok" section="3"]]
535: runs the entire chain twice (once for preliminary checks and once to actually
536: set the password), and in the preliminary phase it treats `binding` and
537: `sufficient` modules as if they were `required`.
538:
539: ## PAM modules
540:
541: ### Common Modules
542:
543: #### pam\_deny(8)
544:
545: The
546: [[!template id=man name="pam\_deny" section="8"]]
547: module is one of the simplest modules available; it responds to any request with
548: `PAM_AUTH_ERR`. It is useful for quickly disabling a service (add it to the top
549: of every chain), or for terminating chains of `sufficient` modules.
550:
551: #### pam\_echo(8)
552:
553: The
554: [[!template id=man name="pam\_echo" section="8"]]
555: module simply passes its arguments to the conversation function as a
556: `PAM_TEXT_INFO` message. It is mostly useful for debugging, but can also serve
557: to display messages such as `Unauthorized access will be prosecuted` before
558: starting the authentication procedure.
559:
560: #### pam\_exec(8)
561:
562: The
563: [[!template id=man name="pam\_exec" section="8"]]
564: module takes its first argument to be the name of a program to execute, and the
565: remaining arguments are passed to that program as command-line arguments. One
566: possible application is to use it to run a program at login time which mounts
567: the user's home directory.
568:
569: #### pam\_ftpusers(8)
570:
571: The
572: [[!template id=man name="pam\_ftpusers" section="8"]]
573: module successes if and only if the user is listed in `/etc/ftpusers`.
574: Currently, in NetBSD, this module doesn't understand the extended syntax of
575: [[!template id=man name="ftpd" section="8"]], but
576: this will be fixed in the future.
577:
578: #### pam\_group(8)
579:
580: The
581: [[!template id=man name="pam\_group" section="8"]]
582: module accepts or rejects applicants on the basis of their membership in a
583: particular file group (normally `wheel` for
584: [[!template id=man name="su" section="1"]]). It is
585: primarily intended for maintaining the traditional behaviour of BSD
586: [[!template id=man name="su" section="1"]], but has
587: many other uses, such as excluding certain groups of users from a particular
588: service.
589:
590: In NetBSD, there is an argument called `authenticate` in which the user is asked
591: to authenticate using his own password.
592:
593: #### pam\_guest(8)
594:
595: The
596: [[!template id=man name="pam\_guest" section="8"]]
597: module allows guest logins using fixed login names. Various requirements can be
598: placed on the password, but the default behaviour is to allow any password as
599: long as the login name is that of a guest account. The
600: [[!template id=man name="pam\_guest" section="8"]]
601: module can easily be used to implement anonymous FTP logins.
602:
603: #### pam\_krb5(8)
604:
605: The
606: [[!template id=man name="pam\_krb5" section="8"]]
607: module provides functions to verify the identity of a user and to set user
608: specific credentials using Kerberos 5. It prompts the user for a password and
609: obtains a new Kerberos TGT for the principal. The TGT is verified by obtaining a
610: service ticket for the local host. The newly acquired credentials are stored in
611: a credential cache and the environment variable KRB5CCNAME is set appropriately.
612: The credentials cache should be destroyed by the user at logout with
613: [[!template id=man name="kdestroy" section="1"]].
614:
615: #### pam\_ksu(8)
616:
617: The
618: [[!template id=man name="pam\_ksu" section="8"]]
619: module provides only authentication services for Kerberos 5 to determine whether
620: or not the applicant is authorized to obtain the privileges of the target
621: account.
622:
623: #### pam\_lastlog(8)
624:
625: The
626: [[!template id=man name="pam\_lastlog" section="8"]]
627: module provides only session management services. It records the session in
628: [[!template id=man name="utmp" section="5"]],
629: [[!template id=man name="utmpx" section="5"]],
630: [[!template id=man name="wtmp" section="5"]],
631: [[!template id=man name="wtmpx" section="5"]],
632: [[!template id=man name="lastlog" section="5"]]
633: and
634: [[!template id=man name="lastlogx" section="5"]]
635: databases.
636:
637: #### pam\_login\_access(8)
638:
639: The
640: [[!template id=man name="pam\_login\_access" section="8"]]
641: module provides an implementation of the account management primitive which
642: enforces the login restrictions specified in the
643: [[!template id=man name="login.access" section="5"]]
644: table.
645:
646: #### pam\_nologin(8)
647:
648: The
649: [[!template id=man name="pam\_nologin" section="8"]]
650: module refuses non-root logins when `/var/run/nologin` exists. This file is
651: normally created by
652: [[!template id=man name="shutdown" section="8"]]
653: when less than five minutes remain until the scheduled shutdown time.
654:
655: #### pam\_permit(8)
656:
657: The
658: [[!template id=man name="pam\_permit" section="8"]]
659: module is one of the simplest modules available; it responds to any request with
660: `PAM_SUCCESS`. It is useful as a placeholder for services where one or more
661: chains would otherwise be empty.
662:
663: #### pam\_radius(8)
664:
665: The
666: [[!template id=man name="pam\_radius" section="8"]]
667: module provides authentication services based upon the RADIUS (Remote
668: Authentication Dial In User Service) protocol.
669:
670: #### pam\_rhosts(8)
671:
672: The
673: [[!template id=man name="pam\_rhosts" section="8"]]
674: module provides only authentication services. It reports success if and only if
675: the target user's ID is not 0 and the remote host and user are listed in
676: `/etc/hosts.equiv` or in the target user's `~/.rhosts`.
677:
678: #### pam\_rootok(8)
679:
680: The
681: [[!template id=man name="pam\_rootok" section="8"]]
682: module reports success if and only if the real user id of the process calling it
683: (which is assumed to be run by the applicant) is 0. This is useful for
684: non-networked services such as
685: [[!template id=man name="su" section="1"]] or
686: [[!template id=man name="passwd" section="1"]], to
687: which the `root` should have automatic access.
688:
689: #### pam\_securetty(8)
690:
691: The
692: [[!template id=man name="pam\_securetty" section="8"]]
693: module provides only account services. It is used when the applicant is
694: attempting to authenticate as superuser, and the process is attached to an
695: insecure TTY.
696:
697: #### pam\_self(8)
698:
699: The
700: [[!template id=man name="pam\_self" section="8"]]
701: module reports success if and only if the names of the applicant matches that of
702: the target account. It is most useful for non-networked services such as
703: [[!template id=man name="su" section="1"]], where the
704: identity of the applicant can be easily verified.
705:
706: #### pam\_ssh(8)
707:
708: The
709: [[!template id=man name="pam\_ssh" section="8"]]
710: module provides both authentication and session services. The authentication
711: service allows users who have passphrase-protected SSH secret keys in their
712: `~/.ssh` directory to authenticate themselves by typing their passphrase. The
713: session service starts
714: [[!template id=man name="ssh-agent" section="1"]]
715: and preloads it with the keys that were decrypted in the authentication phase.
716: This feature is particularly useful for local logins, whether in X (using
717: [[!template id=man name="xdm" section="1"]] or
718: another PAM-aware X login manager) or at the console.
719:
720: This module implements what is fundamentally a password authentication scheme.
721: Care should be taken to only use this module over a secure session (secure TTY,
722: encrypted session, etc.), otherwise the user's SSH passphrase could be
723: compromised.
724:
725: Additional consideration should be given to the use of
726: [[!template id=man name="pam\_ssh" section="8"]].
727: Users often assume that file permissions are sufficient to protect their SSH
728: keys, and thus use weak or no passphrases. Since the system administrator has no
729: effective means of enforcing SSH passphrase quality, this has the potential to
730: expose the system to security risks.
731:
732: #### pam\_unix(8)
733:
734: The
735: [[!template id=man name="pam\_unix" section="8"]]
736: module implements traditional UNIX® password authentication, using
737: [[!template id=man name="getpwnam" section="3"]]
738: under FreeBSD or
739: [[!template id=man name="getpwnam\_r" section="3"]]
740: under NetBSD to obtain the target account's password and compare it with the one
741: provided by the applicant. It also provides account management services
742: (enforcing account and password expiration times) and password-changing
743: services. This is probably the single most useful module, as the great majority
744: of admins will want to maintain historical behaviour for at least some services.
745:
746: ### NetBSD-specific PAM Modules
747:
748: #### pam\_skey(8)
749:
750: The
751: [[!template id=man name="pam\_skey" section="8"]]
752: module implements S/Key One Time Password (OTP) authentication methods, using
753: the `/etc/skeykeys` database.
754:
755: ## PAM Application Programming
756:
757: This section has not yet been written.
758:
759: ## PAM Module Programming
760:
761: This section has not yet been written.
762:
763: ## Sample PAM Application
764:
765: The following is a minimal implementation of
766: [[!template id=man name="su" section="1"]] using PAM.
767: Note that it uses the OpenPAM-specific
768: [[!template id=man name="openpam\_ttyconv" section="3"]]
769: conversation function, which is prototyped in `security/openpam.h`. If you wish
770: build this application on a system with a different PAM library, you will have
771: to provide your own conversation function. A robust conversation function is
772: surprisingly difficult to implement; the one presented in the [Sample PAM
773: Conversation Function](chap-pam.html#pam-sample-conv "18.11. Sample PAM
774: Conversation Function") sub-chapter is a good starting point, but should not be
775: used in real-world applications.
776:
777: #include <sys/param.h>
778: #include <sys/wait.h>
779:
780: #include <err.h>
781: #include <pwd.h>
782: #include <stdio.h>
783: #include <stdlib.h>
784: #include <string.h>
785: #include <syslog.h>
786: #include <unistd.h>
787:
788: #include <security/pam_appl.h>
789: #include <security/openpam.h> /* for openpam_ttyconv() */
790:
791: extern char **environ;
792:
793: static pam_handle_t *pamh;
794: static struct pam_conv pamc;
795:
796: static void
797: usage(void)
798: {
799:
800: fprintf(stderr, "Usage: su [login [args]]\n");
801: exit(1);
802: }
803:
804: int
805: main(int argc, char *argv[])
806: {
807: char hostname[MAXHOSTNAMELEN];
808: const char *user, *tty;
809: char **args, **pam_envlist, **pam_env;
810: struct passwd *pwd;
811: int o, pam_err, status;
812: pid_t pid;
813:
814: while ((o = getopt(argc, argv, "h")) != -1)
815: switch (o) {
816: case 'h':
817: default:
818: usage();
819: }
820:
821: argc -= optind;
822: argv += optind;
823:
824: if (argc > 0) {
825: user = *argv;
826: --argc;
827: ++argv;
828: } else {
829: user = "root";
830: }
831:
832: /* initialize PAM */
833: pamc.conv = &openpam_ttyconv;
834: pam_start("su", user, &pamc, &pamh);
835:
836: /* set some items */
837: gethostname(hostname, sizeof(hostname));
838: if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
839: goto pamerr;
840: user = getlogin();
841: if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS)
842: goto pamerr;
843: tty = ttyname(STDERR_FILENO);
844: if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
845: goto pamerr;
846:
847: /* authenticate the applicant */
848: if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
849: goto pamerr;
850: if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
851: pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
852: if (pam_err != PAM_SUCCESS)
853: goto pamerr;
854:
855: /* establish the requested credentials */
856: if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
857: goto pamerr;
858:
859: /* authentication succeeded; open a session */
860: if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
861: goto pamerr;
862:
863: /* get mapped user name; PAM may have changed it */
864: pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user);
865: if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL)
866: goto pamerr;
867:
868: /* export PAM environment */
869: if ((pam_envlist = pam_getenvlist(pamh)) != NULL) {
870: for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
871: putenv(*pam_env);
872: free(*pam_env);
873: }
874: free(pam_envlist);
875: }
876:
877: /* build argument list */
878: if ((args = calloc(argc + 2, sizeof *args)) == NULL) {
879: warn("calloc()");
880: goto err;
881: }
882: *args = pwd->pw_shell;
883: memcpy(args + 1, argv, argc * sizeof *args);
884:
885: /* fork and exec */
886: switch ((pid = fork())) {
887: case -1:
888: warn("fork()");
889: goto err;
890: case 0:
891: /* child: give up privs and start a shell */
892:
893: /* set uid and groups */
894: if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
895: warn("initgroups()");
896: _exit(1);
897: }
898: if (setgid(pwd->pw_gid) == -1) {
899: warn("setgid()");
900: _exit(1);
901: }
902: if (setuid(pwd->pw_uid) == -1) {
903: warn("setuid()");
904: _exit(1);
905: }
906: execve(*args, args, environ);
907: warn("execve()");
908: _exit(1);
909: default:
910: /* parent: wait for child to exit */
911: waitpid(pid, &status, 0);
912:
913: /* close the session and release PAM resources */
914: pam_err = pam_close_session(pamh, 0);
915: pam_end(pamh, pam_err);
916:
917: exit(WEXITSTATUS(status));
918: }
919:
920: pamerr:
921: fprintf(stderr, "Sorry\n");
922: err:
923: pam_end(pamh, pam_err);
924: exit(1);
925: }
926:
927: ## Sample PAM Module
928:
929: The following is a minimal implementation of
930: [[!template id=man name="pam\_unix" section="8"]],
931: offering only authentication services. It should build and run with most PAM
932: implementations, but takes advantage of OpenPAM extensions if available: note
933: the use of
934: [[!template id=man name="pam\_get\_authtok" section="3"]],
935: which enormously simplifies prompting the user for a password.
936:
937: #include <sys/param.h>
938:
939: #include <pwd.h>
940: #include <stdlib.h>
941: #include <stdio.h>
942: #include <string.h>
943: #include <unistd.h>
944:
945: #include <security/pam_modules.h>
946: #include <security/pam_appl.h>
947:
948: #ifndef _OPENPAM
949: static char password_prompt[] = "Password:";
950: #endif
951:
952: #ifndef PAM_EXTERN
953: #define PAM_EXTERN
954: #endif
955:
956: PAM_EXTERN int
957: pam_sm_authenticate(pam_handle_t *pamh, int flags,
958: int argc, const char *argv[])
959: {
960: #ifndef _OPENPAM
961: const void *ptr;
962: const struct pam_conv *conv;
963: struct pam_message msg;
964: const struct pam_message *msgp;
965: struct pam_response *resp;
966: #endif
967: struct passwd *pwd;
968: const char *user;
969: char *crypt_password, *password;
970: int pam_err, retry;
971:
972: /* identify user */
973: if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
974: return (pam_err);
975: if ((pwd = getpwnam(user)) == NULL)
976: return (PAM_USER_UNKNOWN);
977:
978: /* get password */
979: #ifndef _OPENPAM
980: pam_err = pam_get_item(pamh, PAM_CONV, &ptr);
981: if (pam_err != PAM_SUCCESS)
982: return (PAM_SYSTEM_ERR);
983: conv = ptr;
984: msg.msg_style = PAM_PROMPT_ECHO_OFF;
985: msg.msg = password_prompt;
986: msgp = &msg;
987: #endif
988: password = NULL;
989: for (retry = 0; retry < 3; ++retry) {
990: #ifdef _OPENPAM
991: pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
992: (const char **)&password, NULL);
993: #else
994: resp = NULL;
995: pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
996: if (resp != NULL) {
997: if (pam_err == PAM_SUCCESS)
998: password = resp->resp;
999: else
1000: free(resp->resp);
1001: free(resp);
1002: }
1003: #endif
1004: if (pam_err == PAM_SUCCESS)
1005: break;
1006: }
1007: if (pam_err == PAM_CONV_ERR)
1008: return (pam_err);
1009: if (pam_err != PAM_SUCCESS)
1010: return (PAM_AUTH_ERR);
1011:
1012: /* compare passwords */
1013: if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
1014: (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
1015: strcmp(crypt_password, pwd->pw_passwd) != 0)
1016: pam_err = PAM_AUTH_ERR;
1017: else
1018: pam_err = PAM_SUCCESS;
1019: #ifndef _OPENPAM
1020: free(password);
1021: #endif
1022: return (pam_err);
1023: }
1024:
1025: PAM_EXTERN int
1026: pam_sm_setcred(pam_handle_t *pamh, int flags,
1027: int argc, const char *argv[])
1028: {
1029:
1030: return (PAM_SUCCESS);
1031: }
1032:
1033: PAM_EXTERN int
1034: pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
1035: int argc, const char *argv[])
1036: {
1037:
1038: return (PAM_SUCCESS);
1039: }
1040:
1041: PAM_EXTERN int
1042: pam_sm_open_session(pam_handle_t *pamh, int flags,
1043: int argc, const char *argv[])
1044: {
1045:
1046: return (PAM_SUCCESS);
1047: }
1048:
1049: PAM_EXTERN int
1050: pam_sm_close_session(pam_handle_t *pamh, int flags,
1051: int argc, const char *argv[])
1052: {
1053:
1054: return (PAM_SUCCESS);
1055: }
1056:
1057: PAM_EXTERN int
1058: pam_sm_chauthtok(pam_handle_t *pamh, int flags,
1059: int argc, const char *argv[])
1060: {
1061:
1062: return (PAM_SERVICE_ERR);
1063: }
1064:
1065: #ifdef PAM_MODULE_ENTRY
1066: PAM_MODULE_ENTRY("pam_unix");
1067: #endif
1068:
1069: ## Sample PAM Conversation Function
1070:
1071: The conversation function presented below is a greatly simplified version of
1072: OpenPAM's
1073: [[!template id=man name="openpam\_ttyconv" section="3"]].
1074: It is fully functional, and should give the reader a good idea of how a
1075: conversation function should behave, but it is far too simple for real-world
1076: use. Even if you're not using OpenPAM, feel free to download the source code and
1077: adapt
1078: [[!template id=man name="openpam\_ttyconv" section="3"]]
1079: to your uses; we believe it to be as robust as a tty-oriented conversation
1080: function can reasonably get.
1081:
1082: #include <stdio.h>
1083: #include <stdlib.h>
1084: #include <string.h>
1085: #include <unistd.h>
1086:
1087: #include <security/pam_appl.h>
1088:
1089: int
1090: converse(int n, const struct pam_message **msg,
1091: struct pam_response **resp, void *data)
1092: {
1093: struct pam_response *aresp;
1094: char buf[PAM_MAX_RESP_SIZE];
1095: int i;
1096:
1097: data = data;
1098: if (n <= 0 || n > PAM_MAX_NUM_MSG)
1099: return (PAM_CONV_ERR);
1100: if ((aresp = calloc(n, sizeof *aresp)) == NULL)
1101: return (PAM_BUF_ERR);
1102: for (i = 0; i < n; ++i) {
1103: aresp[i].resp_retcode = 0;
1104: aresp[i].resp = NULL;
1105: switch (msg[i]->msg_style) {
1106: case PAM_PROMPT_ECHO_OFF:
1107: aresp[i].resp = strdup(getpass(msg[i]->msg));
1108: if (aresp[i].resp == NULL)
1109: goto fail;
1110: break;
1111: case PAM_PROMPT_ECHO_ON:
1112: fputs(msg[i]->msg, stderr);
1113: if (fgets(buf, sizeof buf, stdin) == NULL)
1114: goto fail;
1115: aresp[i].resp = strdup(buf);
1116: if (aresp[i].resp == NULL)
1117: goto fail;
1118: break;
1119: case PAM_ERROR_MSG:
1120: fputs(msg[i]->msg, stderr);
1121: if (strlen(msg[i]->msg) > 0 &&
1122: msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
1123: fputc('\n', stderr);
1124: break;
1125: case PAM_TEXT_INFO:
1126: fputs(msg[i]->msg, stdout);
1127: if (strlen(msg[i]->msg) > 0 &&
1128: msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
1129: fputc('\n', stdout);
1130: break;
1131: default:
1132: goto fail;
1133: }
1134: }
1135: *resp = aresp;
1136: return (PAM_SUCCESS);
1137: fail:
1138: for (i = 0; i < n; ++i) {
1139: if (aresp[i].resp != NULL) {
1140: memset(aresp[i].resp, 0, strlen(aresp[i].resp));
1141: free(aresp[i].resp);
1142: }
1143: }
1144: memset(aresp, 0, n * sizeof *aresp);
1145: *resp = NULL;
1146: return (PAM_CONV_ERR);
1147: }
1148:
1149: ## Further Reading
1150:
1151: ### Papers
1152:
1153: * *[sun-pam]: [Making Login Services Independent of Authentication Technologies](http://www.sun.com/software/solaris/pam/pam.external.pdf)*. Vipin Samar and Charlie Lai. Sun Microsystems.
1154: * *[opengroup-singlesignon]: [X/Open Single Sign-on Preliminary Specification](http://www.opengroup.org/pubs/catalog/p702.htm)*. The Open Group. 1-85912-144-6. June 1997.
1155: * *[kernelorg-pamdraft]: [Pluggable Authentication Modules](http://www.kernel.org/pub/linux/libs/pam/pre/doc/current-draft.txt)*. Andrew G. Morgan. October 6, 1999.
1156:
1157: ### User Manuals
1158:
1159: * *[sun-pamadmin]: [PAM Administration](http://www.sun.com/software/solaris/pam/pam.admin.pdf)*. Sun Microsystems.
1160:
1161: ### Related Web pages
1162:
1163: * *[openpam-website]: [OpenPAM homepage](http://openpam.sourceforge.net/)*. Dag-Erling Smørgrav. ThinkSec AS.
1164: * *[linuxpam-website]: [Linux-PAM homepage](http://www.kernel.org/pub/linux/libs/pam/)*. Andrew G. Morgan.
1165: * *[solarispam-website]: [Solaris PAM homepage](http://www.sun.com/software/solaris/pam/)*. Sun Microsystems.
1166:
1167: ### Networks Associates Technology's license on the PAM article
1168:
1169: Copyright (c) 2001-2003 Networks Associates Technology, Inc.
1170: All rights reserved.
1171: This software was developed for the FreeBSD Project by ThinkSec AS and
1172: Network Associates Laboratories, the Security Research Division of
1173: Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
1174: ("CBOSS"), as part of the DARPA CHATS research program.
1175: Redistribution and use in source and binary forms, with or without
1176: modification, are permitted provided that the following conditions
1177: are met:
1178: 1. Redistributions of source code must retain the above copyright
1179: notice, this list of conditions and the following disclaimer.
1180: 2. Redistributions in binary form must reproduce the above copyright
1181: notice, this list of conditions and the following disclaimer in the
1182: documentation and/or other materials provided with the distribution.
1183: 3. The name of the author may not be used to endorse or promote
1184: products derived from this software without specific prior written
1185: permission.
1186: THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
1187: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1188: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1189: ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1190: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1191: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1192: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1193: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1194: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1195: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1196: SUCH DAMAGE.
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb