xref: /freebsd/contrib/pam-krb5/tests/fakepam/README (revision bf6873c5786e333d679a7838d28812febf479a8a)
1                          PAM Testing Framework
2
3Overview
4
5    The files in this directory provide a shim PAM library that's used for
6    testing and a test framework used to exercise a PAM module.
7
8    This library and its include files define the minimum amount
9    of the PAM module interface so that PAM modules can be tested without
10    such problems as needing configuration files in /etc/pam.d or needing
11    changes to the system configuration to run a testing PAM module
12    instead of the normal system PAM modules.
13
14    The goal of this library is that all PAM code should be able to be
15    left unchanged and the code just linked with the fakepam library
16    rather than the regular PAM library.  The testing code can then call
17    pam_start and pam_end as defined in the fakepam/pam.h header file and
18    inspect internal PAM state as needed.
19
20    The library also provides an interface to exercise a PAM module via an
21    interaction script, so that as much of the testing process as possible
22    is moved into simple text files instead of C code.  That test script
23    format supports specifying the PAM configuration, the PAM interfaces
24    to run, the expected prompts and replies, and the expected log
25    messages.  That interface is defined in fakepam/script.h.
26
27Fake PAM Library
28
29    Unfortunately, the standard PAM library for most operating systems
30    does not provide a reasonable testing framework.  The primary problem
31    is configuration: the PAM library usually hard-codes a configuration
32    location such as /etc/pam.conf or /etc/pam.d/<application>.  But there
33    are other problems as well, such as capturing logging rather than
34    having it go to syslog and inspecting PAM internal state to make sure
35    that it's updated properly by the module.
36
37    This library implements some of the same API as the system PAM library
38    and uses the system PAM library headers, but the underlying
39    implementation does not call the system PAM library or dynamically
40    load modules.  Instead, it's meant to be linked into a single
41    executable along with the implementation of a PAM module.  It does not
42    provide most of the application-level PAM interfaces (so one cannot
43    link a PAM-using application against it), just the interfaces called
44    by a module.  The caller of the library can then call the module API
45    (such as pam_sm_authenticate) directly.
46
47    All of the internal state maintained by the PAM library is made
48    available to the test program linked with this library.  See
49    fakepam/pam.h for the data structures.  This allows verification that
50    the PAM module is setting the internal PAM state properly.
51
52  User Handling
53
54    In order to write good test suites, one often has to be able to
55    authenticate as a variety of users, but PAM modules may expect the
56    authenticating user to exist on the system.  The fakepam library
57    provides a pam_modutil_getpwnam (if available) or a getpwnam
58    implementation that returns information for a single user (and user
59    unknown for everyone else).  To set the information for the one valid
60    user, call the pam_set_pwd function and provide a struct passwd that
61    will be returned by pam_modutil_getpwnam.
62
63    The fakepam library also provides a replacement krb5_kuserok function
64    for testing PAM modules that use Kerberos.  This source file should
65    only be included in packages that are building with Kerberos.  It
66    implements the same functionality as the default krb5_kuserok
67    function, but looks for .k5login in the home directory configured by
68    the test framework instead of using getpwnam.
69
70    Only those two functions are intercepted, so if the module looks up
71    users in other ways, it may still bypass the fakepam library and look
72    at system users.
73
74  Output Handling
75
76    The fakepam library intercepts the PAM functions that would normally
77    log to syslog and instead accumulates the output in a static string
78    variable.  To retrieve the logging output so far, call pam_output,
79    which returns a struct of all the output strings up to that point and
80    resets the accumulated output.
81
82Scripted PAM Testing
83
84    Also provided as part of the fakepam library is a test framework for
85    testing PAM modules.  This test framework allows most of the testing
86    process to be encapsulated in a text configuration file per test,
87    rather than in a tedious set of checks and calls written in C.
88
89  Test API
90
91    The basic test API is to call either run_script (to run a single test
92    script) or run_script_dir (to run all scripts in a particular
93    directory).  Both take a configuration struct that controls how the
94    PAM library is set up and called.
95
96    That configuration struct takes the following elements:
97
98    user
99        The user as which to authenticate, passed into pam_start and also
100        substituted for the %u escape.  This should match the user whose
101        home directory information is configured using pam_set_pwd if that
102        function is in use.
103
104    password
105        Only used for the %p escape.  This is not used to set the
106        authentication token in the PAM library (see authtok below).
107
108    newpass
109        Only used for the %n escape.
110
111    extra
112        An array of up to 10 additional strings used by the %0 through %9
113        escapes when parsing the configuration file, as discussed below.
114
115    authtok
116        Sets the default value of the PAM_AUTHTOK data item.  This will be
117        set immediately after initializing the PAM library and before
118        calling any PAM module functions.
119
120    authtok
121        Like authtok, but for the PAM_OLDAUTHTOK data item.
122
123    callback
124        This, and the associated data element, specifies a callback that's
125        called at the end of processing of the script before calling
126        pam_end.  This can be used to inspect and verify the internal
127        state of PAM.  The data element is an opaque pointer passed into
128        the callback.
129
130  Test Script Basic Format
131
132    Test scripts are composed of one or more sections.  Each section
133    begins with:
134
135        [<section>]
136
137    starting in column 1, where <section> is the name of the section.  The
138    valid section types and the format of their contents are described
139    below.
140
141    Blank lines and lines starting with # are ignored.
142
143    Several strings undergo %-escape expansion as mentioned below.  For
144    any such string, the following escapes are supported:
145
146        %i      Current UID (not the UID of the target user)
147        %n      New password
148        %p      Password
149        %u      Username
150        %0      extra[0]
151        ...
152        %9      extra[9]
153
154    All of these are set in the script_config struct.
155
156    Regular expression matching is supported for output lines and for
157    prompts.  To mark an expected prompt or output line as a regular
158    expression, it must begin and end with a slash (/).  Slashes inside
159    the regular expression do not need to be escaped.  If regular
160    expression support is not available in the C library, those matching
161    tests will be skipped.
162
163  The [options] Section
164
165    The [options] section contains the PAM configuration that will be
166    passed to the module.  These are the options that are normally listed
167    in the PAM configuration file after the name of the module.  The
168    syntax of this section is one or more lines of the form:
169
170        <group> = <options>
171
172    where <group> is one of "account", "auth", "password", or "session".
173    The options are space-delimited and may be either option names or
174    option=value pairs.
175
176  The [run] Section
177
178    The [run] section specifies what PAM interfaces to call.  It consists
179    of one or more lines in the format:
180
181        <call> = <status>
182
183    where <call> is the PAM call to make and <status> is the status code
184    that it should return.  <call> is one of the PAM module interface
185    functions without the leading "pam_sm_", so one of "acct_mgmt",
186    "authenticate", "setcred", "chauthtok", "open_session", or
187    "close_session".  The return status is one of the PAM constants
188    defined for return status, such as PAM_IGNORE or PAM_SUCCESS.  The
189    test framework will ensure that the PAM call returns the appropriate
190    status.
191
192    The <call> may be optionally followed by an open parentheses and then
193    a list of flags separated by |, or syntactically:
194
195        <call>(<flag>|<flag>|...) = <status>
196
197    In this form, rather than passing a flags value of 0 to the PAM call,
198    the test framework will pass the combination of the provided flags.
199    The flags are PAM constants without the leading PAM_, so (for example)
200    DELETE_CRED, ESTABLISH_CRED, REFRESH_CRED, or REINITIALIZE_CRED for
201    the "setcred" call.
202
203    As a special case, <call> may be "end" to specify flags to pass to the
204    pam_end call (such as PAM_DATA_SILENT).
205
206  The [end] Section
207
208    The [end] section defines how to call pam_end.  It currently takes
209    only one setting, flags, the syntax of which is:
210
211        flags = <flag>|<flag>
212
213    This allows PAM_DATA_SILENT or other flags to be passed to pam_end
214    when running the test script.
215
216  The [output] Section
217
218    The [output] section defines the logging output expected from the
219    module.  It consists of zero or more lines in the format:
220
221        <priority> <output>
222        <priority> /<regex>/
223
224    where <priority> is a syslog priority and <output> is the remaining
225    output or a regular expression to match against the output.  Valid
226    values for <priority> are DEBUG, INFO, NOTICE, ERR, and CRIT.
227    <output> and <regex> may contain spaces and undergoes %-escape
228    expansion.
229
230    The replacement values are taken from the script_config struct passed
231    as a parameter to run_script or run_script_dir.
232
233    If the [output] section is missing entirely, the test framework will
234    expect there to be no logging output from the PAM module.
235
236    This defines the logging output, not the prompts returned through the
237    conversation function.  For that, see the next section.
238
239  The [prompts] Section
240
241    The [prompts] section defines the prompts that the PAM module is
242    expected to send via the conversation function, and the responses that
243    the test harness will send back (if any).  This consists of zero or
244    more lines in one of the following formats:
245
246        <type> = <prompt>
247        <type> = /<prompt>/
248        <type> = <prompt>|<response>
249        <type> = /<prompt>/|<response>
250
251    The <type> is the style of prompt, chosen from "echo_off", "echo_on",
252    "error_msg", and "info".  The <prompt> is the actual prompt sent and
253    undergoes %-escape expansion.  It may be enclosed in slashes (/) to
254    indicate that it's a regular expression instead of literal text.  The
255    <response> if present (and its presence is signaled by the |
256    character) contains the response sent back by the test framework and
257    also undergoes %-escape expansion.  The response starts with the final
258    | character on the line, so <prompt> regular expressions may freely
259    use | inside the regular expression.
260
261    If the [prompts] section is present and empty, the test harness will
262    check that the PAM module does not send any prompts.  If the [prompts]
263    section is absent entirely, the conversation function passed to the
264    PAM module will be NULL.
265
266License
267
268    This file is part of the documentation of rra-c-util, which can be
269    found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
270
271    Copyright 2011-2012, 2020-2021 Russ Allbery <eagle@eyrie.org>
272
273    Copying and distribution of this file, with or without modification,
274    are permitted in any medium without royalty provided the copyright
275    notice and this notice are preserved.  This file is offered as-is,
276    without any warranty.
277