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 "lib/tsocket/tsocket.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "param/param.h"
31 _PUBLIC_ NTSTATUS
auth4_unix_init(void);
33 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
34 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
36 static NTSTATUS
authunix_make_user_info_dc(TALLOC_CTX
*mem_ctx
,
37 const char *netbios_name
,
38 const struct auth_usersupplied_info
*user_info
,
40 struct auth_user_info_dc
**_user_info_dc
)
42 struct auth_user_info_dc
*user_info_dc
;
43 struct auth_user_info
*info
;
46 /* This is a real, real hack */
47 if (pwd
->pw_uid
== 0) {
48 status
= auth_system_user_info_dc(mem_ctx
, netbios_name
, &user_info_dc
);
49 if (!NT_STATUS_IS_OK(status
)) {
53 user_info_dc
->info
= info
= talloc_zero(user_info_dc
, struct auth_user_info
);
54 NT_STATUS_HAVE_NO_MEMORY(user_info_dc
->info
);
56 info
->account_name
= talloc_steal(info
, pwd
->pw_name
);
57 NT_STATUS_HAVE_NO_MEMORY(info
->account_name
);
59 info
->domain_name
= talloc_strdup(info
, "unix");
60 NT_STATUS_HAVE_NO_MEMORY(info
->domain_name
);
62 user_info_dc
= talloc(mem_ctx
, struct auth_user_info_dc
);
63 NT_STATUS_HAVE_NO_MEMORY(user_info_dc
);
65 user_info_dc
->info
= info
= talloc_zero(user_info_dc
, struct auth_user_info
);
66 NT_STATUS_HAVE_NO_MEMORY(user_info_dc
->info
);
68 info
->authenticated
= true;
70 info
->account_name
= talloc_steal(info
, pwd
->pw_name
);
71 NT_STATUS_HAVE_NO_MEMORY(info
->account_name
);
73 info
->domain_name
= talloc_strdup(info
, "unix");
74 NT_STATUS_HAVE_NO_MEMORY(info
->domain_name
);
76 /* This isn't in any way correct.. */
77 user_info_dc
->num_sids
= 0;
78 user_info_dc
->sids
= NULL
;
80 user_info_dc
->user_session_key
= data_blob(NULL
,0);
81 user_info_dc
->lm_session_key
= data_blob(NULL
,0);
83 info
->full_name
= talloc_steal(info
, pwd
->pw_gecos
);
84 NT_STATUS_HAVE_NO_MEMORY(info
->full_name
);
85 info
->logon_script
= talloc_strdup(info
, "");
86 NT_STATUS_HAVE_NO_MEMORY(info
->logon_script
);
87 info
->profile_path
= talloc_strdup(info
, "");
88 NT_STATUS_HAVE_NO_MEMORY(info
->profile_path
);
89 info
->home_directory
= talloc_strdup(info
, "");
90 NT_STATUS_HAVE_NO_MEMORY(info
->home_directory
);
91 info
->home_drive
= talloc_strdup(info
, "");
92 NT_STATUS_HAVE_NO_MEMORY(info
->home_drive
);
95 info
->last_logoff
= 0;
96 info
->acct_expiry
= 0;
97 info
->last_password_change
= 0;
98 info
->allow_password_change
= 0;
99 info
->force_password_change
= 0;
100 info
->logon_count
= 0;
101 info
->bad_password_count
= 0;
102 info
->acct_flags
= 0;
104 *_user_info_dc
= user_info_dc
;
109 static NTSTATUS
talloc_getpwnam(TALLOC_CTX
*ctx
, const char *username
, struct passwd
**pws
)
116 ret
= talloc(ctx
, struct passwd
);
117 NT_STATUS_HAVE_NO_MEMORY(ret
);
119 from
= getpwnam(username
);
121 return NT_STATUS_NO_SUCH_USER
;
124 ret
->pw_name
= talloc_strdup(ctx
, from
->pw_name
);
125 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_name
);
127 ret
->pw_passwd
= talloc_strdup(ctx
, from
->pw_passwd
);
128 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_passwd
);
130 ret
->pw_uid
= from
->pw_uid
;
131 ret
->pw_gid
= from
->pw_gid
;
132 ret
->pw_gecos
= talloc_strdup(ctx
, from
->pw_gecos
);
133 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_gecos
);
135 ret
->pw_dir
= talloc_strdup(ctx
, from
->pw_dir
);
136 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_dir
);
138 ret
->pw_shell
= talloc_strdup(ctx
, from
->pw_shell
);
139 NT_STATUS_HAVE_NO_MEMORY(ret
->pw_shell
);
147 #ifdef HAVE_SECURITY_PAM_APPL_H
148 #include <security/pam_appl.h>
150 struct smb_pam_user_info
{
151 const char *account_name
;
152 const char *plaintext_password
;
155 #define COPY_STRING(s) (s) ? strdup(s) : NULL
158 * Check user password
159 * Currently it uses PAM only and fails on systems without PAM
160 * Samba3 code located in pass_check.c is to ugly to be used directly it will
161 * need major rework that's why pass_check.c is still there.
164 static int smb_pam_conv(int num_msg
, const struct pam_message
**msg
,
165 struct pam_response
**reply
, void *appdata_ptr
)
167 struct smb_pam_user_info
*info
= (struct smb_pam_user_info
*)appdata_ptr
;
176 * Apparantly HPUX has a buggy PAM that doesn't support the
177 * data pointer. Fail if this is the case. JRA.
186 * PAM frees memory in reply messages by itself
187 * so use malloc instead of talloc here.
189 *reply
= malloc_array_p(struct pam_response
, num_msg
);
190 if (*reply
== NULL
) {
194 for (num
= 0; num
< num_msg
; num
++) {
195 switch (msg
[num
]->msg_style
) {
196 case PAM_PROMPT_ECHO_ON
:
197 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
198 (*reply
)[num
].resp
= COPY_STRING(info
->account_name
);
201 case PAM_PROMPT_ECHO_OFF
:
202 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
203 (*reply
)[num
].resp
= COPY_STRING(info
->plaintext_password
);
207 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
208 (*reply
)[num
].resp
= NULL
;
209 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg
[num
]->msg
)));
213 (*reply
)[num
].resp_retcode
= PAM_SUCCESS
;
214 (*reply
)[num
].resp
= NULL
;
215 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg
[num
]->msg
)));
220 SAFE_FREE((*reply
)[num
-1].resp
);
225 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
234 * Start PAM authentication for specified account
237 static NTSTATUS
smb_pam_start(pam_handle_t
**pamh
, const char *account_name
, const char *remote_host
, struct pam_conv
*pconv
)
241 if (account_name
== NULL
|| remote_host
== NULL
) {
242 return NT_STATUS_INVALID_PARAMETER
;
245 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name
));
247 pam_error
= pam_start("samba", account_name
, pconv
, pamh
);
248 if (pam_error
!= PAM_SUCCESS
) {
249 /* no valid pamh here, can we reliably call pam_strerror ? */
250 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
251 return NT_STATUS_UNSUCCESSFUL
;
255 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host
));
256 pam_error
= pam_set_item(*pamh
, PAM_RHOST
, remote_host
);
257 if (pam_error
!= PAM_SUCCESS
) {
260 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
261 pam_strerror(*pamh
, pam_error
)));
262 nt_status
= pam_to_nt_status(pam_error
);
264 pam_error
= pam_end(*pamh
, 0);
265 if (pam_error
!= PAM_SUCCESS
) {
266 /* no valid pamh here, can we reliably call pam_strerror ? */
267 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
269 return pam_to_nt_status(pam_error
);
275 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
276 pam_error
= pam_set_item(*pamh
, PAM_TTY
, "samba");
277 if (pam_error
!= PAM_SUCCESS
) {
280 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
281 pam_strerror(*pamh
, pam_error
)));
282 nt_status
= pam_to_nt_status(pam_error
);
284 pam_error
= pam_end(*pamh
, 0);
285 if (pam_error
!= PAM_SUCCESS
) {
286 /* no valid pamh here, can we reliably call pam_strerror ? */
287 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
289 return pam_to_nt_status(pam_error
);
294 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name
));
299 static NTSTATUS
smb_pam_end(pam_handle_t
*pamh
)
304 pam_error
= pam_end(pamh
, 0);
305 if (pam_error
!= PAM_SUCCESS
) {
306 /* no valid pamh here, can we reliably call pam_strerror ? */
307 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
309 return pam_to_nt_status(pam_error
);
314 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
315 return NT_STATUS_UNSUCCESSFUL
;
319 * PAM Authentication Handler
321 static NTSTATUS
smb_pam_auth(pam_handle_t
*pamh
, bool allow_null_passwords
, const char *user
)
326 * To enable debugging set in /etc/pam.d/samba:
327 * auth required /lib/security/pam_pwdb.so nullok shadow audit
330 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user
));
332 pam_error
= pam_authenticate(pamh
, PAM_SILENT
| allow_null_passwords
? 0 : PAM_DISALLOW_NULL_AUTHTOK
);
335 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user
));
337 case PAM_CRED_INSUFFICIENT
:
338 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user
));
340 case PAM_AUTHINFO_UNAVAIL
:
341 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user
));
343 case PAM_USER_UNKNOWN
:
344 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user
));
347 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user
));
350 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user
));
353 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user
));
356 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user
));
360 return pam_to_nt_status(pam_error
);
364 * PAM Account Handler
366 static NTSTATUS
smb_pam_account(pam_handle_t
*pamh
, const char * user
)
370 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user
));
372 pam_error
= pam_acct_mgmt(pamh
, PAM_SILENT
); /* Is user account enabled? */
373 switch( pam_error
) {
374 case PAM_AUTHTOK_EXPIRED
:
375 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user
));
377 case PAM_ACCT_EXPIRED
:
378 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user
));
381 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user
));
383 case PAM_PERM_DENIED
:
384 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user
));
386 case PAM_USER_UNKNOWN
:
387 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user
));
390 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user
));
393 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error
, user
));
397 return pam_to_nt_status(pam_error
);
401 * PAM Credential Setting
404 static NTSTATUS
smb_pam_setcred(pam_handle_t
*pamh
, const char * user
)
409 * This will allow samba to aquire a kerberos token. And, when
410 * exporting an AFS cell, be able to /write/ to this cell.
413 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user
));
415 pam_error
= pam_setcred(pamh
, (PAM_ESTABLISH_CRED
|PAM_SILENT
));
416 switch( pam_error
) {
417 case PAM_CRED_UNAVAIL
:
418 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user
));
420 case PAM_CRED_EXPIRED
:
421 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user
));
423 case PAM_USER_UNKNOWN
:
424 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user
));
427 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user
));
430 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user
));
433 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error
, user
));
437 return pam_to_nt_status(pam_error
);
440 static NTSTATUS
check_unix_password(TALLOC_CTX
*ctx
, struct loadparm_context
*lp_ctx
,
441 const struct auth_usersupplied_info
*user_info
, struct passwd
**pws
)
443 struct smb_pam_user_info
*info
;
444 struct pam_conv
*pamconv
;
448 info
= talloc(ctx
, struct smb_pam_user_info
);
450 return NT_STATUS_NO_MEMORY
;
453 info
->account_name
= user_info
->mapped
.account_name
;
454 info
->plaintext_password
= user_info
->password
.plaintext
;
456 pamconv
= talloc(ctx
, struct pam_conv
);
457 if (pamconv
== NULL
) {
458 return NT_STATUS_NO_MEMORY
;
461 pamconv
->conv
= smb_pam_conv
;
462 pamconv
->appdata_ptr
= (void *)info
;
465 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
466 * if true set up a crack name routine.
469 nt_status
= smb_pam_start(&pamh
, user_info
->mapped
.account_name
,
470 user_info
->remote_host
? tsocket_address_inet_addr_string(user_info
->remote_host
, ctx
) : NULL
, pamconv
);
471 if (!NT_STATUS_IS_OK(nt_status
)) {
475 nt_status
= smb_pam_auth(pamh
, lpcfg_null_passwords(lp_ctx
), user_info
->mapped
.account_name
);
476 if (!NT_STATUS_IS_OK(nt_status
)) {
481 if ( ! (user_info
->flags
& USER_INFO_DONT_CHECK_UNIX_ACCOUNT
)) {
483 nt_status
= smb_pam_account(pamh
, user_info
->mapped
.account_name
);
484 if (!NT_STATUS_IS_OK(nt_status
)) {
489 nt_status
= smb_pam_setcred(pamh
, user_info
->mapped
.account_name
);
490 if (!NT_STATUS_IS_OK(nt_status
)) {
498 nt_status
= talloc_getpwnam(ctx
, user_info
->mapped
.account_name
, pws
);
499 if (!NT_STATUS_IS_OK(nt_status
)) {
508 /****************************************************************************
509 core of password checking routine
510 ****************************************************************************/
511 static NTSTATUS
password_check(const char *username
, const char *password
,
512 const char *crypted
, const char *salt
)
520 ret
= (strcmp(osf1_bigcrypt(password
, salt
), crypted
) == 0);
524 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
525 ret
= (strcmp((char *)crypt(password
, salt
), crypted
) == 0);
530 return NT_STATUS_WRONG_PASSWORD
;
533 #endif /* OSF1_ENH_SEC */
536 ret
= (strcmp((char *)crypt16(password
, salt
), crypted
) == 0);
540 return NT_STATUS_WRONG_PASSWORD
;
543 #endif /* ULTRIX_AUTH */
548 ret
= (strcmp(bigcrypt(password
, salt
), crypted
) == 0);
552 return NT_STATUS_WRONG_PASSWORD
;
554 #endif /* HAVE_BIGCRYPT */
557 DEBUG(1, ("Warning - no crypt available\n"));
558 return NT_STATUS_LOGON_FAILURE
;
559 #else /* HAVE_CRYPT */
560 ret
= (strcmp((char *)crypt(password
, salt
), crypted
) == 0);
564 return NT_STATUS_WRONG_PASSWORD
;
566 #endif /* HAVE_CRYPT */
569 static NTSTATUS
check_unix_password(TALLOC_CTX
*ctx
, struct loadparm_context
*lp_ctx
,
570 const struct auth_usersupplied_info
*user_info
, struct passwd
**ret_passwd
)
581 username
= talloc_strdup(ctx
, user_info
->mapped
.account_name
);
582 password
= talloc_strdup(ctx
, user_info
->password
.plaintext
);
584 nt_status
= talloc_getpwnam(ctx
, username
, &pws
);
585 if (!NT_STATUS_IS_OK(nt_status
)) {
589 crypted
= pws
->pw_passwd
;
590 salt
= pws
->pw_passwd
;
596 /* many shadow systems require you to be root to get
597 the password, in most cases this should already be
598 the case when this function is called, except
599 perhaps for IPC password changing requests */
601 spass
= getspnam(pws
->pw_name
);
602 if (spass
&& spass
->sp_pwdp
) {
603 crypted
= talloc_strdup(ctx
, spass
->sp_pwdp
);
604 NT_STATUS_HAVE_NO_MEMORY(crypted
);
605 salt
= talloc_strdup(ctx
, spass
->sp_pwdp
);
606 NT_STATUS_HAVE_NO_MEMORY(salt
);
609 #elif defined(IA_UINFO)
612 /* Need to get password with SVR4.2's ia_ functions
613 instead of get{sp,pw}ent functions. Required by
614 UnixWare 2.x, tested on version
615 2.1. (tangent@cyberport.com) */
617 if (ia_openinfo(pws
->pw_name
, &uinfo
) != -1) {
618 ia_get_logpwd(uinfo
, &ia_password
);
619 crypted
= talloc_strdup(ctx
, ia_password
);
620 NT_STATUS_HAVE_NO_MEMORY(crypted
);
626 #ifdef HAVE_GETPWANAM
628 struct passwd_adjunct
*pwret
;
629 pwret
= getpwanam(s
);
630 if (pwret
&& pwret
->pwa_passwd
) {
631 crypted
= talloc_strdup(ctx
, pwret
->pwa_passwd
);
632 NT_STATUS_HAVE_NO_MEMORY(crypted
);
639 struct pr_passwd
*mypasswd
;
640 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username
));
641 mypasswd
= getprpwnam(username
);
643 username
= talloc_strdup(ctx
, mypasswd
->ufld
.fd_name
);
644 NT_STATUS_HAVE_NO_MEMORY(username
);
645 crypted
= talloc_strdup(ctx
, mypasswd
->ufld
.fd_encrypt
);
646 NT_STATUS_HAVE_NO_MEMORY(crypted
);
648 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username
));
655 AUTHORIZATION
*ap
= getauthuid(pws
->pw_uid
);
657 crypted
= talloc_strdup(ctx
, ap
->a_password
);
659 NT_STATUS_HAVE_NO_MEMORY(crypted
);
665 if (crypted
[0] == '\0') {
666 if (!lpcfg_null_passwords(lp_ctx
)) {
667 DEBUG(2, ("Disallowing %s with null password\n", username
));
668 return NT_STATUS_LOGON_FAILURE
;
670 if (password
== NULL
) {
671 DEBUG(3, ("Allowing access to %s with null password\n", username
));
677 /* try it as it came to us */
678 nt_status
= password_check(username
, password
, crypted
, salt
);
679 if (NT_STATUS_IS_OK(nt_status
)) {
683 else if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_WRONG_PASSWORD
)) {
684 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
688 /* we no longer try different case combinations here. The use
689 * of this code is now web auth, where trying different case
690 * combinations makes no sense
693 return NT_STATUS_WRONG_PASSWORD
;
698 /** Check a plaintext username/password
702 static NTSTATUS
authunix_want_check(struct auth_method_context
*ctx
,
704 const struct auth_usersupplied_info
*user_info
)
706 if (!user_info
->mapped
.account_name
|| !*user_info
->mapped
.account_name
) {
707 return NT_STATUS_NOT_IMPLEMENTED
;
713 static NTSTATUS
authunix_check_password(struct auth_method_context
*ctx
,
715 const struct auth_usersupplied_info
*user_info
,
716 struct auth_user_info_dc
**user_info_dc
)
718 TALLOC_CTX
*check_ctx
;
722 if (user_info
->password_state
!= AUTH_PASSWORD_PLAIN
) {
723 return NT_STATUS_INVALID_PARAMETER
;
726 check_ctx
= talloc_named_const(mem_ctx
, 0, "check_unix_password");
727 if (check_ctx
== NULL
) {
728 return NT_STATUS_NO_MEMORY
;
731 nt_status
= check_unix_password(check_ctx
, ctx
->auth_ctx
->lp_ctx
, user_info
, &pwd
);
732 if (!NT_STATUS_IS_OK(nt_status
)) {
733 talloc_free(check_ctx
);
737 nt_status
= authunix_make_user_info_dc(mem_ctx
, lpcfg_netbios_name(ctx
->auth_ctx
->lp_ctx
),
738 user_info
, pwd
, user_info_dc
);
739 if (!NT_STATUS_IS_OK(nt_status
)) {
740 talloc_free(check_ctx
);
744 talloc_free(check_ctx
);
748 static const struct auth_operations unix_ops
= {
750 .want_check
= authunix_want_check
,
751 .check_password
= authunix_check_password
754 _PUBLIC_ NTSTATUS
auth4_unix_init(void)
758 ret
= auth_register(&unix_ops
);
759 if (!NT_STATUS_IS_OK(ret
)) {
760 DEBUG(0,("Failed to register unix auth backend!\n"));