source: vendor/3.6.0/source3/auth/pass_check.c

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

Samba Server: update vendor to 3.6.0

File size: 23.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Password checking
4 Copyright (C) Andrew Tridgell 1992-1998
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20/* this module is for checking a username/password against a system
21 password database. The SMB encrypted password support is elsewhere */
22
23#include "includes.h"
24#include "system/passwd.h"
25#include "auth.h"
26
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_AUTH
29
30/* what is the longest significant password available on your system?
31 Knowing this speeds up password searches a lot */
32#ifndef PASSWORD_LENGTH
33#define PASSWORD_LENGTH 8
34#endif
35
36/* these are kept here to keep the string_combinations function simple */
37static char *ths_user;
38
39static const char *get_this_user(void)
40{
41 if (!ths_user) {
42 return "";
43 }
44 return ths_user;
45}
46
47#if defined(WITH_PAM) || defined(OSF1_ENH_SEC)
48static const char *set_this_user(const char *newuser)
49{
50 char *orig_user = ths_user;
51 ths_user = SMB_STRDUP(newuser);
52 SAFE_FREE(orig_user);
53 return ths_user;
54}
55#endif
56
57#if !defined(WITH_PAM)
58static char *ths_salt;
59/* This must be writable. */
60static char *get_this_salt(void)
61{
62 return ths_salt;
63}
64
65/* We may be setting a modified version of the same
66 * string, so don't free before use. */
67
68static const char *set_this_salt(const char *newsalt)
69{
70 char *orig_salt = ths_salt;
71 ths_salt = SMB_STRDUP(newsalt);
72 SAFE_FREE(orig_salt);
73 return ths_salt;
74}
75
76static char *ths_crypted;
77static const char *get_this_crypted(void)
78{
79 if (!ths_crypted) {
80 return "";
81 }
82 return ths_crypted;
83}
84
85static const char *set_this_crypted(const char *newcrypted)
86{
87 char *orig_crypted = ths_crypted;
88 ths_crypted = SMB_STRDUP(newcrypted);
89 SAFE_FREE(orig_crypted);
90 return ths_crypted;
91}
92#endif
93
94#ifdef WITH_AFS
95
96#include <afs/stds.h>
97#include <afs/kautils.h>
98
99/*******************************************************************
100check on AFS authentication
101********************************************************************/
102static bool afs_auth(char *user, char *password)
103{
104 long password_expires = 0;
105 char *reason;
106
107 /* For versions of AFS prior to 3.3, this routine has few arguments, */
108 /* but since I can't find the old documentation... :-) */
109 setpag();
110 if (ka_UserAuthenticateGeneral
111 (KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG, user, (char *)0, /* instance */
112 (char *)0, /* cell */
113 password, 0, /* lifetime, default */
114 &password_expires, /*days 'til it expires */
115 0, /* spare 2 */
116 &reason) == 0)
117 {
118 return (True);
119 }
120 DEBUG(1,
121 ("AFS authentication for \"%s\" failed (%s)\n", user, reason));
122 return (False);
123}
124#endif
125
126
127#ifdef WITH_DFS
128
129#include <dce/dce_error.h>
130#include <dce/sec_login.h>
131
132/*****************************************************************
133 This new version of the DFS_AUTH code was donated by Karsten Muuss
134 <muuss@or.uni-bonn.de>. It fixes the following problems with the
135 old code :
136
137 - Server credentials may expire
138 - Client credential cache files have wrong owner
139 - purge_context() function is called with invalid argument
140
141 This new code was modified to ensure that on exit the uid/gid is
142 still root, and the original directory is restored. JRA.
143******************************************************************/
144
145sec_login_handle_t my_dce_sec_context;
146int dcelogin_atmost_once = 0;
147
148/*******************************************************************
149check on a DCE/DFS authentication
150********************************************************************/
151static bool dfs_auth(char *user, char *password)
152{
153 struct tm *t;
154 error_status_t err;
155 int err2;
156 int prterr;
157 signed32 expire_time, current_time;
158 boolean32 password_reset;
159 struct passwd *pw;
160 sec_passwd_rec_t passwd_rec;
161 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
162 unsigned char dce_errstr[dce_c_error_string_len];
163 gid_t egid;
164
165 if (dcelogin_atmost_once)
166 return (False);
167
168#ifdef HAVE_CRYPT
169 /*
170 * We only go for a DCE login context if the given password
171 * matches that stored in the local password file..
172 * Assumes local passwd file is kept in sync w/ DCE RGY!
173 */
174
175 if (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()))
176 {
177 return (False);
178 }
179#endif
180
181 sec_login_get_current_context(&my_dce_sec_context, &err);
182 if (err != error_status_ok)
183 {
184 dce_error_inq_text(err, dce_errstr, &err2);
185 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));
186
187 return (False);
188 }
189
190 sec_login_certify_identity(my_dce_sec_context, &err);
191 if (err != error_status_ok)
192 {
193 dce_error_inq_text(err, dce_errstr, &err2);
194 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));
195
196 return (False);
197 }
198
199 sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
200 if (err != error_status_ok)
201 {
202 dce_error_inq_text(err, dce_errstr, &err2);
203 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));
204
205 return (False);
206 }
207
208 time(&current_time);
209
210 if (expire_time < (current_time + 60))
211 {
212 struct passwd *pw;
213 sec_passwd_rec_t *key;
214
215 sec_login_get_pwent(my_dce_sec_context,
216 (sec_login_passwd_t *) & pw, &err);
217 if (err != error_status_ok)
218 {
219 dce_error_inq_text(err, dce_errstr, &err2);
220 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
221
222 return (False);
223 }
224
225 sec_login_refresh_identity(my_dce_sec_context, &err);
226 if (err != error_status_ok)
227 {
228 dce_error_inq_text(err, dce_errstr, &err2);
229 DEBUG(0, ("DCE can't refresh identity. %s\n",
230 dce_errstr));
231
232 return (False);
233 }
234
235 sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL,
236 (unsigned char *)pw->pw_name,
237 sec_c_key_version_none,
238 (void **)&key, &err);
239 if (err != error_status_ok)
240 {
241 dce_error_inq_text(err, dce_errstr, &err2);
242 DEBUG(0, ("DCE can't get key for %s. %s\n",
243 pw->pw_name, dce_errstr));
244
245 return (False);
246 }
247
248 sec_login_valid_and_cert_ident(my_dce_sec_context, key,
249 &password_reset, &auth_src,
250 &err);
251 if (err != error_status_ok)
252 {
253 dce_error_inq_text(err, dce_errstr, &err2);
254 DEBUG(0,
255 ("DCE can't validate and certify identity for %s. %s\n",
256 pw->pw_name, dce_errstr));
257 }
258
259 sec_key_mgmt_free_key(key, &err);
260 if (err != error_status_ok)
261 {
262 dce_error_inq_text(err, dce_errstr, &err2);
263 DEBUG(0, ("DCE can't free key.\n", dce_errstr));
264 }
265 }
266
267 if (sec_login_setup_identity((unsigned char *)user,
268 sec_login_no_flags,
269 &my_dce_sec_context, &err) == 0)
270 {
271 dce_error_inq_text(err, dce_errstr, &err2);
272 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
273 user, dce_errstr));
274 return (False);
275 }
276
277 sec_login_get_pwent(my_dce_sec_context,
278 (sec_login_passwd_t *) & pw, &err);
279 if (err != error_status_ok)
280 {
281 dce_error_inq_text(err, dce_errstr, &err2);
282 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
283
284 return (False);
285 }
286
287 sec_login_purge_context(&my_dce_sec_context, &err);
288 if (err != error_status_ok)
289 {
290 dce_error_inq_text(err, dce_errstr, &err2);
291 DEBUG(0, ("DCE can't purge context. %s\n", dce_errstr));
292
293 return (False);
294 }
295
296 /*
297 * NB. I'd like to change these to call something like change_to_user()
298 * instead but currently we don't have a connection
299 * context to become the correct user. This is already
300 * fairly platform specific code however, so I think
301 * this should be ok. I have added code to go
302 * back to being root on error though. JRA.
303 */
304
305 egid = getegid();
306
307 set_effective_gid(pw->pw_gid);
308 set_effective_uid(pw->pw_uid);
309
310 if (sec_login_setup_identity((unsigned char *)user,
311 sec_login_no_flags,
312 &my_dce_sec_context, &err) == 0)
313 {
314 dce_error_inq_text(err, dce_errstr, &err2);
315 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
316 user, dce_errstr));
317 goto err;
318 }
319
320 sec_login_get_pwent(my_dce_sec_context,
321 (sec_login_passwd_t *) & pw, &err);
322 if (err != error_status_ok)
323 {
324 dce_error_inq_text(err, dce_errstr, &err2);
325 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
326 goto err;
327 }
328
329 passwd_rec.version_number = sec_passwd_c_version_none;
330 passwd_rec.pepper = NULL;
331 passwd_rec.key.key_type = sec_passwd_plain;
332 passwd_rec.key.tagged_union.plain = (idl_char *) password;
333
334 sec_login_validate_identity(my_dce_sec_context,
335 &passwd_rec, &password_reset,
336 &auth_src, &err);
337 if (err != error_status_ok)
338 {
339 dce_error_inq_text(err, dce_errstr, &err2);
340 DEBUG(0,
341 ("DCE Identity Validation failed for principal %s: %s\n",
342 user, dce_errstr));
343 goto err;
344 }
345
346 sec_login_certify_identity(my_dce_sec_context, &err);
347 if (err != error_status_ok)
348 {
349 dce_error_inq_text(err, dce_errstr, &err2);
350 DEBUG(0, ("DCE certify identity failed: %s\n", dce_errstr));
351 goto err;
352 }
353
354 if (auth_src != sec_login_auth_src_network)
355 {
356 DEBUG(0, ("DCE context has no network credentials.\n"));
357 }
358
359 sec_login_set_context(my_dce_sec_context, &err);
360 if (err != error_status_ok)
361 {
362 dce_error_inq_text(err, dce_errstr, &err2);
363 DEBUG(0,
364 ("DCE login failed for principal %s, cant set context: %s\n",
365 user, dce_errstr));
366
367 sec_login_purge_context(&my_dce_sec_context, &err);
368 goto err;
369 }
370
371 sec_login_get_pwent(my_dce_sec_context,
372 (sec_login_passwd_t *) & pw, &err);
373 if (err != error_status_ok)
374 {
375 dce_error_inq_text(err, dce_errstr, &err2);
376 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
377 goto err;
378 }
379
380 DEBUG(0, ("DCE login succeeded for principal %s on pid %d\n",
381 user, sys_getpid()));
382
383 DEBUG(3, ("DCE principal: %s\n"
384 " uid: %d\n"
385 " gid: %d\n",
386 pw->pw_name, pw->pw_uid, pw->pw_gid));
387 DEBUG(3, (" info: %s\n"
388 " dir: %s\n"
389 " shell: %s\n",
390 pw->pw_gecos, pw->pw_dir, pw->pw_shell));
391
392 sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
393 if (err != error_status_ok)
394 {
395 dce_error_inq_text(err, dce_errstr, &err2);
396 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));
397 goto err;
398 }
399
400 set_effective_uid(0);
401 set_effective_gid(0);
402
403 t = localtime(&expire_time);
404 if (t) {
405 const char *asct = asctime(t);
406 if (asct) {
407 DEBUG(0,("DCE context expires: %s", asct));
408 }
409 }
410
411 dcelogin_atmost_once = 1;
412 return (True);
413
414 err:
415
416 /* Go back to root, JRA. */
417 set_effective_uid(0);
418 set_effective_gid(egid);
419 return (False);
420}
421
422void dfs_unlogin(void)
423{
424 error_status_t err;
425 int err2;
426 unsigned char dce_errstr[dce_c_error_string_len];
427
428 sec_login_purge_context(&my_dce_sec_context, &err);
429 if (err != error_status_ok)
430 {
431 dce_error_inq_text(err, dce_errstr, &err2);
432 DEBUG(0,
433 ("DCE purge login context failed for server instance %d: %s\n",
434 sys_getpid(), dce_errstr));
435 }
436}
437#endif
438
439#ifdef LINUX_BIGCRYPT
440/****************************************************************************
441an enhanced crypt for Linux to handle password longer than 8 characters
442****************************************************************************/
443static int linux_bigcrypt(char *password, char *salt1, char *crypted)
444{
445#define LINUX_PASSWORD_SEG_CHARS 8
446 char salt[3];
447 int i;
448
449 StrnCpy(salt, salt1, 2);
450 crypted += 2;
451
452 for (i = strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
453 char *p = crypt(password, salt) + 2;
454 if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
455 return (0);
456 password += LINUX_PASSWORD_SEG_CHARS;
457 crypted += strlen(p);
458 }
459
460 return (1);
461}
462#endif
463
464#ifdef OSF1_ENH_SEC
465/****************************************************************************
466an enhanced crypt for OSF1
467****************************************************************************/
468static char *osf1_bigcrypt(char *password, char *salt1)
469{
470 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
471 char *p1;
472 char *p2 = password;
473 char salt[3];
474 int i;
475 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
476 if (strlen(password) % AUTH_CLEARTEXT_SEG_CHARS)
477 parts++;
478
479 StrnCpy(salt, salt1, 2);
480 StrnCpy(result, salt1, 2);
481 result[2] = '\0';
482
483 for (i = 0; i < parts; i++) {
484 p1 = crypt(p2, salt);
485 strncat(result, p1 + 2,
486 AUTH_MAX_PASSWD_LENGTH - strlen(p1 + 2) - 1);
487 StrnCpy(salt, &result[2 + i * AUTH_CIPHERTEXT_SEG_CHARS], 2);
488 p2 += AUTH_CLEARTEXT_SEG_CHARS;
489 }
490
491 return (result);
492}
493#endif
494
495
496/****************************************************************************
497apply a function to upper/lower case combinations
498of a string and return true if one of them returns true.
499try all combinations with N uppercase letters.
500offset is the first char to try and change (start with 0)
501it assumes the string starts lowercased
502****************************************************************************/
503static NTSTATUS string_combinations2(char *s, int offset,
504 NTSTATUS (*fn)(const char *s,
505 void *private_data),
506 int N, void *private_data)
507{
508 int len = strlen(s);
509 int i;
510 NTSTATUS nt_status;
511
512#ifdef PASSWORD_LENGTH
513 len = MIN(len, PASSWORD_LENGTH);
514#endif
515
516 if (N <= 0 || offset >= len)
517 return (fn(s, private_data));
518
519 for (i = offset; i < (len - (N - 1)); i++) {
520 char c = s[i];
521 if (!islower_m(c))
522 continue;
523 s[i] = toupper_m(c);
524 nt_status = string_combinations2(s, i + 1, fn, N - 1,
525 private_data);
526 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
527 return nt_status;
528 }
529 s[i] = c;
530 }
531 return (NT_STATUS_WRONG_PASSWORD);
532}
533
534/****************************************************************************
535apply a function to upper/lower case combinations
536of a string and return true if one of them returns true.
537try all combinations with up to N uppercase letters.
538offset is the first char to try and change (start with 0)
539it assumes the string starts lowercased
540****************************************************************************/
541static NTSTATUS string_combinations(char *s,
542 NTSTATUS (*fn)(const char *s,
543 void *private_data),
544 int N, void *private_data)
545{
546 int n;
547 NTSTATUS nt_status;
548 for (n = 1; n <= N; n++) {
549 nt_status = string_combinations2(s, 0, fn, n, private_data);
550 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
551 return nt_status;
552 }
553 }
554 return NT_STATUS_WRONG_PASSWORD;
555}
556
557
558/****************************************************************************
559core of password checking routine
560****************************************************************************/
561static NTSTATUS password_check(const char *password, void *private_data)
562{
563#ifdef WITH_PAM
564 const char *rhost = (const char *)private_data;
565 return smb_pam_passcheck(get_this_user(), rhost, password);
566#else
567
568 bool ret;
569
570#ifdef WITH_AFS
571 if (afs_auth(get_this_user(), password))
572 return NT_STATUS_OK;
573#endif /* WITH_AFS */
574
575#ifdef WITH_DFS
576 if (dfs_auth(get_this_user(), password))
577 return NT_STATUS_OK;
578#endif /* WITH_DFS */
579
580#ifdef OSF1_ENH_SEC
581
582 ret = (strcmp(osf1_bigcrypt(password, get_this_salt()),
583 get_this_crypted()) == 0);
584 if (!ret) {
585 DEBUG(2,
586 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
587 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0);
588 }
589 if (ret) {
590 return NT_STATUS_OK;
591 } else {
592 return NT_STATUS_WRONG_PASSWORD;
593 }
594
595#endif /* OSF1_ENH_SEC */
596
597#ifdef ULTRIX_AUTH
598 ret = (strcmp((char *)crypt16(password, get_this_salt()), get_this_crypted()) == 0);
599 if (ret) {
600 return NT_STATUS_OK;
601 } else {
602 return NT_STATUS_WRONG_PASSWORD;
603 }
604
605#endif /* ULTRIX_AUTH */
606
607#ifdef LINUX_BIGCRYPT
608 ret = (linux_bigcrypt(password, get_this_salt(), get_this_crypted()));
609 if (ret) {
610 return NT_STATUS_OK;
611 } else {
612 return NT_STATUS_WRONG_PASSWORD;
613 }
614#endif /* LINUX_BIGCRYPT */
615
616#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
617
618 /*
619 * Some systems have bigcrypt in the C library but might not
620 * actually use it for the password hashes (HPUX 10.20) is
621 * a noteable example. So we try bigcrypt first, followed
622 * by crypt.
623 */
624
625 if (strcmp(bigcrypt(password, get_this_salt()), get_this_crypted()) == 0)
626 return NT_STATUS_OK;
627 else
628 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0);
629 if (ret) {
630 return NT_STATUS_OK;
631 } else {
632 return NT_STATUS_WRONG_PASSWORD;
633 }
634#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
635
636#ifdef HAVE_BIGCRYPT
637 ret = (strcmp(bigcrypt(password, get_this_salt()), get_this_crypted()) == 0);
638 if (ret) {
639 return NT_STATUS_OK;
640 } else {
641 return NT_STATUS_WRONG_PASSWORD;
642 }
643#endif /* HAVE_BIGCRYPT */
644
645#ifndef HAVE_CRYPT
646 DEBUG(1, ("Warning - no crypt available\n"));
647 return NT_STATUS_LOGON_FAILURE;
648#else /* HAVE_CRYPT */
649 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0);
650 if (ret) {
651 return NT_STATUS_OK;
652 } else {
653 return NT_STATUS_WRONG_PASSWORD;
654 }
655#endif /* HAVE_CRYPT */
656#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
657#endif /* WITH_PAM */
658}
659
660
661
662/****************************************************************************
663CHECK if a username/password is OK
664the function pointer fn() points to a function to call when a successful
665match is found and is used to update the encrypted password file
666return NT_STATUS_OK on correct match, appropriate error otherwise
667****************************************************************************/
668
669NTSTATUS pass_check(const struct passwd *pass,
670 const char *user,
671 const char *rhost,
672 const char *password,
673 bool run_cracker)
674{
675 char *pass2 = NULL;
676 int level = lp_passwordlevel();
677
678 NTSTATUS nt_status;
679
680#ifdef DEBUG_PASSWORD
681 DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password));
682#endif
683
684 if (!password)
685 return NT_STATUS_LOGON_FAILURE;
686
687 if ((!*password) && !lp_null_passwords())
688 return NT_STATUS_LOGON_FAILURE;
689
690#if defined(WITH_PAM)
691
692 /*
693 * If we're using PAM we want to short-circuit all the
694 * checks below and dive straight into the PAM code.
695 */
696
697 if (set_this_user(user) == NULL) {
698 return NT_STATUS_NO_MEMORY;
699 }
700
701 DEBUG(4, ("pass_check: Checking (PAM) password for user %s\n", user));
702
703#else /* Not using PAM */
704
705 DEBUG(4, ("pass_check: Checking password for user %s\n", user));
706
707 if (!pass) {
708 DEBUG(3, ("Couldn't find user %s\n", user));
709 return NT_STATUS_NO_SUCH_USER;
710 }
711
712
713 /* Copy into global for the convenience of looping code */
714 /* Also the place to keep the 'password' no matter what
715 crazy struct it started in... */
716 if (set_this_crypted(pass->pw_passwd) == NULL) {
717 return NT_STATUS_NO_MEMORY;
718 }
719 if (set_this_salt(pass->pw_passwd) == NULL) {
720 return NT_STATUS_NO_MEMORY;
721 }
722
723#ifdef HAVE_GETSPNAM
724 {
725 struct spwd *spass;
726
727 /* many shadow systems require you to be root to get
728 the password, in most cases this should already be
729 the case when this function is called, except
730 perhaps for IPC password changing requests */
731
732 spass = getspnam(pass->pw_name);
733 if (spass && spass->sp_pwdp) {
734 if (set_this_crypted(spass->sp_pwdp) == NULL) {
735 return NT_STATUS_NO_MEMORY;
736 }
737 if (set_this_salt(spass->sp_pwdp) == NULL) {
738 return NT_STATUS_NO_MEMORY;
739 }
740 }
741 }
742#elif defined(IA_UINFO)
743 {
744 /* Need to get password with SVR4.2's ia_ functions
745 instead of get{sp,pw}ent functions. Required by
746 UnixWare 2.x, tested on version
747 2.1. (tangent@cyberport.com) */
748 uinfo_t uinfo;
749 if (ia_openinfo(pass->pw_name, &uinfo) != -1)
750 ia_get_logpwd(uinfo, &(pass->pw_passwd));
751 }
752#endif
753
754#ifdef HAVE_GETPRPWNAM
755 {
756 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
757 if (pr_pw && pr_pw->ufld.fd_encrypt) {
758 if (set_this_crypted(pr_pw->ufld.fd_encrypt) == NULL) {
759 return NT_STATUS_NO_MEMORY;
760 }
761 }
762 }
763#endif
764
765#ifdef HAVE_GETPWANAM
766 {
767 struct passwd_adjunct *pwret;
768 pwret = getpwanam(s);
769 if (pwret && pwret->pwa_passwd) {
770 if (set_this_crypted(pwret->pwa_passwd) == NULL) {
771 return NT_STATUS_NO_MEMORY;
772 }
773 }
774 }
775#endif
776
777#ifdef OSF1_ENH_SEC
778 {
779 struct pr_passwd *mypasswd;
780 DEBUG(5, ("Checking password for user %s in OSF1_ENH_SEC\n",
781 user));
782 mypasswd = getprpwnam(user);
783 if (mypasswd) {
784 if (set_this_user(mypasswd->ufld.fd_name) == NULL) {
785 return NT_STATUS_NO_MEMORY;
786 }
787 if (set_this_crypted(mypasswd->ufld.fd_encrypt) == NULL) {
788 return NT_STATUS_NO_MEMORY;
789 }
790 } else {
791 DEBUG(5,
792 ("OSF1_ENH_SEC: No entry for user %s in protected database !\n",
793 user));
794 }
795 }
796#endif
797
798#ifdef ULTRIX_AUTH
799 {
800 AUTHORIZATION *ap = getauthuid(pass->pw_uid);
801 if (ap) {
802 if (set_this_crypted(ap->a_password) == NULL) {
803 endauthent();
804 return NT_STATUS_NO_MEMORY;
805 }
806 endauthent();
807 }
808 }
809#endif
810
811#if defined(HAVE_TRUNCATED_SALT)
812 /* crypt on some platforms (HPUX in particular)
813 won't work with more than 2 salt characters. */
814 {
815 char *trunc_salt = get_this_salt();
816 if (!trunc_salt || strlen(trunc_salt) < 2) {
817 return NT_STATUS_LOGON_FAILURE;
818 }
819 trunc_salt[2] = 0;
820 if (set_this_salt(trunc_salt) == NULL) {
821 return NT_STATUS_NO_MEMORY;
822 }
823 }
824#endif
825
826 if (!get_this_crypted() || !*get_this_crypted()) {
827 if (!lp_null_passwords()) {
828 DEBUG(2, ("Disallowing %s with null password\n",
829 get_this_user()));
830 return NT_STATUS_LOGON_FAILURE;
831 }
832 if (!*password) {
833 DEBUG(3,
834 ("Allowing access to %s with null password\n",
835 get_this_user()));
836 return NT_STATUS_OK;
837 }
838 }
839
840#endif /* defined(WITH_PAM) */
841
842 /* try it as it came to us */
843 nt_status = password_check(password, (void *)rhost);
844 if NT_STATUS_IS_OK(nt_status) {
845 return (nt_status);
846 } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
847 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
848 return (nt_status);
849 }
850
851 if (!run_cracker) {
852 return (nt_status);
853 }
854
855 /* if the password was given to us with mixed case then we don't
856 * need to proceed as we know it hasn't been case modified by the
857 * client */
858 if (strhasupper(password) && strhaslower(password)) {
859 return nt_status;
860 }
861
862 /* make a copy of it */
863 pass2 = talloc_strdup(talloc_tos(), password);
864 if (!pass2) {
865 return NT_STATUS_NO_MEMORY;
866 }
867
868 /* try all lowercase if it's currently all uppercase */
869 if (strhasupper(pass2)) {
870 strlower_m(pass2);
871 nt_status = password_check(pass2, (void *)rhost);
872 if (NT_STATUS_IS_OK(nt_status)) {
873 return (nt_status);
874 }
875 }
876
877 /* give up? */
878 if (level < 1) {
879 return NT_STATUS_WRONG_PASSWORD;
880 }
881
882 /* last chance - all combinations of up to level chars upper! */
883 strlower_m(pass2);
884
885 nt_status = string_combinations(pass2, password_check, level,
886 (void *)rhost);
887 if (NT_STATUS_IS_OK(nt_status)) {
888 return nt_status;
889 }
890
891 return NT_STATUS_WRONG_PASSWORD;
892}
Note: See TracBrowser for help on using the repository browser.