--- wikisrc/guide/pam.mdwn 2013/03/21 11:11:21 1.4 +++ wikisrc/guide/pam.mdwn 2015/06/19 19:18:31 1.5 @@ -104,7 +104,7 @@ by way of a handful of simple examples. #### Client and server are one This simple example shows `alice` -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386)'ing to +[[!template id=man name="su" section="1"]]'ing to `root`: $ whoami @@ -118,17 +118,17 @@ This simple example shows `alice` * The applicant is `alice`. * The account is `root`. - * The [su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386) + * The [[!template id=man name="su" section="1"]] process is both client and server. * The authentication token is `xi3kiune`. * The arbitrator is `root`, which is why - [su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386) is + [[!template id=man name="su" section="1"]] is setuid `root`. #### Client and server are separate The example below shows `eve` try to initiate an -[ssh(1)](http://netbsd.gw.com/cgi-bin/man-cgi?ssh+1+NetBSD-5.0.1+i386) +[[!template id=man name="ssh" section="1"]] connection to `login.example.com`, ask to log in as `bob`, and succeed. Bob should have chosen a better password! @@ -144,10 +144,10 @@ should have chosen a better password! * The applicant is `eve`. * The client is Eve's - [ssh(1)](http://netbsd.gw.com/cgi-bin/man-cgi?ssh+1+NetBSD-5.0.1+i386) + [[!template id=man name="ssh" section="1"]] process. * The server is the - [sshd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?sshd+8+NetBSD-5.0.1+i386) + [[!template id=man name="sshd" section="8"]] process on `login.example.com` * The account is `bob`. * The authentication token is `god`. @@ -166,7 +166,7 @@ The following is FreeBSD's default polic * This policy applies to the `sshd` service (which is not necessarily restricted to the - [sshd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?sshd+8+NetBSD-5.0.1+i386) + [[!template id=man name="sshd" section="8"]] server.) * `auth`, `account`, `session` and `password` are facilities. @@ -196,12 +196,12 @@ facilities, which are described below. the applicant and establishing the account credentials. It provides two primitives: - * [pam\_authenticate(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_authenticate+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_authenticate" section="3"]] authenticates the applicant, usually by requesting an authentication token and comparing it with a value stored in a database or obtained from an authentication server. - * [pam\_setcred(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_setcred+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_setcred" section="3"]] establishes account credentials such as user ID, group membership and resource limits. @@ -210,18 +210,18 @@ facilities, which are described below. restrictions based on the time of day or the server's work load. It provides a single primitive: - * [pam\_acct\_mgmt(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_acct_mgmt+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_acct\_mgmt" section="3"]] verifies that the requested account is available. * `session` -- *Session management.* This facility handles tasks associated with session set-up and tear-down, such as login accounting. It provides two primitives: - * [pam\_open\_session(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_open_session+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_open\_session" section="3"]] performs tasks associated with session set-up: add an entry in the `utmp` and `wtmp` databases, start an SSH agent, etc. - * [pam\_close\_session(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_close_session+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_close\_session" section="3"]] performs tasks associated with session tear-down: add an entry in the `utmp` and `wtmp` databases, stop the SSH agent, etc. @@ -230,7 +230,7 @@ facilities, which are described below. expired or because the user wishes to change it. It provides a single primitive: - * [pam\_chauthtok(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_chauthtok+3+NetBSD-5.0.1+i386) + * [[!template id=man name="pam\_chauthtok" section="3"]] changes the authentication token, optionally verifying that it is sufficiently hard to guess, has not been used previously, etc. @@ -251,7 +251,7 @@ include the facility name as well as the name one example, Solaris has a `pam_dial_auth.so.1` module which is commonly used to authenticate dialup users. Also, almost every module has a man page with the same name, i.e.: -[pam\_unix(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_unix+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_unix" section="8"]] explains how the `pam_unix.so` module works. #### Module Versioning @@ -282,7 +282,7 @@ located at `/usr/lib` and, under NetBSD, When a server initiates a PAM transaction, the PAM library tries to load a policy for the service specified in the -[pam\_start(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_start+3+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_start" section="3"]] call. The policy specifies how authentication requests should be processed, and is defined in a configuration file. This is the other central concept in PAM: the possibility for the admin to tune the system security policy (in the wider @@ -351,50 +351,50 @@ client and abort the transaction. or of being setuid `root`. 2. The server calls - [pam\_start(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_start+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_start" section="3"]] to initialize the PAM library and specify its service name and the target account, and register a suitable conversation function. 3. The server obtains various information relating to the transaction (such as the applicant's user name and the name of the host the client runs on) and submits it to PAM using - [pam\_set\_item(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_set_item+3+NetBSD-5.0.1+i386). + [[!template id=man name="pam\_set\_item" section="3"]]. 4. The server calls - [pam\_authenticate(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_authenticate+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_authenticate" section="3"]] to authenticate the applicant. 5. The server calls - [pam\_acct\_mgmt(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_acct_mgmt+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_acct\_mgmt" section="3"]] to verify that the requested account is available and valid. If the password is correct but has expired, - [pam\_acct\_mgmt(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_acct_mgmt+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_acct\_mgmt" section="3"]] will return `PAM_NEW_AUTHTOK_REQD` instead of `PAM_SUCCESS`. 6. If the previous step returned `PAM_NEW_AUTHTOK_REQD`, the server now calls - [pam\_chauthtok(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_chauthtok+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_chauthtok" section="3"]] to force the client to change the authentication token for the requested account. 7. Now that the applicant has been properly authenticated, the server calls - [pam\_setcred(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_setcred+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_setcred" section="3"]] to establish the credentials of the requested account. It is able to do this because it acts on behalf of the arbitrator, and holds the arbitrator's credentials. 8. Once the correct credentials have been established, the server calls - [pam\_open\_session(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_open_session+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_open\_session" section="3"]] to set up the session. 9. The server now performs whatever service the client requested -- for instance, provide the applicant with a shell. 10. Once the server is done serving the client, it calls - [pam\_close\_session(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_close_session+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_close\_session" section="3"]] to tear down the session. 11. Finally, the server calls - [pam\_end(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_end+3+NetBSD-5.0.1+i386) + [[!template id=man name="pam\_end" section="3"]] to notify the PAM library that it is done and that it can release whatever resources it has allocated in the course of the transaction. @@ -494,7 +494,7 @@ To configure PAM correctly, it is essent interpreted. When an application calls -[pam\_start(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_start+3+NetBSD-5.0.1+i386), +[[!template id=man name="pam\_start" section="3"]], the PAM library loads the policy for the specified service and constructs four module chains (one for each facility.) If one or more of these chains are empty, the corresponding chains from the policy for the `other` service are @@ -527,11 +527,11 @@ returned `PAM_NEW_AUTHTOK_REQD`, the dis `PAM_NEW_AUTHTOK_REQD`. The second exception is that -[pam\_setcred(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_setcred+3+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_setcred" section="3"]] treats `binding` and `sufficient` modules as if they were `required`. The third and final exception is that -[pam\_chauthtok(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_chauthtok+3+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_chauthtok" section="3"]] runs the entire chain twice (once for preliminary checks and once to actually set the password), and in the preliminary phase it treats `binding` and `sufficient` modules as if they were `required`. @@ -543,7 +543,7 @@ set the password), and in the preliminar #### pam\_deny(8) The -[pam\_deny(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_deny+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_deny" section="8"]] module is one of the simplest modules available; it responds to any request with `PAM_AUTH_ERR`. It is useful for quickly disabling a service (add it to the top of every chain), or for terminating chains of `sufficient` modules. @@ -551,7 +551,7 @@ of every chain), or for terminating chai #### pam\_echo(8) The -[pam\_echo(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_echo+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_echo" section="8"]] module simply passes its arguments to the conversation function as a `PAM_TEXT_INFO` message. It is mostly useful for debugging, but can also serve to display messages such as `Unauthorized access will be prosecuted` before @@ -560,7 +560,7 @@ starting the authentication procedure. #### pam\_exec(8) The -[pam\_exec(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_exec+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_exec" section="8"]] module takes its first argument to be the name of a program to execute, and the remaining arguments are passed to that program as command-line arguments. One possible application is to use it to run a program at login time which mounts @@ -569,21 +569,21 @@ the user's home directory. #### pam\_ftpusers(8) The -[pam\_ftpusers(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_ftpusers+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_ftpusers" section="8"]] module successes if and only if the user is listed in `/etc/ftpusers`. Currently, in NetBSD, this module doesn't understand the extended syntax of -[ftpd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?ftpd+8+NetBSD-5.0.1+i386), but +[[!template id=man name="ftpd" section="8"]], but this will be fixed in the future. #### pam\_group(8) The -[pam\_group(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_group+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_group" section="8"]] module accepts or rejects applicants on the basis of their membership in a particular file group (normally `wheel` for -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386)). It is +[[!template id=man name="su" section="1"]]). It is primarily intended for maintaining the traditional behaviour of BSD -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386), but has +[[!template id=man name="su" section="1"]], but has many other uses, such as excluding certain groups of users from a particular service. @@ -593,29 +593,29 @@ to authenticate using his own password. #### pam\_guest(8) The -[pam\_guest(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_guest+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_guest" section="8"]] module allows guest logins using fixed login names. Various requirements can be placed on the password, but the default behaviour is to allow any password as long as the login name is that of a guest account. The -[pam\_guest(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_guest+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_guest" section="8"]] module can easily be used to implement anonymous FTP logins. #### pam\_krb5(8) The -[pam\_krb5(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_krb5+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_krb5" section="8"]] module provides functions to verify the identity of a user and to set user specific credentials using Kerberos 5. It prompts the user for a password and obtains a new Kerberos TGT for the principal. The TGT is verified by obtaining a service ticket for the local host. The newly acquired credentials are stored in a credential cache and the environment variable KRB5CCNAME is set appropriately. The credentials cache should be destroyed by the user at logout with -[kdestroy(1)](http://netbsd.gw.com/cgi-bin/man-cgi?kdestroy+1+NetBSD-5.0.1+i386). +[[!template id=man name="kdestroy" section="1"]]. #### pam\_ksu(8) The -[pam\_ksu(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_ksu+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_ksu" section="8"]] module provides only authentication services for Kerberos 5 to determine whether or not the applicant is authorized to obtain the privileges of the target account. @@ -623,39 +623,39 @@ account. #### pam\_lastlog(8) The -[pam\_lastlog(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_lastlog+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_lastlog" section="8"]] module provides only session management services. It records the session in -[utmp(5)](http://netbsd.gw.com/cgi-bin/man-cgi?utmp+5+NetBSD-5.0.1+i386), -[utmpx(5)](http://netbsd.gw.com/cgi-bin/man-cgi?utmpx+5+NetBSD-5.0.1+i386), -[wtmp(5)](http://netbsd.gw.com/cgi-bin/man-cgi?wtmp+5+NetBSD-5.0.1+i386), -[wtmpx(5)](http://netbsd.gw.com/cgi-bin/man-cgi?wtmpx+5+NetBSD-5.0.1+i386), -[lastlog(5)](http://netbsd.gw.com/cgi-bin/man-cgi?lastlog+5+NetBSD-5.0.1+i386) +[[!template id=man name="utmp" section="5"]], +[[!template id=man name="utmpx" section="5"]], +[[!template id=man name="wtmp" section="5"]], +[[!template id=man name="wtmpx" section="5"]], +[[!template id=man name="lastlog" section="5"]] and -[lastlogx(5)](http://netbsd.gw.com/cgi-bin/man-cgi?lastlogx+5+NetBSD-5.0.1+i386) +[[!template id=man name="lastlogx" section="5"]] databases. #### pam\_login\_access(8) The -[pam\_login\_access(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_login_access+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_login\_access" section="8"]] module provides an implementation of the account management primitive which enforces the login restrictions specified in the -[login.access(5)](http://netbsd.gw.com/cgi-bin/man-cgi?login.access+5+NetBSD-5.0.1+i386) +[[!template id=man name="login.access" section="5"]] table. #### pam\_nologin(8) The -[pam\_nologin(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_nologin+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_nologin" section="8"]] module refuses non-root logins when `/var/run/nologin` exists. This file is normally created by -[shutdown(8)](http://netbsd.gw.com/cgi-bin/man-cgi?shutdown+8+NetBSD-5.0.1+i386) +[[!template id=man name="shutdown" section="8"]] when less than five minutes remain until the scheduled shutdown time. #### pam\_permit(8) The -[pam\_permit(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_permit+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_permit" section="8"]] module is one of the simplest modules available; it responds to any request with `PAM_SUCCESS`. It is useful as a placeholder for services where one or more chains would otherwise be empty. @@ -663,14 +663,14 @@ chains would otherwise be empty. #### pam\_radius(8) The -[pam\_radius(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_radius+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_radius" section="8"]] module provides authentication services based upon the RADIUS (Remote Authentication Dial In User Service) protocol. #### pam\_rhosts(8) The -[pam\_rhosts(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_rhosts+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_rhosts" section="8"]] module provides only authentication services. It reports success if and only if the target user's ID is not 0 and the remote host and user are listed in `/etc/hosts.equiv` or in the target user's `~/.rhosts`. @@ -678,18 +678,18 @@ the target user's ID is not 0 and the re #### pam\_rootok(8) The -[pam\_rootok(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_rootok+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_rootok" section="8"]] module reports success if and only if the real user id of the process calling it (which is assumed to be run by the applicant) is 0. This is useful for non-networked services such as -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386) or -[passwd(1)](http://netbsd.gw.com/cgi-bin/man-cgi?passwd+1+NetBSD-5.0.1+i386), to +[[!template id=man name="su" section="1"]] or +[[!template id=man name="passwd" section="1"]], to which the `root` should have automatic access. #### pam\_securetty(8) The -[pam\_securetty(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_securetty+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_securetty" section="8"]] module provides only account services. It is used when the applicant is attempting to authenticate as superuser, and the process is attached to an insecure TTY. @@ -697,24 +697,24 @@ insecure TTY. #### pam\_self(8) The -[pam\_self(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_self+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_self" section="8"]] module reports success if and only if the names of the applicant matches that of the target account. It is most useful for non-networked services such as -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386), where the +[[!template id=man name="su" section="1"]], where the identity of the applicant can be easily verified. #### pam\_ssh(8) The -[pam\_ssh(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_ssh+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_ssh" section="8"]] module provides both authentication and session services. The authentication service allows users who have passphrase-protected SSH secret keys in their `~/.ssh` directory to authenticate themselves by typing their passphrase. The session service starts -[ssh-agent(1)](http://netbsd.gw.com/cgi-bin/man-cgi?ssh-agent+1+NetBSD-5.0.1+i386) +[[!template id=man name="ssh-agent" section="1"]] and preloads it with the keys that were decrypted in the authentication phase. This feature is particularly useful for local logins, whether in X (using -[xdm(1)](http://netbsd.gw.com/cgi-bin/man-cgi?xdm+1+NetBSD-5.0.1+i386) or +[[!template id=man name="xdm" section="1"]] or another PAM-aware X login manager) or at the console. This module implements what is fundamentally a password authentication scheme. @@ -723,7 +723,7 @@ encrypted session, etc.), otherwise the compromised. Additional consideration should be given to the use of -[pam\_ssh(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_ssh+8+NetBSD-5.0.1+i386). +[[!template id=man name="pam\_ssh" section="8"]]. Users often assume that file permissions are sufficient to protect their SSH keys, and thus use weak or no passphrases. Since the system administrator has no effective means of enforcing SSH passphrase quality, this has the potential to @@ -732,11 +732,11 @@ expose the system to security risks. #### pam\_unix(8) The -[pam\_unix(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_unix+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_unix" section="8"]] module implements traditional UNIX® password authentication, using -[getpwnam(3)](http://netbsd.gw.com/cgi-bin/man-cgi?getpwnam+3+NetBSD-5.0.1+i386) +[[!template id=man name="getpwnam" section="3"]] under FreeBSD or -[getpwnam\_r(3)](http://netbsd.gw.com/cgi-bin/man-cgi?getpwnam_r+3+NetBSD-5.0.1+i386) +[[!template id=man name="getpwnam\_r" section="3"]] under NetBSD to obtain the target account's password and compare it with the one provided by the applicant. It also provides account management services (enforcing account and password expiration times) and password-changing @@ -748,7 +748,7 @@ of admins will want to maintain historic #### pam\_skey(8) The -[pam\_skey(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_skey+8+NetBSD-5.0.1+i386) +[[!template id=man name="pam\_skey" section="8"]] module implements S/Key One Time Password (OTP) authentication methods, using the `/etc/skeykeys` database. @@ -763,9 +763,9 @@ This section has not yet been written. ## Sample PAM Application The following is a minimal implementation of -[su(1)](http://netbsd.gw.com/cgi-bin/man-cgi?su+1+NetBSD-5.0.1+i386) using PAM. +[[!template id=man name="su" section="1"]] using PAM. Note that it uses the OpenPAM-specific -[openpam\_ttyconv(3)](http://netbsd.gw.com/cgi-bin/man-cgi?openpam_ttyconv+3+NetBSD-5.0.1+i386) +[[!template id=man name="openpam\_ttyconv" section="3"]] conversation function, which is prototyped in `security/openpam.h`. If you wish build this application on a system with a different PAM library, you will have to provide your own conversation function. A robust conversation function is @@ -927,11 +927,11 @@ used in real-world applications. ## Sample PAM Module The following is a minimal implementation of -[pam\_unix(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_unix+8+NetBSD-5.0.1+i386), +[[!template id=man name="pam\_unix" section="8"]], offering only authentication services. It should build and run with most PAM implementations, but takes advantage of OpenPAM extensions if available: note the use of -[pam\_get\_authtok(3)](http://netbsd.gw.com/cgi-bin/man-cgi?pam_get_authtok+3+NetBSD-5.0.1+i386), +[[!template id=man name="pam\_get\_authtok" section="3"]], which enormously simplifies prompting the user for a password. #include @@ -1070,12 +1070,12 @@ which enormously simplifies prompting th The conversation function presented below is a greatly simplified version of OpenPAM's -[openpam\_ttyconv(3)](http://netbsd.gw.com/cgi-bin/man-cgi?openpam_ttyconv+3+NetBSD-5.0.1+i386). +[[!template id=man name="openpam\_ttyconv" section="3"]]. It is fully functional, and should give the reader a good idea of how a conversation function should behave, but it is far too simple for real-world use. Even if you're not using OpenPAM, feel free to download the source code and adapt -[openpam\_ttyconv(3)](http://netbsd.gw.com/cgi-bin/man-cgi?openpam_ttyconv+3+NetBSD-5.0.1+i386) +[[!template id=man name="openpam\_ttyconv" section="3"]] to your uses; we believe it to be as robust as a tty-oriented conversation function can reasonably get.