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 "system/passwd.h" /* needed by some systems for struct passwd */
25 #include "lib/socket/socket.h"
26 #include "auth/pam_errors.h"
28 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
29 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
31 static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx,
32 const struct auth_usersupplied_info *user_info,
34 struct auth_serversupplied_info **_server_info)
36 struct auth_serversupplied_info *server_info;
39 /* This is a real, real hack */
40 if (pwd->pw_uid == 0) {
41 status = auth_system_server_info(mem_ctx, &server_info);
42 if (!NT_STATUS_IS_OK(status)) {
46 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
47 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
49 server_info->domain_name = talloc_strdup(server_info, "unix");
50 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
52 server_info = talloc(mem_ctx, struct auth_serversupplied_info);
53 NT_STATUS_HAVE_NO_MEMORY(server_info);
55 server_info->authenticated = True;
57 server_info->account_name = talloc_steal(server_info, pwd->pw_name);
58 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
60 server_info->domain_name = talloc_strdup(server_info, "unix");
61 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
63 /* This isn't in any way correct.. */
64 server_info->account_sid = NULL;
65 server_info->primary_group_sid = NULL;
66 server_info->n_domain_groups = 0;
67 server_info->domain_groups = NULL;
69 server_info->user_session_key = data_blob(NULL,0);
70 server_info->lm_session_key = data_blob(NULL,0);
72 server_info->full_name = talloc_steal(server_info, pwd->pw_gecos);
73 NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
74 server_info->logon_script = talloc_strdup(server_info, "");
75 NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
76 server_info->profile_path = talloc_strdup(server_info, "");
77 NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
78 server_info->home_directory = talloc_strdup(server_info, "");
79 NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
80 server_info->home_drive = talloc_strdup(server_info, "");
81 NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
83 server_info->last_logon = 0;
84 server_info->last_logoff = 0;
85 server_info->acct_expiry = 0;
86 server_info->last_password_change = 0;
87 server_info->allow_password_change = 0;
88 server_info->force_password_change = 0;
89 server_info->logon_count = 0;
90 server_info->bad_password_count = 0;
91 server_info->acct_flags = 0;
93 *_server_info = server_info;
98 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
105 ret = talloc(ctx, struct passwd);
106 NT_STATUS_HAVE_NO_MEMORY(ret);
108 from = getpwnam(username);
110 return NT_STATUS_NO_SUCH_USER;
113 ret->pw_name = talloc_strdup(ctx, from->pw_name);
114 NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
116 ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
117 NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
119 ret->pw_uid = from->pw_uid;
120 ret->pw_gid = from->pw_gid;
121 ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
122 NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
124 ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
125 NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
127 ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
128 NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
136 #ifdef HAVE_SECURITY_PAM_APPL_H
137 #include <security/pam_appl.h>
139 struct smb_pam_user_info {
140 const char *account_name;
141 const char *plaintext_password;
144 #define COPY_STRING(s) (s) ? strdup(s) : NULL
147 * Check user password
148 * Currently it uses PAM only and fails on systems without PAM
149 * Samba3 code located in pass_check.c is to ugly to be used directly it will
150 * need major rework that's why pass_check.c is still there.
153 static int smb_pam_conv(int num_msg, const struct pam_message **msg,
154 struct pam_response **reply, void *appdata_ptr)
156 struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr;
165 * Apparantly HPUX has a buggy PAM that doesn't support the
166 * data pointer. Fail if this is the case. JRA.
175 * PAM frees memory in reply messages by itself
176 * so use malloc instead of talloc here.
178 *reply = malloc_array_p(struct pam_response, num_msg);
179 if (*reply == NULL) {
183 for (num = 0; num < num_msg; num++) {
184 switch (msg[num]->msg_style) {
185 case PAM_PROMPT_ECHO_ON:
186 (*reply)[num].resp_retcode = PAM_SUCCESS;
187 (*reply)[num].resp = COPY_STRING(info->account_name);
190 case PAM_PROMPT_ECHO_OFF:
191 (*reply)[num].resp_retcode = PAM_SUCCESS;
192 (*reply)[num].resp = COPY_STRING(info->plaintext_password);
196 (*reply)[num].resp_retcode = PAM_SUCCESS;
197 (*reply)[num].resp = NULL;
198 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
202 (*reply)[num].resp_retcode = PAM_SUCCESS;
203 (*reply)[num].resp = NULL;
204 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg)));
209 SAFE_FREE((*reply)[num-1].resp);
214 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
223 * Start PAM authentication for specified account
226 static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
230 if (account_name == NULL || remote_host == NULL) {
231 return NT_STATUS_INVALID_PARAMETER;
234 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name));
236 pam_error = pam_start("samba", account_name, pconv, pamh);
237 if (pam_error != PAM_SUCCESS) {
238 /* no vaild pamh here, can we reliably call pam_strerror ? */
239 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
240 return NT_STATUS_UNSUCCESSFUL;
244 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
245 pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
246 if (pam_error != PAM_SUCCESS) {
249 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
250 pam_strerror(*pamh, pam_error)));
251 nt_status = pam_to_nt_status(pam_error);
253 pam_error = pam_end(*pamh, 0);
254 if (pam_error != PAM_SUCCESS) {
255 /* no vaild pamh here, can we reliably call pam_strerror ? */
256 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
258 return pam_to_nt_status(pam_error);
264 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
265 pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
266 if (pam_error != PAM_SUCCESS) {
269 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
270 pam_strerror(*pamh, pam_error)));
271 nt_status = pam_to_nt_status(pam_error);
273 pam_error = pam_end(*pamh, 0);
274 if (pam_error != PAM_SUCCESS) {
275 /* no vaild pamh here, can we reliably call pam_strerror ? */
276 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
278 return pam_to_nt_status(pam_error);
283 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
288 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
293 pam_error = pam_end(pamh, 0);
294 if (pam_error != PAM_SUCCESS) {
295 /* no vaild pamh here, can we reliably call pam_strerror ? */
296 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
298 return pam_to_nt_status(pam_error);
303 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
304 return NT_STATUS_UNSUCCESSFUL;
308 * PAM Authentication Handler
310 static NTSTATUS smb_pam_auth(pam_handle_t *pamh, const char *user)
315 * To enable debugging set in /etc/pam.d/samba:
316 * auth required /lib/security/pam_pwdb.so nullok shadow audit
319 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
321 pam_error = pam_authenticate(pamh, PAM_SILENT | lp_null_passwords() ? 0 : PAM_DISALLOW_NULL_AUTHTOK);
324 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
326 case PAM_CRED_INSUFFICIENT:
327 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
329 case PAM_AUTHINFO_UNAVAIL:
330 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
332 case PAM_USER_UNKNOWN:
333 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
336 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
339 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
342 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
345 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
349 return pam_to_nt_status(pam_error);
353 * PAM Account Handler
355 static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
359 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
361 pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
362 switch( pam_error ) {
363 case PAM_AUTHTOK_EXPIRED:
364 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
366 case PAM_ACCT_EXPIRED:
367 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
370 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
372 case PAM_PERM_DENIED:
373 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
375 case PAM_USER_UNKNOWN:
376 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
379 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
382 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
386 return pam_to_nt_status(pam_error);
390 * PAM Credential Setting
393 static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
398 * This will allow samba to aquire a kerberos token. And, when
399 * exporting an AFS cell, be able to /write/ to this cell.
402 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
404 pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT));
405 switch( pam_error ) {
406 case PAM_CRED_UNAVAIL:
407 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
409 case PAM_CRED_EXPIRED:
410 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
412 case PAM_USER_UNKNOWN:
413 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
416 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
419 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
422 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
426 return pam_to_nt_status(pam_error);
429 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **pws)
431 struct smb_pam_user_info *info;
432 struct pam_conv *pamconv;
436 info = talloc(ctx, struct smb_pam_user_info);
438 return NT_STATUS_NO_MEMORY;
441 info->account_name = user_info->mapped.account_name;
442 info->plaintext_password = user_info->password.plaintext;
444 pamconv = talloc(ctx, struct pam_conv);
445 if (pamconv == NULL) {
446 return NT_STATUS_NO_MEMORY;
449 pamconv->conv = smb_pam_conv;
450 pamconv->appdata_ptr = (void *)info;
453 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
454 * if true set up a crack name routine.
457 nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host ? user_info->remote_host->addr : NULL, pamconv);
458 if (!NT_STATUS_IS_OK(nt_status)) {
462 nt_status = smb_pam_auth(pamh, user_info->mapped.account_name);
463 if (!NT_STATUS_IS_OK(nt_status)) {
468 if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
470 nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
471 if (!NT_STATUS_IS_OK(nt_status)) {
476 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
477 if (!NT_STATUS_IS_OK(nt_status)) {
485 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
486 if (!NT_STATUS_IS_OK(nt_status)) {
495 /****************************************************************************
496 core of password checking routine
497 ****************************************************************************/
498 static NTSTATUS password_check(const char *username, const char *password,
499 const char *crypted, const char *salt)
504 if (afs_auth(username, password))
506 #endif /* WITH_AFS */
509 if (dfs_auth(username, password))
511 #endif /* WITH_DFS */
515 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
519 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
520 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
525 return NT_STATUS_WRONG_PASSWORD;
528 #endif /* OSF1_ENH_SEC */
531 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
535 return NT_STATUS_WRONG_PASSWORD;
538 #endif /* ULTRIX_AUTH */
540 #ifdef LINUX_BIGCRYPT
541 ret = (linux_bigcrypt(password, salt, crypted));
545 return NT_STATUS_WRONG_PASSWORD;
547 #endif /* LINUX_BIGCRYPT */
549 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
552 * Some systems have bigcrypt in the C library but might not
553 * actually use it for the password hashes (HPUX 10.20) is
554 * a noteable example. So we try bigcrypt first, followed
558 if (strcmp(bigcrypt(password, salt), crypted) == 0)
561 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
565 return NT_STATUS_WRONG_PASSWORD;
567 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
570 ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
574 return NT_STATUS_WRONG_PASSWORD;
576 #endif /* HAVE_BIGCRYPT */
579 DEBUG(1, ("Warning - no crypt available\n"));
580 return NT_STATUS_LOGON_FAILURE;
581 #else /* HAVE_CRYPT */
582 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
586 return NT_STATUS_WRONG_PASSWORD;
588 #endif /* HAVE_CRYPT */
589 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
592 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
601 int level = lp_passwordlevel();
605 username = talloc_strdup(ctx, user_info->mapped.account_name);
606 password = talloc_strdup(ctx, user_info->password.plaintext);
608 nt_status = talloc_getpwnam(ctx, username, &pws);
609 if (!NT_STATUS_IS_OK(nt_status)) {
613 crypted = pws->pw_passwd;
614 salt = pws->pw_passwd;
620 /* many shadow systems require you to be root to get
621 the password, in most cases this should already be
622 the case when this function is called, except
623 perhaps for IPC password changing requests */
625 spass = getspnam(pws->pw_name);
626 if (spass && spass->sp_pwdp) {
627 crypted = talloc_strdup(ctx, spass->sp_pwdp);
628 NT_STATUS_HAVE_NO_MEMORY(crypted);
629 salt = talloc_strdup(ctx, spass->sp_pwdp);
630 NT_STATUS_HAVE_NO_MEMORY(salt);
633 #elif defined(IA_UINFO)
636 /* Need to get password with SVR4.2's ia_ functions
637 instead of get{sp,pw}ent functions. Required by
638 UnixWare 2.x, tested on version
639 2.1. (tangent@cyberport.com) */
641 if (ia_openinfo(pws->pw_name, &uinfo) != -1) {
642 ia_get_logpwd(uinfo, &ia_password);
643 crypted = talloc_strdup(ctx, ia_password);
644 NT_STATUS_HAVE_NO_MEMORY(crypted);
649 #ifdef HAVE_GETPRPWNAM
651 struct pr_passwd *pr_pw = getprpwnam(pws->pw_name);
652 if (pr_pw && pr_pw->ufld.fd_encrypt) {
653 crypted = talloc_strdup(ctx, pr_pw->ufld.fd_encrypt);
654 NT_STATUS_HAVE_NO_MEMORY(crypted);
659 #ifdef HAVE_GETPWANAM
661 struct passwd_adjunct *pwret;
662 pwret = getpwanam(s);
663 if (pwret && pwret->pwa_passwd) {
664 crypted = talloc_strdup(ctx, pwret->pwa_passwd);
665 NT_STATUS_HAVE_NO_MEMORY(crypted);
672 struct pr_passwd *mypasswd;
673 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username));
674 mypasswd = getprpwnam(username);
676 username = talloc_strdup(ctx, mypasswd->ufld.fd_name);
677 NT_STATUS_HAVE_NO_MEMORY(username);
678 crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt);
679 NT_STATUS_HAVE_NO_MEMORY(crypted);
681 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username));
688 AUTHORIZATION *ap = getauthuid(pws->pw_uid);
690 crypted = talloc_strdup(ctx, ap->a_password);
692 NT_STATUS_HAVE_NO_MEMORY(crypted);
697 #if defined(HAVE_TRUNCATED_SALT)
698 /* crypt on some platforms (HPUX in particular)
699 won't work with more than 2 salt characters. */
703 if (crypted[0] == '\0') {
704 if (!lp_null_passwords()) {
705 DEBUG(2, ("Disallowing %s with null password\n", username));
706 return NT_STATUS_LOGON_FAILURE;
708 if (password == NULL) {
709 DEBUG(3, ("Allowing access to %s with null password\n", username));
715 /* try it as it came to us */
716 nt_status = password_check(username, password, crypted, salt);
717 if (NT_STATUS_IS_OK(nt_status)) {
721 else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
722 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
726 if ( user_info->flags | USER_INFO_CASE_INSENSITIVE_PASSWORD) {
730 /* if the password was given to us with mixed case then we don't
731 * need to proceed as we know it hasn't been case modified by the
733 if (strhasupper(password) && strhaslower(password)) {
737 /* make a copy of it */
738 pwcopy = talloc_strdup(ctx, password);
740 return NT_STATUS_NO_MEMORY;
742 /* try all lowercase if it's currently all uppercase */
743 if (strhasupper(pwcopy)) {
745 nt_status = password_check(username, pwcopy, crypted, salt);
746 if NT_STATUS_IS_OK(nt_status) {
754 return NT_STATUS_WRONG_PASSWORD;
757 /* last chance - all combinations of up to level chars upper! */
761 if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) {
766 return NT_STATUS_WRONG_PASSWORD;
771 /** Check a plaintext username/password
775 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
777 const struct auth_usersupplied_info *user_info)
779 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
780 return NT_STATUS_NOT_IMPLEMENTED;
786 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
788 const struct auth_usersupplied_info *user_info,
789 struct auth_serversupplied_info **server_info)
791 TALLOC_CTX *check_ctx;
795 if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
796 return NT_STATUS_INVALID_PARAMETER;
799 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
800 if (check_ctx == NULL) {
801 return NT_STATUS_NO_MEMORY;
804 nt_status = check_unix_password(check_ctx, user_info, &pwd);
805 if (!NT_STATUS_IS_OK(nt_status)) {
806 talloc_free(check_ctx);
810 nt_status = authunix_make_server_info(mem_ctx, user_info, pwd, server_info);
811 if (!NT_STATUS_IS_OK(nt_status)) {
812 talloc_free(check_ctx);
816 talloc_free(check_ctx);
820 static const struct auth_operations unix_ops = {
822 .get_challenge = auth_get_challenge_not_implemented,
823 .want_check = authunix_want_check,
824 .check_password = authunix_check_password
827 NTSTATUS auth_unix_init(void)
831 ret = auth_register(&unix_ops);
832 if (!NT_STATUS_IS_OK(ret)) {
833 DEBUG(0,("Failed to register unix auth backend!\n"));