Print this page
Remove include userdefs.h where not needed
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/pam_modules/unix_auth/unix_auth.c
+++ new/usr/src/lib/pam_modules/unix_auth/unix_auth.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
27 27 #include <stdlib.h>
28 28 #include <pwd.h>
29 29 #include <shadow.h>
30 30 #include <syslog.h>
31 31 #include <errno.h>
32 32 #include <string.h>
33 33 #include <crypt.h>
34 34 #include <unistd.h>
35 35 #include <user_attr.h>
36 36 #include <auth_attr.h>
37 -#include <userdefs.h>
38 37 #include <deflt.h>
39 38 #include <sys/stat.h>
40 39 #include <sys/param.h>
41 40 #include <stdarg.h>
42 41
43 42 #include <security/pam_appl.h>
44 43 #include <security/pam_modules.h>
45 44 #include <security/pam_impl.h>
46 45
47 46 #include <libintl.h>
48 47
49 48 #include <passwdutil.h>
50 49
51 50 #define LOGINADMIN "/etc/default/login"
52 51 #define MAXTRYS 5
53 52
54 53 /*PRINTFLIKE2*/
55 54 void
56 55 error(pam_handle_t *pamh, char *fmt, ...)
57 56 {
58 57 va_list ap;
59 58 char messages[1][PAM_MAX_MSG_SIZE];
60 59
61 60 va_start(ap, fmt);
62 61 (void) vsnprintf(messages[0], sizeof (messages[0]), fmt, ap);
63 62 (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1, messages, NULL);
64 63 va_end(ap);
65 64 }
66 65
67 66 static int
68 67 get_max_failed(char *user)
69 68 {
70 69 char *val = NULL;
71 70 userattr_t *uattr;
72 71 int do_lock = 0;
73 72 int retval = 0;
74 73 char *p;
75 74 void *defp;
76 75
77 76 if ((uattr = getusernam(user)) != NULL)
78 77 val = kva_match(uattr->attr, USERATTR_LOCK_AFTER_RETRIES_KW);
79 78
80 79 if (val != NULL) {
81 80 do_lock = (strcasecmp(val, "yes") == 0);
82 81 } else if ((defp = defopen_r(AUTH_POLICY)) != NULL) {
83 82 int flags;
84 83 flags = defcntl_r(DC_GETFLAGS, 0, defp);
85 84 TURNOFF(flags, DC_CASE);
86 85 (void) defcntl_r(DC_SETFLAGS, flags, defp);
87 86 if ((p = defread_r("LOCK_AFTER_RETRIES=", defp)) != NULL)
88 87 do_lock = (strcasecmp(p, "yes") == 0);
89 88 defclose_r(defp);
90 89 }
91 90
92 91 if (uattr != NULL)
93 92 free_userattr(uattr);
94 93
95 94 if (do_lock) {
96 95 retval = MAXTRYS;
97 96 if ((defp = defopen_r(LOGINADMIN)) != NULL) {
98 97 if ((p = defread_r("RETRIES=", defp)) != NULL)
99 98 retval = atoi(p);
100 99 defclose_r(defp);
101 100 }
102 101 }
103 102
104 103 return (retval);
105 104 }
106 105
107 106 static void
108 107 display_warning(pam_handle_t *pamh, int failures, char *homedir)
109 108 {
110 109 char hushpath[MAXPATHLEN];
111 110 struct stat buf;
112 111
113 112 (void) snprintf(hushpath, sizeof (hushpath), "%s/.hushlogin", homedir);
114 113 if (stat(hushpath, &buf) == 0)
115 114 return;
116 115
117 116 if (failures == 1)
118 117 error(pamh, "Warning: 1 failed login attempt since last "
119 118 "successful login.");
120 119 else if (failures < FAILCOUNT_MASK)
121 120 error(pamh, "Warning: %d failed login attempts since last "
122 121 "successful login.", failures);
123 122 else
124 123 error(pamh, "Warning: at least %d failed login attempts since "
125 124 "last successful login.", failures);
126 125 }
127 126
128 127 /*
129 128 * int pam_sm_authenticate(pamh, flags, arc, argv)
130 129 *
131 130 * This routine verifies that the password as stored in the
132 131 * PAM_AUTHTOK item is indeed the password that belongs to the user
133 132 * as stored in PAM_USER.
134 133 *
135 134 * This routine will not establish Secure RPC Credentials, the pam_dhkeys
136 135 * module should be stacked before us if Secure RPC Credentials are needed
137 136 * to obtain passwords.
138 137 */
139 138 int
140 139 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
141 140 {
142 141 int i;
143 142 int debug = 0;
144 143 int nowarn = (flags & PAM_SILENT) != 0;
145 144 char *user;
146 145 char *passwd;
147 146 char *rep_passwd;
148 147 char *crypt_passwd;
149 148 char *repository_name;
150 149 struct pam_repository *auth_rep;
151 150 pwu_repository_t *pwu_rep;
152 151 attrlist attr_pw[4];
153 152 int result;
154 153 int server_policy = 0;
155 154 int old_failed_count;
156 155 char *homedir = NULL;
157 156 int dolock = 1;
158 157
159 158 for (i = 0; i < argc; i++) {
160 159 if (strcmp(argv[i], "debug") == 0)
161 160 debug = 1;
162 161 else if (strcmp(argv[i], "nowarn") == 0)
163 162 nowarn = 1;
164 163 else if (strcmp(argv[i], "server_policy") == 0)
165 164 server_policy = 1;
166 165 else if (strcmp(argv[i], "nolock") == 0)
167 166 dolock = 0;
168 167 }
169 168
170 169 if (debug)
171 170 __pam_log(LOG_AUTH | LOG_DEBUG,
172 171 "pam_unix_auth: entering pam_sm_authenticate()");
173 172
174 173 if (pam_get_item(pamh, PAM_USER, (void **)&user) != PAM_SUCCESS) {
175 174 __pam_log(LOG_AUTH | LOG_DEBUG, "pam_unix_auth: USER not set");
176 175 return (PAM_SYSTEM_ERR);
177 176 }
178 177
179 178 if (user == NULL || *user == '\0') {
180 179 __pam_log(LOG_AUTH | LOG_DEBUG,
181 180 "pam_unix_auth: USER NULL or empty!\n");
182 181 return (PAM_USER_UNKNOWN);
183 182 }
184 183
185 184 if (pam_get_item(pamh, PAM_AUTHTOK, (void **)&passwd) != PAM_SUCCESS) {
186 185 __pam_log(LOG_AUTH | LOG_DEBUG,
187 186 "pam_unix_auth: AUTHTOK not set!\n");
188 187 return (PAM_SYSTEM_ERR);
189 188 }
190 189
191 190 result = pam_get_item(pamh, PAM_REPOSITORY, (void **)&auth_rep);
192 191 if (result == PAM_SUCCESS && auth_rep != NULL) {
193 192 if ((pwu_rep = calloc(1, sizeof (*pwu_rep))) == NULL)
194 193 return (PAM_BUF_ERR);
195 194 pwu_rep->type = auth_rep->type;
196 195 pwu_rep->scope = auth_rep->scope;
197 196 pwu_rep->scope_len = auth_rep->scope_len;
198 197 } else {
199 198 pwu_rep = PWU_DEFAULT_REP;
200 199 }
201 200
202 201 /*
203 202 * Get password and the name of the repository where the
204 203 * password resides.
205 204 */
206 205 attr_pw[0].type = ATTR_PASSWD; attr_pw[0].next = &attr_pw[1];
207 206 attr_pw[1].type = ATTR_REP_NAME; attr_pw[1].next = &attr_pw[2];
208 207 /*
209 208 * Also get the current number of failed logins; we use
210 209 * this later to determine whether we need to reset the count
211 210 * on a succesful authentication. We use the home-directory
212 211 * to look for .hushlogin in order to optionaly surpress the
213 212 * "failed attempts" message.
214 213 */
215 214 attr_pw[2].type = ATTR_FAILED_LOGINS; attr_pw[2].next = &attr_pw[3];
216 215 attr_pw[3].type = ATTR_HOMEDIR; attr_pw[3].next = NULL;
217 216
218 217 result = __get_authtoken_attr(user, pwu_rep, attr_pw);
219 218
220 219 if (pwu_rep != PWU_DEFAULT_REP)
221 220 free(pwu_rep);
222 221
223 222 if (result == PWU_NOT_FOUND) {
224 223 __pam_log(LOG_AUTH | LOG_DEBUG,
225 224 "pam_unix_auth: user %s not found\n", user);
226 225 return (PAM_USER_UNKNOWN);
227 226 }
228 227
229 228 if (result == PWU_DENIED) {
230 229 __pam_log(LOG_AUTH | LOG_DEBUG,
231 230 "pam_unix_auth: failed to obtain attributes");
232 231 return (PAM_PERM_DENIED);
233 232 }
234 233
235 234 if (result != PWU_SUCCESS)
236 235 return (PAM_SYSTEM_ERR);
237 236
238 237 rep_passwd = attr_pw[0].data.val_s;
239 238 repository_name = attr_pw[1].data.val_s;
240 239 old_failed_count = attr_pw[2].data.val_i;
241 240 homedir = attr_pw[3].data.val_s;
242 241
243 242 /*
244 243 * Chop off old SunOS-style password aging information.
245 244 *
246 245 * Note: old style password aging is only defined for UNIX-style
247 246 * crypt strings, hence the comma will always be at position 14.
248 247 * Note: This code is here because some other vendors might still
249 248 * support this style of password aging. If we don't remove
250 249 * the age field, no one will be able to login.
251 250 * XXX yank this code when we're certain this "compatibility"
252 251 * isn't needed anymore.
253 252 */
254 253 if (rep_passwd != NULL && rep_passwd[0] != '$' &&
255 254 strlen(rep_passwd) > 13 && rep_passwd[13] == ',')
256 255 rep_passwd[13] = '\0';
257 256
258 257 /* Is a password check required? */
259 258 if (rep_passwd == NULL || *rep_passwd == '\0') {
260 259 if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
261 260 result = PAM_AUTH_ERR;
262 261 __pam_log(LOG_AUTH | LOG_NOTICE,
263 262 "pam_unix_auth: empty password for %s not allowed.",
264 263 user);
265 264 goto out;
266 265 } else {
267 266 result = PAM_SUCCESS;
268 267 goto out;
269 268 }
270 269 }
271 270
272 271 /*
273 272 * Password check *is* required. Make sure we have a valid
274 273 * pointer in PAM_AUTHTOK
275 274 */
276 275 if (passwd == NULL) {
277 276 result = PAM_AUTH_ERR;
278 277 goto out;
279 278 }
280 279
281 280 if (server_policy &&
282 281 strcmp(repository_name, "files") != 0 &&
283 282 strcmp(repository_name, "nis") != 0) {
284 283 result = PAM_IGNORE;
285 284 goto out;
286 285 }
287 286
288 287 /* Now check the entered password */
289 288 if ((crypt_passwd = crypt(passwd, rep_passwd)) == NULL) {
290 289 switch (errno) {
291 290 case ENOMEM:
292 291 result = PAM_BUF_ERR;
293 292 break;
294 293 case ELIBACC:
295 294 result = PAM_OPEN_ERR;
296 295 break;
297 296 default:
298 297 result = PAM_SYSTEM_ERR;
299 298 }
300 299 goto out;
301 300 }
302 301
303 302 if (strcmp(crypt_passwd, rep_passwd) == 0)
304 303 result = PAM_SUCCESS;
305 304 else
306 305 result = PAM_AUTH_ERR;
307 306
308 307 /* Clear or increment failed failed count */
309 308 if (dolock && (result == PAM_SUCCESS && old_failed_count > 0)) {
310 309 old_failed_count = __rst_failed_count(user, repository_name);
311 310 if (nowarn == 0 && old_failed_count > 0)
312 311 display_warning(pamh, old_failed_count, homedir);
313 312 } else if (dolock && result == PAM_AUTH_ERR) {
314 313 int max_failed = get_max_failed(user);
315 314 if (max_failed != 0) {
316 315 if (__incr_failed_count(user, repository_name,
317 316 max_failed) == PWU_ACCOUNT_LOCKED)
318 317 result = PAM_MAXTRIES;
319 318 }
320 319 }
321 320 out:
322 321 if (rep_passwd)
323 322 free(rep_passwd);
324 323 if (repository_name)
325 324 free(repository_name);
326 325 if (homedir)
327 326 free(homedir);
328 327 return (result);
329 328 }
330 329
331 330 /*ARGSUSED*/
332 331 int
333 332 pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
334 333 {
335 334 return (PAM_IGNORE);
336 335 }
↓ open down ↓ |
289 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX