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
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.
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.
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/>.
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 "auth/ntlm/pam_errors.h"
28 #include "param/param.h"
30 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
31 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
33 static NTSTATUS
authunix_make_server_info(TALLOC_CTX
*mem_ctx
,
34 const char *netbios_name
,
35 const struct auth_usersupplied_info
*user_info
,
37 struct auth_serversupplied_info
**_server_info
)
39 struct auth_serversupplied_info
*server_info
;
42 /* This is a real, real hack */
43 if (pwd
->pw_uid
== 0) {
44 status
= auth_system_server_info(mem_ctx
, netbios_name
, &server_info
);
45 if (!NT_STATUS_IS_OK(status
)) {
49 server_info
->account_name
= talloc_steal(server_info
, pwd
->pw_name
);
50 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_name
);
52 server_info
->domain_name
= talloc_strdup(server_info
, "unix");
53 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_name
);
55 server_info
= talloc(mem_ctx
, struct auth_serversupplied_info
);
56 NT_STATUS_HAVE_NO_MEMORY(server_info
);
58 server_info
->authenticated
= true;
60 server_info
->account_name
= talloc_steal(server_info
, pwd
->pw_name
);
61 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_name
);
63 server_info
->domain_name
= talloc_strdup(server_info
, "unix");
64 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_name
);
66 /* This isn't in any way correct.. */
67 server_info
->account_sid
= NULL
;
68 server_info
->primary_group_sid
= NULL
;
69 server_info
->n_domain_groups
= 0;
70 server_info
->domain_groups
= NULL
;
72 server_info
->user_session_key
= data_blob(NULL
,0);
73 server_info
->lm_session_key
= data_blob(NULL
,0);
75 server_info
->full_name
= talloc_steal(server_info
, pwd
->pw_gecos
);
76 NT_STATUS_HAVE_NO_MEMORY(server_info
->full_name
);
77 server_info
->logon_script
= talloc_strdup(server_info
, "");
78 NT_STATUS_HAVE_NO_MEMORY(server_info
->logon_script
);
79 server_info
->profile_path
= talloc_strdup(server_info
, "");
80 NT_STATUS_HAVE_NO_MEMORY(server_info
->profile_path
);
81 server_info
->home_directory
= talloc_strdup(server_info
, "");
82 NT_STATUS_HAVE_NO_MEMORY(server_info
->home_directory
);
83 server_info
->home_drive
= talloc_strdup(server_info
, "");
84 NT_STATUS_HAVE_NO_MEMORY(server_info
->home_drive
);
86 server_info
->last_logon
= 0;
87 server_info
->last_logoff
= 0;
88 server_info
->acct_expiry
= 0;
89 server_info
->last_password_change
= 0;
90 server_info
->allow_password_change
= 0;
91 server_info
->force_password_change
= 0;
92 server_info
->logon_count
= 0;
93 server_info
->bad_password_count
= 0;
94 server_info
->acct_flags
= 0;
96 *_server_info
= server_info
;
101 static NTSTATUS
talloc_getpwnam(TALLOC_CTX
*ctx
, const char *username
, struct passwd
**pws
)
108 ret
= talloc(ctx
, struct passwd
);
109 NT_STATUS_HAVE_NO_MEMORY(ret
);
111 from
= getpwnam(username
);
113 return NT_STATUS_NO_SUCH_USER
;
116 ret
->pw_name
= talloc_strdup(ctx
, from
->pw_name
);
117 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_name
);
119 ret
->pw_passwd
= talloc_strdup(ctx
, from
->pw_passwd
);
120 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_passwd
);
122 ret
->pw_uid
= from
->pw_uid
;
123 ret
->pw_gid
= from
->pw_gid
;
124 ret
->pw_gecos
= talloc_strdup(ctx
, from
->pw_gecos
);
125 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_gecos
);
127 ret
->pw_dir
= talloc_strdup(ctx
, from
->pw_dir
);
128 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_dir
);
130 ret
->pw_shell
= talloc_strdup(ctx
, from
->pw_shell
);
131 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_shell
);
139 #ifdef HAVE_SECURITY_PAM_APPL_H
140 #include <security/pam_appl.h>
142 struct smb_pam_user_info
{
143 const char *account_name
;
144 const char *plaintext_password
;
147 #define COPY_STRING(s) (s) ? strdup(s) : NULL
150 * Check user password
151 * Currently it uses PAM only and fails on systems without PAM
152 * Samba3 code located in pass_check.c is to ugly to be used directly it will
153 * need major rework that's why pass_check.c is still there.
156 static int smb_pam_conv(int num_msg
, const struct pam_message
**msg
,
157 struct pam_response
**reply
, void *appdata_ptr
)
159 struct smb_pam_user_info
*info
= (struct smb_pam_user_info
*)appdata_ptr
;
168 * Apparantly HPUX has a buggy PAM that doesn't support the
169 * data pointer. Fail if this is the case. JRA.
178 * PAM frees memory in reply messages by itself
179 * so use malloc instead of talloc here.
181 *reply
= malloc_array_p(struct pam_response
, num_msg
);
182 if (*reply
== NULL
) {
186 for (num
= 0; num
< num_msg
; num
++) {
187 switch (msg
[num
]->msg_style
) {
188 case PAM_PROMPT_ECHO_ON
:
189 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
190 (*reply
)[num
].resp
= COPY_STRING(info
->account_name
);
193 case PAM_PROMPT_ECHO_OFF
:
194 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
195 (*reply
)[num
].resp
= COPY_STRING(info
->plaintext_password
);
199 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
200 (*reply
)[num
].resp
= NULL
;
201 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg
[num
]->msg
)));
205 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
206 (*reply
)[num
].resp
= NULL
;
207 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg
[num
]->msg
)));
212 SAFE_FREE((*reply
)[num
-1].resp
);
217 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
226 * Start PAM authentication for specified account
229 static NTSTATUS
smb_pam_start(pam_handle_t
**pamh
, const char *account_name
, const char *remote_host
, struct pam_conv
*pconv
)
233 if (account_name
== NULL
|| remote_host
== NULL
) {
234 return NT_STATUS_INVALID_PARAMETER
;
237 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name
));
239 pam_error
= pam_start("samba", account_name
, pconv
, pamh
);
240 if (pam_error
!= PAM_SUCCESS
) {
241 /* no valid pamh here, can we reliably call pam_strerror ? */
242 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
243 return NT_STATUS_UNSUCCESSFUL
;
247 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host
));
248 pam_error
= pam_set_item(*pamh
, PAM_RHOST
, remote_host
);
249 if (pam_error
!= PAM_SUCCESS
) {
252 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
253 pam_strerror(*pamh
, pam_error
)));
254 nt_status
= pam_to_nt_status(pam_error
);
256 pam_error
= pam_end(*pamh
, 0);
257 if (pam_error
!= PAM_SUCCESS
) {
258 /* no vaild pamh here, can we reliably call pam_strerror ? */
259 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
261 return pam_to_nt_status(pam_error
);
267 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
268 pam_error
= pam_set_item(*pamh
, PAM_TTY
, "samba");
269 if (pam_error
!= PAM_SUCCESS
) {
272 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
273 pam_strerror(*pamh
, pam_error
)));
274 nt_status
= pam_to_nt_status(pam_error
);
276 pam_error
= pam_end(*pamh
, 0);
277 if (pam_error
!= PAM_SUCCESS
) {
278 /* no vaild pamh here, can we reliably call pam_strerror ? */
279 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
281 return pam_to_nt_status(pam_error
);
286 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name
));
291 static NTSTATUS
smb_pam_end(pam_handle_t
*pamh
)
296 pam_error
= pam_end(pamh
, 0);
297 if (pam_error
!= PAM_SUCCESS
) {
298 /* no vaild pamh here, can we reliably call pam_strerror ? */
299 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
301 return pam_to_nt_status(pam_error
);
306 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
307 return NT_STATUS_UNSUCCESSFUL
;
311 * PAM Authentication Handler
313 static NTSTATUS
smb_pam_auth(pam_handle_t
*pamh
, bool allow_null_passwords
, const char *user
)
318 * To enable debugging set in /etc/pam.d/samba:
319 * auth required /lib/security/pam_pwdb.so nullok shadow audit
322 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user
));
324 pam_error
= pam_authenticate(pamh
, PAM_SILENT
| allow_null_passwords
? 0 : PAM_DISALLOW_NULL_AUTHTOK
);
327 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user
));
329 case PAM_CRED_INSUFFICIENT
:
330 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user
));
332 case PAM_AUTHINFO_UNAVAIL
:
333 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user
));
335 case PAM_USER_UNKNOWN
:
336 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user
));
339 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user
));
342 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user
));
345 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user
));
348 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user
));
352 return pam_to_nt_status(pam_error
);
356 * PAM Account Handler
358 static NTSTATUS
smb_pam_account(pam_handle_t
*pamh
, const char * user
)
362 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user
));
364 pam_error
= pam_acct_mgmt(pamh
, PAM_SILENT
); /* Is user account enabled? */
365 switch( pam_error
) {
366 case PAM_AUTHTOK_EXPIRED
:
367 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user
));
369 case PAM_ACCT_EXPIRED
:
370 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user
));
373 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user
));
375 case PAM_PERM_DENIED
:
376 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user
));
378 case PAM_USER_UNKNOWN
:
379 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user
));
382 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user
));
385 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error
, user
));
389 return pam_to_nt_status(pam_error
);
393 * PAM Credential Setting
396 static NTSTATUS
smb_pam_setcred(pam_handle_t
*pamh
, const char * user
)
401 * This will allow samba to aquire a kerberos token. And, when
402 * exporting an AFS cell, be able to /write/ to this cell.
405 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user
));
407 pam_error
= pam_setcred(pamh
, (PAM_ESTABLISH_CRED
|PAM_SILENT
));
408 switch( pam_error
) {
409 case PAM_CRED_UNAVAIL
:
410 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user
));
412 case PAM_CRED_EXPIRED
:
413 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user
));
415 case PAM_USER_UNKNOWN
:
416 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user
));
419 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user
));
422 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user
));
425 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error
, user
));
429 return pam_to_nt_status(pam_error
);
432 static NTSTATUS
check_unix_password(TALLOC_CTX
*ctx
, struct loadparm_context
*lp_ctx
,
433 const struct auth_usersupplied_info
*user_info
, struct passwd
**pws
)
435 struct smb_pam_user_info
*info
;
436 struct pam_conv
*pamconv
;
440 info
= talloc(ctx
, struct smb_pam_user_info
);
442 return NT_STATUS_NO_MEMORY
;
445 info
->account_name
= user_info
->mapped
.account_name
;
446 info
->plaintext_password
= user_info
->password
.plaintext
;
448 pamconv
= talloc(ctx
, struct pam_conv
);
449 if (pamconv
== NULL
) {
450 return NT_STATUS_NO_MEMORY
;
453 pamconv
->conv
= smb_pam_conv
;
454 pamconv
->appdata_ptr
= (void *)info
;
457 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
458 * if true set up a crack name routine.
461 nt_status
= smb_pam_start(&pamh
, user_info
->mapped
.account_name
, user_info
->remote_host
? user_info
->remote_host
->addr
: NULL
, pamconv
);
462 if (!NT_STATUS_IS_OK(nt_status
)) {
466 nt_status
= smb_pam_auth(pamh
, lp_null_passwords(lp_ctx
), user_info
->mapped
.account_name
);
467 if (!NT_STATUS_IS_OK(nt_status
)) {
472 if ( ! (user_info
->flags
& USER_INFO_DONT_CHECK_UNIX_ACCOUNT
)) {
474 nt_status
= smb_pam_account(pamh
, user_info
->mapped
.account_name
);
475 if (!NT_STATUS_IS_OK(nt_status
)) {
480 nt_status
= smb_pam_setcred(pamh
, user_info
->mapped
.account_name
);
481 if (!NT_STATUS_IS_OK(nt_status
)) {
489 nt_status
= talloc_getpwnam(ctx
, user_info
->mapped
.account_name
, pws
);
490 if (!NT_STATUS_IS_OK(nt_status
)) {
499 /****************************************************************************
500 core of password checking routine
501 ****************************************************************************/
502 static NTSTATUS
password_check(const char *username
, const char *password
,
503 const char *crypted
, const char *salt
)
508 if (afs_auth(username
, password
))
510 #endif /* WITH_AFS */
513 if (dfs_auth(username
, password
))
515 #endif /* WITH_DFS */
519 ret
= (strcmp(osf1_bigcrypt(password
, salt
), crypted
) == 0);
523 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
524 ret
= (strcmp((char *)crypt(password
, salt
), crypted
) == 0);
529 return NT_STATUS_WRONG_PASSWORD
;
532 #endif /* OSF1_ENH_SEC */
535 ret
= (strcmp((char *)crypt16(password
, salt
), crypted
) == 0);
539 return NT_STATUS_WRONG_PASSWORD
;
542 #endif /* ULTRIX_AUTH */
544 #ifdef LINUX_BIGCRYPT
545 ret
= (linux_bigcrypt(password
, salt
, crypted
));
549 return NT_STATUS_WRONG_PASSWORD
;
551 #endif /* LINUX_BIGCRYPT */
553 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
556 * Some systems have bigcrypt in the C library but might not
557 * actually use it for the password hashes (HPUX 10.20) is
558 * a noteable example. So we try bigcrypt first, followed
562 if (strcmp(bigcrypt(password
, salt
), crypted
) == 0)
565 ret
= (strcmp((char *)crypt(password
, salt
), crypted
) == 0);
569 return NT_STATUS_WRONG_PASSWORD
;
571 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
574 ret
= (strcmp(bigcrypt(password
, salt
), crypted
) == 0);
578 return NT_STATUS_WRONG_PASSWORD
;
580 #endif /* HAVE_BIGCRYPT */
583 DEBUG(1, ("Warning - no crypt available\n"));
584 return NT_STATUS_LOGON_FAILURE
;
585 #else /* HAVE_CRYPT */
586 ret
= (strcmp((char *)crypt(password
, salt
), crypted
) == 0);
590 return NT_STATUS_WRONG_PASSWORD
;
592 #endif /* HAVE_CRYPT */
593 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
596 static NTSTATUS
check_unix_password(TALLOC_CTX
*ctx
, struct loadparm_context
*lp_ctx
,
597 const struct auth_usersupplied_info
*user_info
, struct passwd
**ret_passwd
)
606 int level
= lp_passwordlevel(lp_ctx
);
610 username
= talloc_strdup(ctx
, user_info
->mapped
.account_name
);
611 password
= talloc_strdup(ctx
, user_info
->password
.plaintext
);
613 nt_status
= talloc_getpwnam(ctx
, username
, &pws
);
614 if (!NT_STATUS_IS_OK(nt_status
)) {
618 crypted
= pws
->pw_passwd
;
619 salt
= pws
->pw_passwd
;
625 /* many shadow systems require you to be root to get
626 the password, in most cases this should already be
627 the case when this function is called, except
628 perhaps for IPC password changing requests */
630 spass
= getspnam(pws
->pw_name
);
631 if (spass
&& spass
->sp_pwdp
) {
632 crypted
= talloc_strdup(ctx
, spass
->sp_pwdp
);
633 NT_STATUS_HAVE_NO_MEMORY(crypted
);
634 salt
= talloc_strdup(ctx
, spass
->sp_pwdp
);
635 NT_STATUS_HAVE_NO_MEMORY(salt
);
638 #elif defined(IA_UINFO)
641 /* Need to get password with SVR4.2's ia_ functions
642 instead of get{sp,pw}ent functions. Required by
643 UnixWare 2.x, tested on version
644 2.1. (tangent@cyberport.com) */
646 if (ia_openinfo(pws
->pw_name
, &uinfo
) != -1) {
647 ia_get_logpwd(uinfo
, &ia_password
);
648 crypted
= talloc_strdup(ctx
, ia_password
);
649 NT_STATUS_HAVE_NO_MEMORY(crypted
);
654 #ifdef HAVE_GETPRPWNAM
656 struct pr_passwd
*pr_pw
= getprpwnam(pws
->pw_name
);
657 if (pr_pw
&& pr_pw
->ufld
.fd_encrypt
) {
658 crypted
= talloc_strdup(ctx
, pr_pw
->ufld
.fd_encrypt
);
659 NT_STATUS_HAVE_NO_MEMORY(crypted
);
664 #ifdef HAVE_GETPWANAM
666 struct passwd_adjunct
*pwret
;
667 pwret
= getpwanam(s
);
668 if (pwret
&& pwret
->pwa_passwd
) {
669 crypted
= talloc_strdup(ctx
, pwret
->pwa_passwd
);
670 NT_STATUS_HAVE_NO_MEMORY(crypted
);
677 struct pr_passwd
*mypasswd
;
678 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username
));
679 mypasswd
= getprpwnam(username
);
681 username
= talloc_strdup(ctx
, mypasswd
->ufld
.fd_name
);
682 NT_STATUS_HAVE_NO_MEMORY(username
);
683 crypted
= talloc_strdup(ctx
, mypasswd
->ufld
.fd_encrypt
);
684 NT_STATUS_HAVE_NO_MEMORY(crypted
);
686 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username
));
693 AUTHORIZATION
*ap
= getauthuid(pws
->pw_uid
);
695 crypted
= talloc_strdup(ctx
, ap
->a_password
);
697 NT_STATUS_HAVE_NO_MEMORY(crypted
);
702 #if defined(HAVE_TRUNCATED_SALT)
703 /* crypt on some platforms (HPUX in particular)
704 won't work with more than 2 salt characters. */
708 if (crypted
[0] == '\0') {
709 if (!lp_null_passwords(lp_ctx
)) {
710 DEBUG(2, ("Disallowing %s with null password\n", username
));
711 return NT_STATUS_LOGON_FAILURE
;
713 if (password
== NULL
) {
714 DEBUG(3, ("Allowing access to %s with null password\n", username
));
720 /* try it as it came to us */
721 nt_status
= password_check(username
, password
, crypted
, salt
);
722 if (NT_STATUS_IS_OK(nt_status
)) {
726 else if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_WRONG_PASSWORD
)) {
727 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
731 if ( user_info
->flags
| USER_INFO_CASE_INSENSITIVE_PASSWORD
) {
735 /* if the password was given to us with mixed case then we don't
736 * need to proceed as we know it hasn't been case modified by the
738 if (strhasupper(password
) && strhaslower(password
)) {
742 /* make a copy of it */
743 pwcopy
= talloc_strdup(ctx
, password
);
745 return NT_STATUS_NO_MEMORY
;
747 /* try all lowercase if it's currently all uppercase */
748 if (strhasupper(pwcopy
)) {
750 nt_status
= password_check(username
, pwcopy
, crypted
, salt
);
751 if NT_STATUS_IS_OK(nt_status
) {
759 return NT_STATUS_WRONG_PASSWORD
;
762 /* last chance - all combinations of up to level chars upper! */
766 if (NT_STATUS_IS_OK(nt_status
= string_combinations(pwcopy
, password_check
, level
))) {
771 return NT_STATUS_WRONG_PASSWORD
;
776 /** Check a plaintext username/password
780 static NTSTATUS
authunix_want_check(struct auth_method_context
*ctx
,
782 const struct auth_usersupplied_info
*user_info
)
784 if (!user_info
->mapped
.account_name
|| !*user_info
->mapped
.account_name
) {
785 return NT_STATUS_NOT_IMPLEMENTED
;
791 static NTSTATUS
authunix_check_password(struct auth_method_context
*ctx
,
793 const struct auth_usersupplied_info
*user_info
,
794 struct auth_serversupplied_info
**server_info
)
796 TALLOC_CTX
*check_ctx
;
800 if (user_info
->password_state
!= AUTH_PASSWORD_PLAIN
) {
801 return NT_STATUS_INVALID_PARAMETER
;
804 check_ctx
= talloc_named_const(mem_ctx
, 0, "check_unix_password");
805 if (check_ctx
== NULL
) {
806 return NT_STATUS_NO_MEMORY
;
809 nt_status
= check_unix_password(check_ctx
, ctx
->auth_ctx
->lp_ctx
, user_info
, &pwd
);
810 if (!NT_STATUS_IS_OK(nt_status
)) {
811 talloc_free(check_ctx
);
815 nt_status
= authunix_make_server_info(mem_ctx
, lp_netbios_name(ctx
->auth_ctx
->lp_ctx
),
816 user_info
, pwd
, server_info
);
817 if (!NT_STATUS_IS_OK(nt_status
)) {
818 talloc_free(check_ctx
);
822 talloc_free(check_ctx
);
826 static const struct auth_operations unix_ops
= {
828 .get_challenge
= auth_get_challenge_not_implemented
,
829 .want_check
= authunix_want_check
,
830 .check_password
= authunix_check_password
833 _PUBLIC_ NTSTATUS
auth_unix_init(void)
837 ret
= auth_register(&unix_ops
);
838 if (!NT_STATUS_IS_OK(ret
)) {
839 DEBUG(0,("Failed to register unix auth backend!\n"));