1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Bartlett 2001
5 Copyright (C) Jeremy Allison 2001
6 Copyright (C) Simo Sorce 2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "system/passwd.h" /* needed by some systems for struct passwd */
26 #include "lib/socket/socket.h"
27 #include "auth/pam_errors.h"
28
29 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
30 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
31 */
authunix_make_server_info(TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info,struct passwd * pwd,struct auth_serversupplied_info ** _server_info)32 static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx,
33 const struct auth_usersupplied_info *user_info,
34 struct passwd *pwd,
35 struct auth_serversupplied_info **_server_info)
36 {
37 struct auth_serversupplied_info *server_info;
38 NTSTATUS status;
39
40 /* This is a real, real hack */
41 if (pwd->pw_uid == 0) {
42 status = auth_system_server_info(mem_ctx, &server_info);
43 if (!NT_STATUS_IS_OK(status)) {
44 return status;
45 }
46
47 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
48 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
49
50 server_info->domain_name = talloc_strdup(server_info, "unix");
51 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
52 } else {
53 server_info = talloc(mem_ctx, struct auth_serversupplied_info);
54 NT_STATUS_HAVE_NO_MEMORY(server_info);
55
56 server_info->authenticated = True;
57
58 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
59 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
60
61 server_info->domain_name = talloc_strdup(server_info, "unix");
62 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
63
64 /* This isn't in any way correct.. */
65 server_info->account_sid = NULL;
66 server_info->primary_group_sid = NULL;
67 server_info->n_domain_groups = 0;
68 server_info->domain_groups = NULL;
69 }
70 server_info->user_session_key = data_blob(NULL,0);
71 server_info->lm_session_key = data_blob(NULL,0);
72
73 server_info->full_name = talloc_steal(server_info, pwd->pw_gecos);
74 NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
75 server_info->logon_script = talloc_strdup(server_info, "");
76 NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
77 server_info->profile_path = talloc_strdup(server_info, "");
78 NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
79 server_info->home_directory = talloc_strdup(server_info, "");
80 NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
81 server_info->home_drive = talloc_strdup(server_info, "");
82 NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
83
84 server_info->last_logon = 0;
85 server_info->last_logoff = 0;
86 server_info->acct_expiry = 0;
87 server_info->last_password_change = 0;
88 server_info->allow_password_change = 0;
89 server_info->force_password_change = 0;
90 server_info->logon_count = 0;
91 server_info->bad_password_count = 0;
92 server_info->acct_flags = 0;
93
94 *_server_info = server_info;
95
96 return NT_STATUS_OK;
97 }
98
talloc_getpwnam(TALLOC_CTX * ctx,const char * username,struct passwd ** pws)99 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
100 {
101 struct passwd *ret;
102 struct passwd *from;
103
104 *pws = NULL;
105
106 ret = talloc(ctx, struct passwd);
107 NT_STATUS_HAVE_NO_MEMORY(ret);
108
109 from = getpwnam(username);
110 if (!from) {
111 return NT_STATUS_NO_SUCH_USER;
112 }
113
114 ret->pw_name = talloc_strdup(ctx, from->pw_name);
115 NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
116
117 ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
118 NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
119
120 ret->pw_uid = from->pw_uid;
121 ret->pw_gid = from->pw_gid;
122 ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
123 NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
124
125 ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
126 NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
127
128 ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
129 NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
130
131 *pws = ret;
132
133 return NT_STATUS_OK;
134 }
135
136
137 #ifdef HAVE_SECURITY_PAM_APPL_H
138 #include <security/pam_appl.h>
139
140 struct smb_pam_user_info {
141 const char *account_name;
142 const char *plaintext_password;
143 };
144
145 #define COPY_STRING(s) (s) ? strdup(s) : NULL
146
147 /*
148 * Check user password
149 * Currently it uses PAM only and fails on systems without PAM
150 * Samba3 code located in pass_check.c is to ugly to be used directly it will
151 * need major rework that's why pass_check.c is still there.
152 */
153
smb_pam_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** reply,void * appdata_ptr)154 static int smb_pam_conv(int num_msg, const struct pam_message **msg,
155 struct pam_response **reply, void *appdata_ptr)
156 {
157 struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr;
158 int num;
159
160 if (num_msg <= 0) {
161 *reply = NULL;
162 return PAM_CONV_ERR;
163 }
164
165 /*
166 * Apparantly HPUX has a buggy PAM that doesn't support the
167 * data pointer. Fail if this is the case. JRA.
168 */
169
170 if (info == NULL) {
171 *reply = NULL;
172 return PAM_CONV_ERR;
173 }
174
175 /*
176 * PAM frees memory in reply messages by itself
177 * so use malloc instead of talloc here.
178 */
179 *reply = malloc_array_p(struct pam_response, num_msg);
180 if (*reply == NULL) {
181 return PAM_CONV_ERR;
182 }
183
184 for (num = 0; num < num_msg; num++) {
185 switch (msg[num]->msg_style) {
186 case PAM_PROMPT_ECHO_ON:
187 (*reply)[num].resp_retcode = PAM_SUCCESS;
188 (*reply)[num].resp = COPY_STRING(info->account_name);
189 break;
190
191 case PAM_PROMPT_ECHO_OFF:
192 (*reply)[num].resp_retcode = PAM_SUCCESS;
193 (*reply)[num].resp = COPY_STRING(info->plaintext_password);
194 break;
195
196 case PAM_TEXT_INFO:
197 (*reply)[num].resp_retcode = PAM_SUCCESS;
198 (*reply)[num].resp = NULL;
199 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
200 break;
201
202 case PAM_ERROR_MSG:
203 (*reply)[num].resp_retcode = PAM_SUCCESS;
204 (*reply)[num].resp = NULL;
205 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg)));
206 break;
207
208 default:
209 while (num > 0) {
210 SAFE_FREE((*reply)[num-1].resp);
211 num--;
212 }
213 SAFE_FREE(*reply);
214 *reply = NULL;
215 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
216 return PAM_CONV_ERR;
217 }
218 }
219
220 return PAM_SUCCESS;
221 }
222
223 /*
224 * Start PAM authentication for specified account
225 */
226
smb_pam_start(pam_handle_t ** pamh,const char * account_name,const char * remote_host,struct pam_conv * pconv)227 static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
228 {
229 int pam_error;
230
231 if (account_name == NULL || remote_host == NULL) {
232 return NT_STATUS_INVALID_PARAMETER;
233 }
234
235 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name));
236
237 pam_error = pam_start("samba", account_name, pconv, pamh);
238 if (pam_error != PAM_SUCCESS) {
239 /* no vaild pamh here, can we reliably call pam_strerror ? */
240 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
241 return NT_STATUS_UNSUCCESSFUL;
242 }
243
244 #ifdef PAM_RHOST
245 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
246 pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
247 if (pam_error != PAM_SUCCESS) {
248 NTSTATUS nt_status;
249
250 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
251 pam_strerror(*pamh, pam_error)));
252 nt_status = pam_to_nt_status(pam_error);
253
254 pam_error = pam_end(*pamh, 0);
255 if (pam_error != PAM_SUCCESS) {
256 /* no vaild pamh here, can we reliably call pam_strerror ? */
257 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
258 pam_error));
259 return pam_to_nt_status(pam_error);
260 }
261 return nt_status;
262 }
263 #endif
264 #ifdef PAM_TTY
265 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
266 pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
267 if (pam_error != PAM_SUCCESS) {
268 NTSTATUS nt_status;
269
270 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
271 pam_strerror(*pamh, pam_error)));
272 nt_status = pam_to_nt_status(pam_error);
273
274 pam_error = pam_end(*pamh, 0);
275 if (pam_error != PAM_SUCCESS) {
276 /* no vaild pamh here, can we reliably call pam_strerror ? */
277 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
278 pam_error));
279 return pam_to_nt_status(pam_error);
280 }
281 return nt_status;
282 }
283 #endif
284 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
285
286 return NT_STATUS_OK;
287 }
288
smb_pam_end(pam_handle_t * pamh)289 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
290 {
291 int pam_error;
292
293 if (pamh != NULL) {
294 pam_error = pam_end(pamh, 0);
295 if (pam_error != PAM_SUCCESS) {
296 /* no vaild pamh here, can we reliably call pam_strerror ? */
297 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
298 pam_error));
299 return pam_to_nt_status(pam_error);
300 }
301 return NT_STATUS_OK;
302 }
303
304 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
305 return NT_STATUS_UNSUCCESSFUL;
306 }
307
308 /*
309 * PAM Authentication Handler
310 */
smb_pam_auth(pam_handle_t * pamh,const char * user)311 static NTSTATUS smb_pam_auth(pam_handle_t *pamh, const char *user)
312 {
313 int pam_error;
314
315 /*
316 * To enable debugging set in /etc/pam.d/samba:
317 * auth required /lib/security/pam_pwdb.so nullok shadow audit
318 */
319
320 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
321
322 pam_error = pam_authenticate(pamh, PAM_SILENT | lp_null_passwords() ? 0 : PAM_DISALLOW_NULL_AUTHTOK);
323 switch( pam_error ){
324 case PAM_AUTH_ERR:
325 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
326 break;
327 case PAM_CRED_INSUFFICIENT:
328 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
329 break;
330 case PAM_AUTHINFO_UNAVAIL:
331 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
332 break;
333 case PAM_USER_UNKNOWN:
334 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
335 break;
336 case PAM_MAXTRIES:
337 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
338 break;
339 case PAM_ABORT:
340 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
341 break;
342 case PAM_SUCCESS:
343 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
344 break;
345 default:
346 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
347 break;
348 }
349
350 return pam_to_nt_status(pam_error);
351 }
352
353 /*
354 * PAM Account Handler
355 */
smb_pam_account(pam_handle_t * pamh,const char * user)356 static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
357 {
358 int pam_error;
359
360 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
361
362 pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
363 switch( pam_error ) {
364 case PAM_AUTHTOK_EXPIRED:
365 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
366 break;
367 case PAM_ACCT_EXPIRED:
368 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
369 break;
370 case PAM_AUTH_ERR:
371 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
372 break;
373 case PAM_PERM_DENIED:
374 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
375 break;
376 case PAM_USER_UNKNOWN:
377 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
378 break;
379 case PAM_SUCCESS:
380 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
381 break;
382 default:
383 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
384 break;
385 }
386
387 return pam_to_nt_status(pam_error);
388 }
389
390 /*
391 * PAM Credential Setting
392 */
393
smb_pam_setcred(pam_handle_t * pamh,const char * user)394 static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
395 {
396 int pam_error;
397
398 /*
399 * This will allow samba to aquire a kerberos token. And, when
400 * exporting an AFS cell, be able to /write/ to this cell.
401 */
402
403 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
404
405 pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT));
406 switch( pam_error ) {
407 case PAM_CRED_UNAVAIL:
408 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
409 break;
410 case PAM_CRED_EXPIRED:
411 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
412 break;
413 case PAM_USER_UNKNOWN:
414 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
415 break;
416 case PAM_CRED_ERR:
417 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
418 break;
419 case PAM_SUCCESS:
420 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
421 break;
422 default:
423 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
424 break;
425 }
426
427 return pam_to_nt_status(pam_error);
428 }
429
check_unix_password(TALLOC_CTX * ctx,const struct auth_usersupplied_info * user_info,struct passwd ** pws)430 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **pws)
431 {
432 struct smb_pam_user_info *info;
433 struct pam_conv *pamconv;
434 pam_handle_t *pamh;
435 NTSTATUS nt_status;
436
437 info = talloc(ctx, struct smb_pam_user_info);
438 if (info == NULL) {
439 return NT_STATUS_NO_MEMORY;
440 }
441
442 info->account_name = user_info->mapped.account_name;
443 info->plaintext_password = user_info->password.plaintext;
444
445 pamconv = talloc(ctx, struct pam_conv);
446 if (pamconv == NULL) {
447 return NT_STATUS_NO_MEMORY;
448 }
449
450 pamconv->conv = smb_pam_conv;
451 pamconv->appdata_ptr = (void *)info;
452
453 /* TODO:
454 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
455 * if true set up a crack name routine.
456 */
457
458 nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host ? user_info->remote_host->addr : NULL, pamconv);
459 if (!NT_STATUS_IS_OK(nt_status)) {
460 return nt_status;
461 }
462
463 nt_status = smb_pam_auth(pamh, user_info->mapped.account_name);
464 if (!NT_STATUS_IS_OK(nt_status)) {
465 smb_pam_end(pamh);
466 return nt_status;
467 }
468
469 if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
470
471 nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
472 if (!NT_STATUS_IS_OK(nt_status)) {
473 smb_pam_end(pamh);
474 return nt_status;
475 }
476
477 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
478 if (!NT_STATUS_IS_OK(nt_status)) {
479 smb_pam_end(pamh);
480 return nt_status;
481 }
482 }
483
484 smb_pam_end(pamh);
485
486 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
487 if (!NT_STATUS_IS_OK(nt_status)) {
488 return nt_status;
489 }
490
491 return NT_STATUS_OK;
492 }
493
494 #else
495
496 /****************************************************************************
497 core of password checking routine
498 ****************************************************************************/
password_check(const char * username,const char * password,const char * crypted,const char * salt)499 static NTSTATUS password_check(const char *username, const char *password,
500 const char *crypted, const char *salt)
501 {
502 BOOL ret;
503
504 #ifdef WITH_AFS
505 if (afs_auth(username, password))
506 return NT_STATUS_OK;
507 #endif /* WITH_AFS */
508
509 #ifdef WITH_DFS
510 if (dfs_auth(username, password))
511 return NT_STATUS_OK;
512 #endif /* WITH_DFS */
513
514 #ifdef OSF1_ENH_SEC
515
516 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
517
518 if (!ret) {
519 DEBUG(2,
520 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
521 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
522 }
523 if (ret) {
524 return NT_STATUS_OK;
525 } else {
526 return NT_STATUS_WRONG_PASSWORD;
527 }
528
529 #endif /* OSF1_ENH_SEC */
530
531 #ifdef ULTRIX_AUTH
532 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
533 if (ret) {
534 return NT_STATUS_OK;
535 } else {
536 return NT_STATUS_WRONG_PASSWORD;
537 }
538
539 #endif /* ULTRIX_AUTH */
540
541 #ifdef LINUX_BIGCRYPT
542 ret = (linux_bigcrypt(password, salt, crypted));
543 if (ret) {
544 return NT_STATUS_OK;
545 } else {
546 return NT_STATUS_WRONG_PASSWORD;
547 }
548 #endif /* LINUX_BIGCRYPT */
549
550 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
551
552 /*
553 * Some systems have bigcrypt in the C library but might not
554 * actually use it for the password hashes (HPUX 10.20) is
555 * a noteable example. So we try bigcrypt first, followed
556 * by crypt.
557 */
558
559 if (strcmp(bigcrypt(password, salt), crypted) == 0)
560 return NT_STATUS_OK;
561 else
562 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
563 if (ret) {
564 return NT_STATUS_OK;
565 } else {
566 return NT_STATUS_WRONG_PASSWORD;
567 }
568 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
569
570 #ifdef HAVE_BIGCRYPT
571 ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
572 if (ret) {
573 return NT_STATUS_OK;
574 } else {
575 return NT_STATUS_WRONG_PASSWORD;
576 }
577 #endif /* HAVE_BIGCRYPT */
578
579 #ifndef HAVE_CRYPT
580 DEBUG(1, ("Warning - no crypt available\n"));
581 return NT_STATUS_LOGON_FAILURE;
582 #else /* HAVE_CRYPT */
583 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
584 if (ret) {
585 return NT_STATUS_OK;
586 } else {
587 return NT_STATUS_WRONG_PASSWORD;
588 }
589 #endif /* HAVE_CRYPT */
590 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
591 }
592
check_unix_password(TALLOC_CTX * ctx,const struct auth_usersupplied_info * user_info,struct passwd ** ret_passwd)593 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
594 {
595 char *username;
596 char *password;
597 char *pwcopy;
598 char *salt;
599 char *crypted;
600 struct passwd *pws;
601 NTSTATUS nt_status;
602 int level = lp_passwordlevel();
603
604 *ret_passwd = NULL;
605
606 username = talloc_strdup(ctx, user_info->mapped.account_name);
607 password = talloc_strdup(ctx, user_info->password.plaintext);
608
609 nt_status = talloc_getpwnam(ctx, username, &pws);
610 if (!NT_STATUS_IS_OK(nt_status)) {
611 return nt_status;
612 }
613
614 crypted = pws->pw_passwd;
615 salt = pws->pw_passwd;
616
617 #ifdef HAVE_GETSPNAM
618 {
619 struct spwd *spass;
620
621 /* many shadow systems require you to be root to get
622 the password, in most cases this should already be
623 the case when this function is called, except
624 perhaps for IPC password changing requests */
625
626 spass = getspnam(pws->pw_name);
627 if (spass && spass->sp_pwdp) {
628 crypted = talloc_strdup(ctx, spass->sp_pwdp);
629 NT_STATUS_HAVE_NO_MEMORY(crypted);
630 salt = talloc_strdup(ctx, spass->sp_pwdp);
631 NT_STATUS_HAVE_NO_MEMORY(salt);
632 }
633 }
634 #elif defined(IA_UINFO)
635 {
636 char *ia_password;
637 /* Need to get password with SVR4.2's ia_ functions
638 instead of get{sp,pw}ent functions. Required by
639 UnixWare 2.x, tested on version
640 2.1. (tangent@cyberport.com) */
641 uinfo_t uinfo;
642 if (ia_openinfo(pws->pw_name, &uinfo) != -1) {
643 ia_get_logpwd(uinfo, &ia_password);
644 crypted = talloc_strdup(ctx, ia_password);
645 NT_STATUS_HAVE_NO_MEMORY(crypted);
646 }
647 }
648 #endif
649
650 #ifdef HAVE_GETPRPWNAM
651 {
652 struct pr_passwd *pr_pw = getprpwnam(pws->pw_name);
653 if (pr_pw && pr_pw->ufld.fd_encrypt) {
654 crypted = talloc_strdup(ctx, pr_pw->ufld.fd_encrypt);
655 NT_STATUS_HAVE_NO_MEMORY(crypted);
656 }
657 }
658 #endif
659
660 #ifdef HAVE_GETPWANAM
661 {
662 struct passwd_adjunct *pwret;
663 pwret = getpwanam(s);
664 if (pwret && pwret->pwa_passwd) {
665 crypted = talloc_strdup(ctx, pwret->pwa_passwd);
666 NT_STATUS_HAVE_NO_MEMORY(crypted);
667 }
668 }
669 #endif
670
671 #ifdef OSF1_ENH_SEC
672 {
673 struct pr_passwd *mypasswd;
674 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username));
675 mypasswd = getprpwnam(username);
676 if (mypasswd) {
677 username = talloc_strdup(ctx, mypasswd->ufld.fd_name);
678 NT_STATUS_HAVE_NO_MEMORY(username);
679 crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt);
680 NT_STATUS_HAVE_NO_MEMORY(crypted);
681 } else {
682 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username));
683 }
684 }
685 #endif
686
687 #ifdef ULTRIX_AUTH
688 {
689 AUTHORIZATION *ap = getauthuid(pws->pw_uid);
690 if (ap) {
691 crypted = talloc_strdup(ctx, ap->a_password);
692 endauthent();
693 NT_STATUS_HAVE_NO_MEMORY(crypted);
694 }
695 }
696 #endif
697
698 #if defined(HAVE_TRUNCATED_SALT)
699 /* crypt on some platforms (HPUX in particular)
700 won't work with more than 2 salt characters. */
701 salt[2] = 0;
702 #endif
703
704 if (crypted[0] == '\0') {
705 if (!lp_null_passwords()) {
706 DEBUG(2, ("Disallowing %s with null password\n", username));
707 return NT_STATUS_LOGON_FAILURE;
708 }
709 if (password == NULL) {
710 DEBUG(3, ("Allowing access to %s with null password\n", username));
711 *ret_passwd = pws;
712 return NT_STATUS_OK;
713 }
714 }
715
716 /* try it as it came to us */
717 nt_status = password_check(username, password, crypted, salt);
718 if (NT_STATUS_IS_OK(nt_status)) {
719 *ret_passwd = pws;
720 return nt_status;
721 }
722 else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
723 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
724 return nt_status;
725 }
726
727 if ( user_info->flags | USER_INFO_CASE_INSENSITIVE_PASSWORD) {
728 return nt_status;
729 }
730
731 /* if the password was given to us with mixed case then we don't
732 * need to proceed as we know it hasn't been case modified by the
733 * client */
734 if (strhasupper(password) && strhaslower(password)) {
735 return nt_status;
736 }
737
738 /* make a copy of it */
739 pwcopy = talloc_strdup(ctx, password);
740 if (!pwcopy)
741 return NT_STATUS_NO_MEMORY;
742
743 /* try all lowercase if it's currently all uppercase */
744 if (strhasupper(pwcopy)) {
745 strlower(pwcopy);
746 nt_status = password_check(username, pwcopy, crypted, salt);
747 if NT_STATUS_IS_OK(nt_status) {
748 *ret_passwd = pws;
749 return nt_status;
750 }
751 }
752
753 /* give up? */
754 if (level < 1) {
755 return NT_STATUS_WRONG_PASSWORD;
756 }
757
758 /* last chance - all combinations of up to level chars upper! */
759 strlower(pwcopy);
760
761 #if 0
762 if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) {
763 *ret_passwd = pws;
764 return nt_status;
765 }
766 #endif
767 return NT_STATUS_WRONG_PASSWORD;
768 }
769
770 #endif
771
772 /** Check a plaintext username/password
773 *
774 **/
775
authunix_want_check(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info)776 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
777 TALLOC_CTX *mem_ctx,
778 const struct auth_usersupplied_info *user_info)
779 {
780 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
781 return NT_STATUS_NOT_IMPLEMENTED;
782 }
783
784 return NT_STATUS_OK;
785 }
786
authunix_check_password(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info,struct auth_serversupplied_info ** server_info)787 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
788 TALLOC_CTX *mem_ctx,
789 const struct auth_usersupplied_info *user_info,
790 struct auth_serversupplied_info **server_info)
791 {
792 TALLOC_CTX *check_ctx;
793 NTSTATUS nt_status;
794 struct passwd *pwd;
795
796 if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
797 return NT_STATUS_INVALID_PARAMETER;
798 }
799
800 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
801 if (check_ctx == NULL) {
802 return NT_STATUS_NO_MEMORY;
803 }
804
805 nt_status = check_unix_password(check_ctx, user_info, &pwd);
806 if (!NT_STATUS_IS_OK(nt_status)) {
807 talloc_free(check_ctx);
808 return nt_status;
809 }
810
811 nt_status = authunix_make_server_info(mem_ctx, user_info, pwd, server_info);
812 if (!NT_STATUS_IS_OK(nt_status)) {
813 talloc_free(check_ctx);
814 return nt_status;
815 }
816
817 talloc_free(check_ctx);
818 return NT_STATUS_OK;
819 }
820
821 static const struct auth_operations unix_ops = {
822 .name = "unix",
823 .get_challenge = auth_get_challenge_not_implemented,
824 .want_check = authunix_want_check,
825 .check_password = authunix_check_password
826 };
827
auth_unix_init(void)828 NTSTATUS auth_unix_init(void)
829 {
830 NTSTATUS ret;
831
832 ret = auth_register(&unix_ops);
833 if (!NT_STATUS_IS_OK(ret)) {
834 DEBUG(0,("Failed to register unix auth backend!\n"));
835 return ret;
836 }
837
838 return ret;
839 }
840