Catch up with the current state of -CURRENT, and discuss the differences

between OpenPAM, Linux-PAM and Solaris PAM in some more detail.  Also add
IDs to most sections and their titles, and an appendix listing a sample
conversation function.

Translators: please leave for later, there's still a lot to do.

Sponsored by:	DARPA, NAI Labs
This commit is contained in:
Dag-Erling Smørgrav 2002-06-07 15:45:24 +00:00
parent 70a78a3610
commit a0e5c66ae0
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=13327
2 changed files with 190 additions and 117 deletions

View file

@ -9,13 +9,16 @@ INSTALL_ONLY_COMPRESSED?=
JADEFLAGS+= -V %generate-article-toc%
SRCS= article.sgml pam_app.c pam_module.c
SRCS= article.sgml pam_app.c pam_conv.c pam_module.c
CLEANFILES+= pam_app.c pam_module.c
CLEANFILES+= pam_app.c pam_conv.c pam_module.c
pam_app.c: su.c
sed -e '/^[\/ ]\*/d' ${.ALLSRC} >${.TARGET}
pam_conv.c: converse.c
sed -e '/^[\/ ]\*/d' ${.ALLSRC} >${.TARGET}
pam_module.c: pam_unix.c
sed -e '/^[\/ ]\*/d' ${.ALLSRC} >${.TARGET}

View file

@ -76,13 +76,13 @@
At the time of this writing, this specification has not yet been
adopted as a standard.</para>
<para>Although this article focuses on FreeBSD's implementation of
PAM, which is based on Linux-PAM, most of it should be
applicable to most other operating systems which implement PAM,
including Solaris.</para>
<para>Although this article focuses primarily on FreeBSD 5.x,
which uses OpenPAM, it should be equally applicable to FreeBSD
4.x, which uses Linux-PAM, and other operating systems such as
Linux and Solaris.</para>
<section>
<title>Trademarks</title>
<section id="pam-trademarks">
<title id="pam-trademarks.title">Trademarks</title>
<para>Sun, Sun Microsystems and Solaris are trademarks or
registered trademarks of Sun Microsystems, Inc.</para>
@ -245,8 +245,8 @@
</glosslist>
</section>
<section>
<title>Usage examples</title>
<section id="pam-usage-examples">
<title id="pam-usage-examples.title">Usage examples</title>
<para>This section aims to illustrate the meanings of some of
the terms defined above by way of a handful of simple
@ -342,11 +342,14 @@ Welcome to FreeBSD!
<para>The following is FreeBSD's default policy for
<literal>sshd</literal>:</para>
<programlisting>sshd auth required pam_nologin.so no_warn
sshd auth required pam_unix.so no_warn try_first_pass
sshd account required pam_unix.so
sshd session required pam_permit.so
sshd password required pam_permit.so</programlisting>
<programlisting>
sshd auth required pam_nologin.so no_warn
sshd auth required pam_unix.so no_warn try_first_pass
sshd account required pam_login_access.so
sshd account required pam_unix.so
sshd session required pam_lastlog.so no_fail
sshd password required pam_permit.so
</programlisting>
<itemizedlist>
@ -362,19 +365,21 @@ sshd password required pam_permit.so</programlisting>
</listitem>
<listitem>
<para><filename>pam_nologin.so</filename>,
<filename>pam_unix.so</filename> and
<filename>pam_unix.so</filename>,
<filename>pam_login_access.so</filename>,
<filename>pam_lastlog.so</filename> and
<filename>pam_permit.so</filename> are modules. It is
clear from this example that
<filename>pam_unix.so</filename> and
<filename>pam_permit.so</filename> provide at least two
facilities each.</para>
<filename>pam_unix.so</filename> provides at least two
facilities (authentication and account
management.)</para>
</listitem>
</itemizedlist>
</section>
</section>
<section>
<title>Conventions</title>
<section id="pam-conventions">
<title id="pam-conventions.title">Conventions</title>
<para><!--XXX-->This section has not yet been written.</para>
</section>
@ -401,17 +406,17 @@ sshd password required pam_permit.so</programlisting>
<itemizedlist>
<listitem>
<para><function>pam_authenticate</function>
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.</para>
<para>&man.pam.authenticate.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.</para>
</listitem>
<listitem>
<para><function>pam_setcred</function> establishes
account credentials such as user ID, group
membership and resource limits.</para>
<para>&man.pam.setcred.3; establishes account
credentials such as user ID, group membership and
resource limits.</para>
</listitem>
</itemizedlist>
</listitem>
@ -428,8 +433,8 @@ sshd password required pam_permit.so</programlisting>
<itemizedlist>
<listitem>
<para><function>pam_acct_mgmt</function> verifies that
the requested account is available.</para>
<para>&man.pam.acct.mgmt.3; verifies that the
requested account is available.</para>
</listitem>
</itemizedlist>
</listitem>
@ -445,17 +450,17 @@ sshd password required pam_permit.so</programlisting>
<itemizedlist>
<listitem>
<para><function>pam_open_session</function> performs
tasks associated with session set-up: add an entry
in the <filename>utmp</filename> and
<para>&man.pam.open.session.3; performs tasks
associated with session set-up: add an entry in the
<filename>utmp</filename> and
<filename>wtmp</filename> databases, start an SSH
agent, etc.</para>
</listitem>
<listitem>
<para><function>pam_close_session</function> performs
tasks associated with session tear-down: add an
entry in the <filename>utmp</filename> and
<para>&man.pam.close.session.3; performs tasks
associated with session tear-down: add an entry in
the <filename>utmp</filename> and
<filename>wtmp</filename> databases, stop the SSH
agent, etc.</para>
</listitem>
@ -474,10 +479,10 @@ sshd password required pam_permit.so</programlisting>
<itemizedlist>
<listitem>
<para><function>pam_chauthtok</function> changes the
authentication token, optionally verifying that it
is sufficiently hard to guess, has not been used
previously, etc.</para>
<para>&man.pam.chauthtok.3; changes the authentication
token, optionally verifying that it is sufficiently
hard to guess, has not been used previously,
etc.</para>
</listitem>
</itemizedlist>
</listitem>
@ -486,8 +491,8 @@ sshd password required pam_permit.so</programlisting>
</section>
<section>
<title>Modules</title>
<section id="pam-modules">
<title id="pam-modules.title">Modules</title>
<para>Modules are a very central concept in PAM; after all,
they are the <quote>M</quote> in <quote>PAM</quote>. A PAM
@ -497,14 +502,44 @@ sshd password required pam_permit.so</programlisting>
authentication facility, for instance, include the UNIX
password database, NIS, LDAP and Radius.</para>
<para>FreeBSD groups all facilities for the same mechanism in
one module called
<literal>pam_<replaceable>mechanism</replaceable>.so</literal> (e.g.
<literal>pam_unix.so</literal>.) The original PAM
implementation, on the other hand, had separate modules for
each facility, called
<literal>pam_<replaceable>mechanism</replaceable>_<replaceable>facility</replaceable>.so</literal>
(e.g. <literal>pam_unix_auth.so</literal>.)</para>
<section id="pam-module-naming">
<title id="pam-module-naming.title">Module Naming</title>
<para>FreeBSD implements each mechanism in a single module,
named
<literal>pam_<replaceable>mechanism</replaceable>.so</literal>
(for instance, <literal>pam_unix.so</literal> for the Unix
mechanism.) Other implementations sometimes have separate
modules for separate facilities, and include the facility
name as well as the mechanism name in the module name. To
name one example, Solaris has a
<literal>pam_dial_auth.so.1</literal> module which is
commonly used to authenticate dialup users.</para>
</section>
<section id="pam-module-versioning">
<title id="pam-module-versioning.title">Module Versioning</title>
<para>FreeBSD's original PAM implementation, based on
Linux-PAM, did not use version numbers for PAM modules.
This would commonly cause problems with legacy applications,
which might be linked against older versions of the system
libraries, as there was no way to load a matching version of
the required modules.</para>
<para>OpenPAM, on the other hand, looks for modules that have
the same version number as the PAM library (currently 2),
and only falls back to an unversioned module if no versioned
module could be loaded. Thus legacy modules can be provided
for legacy applications, while allowing new (or newly built)
applications to take advantage of the most recent
modules.</para>
<para>Although Solaris PAM modules commonly have a version
number, they're not truly versioned, because the number is a
part of the module name and must be included in the
configuration.</para>
</section>
</section>
<section id="pam-chains-policies">
@ -513,7 +548,7 @@ sshd password required pam_permit.so</programlisting>
<para>When a server initiates a PAM transaction, the PAM library
tries to load a policy for the service specified in the
<function>pam_start</function> call. The policy specifies how
&man.pam.start.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
@ -586,8 +621,8 @@ sshd password required pam_permit.so</programlisting>
in the same chain as different, unrelated modules.</para>
</section>
<section>
<title>Transactions</title>
<section id="pam-transactions">
<title id="pam-transactions.title">Transactions</title>
<para>The lifecycle of a typical PAM transaction is described
below. Note that if this any of these steps fails, the server
@ -604,53 +639,51 @@ sshd password required pam_permit.so</programlisting>
</listitem>
<listitem>
<para>The server calls <function>pam_start</function> to
initialize the PAM library and specify its service name
and the target account, and register a suitable
conversation function.</para>
<para>The server calls &man.pam.start.3; to initialize the
PAM library and specify its service name and the target
account, and register a suitable conversation
function.</para>
</listitem>
<listitem>
<para>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 <function>pam_set_item</function>.</para>
using &man.pam.set.item.3;.</para>
</listitem>
<listitem>
<para>The server calls <function>pam_authenticate</function>
to authenticate the applicant.</para>
<para>The server calls &man.pam.authenticate.3; to
authenticate the applicant.</para>
</listitem>
<listitem>
<para>The server calls <function>pam_acct_mgmt</function> to
verify that the requested account is available and valid.
The <function>pam_acct_mgmt</function> function will
return <literal>PAM_NEW_AUTHTOK_REQD</literal> if the
account's password has expired.</para>
<para>The server calls &man.pam.acct.mgmt.3; verify that the
requested account is available and valid. If the password
is correct but has expired, &man.pam.acct.mgmt.3; will
return <literal>PAM_NEW_AUTHTOK_REQD</literal> instead of
<literal>PAM_SUCCESS</literal>.</para>
</listitem>
<listitem>
<para>If the previous step returned
<literal>PAM_NEW_AUTHTOK_REQD</literal>, the server now
calls <function>pam_chauthtok</function> to force the
client to change the authentication token for the
requested account.</para>
calls &man.pam.chauthtok.3; to force the client to change
the authentication token for the requested account.</para>
</listitem>
<listitem>
<para>Now that the applicant has been properly
authenticated, the server calls
<function>pam_setcred</function> 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.</para>
authenticated, the server calls &man.pam.setcred.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.</para>
</listitem>
<listitem>
<para>Once the correct credentials have been established,
the server calls <function>pam_open_session</function> to
set up the session.</para>
the server calls &man.pam.open.session.3; to set up the
session.</para>
</listitem>
<listitem>
@ -661,15 +694,14 @@ sshd password required pam_permit.so</programlisting>
<listitem>
<para>Once the server is done serving the client, it calls
<function>pam_close_session</function> to tear down the
session.</para>
&man.pam.close.session.3; to tear down the session.</para>
</listitem>
<listitem>
<para>Finally, the server calls <function>pam_end</function>
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.</para>
<para>Finally, the server calls &man.pam.end.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.</para>
</listitem>
</orderedlist>
</section>
@ -679,7 +711,8 @@ sshd password required pam_permit.so</programlisting>
<title id="pam-config.title">PAM Configuration</title>
<section id="pam-config-file-locations">
<title>Location of configuration files</title>
<title id="pam-config-file-locations.title">Location of
configuration files</title>
<para>The traditional PAM configuration file is
<filename>/etc/pam.conf</filename>. This file contains all
@ -701,20 +734,20 @@ sshd password required pam_permit.so</programlisting>
service, which serves as a fall-back, should come last. The
examples in the original PAM paper grouped configuration lines
by facility, and Solaris' stock <filename>pam.conf</filename>
still does that, but Linux-PAM (and hence FreeBSD) groups
still does that, but FreeBSD's stock configuration groups
configuration lines by service. Either way is fine; either
way makes equal sense.</para>
<para>Linux-PAM offers an alternate configuration mechanism,
where policies are contained in separate files, named for the
service they apply to, in <filename>/etc/pam.d/</filename>,
with only four fields instead of five&mdash;the service name
field is omitted. In FreeBSD 5.0, starting from mid-January
2002, this is the preferred mechanism. Note, however, that if
<filename>/etc/pam.conf</filename> exists, and contains
configuration statements for services which do not have a
specific policy in <filename>/etc/pam.d/</filename>, it will
be used as a fall-back for these services.</para>
<para>OpenPAM and Linux-PAM offer an alternate configuration
mechanism, where policies are contained in separate files,
named for the service they apply to, in
<filename>/etc/pam.d/</filename>, with only four fields
instead of five&mdash;the service name field is omitted. This
is the preferred mechanism in FreeBSD 5.x.. Note, however,
that if <filename>/etc/pam.conf</filename> exists, and
contains configuration statements for services which do not
have a specific policy in <filename>/etc/pam.d/</filename>, it
will be used as a fall-back for these services.</para>
<para>The great advantage of <filename>/etc/pam.d/</filename>
over <filename>/etc/pam.conf</filename> is that it is possible
@ -729,25 +762,35 @@ sshd password required pam_permit.so</programlisting>
<para>This works because the service name is determined from the
file name rather than specified in the policy file, so the
same file can be used for arbitrary services.</para>
same file can be used for multiple differently-named
services.</para>
<para>One other advantage is that third-party software can
easily install policies for their services without the need to
edit <filename>/etc/pam.conf</filename>.</para>
edit <filename>/etc/pam.conf</filename>. True to the FreeBSD
tradition, OpenPAM will even look for policy files in
<filename>/usr/local/etc/pam.d/</filename> if no configuration
for the requested service is present in
<filename>/etc/pam.d/</filename> or
<filename>/etc/pam.conf</filename>.</para>
<para>Whether you use <filename>/etc/pam.conf</filename> or
<filename>/etc/pam.d/</filename>, the policy for the special
service <literal>other</literal> is used as a fall-back for
any service that does not have its own policy.</para>
<para>Finally, whichever configuration mechanism you choose, the
<quote>magic</quote> policy <literal>other</literal> is used
as a fall-back for any service that does not have its own
policy.</para>
</section>
<section>
<title>Breakdown of a configuration line</title>
<section id="pam-config-breakdown">
<title id="pam-config-breakdown.title">Breakdown of a
configuration line</title>
<para>As explained in <xref linkend="pam-config-file-locations">,
each line in <filename>/etc/pam.conf</filename> consists of four
or more fields: the service name, the facility name, the control
flag, the module name, and zero or more module arguments.</para>
<para>As explained in the <link
linkend="pam-config-file-locations"
endterm="pam-config-file-locations.title"></link> section,
each line in <filename>/etc/pam.conf</filename> consists of
four or more fields: the service name, the facility name, the
control flag, the module name, and zero or more module
arguments.</para>
<para>The service name is generally (though not always) the name
of the application the statement applies to. If you are
@ -771,19 +814,21 @@ sshd password required pam_permit.so</programlisting>
describing how to interpret the return code from the module.
Linux-PAM supports an alternate syntax that lets you specify
the action to associate with each possible return code, but
this should be avoided as it is non-standard and requires very
detailed knowledge of the PAM library to use properly.</para>
this should be avoided as it is non-standard and closely tied
in with the way Linux-PAM dispatches service calls (which
differs greatly from the way Solaris and OpenPAM do it.)
Unsurprisingly, OpenPAM does not support this syntax.</para>
</section>
<section>
<title>Policies</title>
<section id="pam-policies">
<title id="pam-policies.title">Policies</title>
<para><!--XXX-->This section has not yet been written.</para>
</section>
</section>
<section id="pam-modules">
<title id="pam-modules.title">PAM Modules</title>
<section id="pam-freebsd-modules">
<title id="pam-freebsd-modules.title">FreeBSD PAM Modules</title>
<para><!--XXX-->This section has not yet been written.</para>
</section>
@ -815,20 +860,28 @@ sshd password required pam_permit.so</programlisting>
</section>
<appendix id="pam-sample-appl">
<title id="pam-sample-appl.title">Sample PAM application</title>
<title id="pam-sample-appl.title">Sample PAM Application</title>
<para>The following is a minimal implementation of &man.su.1;
using PAM. Note that it uses the Linux-PAM-specific
<function>misc_conv</function> conversation function, which is
using PAM. Note that it uses the OpenPAM-specific
&man.openpam.ttyconv.3; conversation function, which is
prototyped in <filename
class="headerfile">security/pam_misc.h</filename>.</para>
class="headerfile">security/openpam.h</filename>. 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 surprisingly difficult to
implement; the one presented in the <link
linkend="pam-sample-conv"
endterm="pam-sample-conv.title"></link> appendix is a good
starting point, but should not be used in real-world
applications.</para>
<programlisting><inlinegraphic fileref="pam_app.c"
format="linespecific"></programlisting>
</appendix>
<appendix id="pam-sample-module">
<title id="pam-sample-module.title">Sample PAM module</title>
<title id="pam-sample-module.title">Sample PAM Module</title>
<para>The following is a minimal implementation of
&man.pam.unix.8;, offering only authentication services. It
@ -841,6 +894,23 @@ sshd password required pam_permit.so</programlisting>
format="linespecific"></programlisting>
</appendix>
<appendix id="pam-sample-conv">
<title id="pam-sample-conv.title">Sample PAM Conversation
Function</title>
<para>The conversation function presented below is a greatly
simplified version of OpenPAM's &man.openpam.ttyconv.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 &man.openpam.ttyconv.3; to
your uses; we believe it to be as robust as a tty-oriented
convesation function can reasonably get.</para>
<programlisting><inlinegraphic fileref="pam_conv.c"
format="linespecific"></programlisting>
</appendix>
<bibliography id="pam-further">
<title id="pam-further.title">Further Reading</title>