source: trunk/server/source4/auth/ntlm/auth_unix.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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