1 /*
2 * pam_faildelay module
3 *
4 * Allows an admin to set the delay on failure per-application.
5 * Provides "auth" interface only.
6 *
7 * Use by putting something like this in the relevant pam config:
8 * auth required pam_faildelay.so delay=[microseconds]
9 *
10 * eg:
11 * auth required pam_faildelay.so delay=10000000
12 * will set the delay on failure to 10 seconds.
13 *
14 * If no delay option was given, pam_faildelay.so will use the
15 * FAIL_DELAY value of /etc/login.defs.
16 *
17 * Based on pam_rootok and parts of pam_unix both by Andrew Morgan
18 * <morgan@linux.kernel.org>
19 *
20 * Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de>
21 * - Rewrite to use extended PAM functions
22 * - Add /etc/login.defs support
23 *
24 * Portions Copyright (c) 2005 Darren Tucker <dtucker at zip com au>.
25 *
26 * Redistribution and use in source and binary forms of, with
27 * or without modification, are permitted provided that the following
28 * conditions are met:
29 *
30 * 1. Redistributions of source code must retain any existing copyright
31 * notice, and this entire permission notice in its entirety,
32 * including the disclaimer of warranties.
33 *
34 * 2. Redistributions in binary form must reproduce all prior and current
35 * copyright notices, this list of conditions, and the following
36 * disclaimer in the documentation and/or other materials provided
37 * with the distribution.
38 *
39 * 3. The name of any author may not be used to endorse or promote
40 * products derived from this software without their specific prior
41 * written permission.
42 *
43 * ALTERNATIVELY, this product may be distributed under the terms of the
44 * GNU General Public License, in which case the provisions of the GNU
45 * GPL are required INSTEAD OF the above restrictions. (This clause is
46 * necessary due to a potential conflict between the GNU GPL and the
47 * restrictions contained in a BSD-style copyright.)
48 *
49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
54 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
55 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
56 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
57 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
58 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 * DAMAGE.
60 */
61
62 #include "config.h"
63
64 #include <errno.h>
65 #include <ctype.h>
66 #include <stdio.h>
67 #include <limits.h>
68 #include <unistd.h>
69 #include <syslog.h>
70 #include <string.h>
71 #include <stdlib.h>
72
73 #include <security/pam_modules.h>
74 #include <security/pam_ext.h>
75 #include <security/pam_modutil.h>
76
77 #define LOGIN_DEFS "/etc/login.defs"
78
79 /* --- authentication management functions (only) --- */
80
81 int pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
82 int argc, const char **argv)
83 {
84 int i, debug_flag = 0;
85 long int delay = -1;
86
87 /* step through arguments */
88 for (i = 0; i < argc; i++) {
89 if (sscanf(argv[i], "delay=%ld", &delay) == 1) {
90 /* sscanf did already everything necessary */
91 } else if (strcmp (argv[i], "debug") == 0)
92 debug_flag = 1;
93 else
94 pam_syslog (pamh, LOG_ERR, "unknown option; %s", argv[i]);
95 }
96
97 if (delay == -1)
98 {
99 char *endptr;
100 char *val = pam_modutil_search_key (pamh, LOGIN_DEFS, "FAIL_DELAY");
101 const char *val_orig = val;
102
103 if (val == NULL)
104 return PAM_IGNORE;
105
106 errno = 0;
107 delay = strtol (val, &endptr, 10) & 0777;
108 if (((delay == 0) && (val_orig == endptr)) ||
109 ((delay == LONG_MIN || delay == LONG_MAX) && (errno == ERANGE)))
110 {
111 pam_syslog (pamh, LOG_ERR, "FAIL_DELAY=%s in %s not valid",
112 val, LOGIN_DEFS);
113 free (val);
114 return PAM_IGNORE;
115 }
116
117 free (val);
118 /* delay is in seconds, convert to microseconds. */
119 delay *= 1000000;
120 }
121
122 if (debug_flag)
123 pam_syslog (pamh, LOG_DEBUG, "setting fail delay to %ld", delay);
124
125 i = pam_fail_delay(pamh, delay);
126 if (i == PAM_SUCCESS)
127 return PAM_IGNORE;
128 else
129 return i;
130 }
131
132 int pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
133 int argc UNUSED, const char **argv UNUSED)
134 {
135 return PAM_IGNORE;
136 }
137
138 /* end of module definition */