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 "auth/ntlm/pam_errors.h"
29 #include "param/param.h"
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
34 static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx,
35 const char *netbios_name,
36 const struct auth_usersupplied_info *user_info,
38 struct auth_serversupplied_info **_server_info)
40 struct auth_serversupplied_info *server_info;
43 /* This is a real, real hack */
44 if (pwd->pw_uid == 0) {
45 status = auth_system_server_info(mem_ctx, netbios_name, &server_info);
46 if (!NT_STATUS_IS_OK(status)) {
50 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
51 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
53 server_info->domain_name = talloc_strdup(server_info, "unix");
54 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
56 server_info = talloc(mem_ctx, struct auth_serversupplied_info);
57 NT_STATUS_HAVE_NO_MEMORY(server_info);
59 server_info->authenticated = true;
61 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
62 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
64 server_info->domain_name = talloc_strdup(server_info, "unix");
65 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
67 /* This isn't in any way correct.. */
68 server_info->account_sid = NULL;
69 server_info->primary_group_sid = NULL;
70 server_info->n_domain_groups = 0;
71 server_info->domain_groups = NULL;
73 server_info->user_session_key = data_blob(NULL,0);
74 server_info->lm_session_key = data_blob(NULL,0);
76 server_info->full_name = talloc_steal(server_info, pwd->pw_gecos);
77 NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
78 server_info->logon_script = talloc_strdup(server_info, "");
79 NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
80 server_info->profile_path = talloc_strdup(server_info, "");
81 NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
82 server_info->home_directory = talloc_strdup(server_info, "");
83 NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
84 server_info->home_drive = talloc_strdup(server_info, "");
85 NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
87 server_info->last_logon = 0;
88 server_info->last_logoff = 0;
89 server_info->acct_expiry = 0;
90 server_info->last_password_change = 0;
91 server_info->allow_password_change = 0;
92 server_info->force_password_change = 0;
93 server_info->logon_count = 0;
94 server_info->bad_password_count = 0;
95 server_info->acct_flags = 0;
97 *_server_info = server_info;
102 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
109 ret = talloc(ctx, struct passwd);
110 NT_STATUS_HAVE_NO_MEMORY(ret);
112 from = getpwnam(username);
114 return NT_STATUS_NO_SUCH_USER;
117 ret->pw_name = talloc_strdup(ctx, from->pw_name);
118 NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
120 ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
121 NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
123 ret->pw_uid = from->pw_uid;
124 ret->pw_gid = from->pw_gid;
125 ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
126 NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
128 ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
129 NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
131 ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
132 NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
140 #ifdef HAVE_SECURITY_PAM_APPL_H
141 #include <security/pam_appl.h>
143 struct smb_pam_user_info {
144 const char *account_name;
145 const char *plaintext_password;
148 #define COPY_STRING(s) (s) ? strdup(s) : NULL
151 * Check user password
152 * Currently it uses PAM only and fails on systems without PAM
153 * Samba3 code located in pass_check.c is to ugly to be used directly it will
154 * need major rework that's why pass_check.c is still there.
157 static int smb_pam_conv(int num_msg, const struct pam_message **msg,
158 struct pam_response **reply, void *appdata_ptr)
160 struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr;
169 * Apparantly HPUX has a buggy PAM that doesn't support the
170 * data pointer. Fail if this is the case. JRA.
179 * PAM frees memory in reply messages by itself
180 * so use malloc instead of talloc here.
182 *reply = malloc_array_p(struct pam_response, num_msg);
183 if (*reply == NULL) {
187 for (num = 0; num < num_msg; num++) {
188 switch (msg[num]->msg_style) {
189 case PAM_PROMPT_ECHO_ON:
190 (*reply)[num].resp_retcode = PAM_SUCCESS;
191 (*reply)[num].resp = COPY_STRING(info->account_name);
194 case PAM_PROMPT_ECHO_OFF:
195 (*reply)[num].resp_retcode = PAM_SUCCESS;
196 (*reply)[num].resp = COPY_STRING(info->plaintext_password);
200 (*reply)[num].resp_retcode = PAM_SUCCESS;
201 (*reply)[num].resp = NULL;
202 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
206 (*reply)[num].resp_retcode = PAM_SUCCESS;
207 (*reply)[num].resp = NULL;
208 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg)));
213 SAFE_FREE((*reply)[num-1].resp);
218 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
227 * Start PAM authentication for specified account
230 static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
234 if (account_name == NULL || remote_host == NULL) {
235 return NT_STATUS_INVALID_PARAMETER;
238 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name));
240 pam_error = pam_start("samba", account_name, pconv, pamh);
241 if (pam_error != PAM_SUCCESS) {
242 /* no valid pamh here, can we reliably call pam_strerror ? */
243 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
244 return NT_STATUS_UNSUCCESSFUL;
248 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
249 pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
250 if (pam_error != PAM_SUCCESS) {
253 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
254 pam_strerror(*pamh, pam_error)));
255 nt_status = pam_to_nt_status(pam_error);
257 pam_error = pam_end(*pamh, 0);
258 if (pam_error != PAM_SUCCESS) {
259 /* no vaild pamh here, can we reliably call pam_strerror ? */
260 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
262 return pam_to_nt_status(pam_error);
268 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
269 pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
270 if (pam_error != PAM_SUCCESS) {
273 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
274 pam_strerror(*pamh, pam_error)));
275 nt_status = pam_to_nt_status(pam_error);
277 pam_error = pam_end(*pamh, 0);
278 if (pam_error != PAM_SUCCESS) {
279 /* no vaild pamh here, can we reliably call pam_strerror ? */
280 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
282 return pam_to_nt_status(pam_error);
287 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
292 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
297 pam_error = pam_end(pamh, 0);
298 if (pam_error != PAM_SUCCESS) {
299 /* no vaild pamh here, can we reliably call pam_strerror ? */
300 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
302 return pam_to_nt_status(pam_error);
307 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
308 return NT_STATUS_UNSUCCESSFUL;
312 * PAM Authentication Handler
314 static NTSTATUS smb_pam_auth(pam_handle_t *pamh, bool allow_null_passwords, const char *user)
319 * To enable debugging set in /etc/pam.d/samba:
320 * auth required /lib/security/pam_pwdb.so nullok shadow audit
323 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
325 pam_error = pam_authenticate(pamh, PAM_SILENT | allow_null_passwords ? 0 : PAM_DISALLOW_NULL_AUTHTOK);
328 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
330 case PAM_CRED_INSUFFICIENT:
331 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
333 case PAM_AUTHINFO_UNAVAIL:
334 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
336 case PAM_USER_UNKNOWN:
337 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
340 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
343 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
346 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
349 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
353 return pam_to_nt_status(pam_error);
357 * PAM Account Handler
359 static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
363 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
365 pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
366 switch( pam_error ) {
367 case PAM_AUTHTOK_EXPIRED:
368 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
370 case PAM_ACCT_EXPIRED:
371 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
374 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
376 case PAM_PERM_DENIED:
377 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
379 case PAM_USER_UNKNOWN:
380 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
383 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
386 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
390 return pam_to_nt_status(pam_error);
394 * PAM Credential Setting
397 static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
402 * This will allow samba to aquire a kerberos token. And, when
403 * exporting an AFS cell, be able to /write/ to this cell.
406 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
408 pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT));
409 switch( pam_error ) {
410 case PAM_CRED_UNAVAIL:
411 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
413 case PAM_CRED_EXPIRED:
414 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
416 case PAM_USER_UNKNOWN:
417 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
420 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
423 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
426 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
430 return pam_to_nt_status(pam_error);
433 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
434 const struct auth_usersupplied_info *user_info, struct passwd **pws)
436 struct smb_pam_user_info *info;
437 struct pam_conv *pamconv;
441 info = talloc(ctx, struct smb_pam_user_info);
443 return NT_STATUS_NO_MEMORY;
446 info->account_name = user_info->mapped.account_name;
447 info->plaintext_password = user_info->password.plaintext;
449 pamconv = talloc(ctx, struct pam_conv);
450 if (pamconv == NULL) {
451 return NT_STATUS_NO_MEMORY;
454 pamconv->conv = smb_pam_conv;
455 pamconv->appdata_ptr = (void *)info;
458 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
459 * if true set up a crack name routine.
462 nt_status = smb_pam_start(&pamh, user_info->mapped.account_name,
463 user_info->remote_host ? tsocket_address_inet_addr_string(user_info->remote_host, ctx) : NULL, pamconv);
464 if (!NT_STATUS_IS_OK(nt_status)) {
468 nt_status = smb_pam_auth(pamh, lp_null_passwords(lp_ctx), user_info->mapped.account_name);
469 if (!NT_STATUS_IS_OK(nt_status)) {
474 if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
476 nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
477 if (!NT_STATUS_IS_OK(nt_status)) {
482 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
483 if (!NT_STATUS_IS_OK(nt_status)) {
491 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
492 if (!NT_STATUS_IS_OK(nt_status)) {
501 /****************************************************************************
502 core of password checking routine
503 ****************************************************************************/
504 static NTSTATUS password_check(const char *username, const char *password,
505 const char *crypted, const char *salt)
510 if (afs_auth(username, password))
512 #endif /* WITH_AFS */
515 if (dfs_auth(username, password))
517 #endif /* WITH_DFS */
521 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
525 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
526 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
531 return NT_STATUS_WRONG_PASSWORD;
534 #endif /* OSF1_ENH_SEC */
537 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
541 return NT_STATUS_WRONG_PASSWORD;
544 #endif /* ULTRIX_AUTH */
546 #ifdef LINUX_BIGCRYPT
547 ret = (linux_bigcrypt(password, salt, crypted));
551 return NT_STATUS_WRONG_PASSWORD;
553 #endif /* LINUX_BIGCRYPT */
555 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
558 * Some systems have bigcrypt in the C library but might not
559 * actually use it for the password hashes (HPUX 10.20) is
560 * a noteable example. So we try bigcrypt first, followed
564 if (strcmp(bigcrypt(password, salt), crypted) == 0)
567 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
571 return NT_STATUS_WRONG_PASSWORD;
573 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
576 ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
580 return NT_STATUS_WRONG_PASSWORD;
582 #endif /* HAVE_BIGCRYPT */
585 DEBUG(1, ("Warning - no crypt available\n"));
586 return NT_STATUS_LOGON_FAILURE;
587 #else /* HAVE_CRYPT */
588 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
592 return NT_STATUS_WRONG_PASSWORD;
594 #endif /* HAVE_CRYPT */
595 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
598 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
599 const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
608 int level = lp_passwordlevel(lp_ctx);
612 username = talloc_strdup(ctx, user_info->mapped.account_name);
613 password = talloc_strdup(ctx, user_info->password.plaintext);
615 nt_status = talloc_getpwnam(ctx, username, &pws);
616 if (!NT_STATUS_IS_OK(nt_status)) {
620 crypted = pws->pw_passwd;
621 salt = pws->pw_passwd;
627 /* many shadow systems require you to be root to get
628 the password, in most cases this should already be
629 the case when this function is called, except
630 perhaps for IPC password changing requests */
632 spass = getspnam(pws->pw_name);
633 if (spass && spass->sp_pwdp) {
634 crypted = talloc_strdup(ctx, spass->sp_pwdp);
635 NT_STATUS_HAVE_NO_MEMORY(crypted);
636 salt = talloc_strdup(ctx, spass->sp_pwdp);
637 NT_STATUS_HAVE_NO_MEMORY(salt);
640 #elif defined(IA_UINFO)
643 /* Need to get password with SVR4.2's ia_ functions
644 instead of get{sp,pw}ent functions. Required by
645 UnixWare 2.x, tested on version
646 2.1. (tangent@cyberport.com) */
648 if (ia_openinfo(pws->pw_name, &uinfo) != -1) {
649 ia_get_logpwd(uinfo, &ia_password);
650 crypted = talloc_strdup(ctx, ia_password);
651 NT_STATUS_HAVE_NO_MEMORY(crypted);
656 #ifdef HAVE_GETPRPWNAM
658 struct pr_passwd *pr_pw = getprpwnam(pws->pw_name);
659 if (pr_pw && pr_pw->ufld.fd_encrypt) {
660 crypted = talloc_strdup(ctx, pr_pw->ufld.fd_encrypt);
661 NT_STATUS_HAVE_NO_MEMORY(crypted);
666 #ifdef HAVE_GETPWANAM
668 struct passwd_adjunct *pwret;
669 pwret = getpwanam(s);
670 if (pwret && pwret->pwa_passwd) {
671 crypted = talloc_strdup(ctx, pwret->pwa_passwd);
672 NT_STATUS_HAVE_NO_MEMORY(crypted);
679 struct pr_passwd *mypasswd;
680 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username));
681 mypasswd = getprpwnam(username);
683 username = talloc_strdup(ctx, mypasswd->ufld.fd_name);
684 NT_STATUS_HAVE_NO_MEMORY(username);
685 crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt);
686 NT_STATUS_HAVE_NO_MEMORY(crypted);
688 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username));
695 AUTHORIZATION *ap = getauthuid(pws->pw_uid);
697 crypted = talloc_strdup(ctx, ap->a_password);
699 NT_STATUS_HAVE_NO_MEMORY(crypted);
704 #if defined(HAVE_TRUNCATED_SALT)
705 /* crypt on some platforms (HPUX in particular)
706 won't work with more than 2 salt characters. */
710 if (crypted[0] == '\0') {
711 if (!lp_null_passwords(lp_ctx)) {
712 DEBUG(2, ("Disallowing %s with null password\n", username));
713 return NT_STATUS_LOGON_FAILURE;
715 if (password == NULL) {
716 DEBUG(3, ("Allowing access to %s with null password\n", username));
722 /* try it as it came to us */
723 nt_status = password_check(username, password, crypted, salt);
724 if (NT_STATUS_IS_OK(nt_status)) {
728 else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
729 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
733 if ( user_info->flags | USER_INFO_CASE_INSENSITIVE_PASSWORD) {
737 /* if the password was given to us with mixed case then we don't
738 * need to proceed as we know it hasn't been case modified by the
740 if (strhasupper(password) && strhaslower(password)) {
744 /* make a copy of it */
745 pwcopy = talloc_strdup(ctx, password);
747 return NT_STATUS_NO_MEMORY;
749 /* try all lowercase if it's currently all uppercase */
750 if (strhasupper(pwcopy)) {
752 nt_status = password_check(username, pwcopy, crypted, salt);
753 if NT_STATUS_IS_OK(nt_status) {
761 return NT_STATUS_WRONG_PASSWORD;
764 /* last chance - all combinations of up to level chars upper! */
768 if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) {
773 return NT_STATUS_WRONG_PASSWORD;
778 /** Check a plaintext username/password
782 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
784 const struct auth_usersupplied_info *user_info)
786 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
787 return NT_STATUS_NOT_IMPLEMENTED;
793 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
795 const struct auth_usersupplied_info *user_info,
796 struct auth_serversupplied_info **server_info)
798 TALLOC_CTX *check_ctx;
802 if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
803 return NT_STATUS_INVALID_PARAMETER;
806 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
807 if (check_ctx == NULL) {
808 return NT_STATUS_NO_MEMORY;
811 nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd);
812 if (!NT_STATUS_IS_OK(nt_status)) {
813 talloc_free(check_ctx);
817 nt_status = authunix_make_server_info(mem_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx),
818 user_info, pwd, server_info);
819 if (!NT_STATUS_IS_OK(nt_status)) {
820 talloc_free(check_ctx);
824 talloc_free(check_ctx);
828 static const struct auth_operations unix_ops = {
830 .get_challenge = auth_get_challenge_not_implemented,
831 .want_check = authunix_want_check,
832 .check_password = authunix_check_password
835 _PUBLIC_ NTSTATUS auth_unix_init(void)
839 ret = auth_register(&unix_ops);
840 if (!NT_STATUS_IS_OK(ret)) {
841 DEBUG(0,("Failed to register unix auth backend!\n"));