Build courier-authlib 0.60.2-0hcoop3.
[hcoop/debian/courier-authlib.git] / README_authlib.html.in
1 <?xml version="1.0"?>
2 <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>Courier Authentication Library</title><link rel="stylesheet" href="style.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"/><link rel="start" href="#authlib" title="Courier Authentication Library"/><link rel="next" href="#authpwd" title="The authpwd authentication module"/><link xmlns="" rel="stylesheet" type="text/css" href="manpage.css"/><meta xmlns="" name="MSSmartTagsPreventParsing" content="TRUE"/><link xmlns="" rel="icon" href="icon.gif" type="image/gif"/><!--
3
4 Copyright 1998 - 2007 Double Precision, Inc. See COPYING for distribution
5 information.
6
7 --></head><body><div class="chapter" lang="en" xml:lang="en"><div class="titlepage"><div><div><h1 class="title"><a id="authlib" shape="rect"> </a>Courier Authentication Library</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#authpwd" shape="rect">The <code class="literal">authpwd</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authshadow" shape="rect">The <code class="literal">authshadow</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authpam" shape="rect">The <code class="literal">authpam</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authpipe" shape="rect">The <code class="literal">authpipe</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authpipeproto" shape="rect">The <code class="literal">authpipe</code> protocol</a></span></dt><dt><span class="sect1"><a href="#authuserdb" shape="rect">The <code class="literal">authuserdb</code> authentication module</a></span></dt><dd><dl><dt><span class="sect2"><a href="#userdbprimer" shape="rect">A brief <code class="literal">userdb</code> primer</a></span></dt><dt><span class="sect2"><a href="#userdbsimple" shape="rect">A simple userdb setup</a></span></dt><dt><span class="sect2"><a href="#userdbcomplex" shape="rect">Large virtual domain farm</a></span></dt><dt><span class="sect2"><a href="#moreuserdb" shape="rect">Beyond <code class="literal">userdb</code></a></span></dt></dl></dd><dt><span class="sect1"><a href="#authvchkpw" shape="rect">The <code class="literal">authvchkpw</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authmysql" shape="rect">The <code class="literal">authmysql</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authpgsql" shape="rect">The <code class="literal">authpgsql</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authldap" shape="rect">The <code class="literal">authldap</code> authentication module</a></span></dt><dt><span class="sect1"><a href="#authcustom" shape="rect"><code class="literal">authcustom</code></a></span></dt><dt><span class="sect1"><a href="#options" shape="rect">Account options</a></span></dt><dt><span class="sect1"><a href="#authtest" shape="rect">Running <span><strong class="command">authtest</strong></span></a></span></dt><dd><dl><dt><span class="sect2"><a href="#pwchange" shape="rect">Changing account passwords</a></span></dt></dl></dd><dt><span class="sect1"><a href="#internals" shape="rect">Authentication internals</a></span></dt><dt><span class="sect1"><a href="#files" shape="rect">FILES</a></span></dt><dt><span class="sect1"><a href="#seealso" shape="rect">SEE ALSO</a></span></dt></dl></div><p>
8 This library is used for two purposes:</p><p>
9 1. Read the name of a mail account.
10 Determine the local account's home directory, and system userid and
11 groupid.</p><p>
12 2. Read an account name, and a password.
13 If valid, determine the account's home directory, system userid, and
14 groupid.</p><p>
15 The term "authentication" is used in the following documentation to refer
16 to either one of these two functions.
17 The library contains several alternative authentication modules to choose
18 from, described below.</p><p>
19 The configuration file <code class="filename">@authdaemonrc@</code> contains several
20 settings. The most important of them are:</p><div class="itemizedlist"><ul type="disc"><li><p>
21 A list of authentication modules to activate.
22 By default, this list includes all available authentication modules,
23 even if some are not actually installed at the moment.
24 When the authentication library is set up, only those authentication
25 modules that can be supported by the operating system will be installed.
26 Some of the listed modules may not actually be there,
27 however that's not a problem.
28 Any unavailable authentication modules will be ignored.
29 Also, on some platforms certain authentication modules are installed by
30 optional sub-packages.
31 Installing the sub-package is the only action needed to make use of it.</p><p>
32 The only time the list of authentication modules need to be adjusted is
33 when an available authentication module must be disabled for some reason.
34 This should only be needed in the most unusual circumstances.</p></li><li><p>
35 Number of authentication processes.
36 The default setting is to start five authentication processes, which should be
37 sufficient for normal usage.
38 Try increasing this setting if its taking too long to log into an account,
39 and you have determined that this is not due to a bottleneck in the whatever
40 authentication database you're using (LDAP, MySQL, or PostgreSQL).</p><p>
41 An authentication request must be completed within thirty seconds, otherwise
42 it gets rejected.
43 When authentication requests come in faster than all five authentication
44 processes can get to them, delays build up, and the timer is ticking.
45 If all the activity maxes out the CPU or I/O bandwidth,
46 nothing can be done about it, short
47 of getting another server. However if there's plenty of available CPU and
48 I/O, increasing the number of processes will do the trick.</p></li></ul></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authpwd" shape="rect"> </a>The <code class="literal">authpwd</code> authentication module</h2></div></div></div><p>
49 This modules obtains account information and passwords from the
50 <code class="filename">/etc/passwd</code> file.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
51 This module doesn't actually read the <code class="filename">/etc/passwd</code>
52 file, it uses the C library's getpw() functions.
53 The C library implementation could use any mechanism to obtain the equivalent
54 information.</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authshadow" shape="rect"> </a>The <code class="literal">authshadow</code> authentication module</h2></div></div></div><p>
55 This module is a version of the <code class="literal">authpwd</code> module that
56 reads passwords
57 from <code class="filename">/etc/shadow</code> (the C library's getsp()
58 functions).</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authpam" shape="rect"> </a>The <code class="literal">authpam</code> authentication module</h2></div></div></div><p>
59 This modules uses the system's PAM library
60 (pluggable authentication modules) for authentication.
61 This is, essentially, a way to use existing PAM modules for authentication.
62 Note, however, that the authenticated account's home directory, userid and
63 groupid are still read from the <code class="filename">/etc/passwd</code> file,
64 since PAM functionality is limited to validating account passwords.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
65 Not all PAM modules are compatible with Courier's authentication library.
66 PAM modules that make use of PAM's session functions, or authentication token
67 functions, like <code class="literal">pam_krb5</code> will not work with Courier.</p></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
68 Additional configuration steps will be required to set up
69 the PAM library to authenticate Courier's services.
70 Courier's IMAP and POP3 servers, for example, require that the
71<span class="quote">imap</span>” and “<span class="quote">pop3</span>” PAM service to be
72 configured.</p><p>
73 The specific configuration steps differ from system to system.
74 Consult the system documentation for more information.
75 It might be tempting to throw in a towel and use
76 <code class="literal">authshadow</code> or <code class="literal">authpwd</code>
77 if you cannot figure out how to install PAM support,
78 however that is not advisable.
79 It is highly recommended to use
80 <code class="filename">authpam</code> wherever the PAM library is available.</p><p>
81 The exact configuration procedure depends on the PAM implementation.
82 Most PAM libraries use configuration files in the
83 <code class="filename">/etc/pam.d</code> directory.
84 Therefore, it will be necessary to install the configuration files
85 <code class="filename">/etc/pam.d/imap</code> and
86 <code class="filename">/etc/pam.d/pop3</code>. Similarly, Courier's webmail
87 server, SqWebMail, uses <code class="filename">/etc/pam.d/webmail</code>, and
88 its optional calendar component uses <code class="filename">/etc/pam.d/webmail</code>.
89 Courier-MTA's authenticated SMTP component uses the
90 <code class="filename">/etc/pam.d/smtp</code> service.</p><p>
91 In nearly all cases all these configuration files will specify an
92 identical PAM library configuration for all services.
93 The exact configuration details are site-specific.
94 Here's an example of a PAM configuration file for a recent version of the
95 most common PAM library:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
96 auth required pam_nologin.so
97 auth required pam_stack.so service=system-auth
98 account required pam_stack.so service=system-auth
99 session required pam_stack.so service=system-auth
100 </pre></div><p>
101 Again, the actual configuration is site specific.
102 Examine the contents of existing configuration files in
103 <code class="filename">/etc/pam.d</code> for similar services (if there's
104 <code class="filename">/etc/pam.d/ppp</code>
105 it's often a good example to follow) in order
106 to derive the correct setup for Courier.</p><p>
107 Older PAM libraries use a single configuration file, usually
108 <code class="filename">/etc/pam.conf</code>.
109 Append Courier-specific PAM settings to this configuration file, again
110 using settings for existing services as a guide.
111 For example:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
112 imap auth required pam_unix.so try_first_pass
113 imap account required pam_unix.so
114 imap session required pam_permit.so
115 pop3 auth required pam_unix.so try_first_pass
116 pop3 account required pam_unix.so
117 </pre></div><p>
118 Some PAM libraries use
119 <code class="filename">pam_pwdb.so</code> instead of
120 <code class="filename">pam_unix.so</code>; consult the PAM library's
121 documentation for more information.</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authpipe" shape="rect"> </a>The <code class="literal">authpipe</code> authentication module</h2></div></div></div><p>This is a generic plug-in module that runs an external script,
122 or a program, in response to authentication requests.</p><p>The external program reads from stdin and writes to stdout. It
123 can be persistent and handle many authentication requests. Only one request
124 will be sent to it at a time; each authdaemon process starts its own copy of
125 the external script.</p><p>The location of the external program is set by the
126 <code class="literal">--with-pipeprog</code> configure option,
127 which defaults to
128 <code class="filename">@sysconfdir@/authlib/authProg</code>. A sample program
129 is included in the courier-authlib source.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authpipeproto" shape="rect"> </a>The <code class="literal">authpipe</code> protocol</h2></div></div></div><p>
130 authpipe uses the same protocol as authdaemon clients use to communicate
131 with authdaemond.</p><p>There are four possible requests: <code class="literal">PRE</code>,
132 <code class="literal">AUTH</code>, <code class="literal">PASSWD</code> and
133 <code class="literal">ENUMERATE</code>. Apart from <code class="literal">AUTH</code>, each
134 request is a single line terminated by newline.
135 </p><div class="variablelist"><dl><dt><span class="term">PRE . <em class="replaceable"><code>authservice</code></em> <em class="replaceable"><code>username</code></em> <span class="emphasis"><em>&lt;newline&gt;</em></span></span></dt><dd><p>Look up data for an account.
136 <em class="replaceable"><code>authservice</code></em> identifies the service the
137 user is trying to use - e.g. pop3, imap, webmail etc.</p><p>If the account exists, return the account
138 data as a series of ATTR=value newline-terminated lines, followed by a
139 period on a line of its own. Valid attributes are:
140 </p><pre class="screen" xml:space="preserve">
141 USERNAME=username -- system account which owns mailbox (name)
142 UID=uid -- system account which owns mailbox (numeric uid)
143 GID=gid -- numeric groupid
144 HOME=homedir -- home directory
145 ADDRESS=addr -- e-mail address
146 NAME=name -- full name
147 MAILDIR=maildir -- Maildir relative to home directory
148 QUOTA=quota -- quota string: maxbytesS,maxfilesC
149 PASSWD=cryptpasswd -- encrypted password
150 PASSWD2=plainpasswd -- plain text password
151 OPTIONS=acctoptions -- option1=val1,option2=val2,...
152 .
153 </pre><p>
154 Of these, it is mandatory to return ADDRESS, HOME, GID, and either UID
155 or USERNAME; the others are optional.
156 </p><p>If the account is not known, return <code class="literal">FAIL</code><span class="emphasis"><em><code class="literal">&lt;newline&gt;</code></em></span>.
157 If there is a temporary failure, such as a database being down, authProg
158 should terminate (thereby closing stdin/stdout) without sending any
159 response. authdaemon will restart the pipe module for the next
160 request, thus ensuring it is properly reinitialized.
161 </p></dd><dt><span class="term">AUTH <em class="replaceable"><code>len</code></em><span class="emphasis"><em>&lt;newline&gt;</em></span><em class="replaceable"><code>len-bytes</code></em></span></dt><dd><p>
162 Validate a login attempt. The AUTH line is followed by
163 <span class="emphasis"><em>len-bytes</em></span> of authentication data, which does not
164 necessarily end with a newline. The currently defined authentication
165 requests are:
166 </p><pre class="screen" xml:space="preserve">
167 login \n username \n password [\n] -- plaintext login
168 cram-md5 \n challenge \n response [\n] -- base-64 encoded challenge and response
169 cram-sha1 \n challenge \n response [\n] -- ditto
170 cram-sha256 \n challenge \n response [\n] -- ditto
171 </pre><p>
172 In the case of success, return the complete set of
173 account parameters in the same format as PRE, ending with a period on
174 a line of its own. In the case of failure (e.g. username does not exist,
175 password wrong, unsupported authentication type), return
176 <code class="literal">FAIL</code><span class="emphasis"><em><code class="literal">&lt;newline&gt;</code></em></span>.
177 If there is a temporary failure, such as a database being down, authProg
178 should terminate without sending any response.
179 </p><p>
180 Note: if the user provides a plaintext password and authenticates
181 successfully, then you can return it as PASSWD2 (plain text password)
182 even if the database contains an encrypted password. This is useful
183 when using the POP3/IMAP proxy functions of courier-imap.
184 </p></dd><dt><span class="term">PASSWD <em class="replaceable"><code>service</code></em><span class="emphasis"><em>&lt;tab&gt;</em></span>
185 <em class="replaceable"><code>username</code></em><span class="emphasis"><em>&lt;tab&gt;</em></span>
186 <em class="replaceable"><code>oldpasswd</code></em><span class="emphasis"><em>&lt;tab&gt;</em></span>
187 <em class="replaceable"><code>newpasswd</code></em><span class="emphasis"><em>&lt;tab&gt;</em></span>
188 <span class="emphasis"><em>&lt;newline&gt;</em></span>
189 </span></dt><dd><p>Request a password change for the given account: validate that
190 the oldpassword is correct, and if so, change it to the newpassword.
191 </p><p>Reply: the string
192 for success, or <code class="literal">FAIL</code><span class="emphasis"><em><code class="literal">&lt;newline&gt;</code></em></span> for
193 a data error (e.g. no such account, old password wrong, new password not
194 acceptable). In the case of a temporary failure, such as a database
195 being down, authProg should terminate without sending any response.
196 </p></dd><dt><span class="term">ENUMERATE <span class="emphasis"><em>&lt;newline&gt;</em></span></span></dt><dd><p>
197 Return a list of all accounts, one per line in the following format,
198 ending with a period on a line of its own:
199 </p><pre class="screen" xml:space="preserve">
200 username \t uid \t gid \t homedir \t maildir \t options \n
201 .
202 </pre><p>
203 If your module does not support the ENUMERATE command then return just
204 a period on a line of its own (which will still allow enumeration data
205 from other modules to be returned). In the case of a temporary failure,
206 such as a database being down or an error occuring mid-way through
207 returning account data, authProg should terminate before sending
208 the terminating period.
209 </p></dd></dl></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authuserdb" shape="rect"> </a>The <code class="literal">authuserdb</code> authentication module</h2></div></div></div><p>
210 This module
211 uses a GDBM or a DB-based
212 <a href="userdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">userdb</span>(8)</span></a> database.
213 This module also incorporates userdb-based challenge-response authentication
214 implementation that was done by a separate <code class="literal">authcram</code> module
215 in previous versions of the Courier authentication library.</p><p>
216 <code class="filename">@sysconfdir@/authlib/userdb</code> is a plain file that
217 can be edited with any text editor.
218 The file contains a list of account names, and their pertinent information.
219 <code class="filename">@sysconfdir@/authlib/userdb</code> may alternatively be a
220 directory containing plain text files, which are effectively concatenated
221 together to form the actual list of accounts.
222 The <span><strong class="command">makeuserdb</strong></span> script compiles the account information
223 into a GDBM or DB database file, which can be quickly looked up.</p><p>
224 <code class="filename">@sysconfdir@/authlib/userdb</code> is loosely equivalent in
225 function to <code class="filename">/etc/passwd</code> and
226 <code class="filename">/etc/shadow</code>, and contain analous information: account
227 name, its numeric userid and groupid, home directory, and passwords.
228 <code class="filename">@sysconfdir@/authlib/userdb</code> also contains additional
229 Courier-specific metadata, such as account quotas and other account-specific
230 settings.
231 <code class="filename">@sysconfdir@/authlib/userdb</code> files can also be
232 maintained by custom-written Perl scripts, instead of being edited
233 by hand.</p><p>
234 <code class="filename">@sysconfdir@/authlib/userdb</code>
235 allows creation of virtual mail accounts that do not have a corresponding
236 login account -- virtual mail accounts that can share the same, reserved,
237 system userid.
238 <code class="filename">@sysconfdir@/authlib/userdb</code>
239 can also be used to completely supersede
240 <code class="filename">/etc/passwd</code>.
241 With many accounts it can be quite a drain to have to continuously linearly
242 scan <code class="filename">/etc/passwd</code> in order to look up an account.
243 Instead, a fast database lookup can retrieve the same information from the
244 database file.
245 Review the included manual pages, starting with
246 <a href="userdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">userdb</span>(8)</span></a>, for more information.</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="userdbprimer" shape="rect"> </a>A brief <code class="literal">userdb</code> primer</h3></div></div></div><p>
247 <code class="literal">userdb</code> is a way to implement many virtual mailboxes - many
248 mailboxes that do not have to have a separate system userid allocated for
249 each one, and there is no system login associated with each mailbox.
250 <code class="literal">userdb</code> uses a database for mapping virtual addresses to physical
251 maildirs. It should be scalable to thousands of mailboxes. It can also be
252 used to replace linear searches of <code class="filename">/etc/passwd</code> with a database
253 lookup, see
254 <a href="pw2userdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">pw2userdb</span>(8)</span></a>.</p><p>
255 Note - you still MUST use some valid system userid and groupid that is
256 shared by all virtual mailboxes. Instead of allocating a single userid and
257 groupid per each mailbox, the same userid and groupid is used for all of
258 them.</p><p>
259 This is a rough overview of using userdb. For additional information, read
260 <a href="userdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">userdb</span>(8)</span></a>
261 and
262 <a href="makeuserdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">makeuserdb</span>(8)</span></a>. All the scripts will
263 be installed in <code class="filename">@sbindir@</code>, so look for them there.</p><p>
264 The best way to describe how <code class="literal">userdb</code> works is to try to create
265 one virtual mail account. As mentioned before, virtual mailboxes still need
266 one system account to be used for uid/gid purposes. Let's call this system
267 account "vmail".</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="userdbsimple" shape="rect"> </a>A simple userdb setup</h3></div></div></div><p>
268 This approach should be used if you do not have many virtual mailboxes.
269 It's very simple, but quickly becomes cumbersome if you administer many
270 virtual mailboxes.</p><p>Create an empty <code class="filename">@userdb@</code> file:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
271 # cp /dev/null @userdb@
272 # chmod 700 @userdb@</pre></div><p>
273 <code class="filename">@userdb@</code> must have 700 permissions,
274 since it will contain passwords.</p><p>
275 Now, run the script <span><strong class="command">pw2userdb</strong></span>, as root.
276 This script converts the
277 contents of <code class="filename">/etc/passwd</code>
278 to the <code class="filename">@userdb@</code> format
279 (including the contents of <code class="filename">/etc/shadow</code>,
280 this is why permissions
281 on <code class="filename">@userdb@</code> must be 700). This script is usually used
282 where you
283 want to convert a very large <code class="filename">/etc/passwd</code> to
284 <code class="filename">@userdb@</code>. <code class="literal">userdb</code> applications can now
285 use a fast
286 <code class="literal">userdb</code> database instead of a linear scan
287 of <code class="filename">/etc/passwd</code>
288 in order to look up system accounts. However, you probably don't want to
289 use this feature right now, so what you want to do is take the output
290 of <span><strong class="command">pw2userdb</strong></span>, and find the entry for the vmail account
291 that you
292 created earlier. Look for a line that starts with 'vmail' followed by tab,
293 followed by familiar fields from <code class="filename">/etc/passwd</code>. Save the
294 output of
295 <span><strong class="command">pw2userdb</strong></span> in a temporary file, edit it, and remove
296 everything
297 except the line containing vmail, and the very next line, which is a special
298 entry that maps vmail's userid back to the vmail record.</p><p>
299 Here's what you might find in the output of
300 <span><strong class="command">pw2userdb</strong></span>:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
301 vmail uid=1012|gid=1012|home=/home/vmail|systempw=*
302 1012= vmail</pre></div><p>
303 The actual numerical values and the home directory location may vary.
304 Save
305 these two lines as <code class="filename">@userdb@</code>, and set the permissions on
306 <code class="filename">@userdb@</code> to 700:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
307 $ chmod 700 <code class="filename">@userdb@</code>
308 </pre></div><p>
309 Now, with that out of the way, let's really create a virtual account. In
310 this example we'll create a virtual mailbox for 'john@example.com'.</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
311 # su vmail
312 $ cd ~vmail
313 $ mkdir john-example
314 $ maildirmake john-example/Maildir
315 $ exit
316 #
317 </pre></div><p>
318 You may need to specify a full path to your <span><strong class="command">maildirmake</strong></span>
319 program. The end result is that you created
320 <code class="filename">$HOME/john-example</code> in vmail's account, which
321 can be thought of as a “<span class="quote">virtual home directory</span>” for
322<span class="quote">john@example.com</span>”, that contains the account's maildir
323 mailbox.</p><p>
324 Now, let's connect the dots here, and create an entry in
325 <code class="filename">@userdb@</code> for <code class="filename">john@example.com</code>:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
326 # userdb "john@example.com" set home=/home/vmail/john-example \
327 uid=UUU gid=GGG
328 </pre></div><p>
329 This command runs the script named <code class="filename">userdb</code> , which is
330 installed, by default in <code class="filename">@sbindir@</code>. Replace UUU and
331 GGG with the userid and groupid of the vmail account. If you now look in
332 <code class="filename">@userdb@</code>, you will see that a new record for
333<span class="quote">john@example.com</span>
334 has been appended to the end of the file.</p><p>
335 One more detail: we need to set the IMAP password for this
336 mailbox:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
337 # userdbpw | userdb "john@example.com" set imappw</pre></div><p>
338 On most modern Linux and BSD distributions, you can specify the -md5
339 option to <span><strong class="command">userdbpw</strong></span>, in order to use MD5 password hashes,
340 instead of crypt. The traditional password function allows passwords only
341 up to 8 characters long; everything in excess is ignored.
342 The newer MD5 passwords, now supported by most modern systems, allow
343 longer passwords.</p><p>
344 Use "<code class="literal">systempw</code>" instead of
345 "<code class="literal">imappw</code>" if you would like to use the same password for the POP3
346 server, and for all other services.
347 The "<code class="literal">imappw</code>" field is only checked by the IMAP server.
348 If not
349 defined, "<code class="literal">systempw</code>" is used instead. The field
350 <code class="literal">pop3pw</code>
351 is checked only by Courier's POP3 server. If it is
352 not defined the POP3 server will check <code class="literal">systempw</code> too.</p><p>Finally, compile the database:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
353 # makeuserdb
354 </pre></div><p>
355 This command creates the actual database, <code class="filename">@userdb@.dat</code> and
356 <code class="filename">@userdb@shadow.dat</code> from the plain text file
357 <code class="filename">@userdb@</code>. Courier will now start accepting logins to this
358 mailbox. Adding and removing mailboxes can be done while Courier is
359 running.</p><p>
360 Courier reads <code class="filename">@userdb@.dat</code> and
361 <code class="filename">@userdb@shadow.dat</code> only. The plain text source,
362 <code class="filename">@userdb@</code> is not read by Courier itself. Changes take
363 effect
364 only when <span><strong class="command">makeuserdb</strong></span> runs.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="userdbcomplex" shape="rect"> </a>Large virtual domain farm</h3></div></div></div><p>
365 The previous approach used a single flat file, <code class="filename">@userdb@</code>.
366 This
367 will work for up to a couple of hundred accounts.
368 An slightly different approach can scale to thousands of
369 domains and mailboxes.</p><p>
370 Instead of creating a <code class="filename">@userdb@</code> file, create a
371 subdirectory:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
372 # mkdir @userdb@
373 # chmod 700 @userdb@
374 </pre></div><p>
375 Now, create <code class="filename">@userdb@/default</code>, containing pw2userdb's
376 output
377 for the vmail account, as previously described.</p><p>
378 This time, you probably want to create all mailboxes for the same domain
379 in a separate subdirectory:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
380 # su - vmail
381 $ cd ~vmail
382 $ mkdir -p domains/example-com
383 $ mkdir domains/example-com/john
384 $ maildirmake domains/example-com/john
385 $ exit
386 </pre></div><p>
387 The idea is that all the maildirs for <code class="literal">@example.com</code> will
388 now be found
389 in <code class="filename">~vmail/domains/example-com</code>. All maildirs for
390 <code class="literal">domain.org</code> will be in
391 <code class="filename">~vmail/domains/domain.org</code>. The actual layout and naming
392 conventions are entirely up to you to define.</p><p>Here's how configure <code class="filename">@userdb@</code>:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
393 $ userdb "example-com/john@example.com" set \
394 home=/home/vmail/domains/example-com/john \
395 uid=UUU gid=GGG</pre></div><p>
396 This creates the file <code class="filename">@userdb@/example-com</code> (the first
397 parameter to the <span><strong class="command">userdb</strong></span> command), and appends a record named
398 "john@example.com". You will store all <code class="literal">userdb</code> entries for
399 <code class="literal">@example.com</code> in the file
400 <code class="filename">@userdb@/example-com</code>. All
401 entries for <code class="literal">@domain.org</code> will be maintained in
402 <code class="filename">@userdb@/domain-org</code>, and so on.</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
403 $ userdbpw | userdb "example-com/john@example.com" set imappw
404 </pre></div><p>
405 This sets the IMAP access password for this account. Finally:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
406 $ makeuserdb
407 </pre></div></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="moreuserdb" shape="rect"> </a>Beyond <code class="literal">userdb</code></h3></div></div></div><p>
408 <code class="literal">userdb</code> is a simple, straightforward solution that scales
409 to a couple of thousand of mail accounts, depending on the hardware.
410 Beyond that, one of database-based modules will need to be used,
411 such as
412 <code class="literal">authldap</code>,
413 <code class="literal">authmysql</code>,
414 <code class="literal">authpgsql</code>.
415 Since <code class="literal">userdb</code> is maintained as plain text files that
416 are easily parsed by a script, migrating data from userdb will not be
417 difficult.</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authvchkpw" shape="rect"> </a>The <code class="literal">authvchkpw</code> authentication module</h2></div></div></div><p>
418 This module uses
419 the <code class="literal">vpopmail/vchkpw</code> library for authentication.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authmysql" shape="rect"> </a>The <code class="literal">authmysql</code> authentication module</h2></div></div></div><p>
420 This module reads
421 the list of mail accounts and passwords from a table in a
422 MySQL database.
423 The <code class="filename">@authmysqlrc@</code> configuration file defines the
424 particular details regarding the MySQL database and the schema of the
425 mail account table.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authpgsql" shape="rect"> </a>The <code class="literal">authpgsql</code> authentication module</h2></div></div></div><p>
426 This module reads
427 the list of mail accounts and passwords from a table in a
428 PostgreSQL database.
429 The <code class="filename">@authpgsqlrc@</code> configuration file defines the
430 particular details regarding the PostgreSQL database and the schema of the
431 mail account table.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authldap" shape="rect"> </a>The <code class="literal">authldap</code> authentication module</h2></div></div></div><p>
432 This module reads
433 the list of mail accounts and passwords from an LDAP directory.
434 The <code class="filename">@authldaprc@</code> configuration file defines the
435 particular details regarding the LDAP directory layout.</p><p>
436 A suggested LDAP schema can be found in the file
437 <code class="filename">authldap.schema</code>,
438 which is included in Courier authentication library's source code, and
439 may be installed on your system.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authcustom" shape="rect"> </a><code class="literal">authcustom</code></h2></div></div></div><p>
440 This is a do-nothing module where custom authentication code
441 can be added.
442 This authentication module is just a stub that doesn't really do anything.
443 It's purpose is to serve as a placeholder where custom authentication code
444 can be easily implement.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="options" shape="rect"> </a>Account options</h2></div></div></div><p>
445 The authentication library has a facility for keep arbitrary
446<span class="quote">name=value</span>”-type settings,
447 called “<span class="quote">options</span>”, for individual accounts. This feature is
448 only available with
449 <code class="literal">userdb</code>,
450 <code class="literal">LDAP</code>, <code class="literal">MySQL</code>, and
451 <code class="literal">PostgresSQL</code>
452 modules. Individual account options are not supported with
453 system-based authentication modules (password/shadow files, or PAM).</p><p>
454 See the
455 <a href="auth_generic.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">auth_generic</span>(3)</span></a>
456 for a description of option names used by various Courier packages.
457 Other applications can make up names for their own settings, and
458 use them in the same way.</p><p>
459 Account options are specified via the authentication modules in the
460 following manner:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">userdb</code></span></dt><dd><p>
461 Use the <span><strong class="command">userdb</strong></span> command to set a field called
462 "<code class="literal">options</code>". Example:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
463 userdb user1@example.com set options=disableimap=1,sharedgroup=44
464 makeuserdb
465 </pre></div><p>
466 The option text string here is
467 "<code class="literal">disableimap=1,sharedgroup=44</code>".
468 It specifies two options.</p></dd><dt><span class="term"><code class="literal">LDAP</code></span></dt><dd><p>
469 Account options are defined by the <code class="literal">LDAP_AUXOPTIONS</code>
470 setting in the <code class="filename">authldaprc</code> configuration file.
471 <code class="literal">LDAP_AUXOPTIONS</code> consists of a comma-separated list of
472 "<code class="literal">attribute=setting</code>". "attribute" is the name of an LDAP
473 attribute, and "setting" is the corresponding account setting name. The
474 value of the attribute becomes the value of the setting. Unless you
475 value your sanity, the names of LDAP attributes should be the same as
476 the actual setting names (in which case "=setting" may be dropped and
477 <code class="literal">LDAP_AUXOPTIONS</code> becomes a simple comma-separated list of
478 supported settings), but they don't have to be.</p><p>
479 <code class="literal">LDAP_AUXOPTIONS</code> is nothing more than a simple mapping
480 of LDAP attributes to account settings. A <code class="literal">LDAP_AUXOPTIONS</code>
481 of "shared=sharedgroup,disableimap" means that the LDAP attribute
482 called "shared" contains the "sharedgroup" setting, as described
483 previously; and an LDAP attribute of disableimap contains the setting
484 of the same name.</p></dd><dt><span class="term"><span class="application">MySQL</span>, and <span class="application">PostgreSQL</span></span></dt><dd><p>
485 Account options are defined by <code class="literal">MYSQL_AUXOPTIONS_FIELD</code>
486 or <code class="literal">POSTGRESQL_AUXOPTIONS_FIELD</code>, in its corresponding
487 configuration file. In the most simplest case, add a character field to
488 the database, and put the field name into the
489 <code class="literal">MYSQL_AUXOPTIONS_FIELD</code> or
490 <code class="literal">POSTGRESQL_AUXOPTIONS_FIELD</code> configuration file setting.
491 For each account, the character field should contain the literal option
492 string. Yes, you'll just put "shared=sharedgroup,disableimap"
493 literally, in that field.</p><p>
494 Fortunately, there is a cleaner way to do this, which avoid driving
495 a database designer batty. Keep in mind that the contents of
496 <code class="literal">MYSQL_AUXOPTIONS_FIELD</code>/<code class="literal">POSTGRESQL_AUXOPTIONS_FIELD</code>
497 are simply inserted directly into the SQL query that fetches the
498 account information. Both MySQL and PostgreSQL have a rich SQL that can
499 be used to manufacture a suitable option string from plain,
500 garden-variety, database fields. That is, you may define individual
501 table fields like "disableimap", and "disablepop3", then provide a
502 suitable (albeit ugly) SQL fragment that combines them together into
503 the expected option string. An example of such an SQL string is
504 provided in the comments portion of the configuration file.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
505 When using the alternative custom query option, the option string
506 is the last field that the custom SQL query should return.</p></div></dd></dl></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="authtest" shape="rect"> </a>Running <span><strong class="command">authtest</strong></span></h2></div></div></div><p>
507 The <span><strong class="command">authtest</strong></span> command may be used to verify that the
508 authentication library is working:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
509 authtest userid
510 authtest userid password
511 authtest userid password newpassword
512 authenumerate</pre></div><p>
513 Running
514 <span><strong class="command">authtest</strong></span>
515 with one argument should display the selected account's
516 home directory, userid, groupid,
517 and other related data.
518 The second argument to
519 <span><strong class="command">authtest</strong></span>,
520 if supplied, specifies the account's password.
521 The two argument form of
522 <span><strong class="command">authtest</strong></span>
523 validates the password, and displays an indication whether the given
524 password is valid, or not.
525 The three argument form of the
526 <span><strong class="command">authtest</strong></span>
527 command attemps to change the account's password.
528 The second argument is the old password, the third argument is the
529 new password.</p><p>
530 See <a href="README.authdebug.html" target="_top" shape="rect"><code class="filename">README.authdebug.html</code></a> for more information.</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="pwchange" shape="rect"> </a>Changing account passwords</h3></div></div></div><p>For the virtual domain modules (<code class="literal">authldap</code>,
531 <code class="literal">authmysql</code>, <code class="literal">authpgsql</code> and friends) changing the
532 login is a no-brainer. The tricky situation is when SqWebMail uses system
533 passwords to log in (the <code class="literal">authpwd</code>, <code class="literal">authshadow</code>, or
534 <code class="literal">authpam</code> authentication module). Different systems use different
535 ways to keep login passwords. Many systems use the traditional
536 <code class="filename">/etc/passwd</code> and <code class="filename">/etc/shadow</code> files. Other systems
537 use a binary database; other systems use NIS. And on some systems the
538 password file lookup library is a wrapper that goes against an external LDAP
539 directory, or a database. For maximum compatibility, SqWebMail changes login
540 passwords by running the <span><strong class="command">passwd</strong></span> command. This is the traditinal
541 *nix command that changes login passwords. <span><strong class="command">passwd</strong></span> is an
542 interactive command. It's normally run from a terminal.
543 SqWebMail uses an
544 <span><strong class="command">expect</strong></span> script - as mentioned in
545 the introduction - to answer interactive
546 prompts from <span><strong class="command">passwd</strong></span>. The <span><strong class="command">expect</strong></span> script expects to
547 get a plain, garden-variety, <span><strong class="command">passwd</strong></span> command, which acts
548 something like this:</p><div class="informalexample"><pre class="programlisting" xml:space="preserve">
549 # passwd
550 Changing password for luser
551 (current) UNIX password: (old password typed here)
552 New UNIX password: (new password typed here)
553 Retype new UNIX password: (new password retyped here)
554 passwd: all authentication tokens updated successfully
555 #
556 </pre></div><p>
557 Systems that use a <span><strong class="command">passwd</strong></span> command with very different prompts
558 may find that the default <span><strong class="command">expect</strong></span> script will fail. In which case
559 it will be necessary to tweak the <span><strong class="command">expect</strong></span> script to match the
560 prompts from the system's <span><strong class="command">passwd</strong></span> command.</p><p>
561 Modern systems use a <span><strong class="command">passwd</strong></span> command that rejects "bad"
562 passwords - passwords that are based on dictionary words, are too short, or
563 are obvious for other reasons. When testing the ability to change
564 system passwords be sure to use randomly-generated gibberish for the test
565 passwords. Otherwise, the default <span><strong class="command">expect</strong></span> script will
566 actually be
567 working, but you won't be the wiser. For security reasons, the actual
568 messages from <span><strong class="command">passwd</strong></span> will not be shown by.</p><p>
569 The <span><strong class="command">expect</strong></span> script is installed as
570 <code class="filename">/usr/local/libexec/courier-authlib/authsystem.passwd</code>
571 (assuming default options to the <span><strong class="command">configure</strong></span> script).</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="internals" shape="rect"> </a>Authentication internals</h2></div></div></div><p>
572 The following structure describes an authentication module:</p><div class="blockquote"><blockquote class="blockquote"><div class="example"><a id="authstaticinfo" shape="rect"> </a><p class="title"><b>Example 1. struct authstaticinfo</b></p><div class="example-contents"><pre class="programlisting" xml:space="preserve">
573 struct authstaticinfo {
574 const char *auth_name;
575 int (*auth_func)(const char *, const char *, char *, int,
576 int (*)(struct authinfo *, void *),
577 void *);
578 int (*auth_prefunc)(const char *, const char *,
579 int (*)(struct authinfo *, void *),
580 void *);
581 void (*auth_cleanupfunc)();
582 int (*auth_changepwd)(const char *, /* service */
583 const char *, /* userid */
584 const char *, /* oldpassword */
585 const char *); /* new password */
586
587 void (*auth_idle)();
588 /* Not null - gets called every 5 mins when we're idle */
589
590 void (*auth_enumerate)( void(*cb_func)(const char *name,
591 uid_t uid,
592 gid_t gid,
593 const char *homedir,
594 const char *maildir,
595 void *void_arg),
596 void *void_arg);
597 } ;
598 </pre></div></div><br class="example-break" clear="none"/></blockquote></div><p>
599 An authentication module is a shared library that defines a single function
600 called
601<span class="quote">courier_auth_<em class="replaceable"><code>NAME</code></em>_init</span>”, where
602<span class="quote">NAME</span>” is the name of the authentication module.
603 The shared library does not need to export any other symbols, this is the
604 only function that needs to be exported.
605 The function returns a pointer to the <span class="structname">authstaticinfo</span>
606 structure.
607 For example, the relevant code from the <code class="literal">authmysql</code> module is:
608 </p><div class="blockquote"><blockquote class="blockquote"><div class="example"><a id="authmysqlex" shape="rect"> </a><p class="title"><b>Example 2. authmysql</b></p><div class="example-contents"><pre class="programlisting" xml:space="preserve">
609 static struct authstaticinfo authmysql_info={
610 "authmysql",
611 auth_mysql,
612 auth_mysql_pre,
613 auth_mysql_cleanup,
614 auth_mysql_changepw,
615 auth_mysql_cleanup,
616 auth_mysql_enumerate};
617
618
619 struct authstaticinfo *courier_authmysql_init()
620 {
621 return &amp;authmysql_info;
622 }
623 </pre></div></div><br class="example-break" clear="none"/></blockquote></div><p>
624 <code class="function">auth_func</code> points to a function that handles an
625 authentication request. The function is invoked as follows:</p><div class="blockquote"><blockquote class="blockquote"><div class="example"><a id="auth_func" shape="rect"> </a><p class="title"><b>Example 3. auth_func</b></p><div class="example-contents"><pre class="programlisting" xml:space="preserve">
626 int result=auth_func(const char *service, const char *authtype,
627 const char *authdata,
628 int (*callback_func)(struct authinfo *, void *),
629 void *callback_arg);
630 </pre></div></div><br class="example-break" clear="none"/></blockquote></div><p>
631<span class="quote">service</span>” is the name of the service being authenticated,
632 such as “<span class="quote"><code class="literal">imap</code></span>” or
633<span class="quote"><code class="literal">pop3</code></span>”.
634<span class="quote">authtype</span>” defines the authentication format,
635 and “<span class="quote">authdata</span>” is the actual authentication request.</p><p>
636 Two authentication formats are defined at this time.
637 The “<span class="quote">authtype</span>” string is set to one of the following
638 strings:</p><div class="variablelist"><dl><dt><span class="term"><span class="quote">login</span></span></dt><dd><p>
639 Tradition userid/password authentication.
640 <code class="literal">authdata</code> points to a string that consists of:
641 the userid; a newline character; the password; a final newline
642 character.</p></dd><dt><span class="term"><span class="quote">cram-md5</span>”, or “<span class="quote">cram-sha1</span></span></dt><dd><p>
643 Challenge/response authentication.
644 <code class="literal">authdata</code> points to a string that consists of:
645 the base64-encoded challenge; a newline character;
646 the base64-encoded response string; and a final newline
647 character. Furthermore, the base64-encoded response string consists of:
648 the login ID, a space character, and the response as a hexadecimal
649 string (yes, base64-encoding of the response string is not strictly
650 necessary).</p></dd></dl></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
651 Not all authentication modules may implement all authentication formats.
652 An authentication module that does not implement a particular authentication
653 format should handle it the same way as an invalid login ID.</p></div><p>
654 The authentication function should return a negative value if the login ID
655 is invalid. The authentication library will try the next authentication
656 module.</p><p>
657 The authentication function should return a positive value if the login ID
658 is valid, but the password is invalid. The authentication library will not
659 try any more authentication modules.</p><p>
660 Otherwise, the authentication module should call the
661 <code class="function">callback_func</code> function, and return the same value that's
662 returned by this function.</p><p>
663 The authentication module should pass through <code class="literal">callback_arg</code>
664 to the callback function as a second argument.
665 The first argument is a pointer to the
666 <span class="structname">authinfo</span> structure, which is described in detail
667 in the
668 <a href="auth_generic.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">auth_generic</span>(3)</span></a>
669 manual page.
670 The authentication module is responsible for allocating this structure.
671 After the callback function returns this structure can be deallocated.
672 The authentication module initializes the following fields:</p><p>
673 <code class="function">auth_pre_func</code> points to a function that obtains
674 account information. The function is invoked as follows:</p><div class="blockquote"><blockquote class="blockquote"><div class="example"><a id="auth_pre_func" shape="rect"> </a><p class="title"><b>Example 4. auth_pre_func</b></p><div class="example-contents"><pre class="programlisting" xml:space="preserve">
675 int auth_pre_func(const char *user, const char *service,
676 int (*callback)(struct authinfo *, void *), void *arg);
677 </pre></div></div><br class="example-break" clear="none"/></blockquote></div><p>
678 This function does the same thing as “<span class="quote">auth_func</span>” except that
679 the password is not actually verified.
680 If the account exists, the callback function is invoked with the
681 same callback arguments.</p><p>
682 <code class="function">auth_cleanup_func</code> points to a function that will be
683 invoked just before the authentication module is uninstalled, giving it
684 the opportunity for some last-minute cleanup.</p><p>
685 <code class="function">auth_idle</code> points to a function that will be
686 invoked when no authentication requests are received for a couple of minutes,
687 giving the authentication module an opportunity to close any database
688 connections, so that they do not get shut down by the server, for inactivity,
689 resulting in an error the next time an authentication request is
690 received.</p><p>
691 <code class="function">auth_changepwd</code> points to a function that will be
692 invoked to change a password on an account, as follows.</p><div class="blockquote"><blockquote class="blockquote"><div class="example"><a id="auth_changepwd" shape="rect"> </a><p class="title"><b>Example 5. auth_changepwd</b></p><div class="example-contents"><pre class="programlisting" xml:space="preserve">
693 int auth_changepwd(const char *service, const char *user,
694 const char *oldpw, const char *newpw);
695 </pre></div></div><br class="example-break" clear="none"/></blockquote></div><p>
696 <code class="literal">service</code> is the name of the service whose password is to
697 be changed (such as “<span class="quote">imap</span>” or “<span class="quote">pop3</span>”).
698 <code class="function">auth_changepwd</code> should return 0 if the password was
699 changed succesfully, a negative value if <code class="literal">user</code> is invalid
700 (the next authentication module will be tried), or a positive value if
701 the password change request failed (no more modules will be tried).</p><p>
702 <code class="function">auth_enumerate</code> points to a function that enumerates
703 the list of all login IDs known to the authentication module.
704 The first argument <code class="function">auth_enumerate</code> is a callback
705 function. <code class="function">auth_enumerate</code> invokes the callback
706 function once for each login ID, supplying the login ID, the userid,
707 groupid, home directory and maildir as arguments.
708 The last argument to the callback function is passed through from the
709 second argument to <code class="function">auth_enumerate</code>.</p><p>
710 After enumerating all login IDs <code class="function">auth_enumerate</code> calls
711 the callback function one last time, with a NULL pointer for the login ID,
712 then returns. If an error is encountered while enumerating the login IDs,
713 <code class="function">auth_enumerate</code> terminates without invoking
714 the callback function with a NULL login ID.</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="files" shape="rect"> </a>FILES</h2></div></div></div><p>
715 <code class="filename"> @authdaemonrc@</code> - <span><strong class="command">authdaemond</strong></span> configuration file</p><p>
716 <code class="filename"> @authldaprc@</code> - <span><strong class="command">authldap</strong></span> configuration file</p><p>
717 <code class="filename"> @authmysqlrc@</code> - <span><strong class="command">authmysql</strong></span> configuration file</p><p>
718 <code class="filename"> @authpgsqlrc@</code> - <span><strong class="command">authpgsql</strong></span> configuration file</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="seealso" shape="rect"> </a>SEE ALSO</h2></div></div></div><p>
719 <a href="courier.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">courier</span>(8)</span></a>,
720
721 <a href="userdb.html" target="_top" shape="rect"><span class="citerefentry"><span class="refentrytitle">userdb</span>(8)</span></a></p></div></div></body></html>