File:  [NetBSD Developer Wiki] / wikisrc / guide / pam.mdwn
Revision 1.5: download - view: text, annotated - select for diffs
Fri Jun 19 19:18:31 2015 UTC (5 years ago) by plunky
Branches: MAIN
CVS tags: HEAD
replace direct links to manpages on netbsd.gw.com with templates

    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