dsdb-acl: make use of acl_check_access_on_objectclass() for the object in acl_delete()
[Samba/gebeck_regimport.git] / source4 / auth / ntlm / auth_unix.c
blob57bca6cc5b531da8af13ebb508e6926fca1e43cf
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
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/>.
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"
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,
39 struct passwd *pwd,
40 struct auth_user_info_dc **_user_info_dc)
42 struct auth_user_info_dc *user_info_dc;
43 struct auth_user_info *info;
44 NTSTATUS status;
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)) {
50 return 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);
61 } else {
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);
94 info->last_logon = 0;
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;
106 return NT_STATUS_OK;
109 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
111 struct passwd *ret;
112 struct passwd *from;
114 *pws = NULL;
116 ret = talloc(ctx, struct passwd);
117 NT_STATUS_HAVE_NO_MEMORY(ret);
119 from = getpwnam(username);
120 if (!from) {
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);
141 *pws = ret;
143 return NT_STATUS_OK;
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;
168 int num;
170 if (num_msg <= 0) {
171 *reply = NULL;
172 return PAM_CONV_ERR;
176 * Apparantly HPUX has a buggy PAM that doesn't support the
177 * data pointer. Fail if this is the case. JRA.
180 if (info == NULL) {
181 *reply = NULL;
182 return PAM_CONV_ERR;
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) {
191 return PAM_CONV_ERR;
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);
199 break;
201 case PAM_PROMPT_ECHO_OFF:
202 (*reply)[num].resp_retcode = PAM_SUCCESS;
203 (*reply)[num].resp = COPY_STRING(info->plaintext_password);
204 break;
206 case PAM_TEXT_INFO:
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)));
210 break;
212 case PAM_ERROR_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)));
216 break;
218 default:
219 while (num > 0) {
220 SAFE_FREE((*reply)[num-1].resp);
221 num--;
223 SAFE_FREE(*reply);
224 *reply = NULL;
225 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
226 return PAM_CONV_ERR;
230 return PAM_SUCCESS;
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)
239 int pam_error;
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;
254 #ifdef PAM_RHOST
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) {
258 NTSTATUS nt_status;
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 vaild pamh here, can we reliably call pam_strerror ? */
267 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
268 pam_error));
269 return pam_to_nt_status(pam_error);
271 return nt_status;
273 #endif
274 #ifdef PAM_TTY
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) {
278 NTSTATUS nt_status;
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 vaild pamh here, can we reliably call pam_strerror ? */
287 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
288 pam_error));
289 return pam_to_nt_status(pam_error);
291 return nt_status;
293 #endif
294 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
296 return NT_STATUS_OK;
299 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
301 int pam_error;
303 if (pamh != NULL) {
304 pam_error = pam_end(pamh, 0);
305 if (pam_error != PAM_SUCCESS) {
306 /* no vaild pamh here, can we reliably call pam_strerror ? */
307 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
308 pam_error));
309 return pam_to_nt_status(pam_error);
311 return NT_STATUS_OK;
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)
323 int pam_error;
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);
333 switch( pam_error ){
334 case PAM_AUTH_ERR:
335 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
336 break;
337 case PAM_CRED_INSUFFICIENT:
338 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
339 break;
340 case PAM_AUTHINFO_UNAVAIL:
341 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
342 break;
343 case PAM_USER_UNKNOWN:
344 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
345 break;
346 case PAM_MAXTRIES:
347 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
348 break;
349 case PAM_ABORT:
350 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
351 break;
352 case PAM_SUCCESS:
353 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
354 break;
355 default:
356 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
357 break;
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)
368 int pam_error;
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));
376 break;
377 case PAM_ACCT_EXPIRED:
378 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
379 break;
380 case PAM_AUTH_ERR:
381 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
382 break;
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));
385 break;
386 case PAM_USER_UNKNOWN:
387 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
388 break;
389 case PAM_SUCCESS:
390 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
391 break;
392 default:
393 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
394 break;
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)
406 int pam_error;
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 ));
419 break;
420 case PAM_CRED_EXPIRED:
421 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
422 break;
423 case PAM_USER_UNKNOWN:
424 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
425 break;
426 case PAM_CRED_ERR:
427 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
428 break;
429 case PAM_SUCCESS:
430 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
431 break;
432 default:
433 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
434 break;
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;
445 pam_handle_t *pamh;
446 NTSTATUS nt_status;
448 info = talloc(ctx, struct smb_pam_user_info);
449 if (info == NULL) {
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;
464 /* TODO:
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)) {
472 return 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)) {
477 smb_pam_end(pamh);
478 return 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)) {
485 smb_pam_end(pamh);
486 return nt_status;
489 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
490 if (!NT_STATUS_IS_OK(nt_status)) {
491 smb_pam_end(pamh);
492 return nt_status;
496 smb_pam_end(pamh);
498 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
499 if (!NT_STATUS_IS_OK(nt_status)) {
500 return nt_status;
503 return NT_STATUS_OK;
506 #else
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)
514 bool ret;
516 #ifdef WITH_AFS
517 if (afs_auth(username, password))
518 return NT_STATUS_OK;
519 #endif /* WITH_AFS */
521 #ifdef WITH_DFS
522 if (dfs_auth(username, password))
523 return NT_STATUS_OK;
524 #endif /* WITH_DFS */
526 #ifdef OSF1_ENH_SEC
528 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
530 if (!ret) {
531 DEBUG(2,
532 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
533 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
535 if (ret) {
536 return NT_STATUS_OK;
537 } else {
538 return NT_STATUS_WRONG_PASSWORD;
541 #endif /* OSF1_ENH_SEC */
543 #ifdef ULTRIX_AUTH
544 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
545 if (ret) {
546 return NT_STATUS_OK;
547 } else {
548 return NT_STATUS_WRONG_PASSWORD;
551 #endif /* ULTRIX_AUTH */
553 #ifdef LINUX_BIGCRYPT
554 ret = (linux_bigcrypt(password, salt, crypted));
555 if (ret) {
556 return NT_STATUS_OK;
557 } else {
558 return NT_STATUS_WRONG_PASSWORD;
560 #endif /* LINUX_BIGCRYPT */
562 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
565 * Some systems have bigcrypt in the C library but might not
566 * actually use it for the password hashes (HPUX 10.20) is
567 * a noteable example. So we try bigcrypt first, followed
568 * by crypt.
571 if (strcmp(bigcrypt(password, salt), crypted) == 0)
572 return NT_STATUS_OK;
573 else
574 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
575 if (ret) {
576 return NT_STATUS_OK;
577 } else {
578 return NT_STATUS_WRONG_PASSWORD;
580 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
582 #ifdef HAVE_BIGCRYPT
583 ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
584 if (ret) {
585 return NT_STATUS_OK;
586 } else {
587 return NT_STATUS_WRONG_PASSWORD;
589 #endif /* HAVE_BIGCRYPT */
591 #ifndef HAVE_CRYPT
592 DEBUG(1, ("Warning - no crypt available\n"));
593 return NT_STATUS_LOGON_FAILURE;
594 #else /* HAVE_CRYPT */
595 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
596 if (ret) {
597 return NT_STATUS_OK;
598 } else {
599 return NT_STATUS_WRONG_PASSWORD;
601 #endif /* HAVE_CRYPT */
602 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
605 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
606 const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
608 char *username;
609 char *password;
610 char *salt;
611 char *crypted;
612 struct passwd *pws;
613 NTSTATUS nt_status;
615 *ret_passwd = NULL;
617 username = talloc_strdup(ctx, user_info->mapped.account_name);
618 password = talloc_strdup(ctx, user_info->password.plaintext);
620 nt_status = talloc_getpwnam(ctx, username, &pws);
621 if (!NT_STATUS_IS_OK(nt_status)) {
622 return nt_status;
625 crypted = pws->pw_passwd;
626 salt = pws->pw_passwd;
628 #ifdef HAVE_GETSPNAM
630 struct spwd *spass;
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 */
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);
645 #elif defined(IA_UINFO)
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);
659 #endif
661 #ifdef HAVE_GETPRPWNAM
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);
669 #endif
671 #ifdef HAVE_GETPWANAM
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);
680 #endif
682 #ifdef OSF1_ENH_SEC
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));
696 #endif
698 #ifdef ULTRIX_AUTH
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);
707 #endif
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
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;
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;
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;
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;
738 /* we no longer try different case combinations here. The use
739 * of this code is now web auth, where trying different case
740 * combinations makes no sense
743 return NT_STATUS_WRONG_PASSWORD;
746 #endif
748 /** Check a plaintext username/password
752 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
753 TALLOC_CTX *mem_ctx,
754 const struct auth_usersupplied_info *user_info)
756 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
757 return NT_STATUS_NOT_IMPLEMENTED;
760 return NT_STATUS_OK;
763 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
764 TALLOC_CTX *mem_ctx,
765 const struct auth_usersupplied_info *user_info,
766 struct auth_user_info_dc **user_info_dc)
768 TALLOC_CTX *check_ctx;
769 NTSTATUS nt_status;
770 struct passwd *pwd;
772 if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
773 return NT_STATUS_INVALID_PARAMETER;
776 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
777 if (check_ctx == NULL) {
778 return NT_STATUS_NO_MEMORY;
781 nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd);
782 if (!NT_STATUS_IS_OK(nt_status)) {
783 talloc_free(check_ctx);
784 return nt_status;
787 nt_status = authunix_make_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
788 user_info, pwd, user_info_dc);
789 if (!NT_STATUS_IS_OK(nt_status)) {
790 talloc_free(check_ctx);
791 return nt_status;
794 talloc_free(check_ctx);
795 return NT_STATUS_OK;
798 static const struct auth_operations unix_ops = {
799 .name = "unix",
800 .want_check = authunix_want_check,
801 .check_password = authunix_check_password
804 _PUBLIC_ NTSTATUS auth4_unix_init(void)
806 NTSTATUS ret;
808 ret = auth_register(&unix_ops);
809 if (!NT_STATUS_IS_OK(ret)) {
810 DEBUG(0,("Failed to register unix auth backend!\n"));
811 return ret;
814 return ret;