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
7 
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.
12 
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.
17 
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/>.
20 */
21 
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"
30 
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_AUTH
33 
34 _PUBLIC_ NTSTATUS auth4_unix_init(TALLOC_CTX *);
35 
36 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
37  * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
38  */
authunix_make_user_info_dc(TALLOC_CTX * mem_ctx,const char * netbios_name,const struct auth_usersupplied_info * user_info,struct passwd * pwd,struct auth_user_info_dc ** _user_info_dc)39 static NTSTATUS authunix_make_user_info_dc(TALLOC_CTX *mem_ctx,
40 					  const char *netbios_name,
41 					  const struct auth_usersupplied_info *user_info,
42 					  struct passwd *pwd,
43 					  struct auth_user_info_dc **_user_info_dc)
44 {
45 	struct auth_user_info_dc *user_info_dc;
46 	struct auth_user_info *info;
47 	NTSTATUS status;
48 
49 	/* This is a real, real hack */
50 	if (pwd->pw_uid == 0) {
51 		status = auth_system_user_info_dc(mem_ctx, netbios_name, &user_info_dc);
52 		if (!NT_STATUS_IS_OK(status)) {
53 			return status;
54 		}
55 
56 		user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
57 		NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
58 
59 		info->account_name = talloc_steal(info, pwd->pw_name);
60 		NT_STATUS_HAVE_NO_MEMORY(info->account_name);
61 
62 		info->domain_name = talloc_strdup(info, "unix");
63 		NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
64 	} else {
65 		user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
66 		NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
67 
68 		user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
69 		NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
70 
71 		info->authenticated = true;
72 
73 		info->account_name = talloc_steal(info, pwd->pw_name);
74 		NT_STATUS_HAVE_NO_MEMORY(info->account_name);
75 
76 		info->domain_name = talloc_strdup(info, "unix");
77 		NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
78 
79 		/* This isn't in any way correct.. */
80 		user_info_dc->num_sids = 0;
81 		user_info_dc->sids = NULL;
82 	}
83 	user_info_dc->user_session_key = data_blob(NULL,0);
84 	user_info_dc->lm_session_key = data_blob(NULL,0);
85 
86 	info->full_name = talloc_steal(info, pwd->pw_gecos);
87 	NT_STATUS_HAVE_NO_MEMORY(info->full_name);
88 	info->logon_script = talloc_strdup(info, "");
89 	NT_STATUS_HAVE_NO_MEMORY(info->logon_script);
90 	info->profile_path = talloc_strdup(info, "");
91 	NT_STATUS_HAVE_NO_MEMORY(info->profile_path);
92 	info->home_directory = talloc_strdup(info, "");
93 	NT_STATUS_HAVE_NO_MEMORY(info->home_directory);
94 	info->home_drive = talloc_strdup(info, "");
95 	NT_STATUS_HAVE_NO_MEMORY(info->home_drive);
96 
97 	info->last_logon = 0;
98 	info->last_logoff = 0;
99 	info->acct_expiry = 0;
100 	info->last_password_change = 0;
101 	info->allow_password_change = 0;
102 	info->force_password_change = 0;
103 	info->logon_count = 0;
104 	info->bad_password_count = 0;
105 	info->acct_flags = 0;
106 
107 	*_user_info_dc = user_info_dc;
108 
109 	return NT_STATUS_OK;
110 }
111 
talloc_getpwnam(TALLOC_CTX * ctx,const char * username,struct passwd ** pws)112 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
113 {
114         struct passwd *ret;
115 	struct passwd *from;
116 
117 	*pws = NULL;
118 
119 	ret = talloc(ctx, struct passwd);
120 	NT_STATUS_HAVE_NO_MEMORY(ret);
121 
122 	from = getpwnam(username);
123 	if (!from) {
124 		return NT_STATUS_NO_SUCH_USER;
125 	}
126 
127         ret->pw_name = talloc_strdup(ctx, from->pw_name);
128 	NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
129 
130         ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
131 	NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
132 
133         ret->pw_uid = from->pw_uid;
134         ret->pw_gid = from->pw_gid;
135         ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
136 	NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
137 
138         ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
139 	NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
140 
141         ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
142 	NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
143 
144 	*pws = ret;
145 
146 	return NT_STATUS_OK;
147 }
148 
149 
150 #ifdef HAVE_SECURITY_PAM_APPL_H
151 #include <security/pam_appl.h>
152 
153 struct smb_pam_user_info {
154 	const char *account_name;
155 	const char *plaintext_password;
156 };
157 
158 #define COPY_STRING(s) (s) ? strdup(s) : NULL
159 
160 /*
161  * Check user password
162  * Currently it uses PAM only and fails on systems without PAM
163  * Samba3 code located in pass_check.c is to ugly to be used directly it will
164  * need major rework that's why pass_check.c is still there.
165 */
166 
smb_pam_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** reply,void * appdata_ptr)167 static int smb_pam_conv(int num_msg, const struct pam_message **msg,
168 			 struct pam_response **reply, void *appdata_ptr)
169 {
170 	struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr;
171 	int num;
172 
173 	if (num_msg <= 0) {
174 		*reply = NULL;
175 		return PAM_CONV_ERR;
176 	}
177 
178 	/*
179 	 * Apparantly HPUX has a buggy PAM that doesn't support the
180 	 * data pointer. Fail if this is the case. JRA.
181 	 */
182 
183 	if (info == NULL) {
184 		*reply = NULL;
185 		return PAM_CONV_ERR;
186 	}
187 
188 	/*
189 	 * PAM frees memory in reply messages by itself
190 	 * so use malloc instead of talloc here.
191 	 */
192 	*reply = malloc_array_p(struct pam_response, num_msg);
193 	if (*reply == NULL) {
194 		return PAM_CONV_ERR;
195 	}
196 
197 	for (num = 0; num < num_msg; num++) {
198 		switch  (msg[num]->msg_style) {
199 			case PAM_PROMPT_ECHO_ON:
200 				(*reply)[num].resp_retcode = PAM_SUCCESS;
201 				(*reply)[num].resp = COPY_STRING(info->account_name);
202 				break;
203 
204 			case PAM_PROMPT_ECHO_OFF:
205 				(*reply)[num].resp_retcode = PAM_SUCCESS;
206 				(*reply)[num].resp = COPY_STRING(info->plaintext_password);
207 				break;
208 
209 			case PAM_TEXT_INFO:
210 				(*reply)[num].resp_retcode = PAM_SUCCESS;
211 				(*reply)[num].resp = NULL;
212 				DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
213 				break;
214 
215 			case PAM_ERROR_MSG:
216 				(*reply)[num].resp_retcode = PAM_SUCCESS;
217 				(*reply)[num].resp = NULL;
218 				DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg)));
219 				break;
220 
221 			default:
222 				while (num > 0) {
223 					SAFE_FREE((*reply)[num-1].resp);
224 					num--;
225 				}
226 				SAFE_FREE(*reply);
227 				*reply = NULL;
228 				DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
229 				return PAM_CONV_ERR;
230 		}
231 	}
232 
233 	return PAM_SUCCESS;
234 }
235 
236 /*
237  * Start PAM authentication for specified account
238  */
239 
smb_pam_start(pam_handle_t ** pamh,const char * account_name,const char * remote_host,struct pam_conv * pconv)240 static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
241 {
242 	int pam_error;
243 
244 	if (account_name == NULL || remote_host == NULL) {
245 		return NT_STATUS_INVALID_PARAMETER;
246 	}
247 
248 	DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name));
249 
250 	pam_error = pam_start("samba", account_name, pconv, pamh);
251 	if (pam_error != PAM_SUCCESS) {
252 		/* no valid pamh here, can we reliably call pam_strerror ? */
253 		DEBUG(4,("smb_pam_start: pam_start failed!\n"));
254 		return NT_STATUS_UNSUCCESSFUL;
255 	}
256 
257 #ifdef PAM_RHOST
258 	DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
259 	pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
260 	if (pam_error != PAM_SUCCESS) {
261 		NTSTATUS nt_status;
262 
263 		DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
264 			 pam_strerror(*pamh, pam_error)));
265 		nt_status = pam_to_nt_status(pam_error);
266 
267 		pam_error = pam_end(*pamh, 0);
268 		if (pam_error != PAM_SUCCESS) {
269 			/* no valid pamh here, can we reliably call pam_strerror ? */
270 			DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
271 				 pam_error));
272 			return pam_to_nt_status(pam_error);
273 		}
274 		return nt_status;
275 	}
276 #endif
277 #ifdef PAM_TTY
278 	DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
279 	pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
280 	if (pam_error != PAM_SUCCESS) {
281 		NTSTATUS nt_status;
282 
283 		DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
284 			 pam_strerror(*pamh, pam_error)));
285 		nt_status = pam_to_nt_status(pam_error);
286 
287 		pam_error = pam_end(*pamh, 0);
288 		if (pam_error != PAM_SUCCESS) {
289 			/* no valid pamh here, can we reliably call pam_strerror ? */
290 			DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
291 				 pam_error));
292 			return pam_to_nt_status(pam_error);
293 		}
294 		return nt_status;
295 	}
296 #endif
297 	DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
298 
299 	return NT_STATUS_OK;
300 }
301 
smb_pam_end(pam_handle_t * pamh)302 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
303 {
304 	int pam_error;
305 
306 	if (pamh != NULL) {
307 		pam_error = pam_end(pamh, 0);
308 		if (pam_error != PAM_SUCCESS) {
309 			/* no valid pamh here, can we reliably call pam_strerror ? */
310 			DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
311 				 pam_error));
312 			return pam_to_nt_status(pam_error);
313 		}
314 		return NT_STATUS_OK;
315 	}
316 
317 	DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
318 	return NT_STATUS_UNSUCCESSFUL;
319 }
320 
321 /*
322  * PAM Authentication Handler
323  */
smb_pam_auth(pam_handle_t * pamh,bool allow_null_passwords,const char * user)324 static NTSTATUS smb_pam_auth(pam_handle_t *pamh, bool allow_null_passwords, const char *user)
325 {
326 	int pam_error;
327 
328 	/*
329 	 * To enable debugging set in /etc/pam.d/samba:
330 	 *	auth required /lib/security/pam_pwdb.so nullok shadow audit
331 	 */
332 
333 	DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
334 
335 	pam_error = pam_authenticate(pamh, PAM_SILENT | (allow_null_passwords ? 0 : PAM_DISALLOW_NULL_AUTHTOK));
336 	switch( pam_error ){
337 		case PAM_AUTH_ERR:
338 			DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
339 			break;
340 		case PAM_CRED_INSUFFICIENT:
341 			DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
342 			break;
343 		case PAM_AUTHINFO_UNAVAIL:
344 			DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
345 			break;
346 		case PAM_USER_UNKNOWN:
347 			DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
348 			break;
349 		case PAM_MAXTRIES:
350 			DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
351 			break;
352 		case PAM_ABORT:
353 			DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
354 			break;
355 		case PAM_SUCCESS:
356 			DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
357 			break;
358 		default:
359 			DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
360 			break;
361 	}
362 
363 	return pam_to_nt_status(pam_error);
364 }
365 
366 /*
367  * PAM Account Handler
368  */
smb_pam_account(pam_handle_t * pamh,const char * user)369 static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
370 {
371 	int pam_error;
372 
373 	DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
374 
375 	pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
376 	switch( pam_error ) {
377 		case PAM_AUTHTOK_EXPIRED:
378 			DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
379 			break;
380 		case PAM_ACCT_EXPIRED:
381 			DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
382 			break;
383 		case PAM_AUTH_ERR:
384 			DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
385 			break;
386 		case PAM_PERM_DENIED:
387 			DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
388 			break;
389 		case PAM_USER_UNKNOWN:
390 			DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
391 			break;
392 		case PAM_SUCCESS:
393 			DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
394 			break;
395 		default:
396 			DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
397 			break;
398 	}
399 
400 	return pam_to_nt_status(pam_error);
401 }
402 
403 /*
404  * PAM Credential Setting
405  */
406 
smb_pam_setcred(pam_handle_t * pamh,const char * user)407 static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
408 {
409 	int pam_error;
410 
411 	/*
412 	 * This will allow samba to aquire a kerberos token. And, when
413 	 * exporting an AFS cell, be able to /write/ to this cell.
414 	 */
415 
416 	DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
417 
418 	pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT));
419 	switch( pam_error ) {
420 		case PAM_CRED_UNAVAIL:
421 			DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
422 			break;
423 		case PAM_CRED_EXPIRED:
424 			DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
425 			break;
426 		case PAM_USER_UNKNOWN:
427 			DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
428 			break;
429 		case PAM_CRED_ERR:
430 			DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
431 			break;
432 		case PAM_SUCCESS:
433 			DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
434 			break;
435 		default:
436 			DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
437 			break;
438 	}
439 
440 	return pam_to_nt_status(pam_error);
441 }
442 
check_unix_password(TALLOC_CTX * ctx,struct loadparm_context * lp_ctx,const struct auth_usersupplied_info * user_info,struct passwd ** pws)443 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
444 				    const struct auth_usersupplied_info *user_info, struct passwd **pws)
445 {
446 	struct smb_pam_user_info *info;
447 	struct pam_conv *pamconv;
448 	pam_handle_t *pamh;
449 	NTSTATUS nt_status;
450 
451 	info = talloc(ctx, struct smb_pam_user_info);
452 	if (info == NULL) {
453 		return NT_STATUS_NO_MEMORY;
454 	}
455 
456 	info->account_name = user_info->mapped.account_name;
457 	info->plaintext_password = user_info->password.plaintext;
458 
459 	pamconv = talloc(ctx, struct pam_conv);
460 	if (pamconv == NULL) {
461 		return NT_STATUS_NO_MEMORY;
462 	}
463 
464 	pamconv->conv = smb_pam_conv;
465 	pamconv->appdata_ptr = (void *)info;
466 
467 	/* TODO:
468 	 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
469 	 * if true set up a crack name routine.
470 	 */
471 
472 	nt_status = smb_pam_start(&pamh, user_info->mapped.account_name,
473 			user_info->remote_host ? tsocket_address_inet_addr_string(user_info->remote_host, ctx) : NULL, pamconv);
474 	if (!NT_STATUS_IS_OK(nt_status)) {
475 		return nt_status;
476 	}
477 
478 	nt_status = smb_pam_auth(pamh, lpcfg_null_passwords(lp_ctx), user_info->mapped.account_name);
479 	if (!NT_STATUS_IS_OK(nt_status)) {
480 		smb_pam_end(pamh);
481 		return nt_status;
482 	}
483 
484 	if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
485 
486 		nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
487 		if (!NT_STATUS_IS_OK(nt_status)) {
488 			smb_pam_end(pamh);
489 			return nt_status;
490 		}
491 
492 		nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
493 		if (!NT_STATUS_IS_OK(nt_status)) {
494 			smb_pam_end(pamh);
495 			return nt_status;
496 		}
497 	}
498 
499 	smb_pam_end(pamh);
500 
501 	nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
502 	if (!NT_STATUS_IS_OK(nt_status)) {
503 		return nt_status;
504 	}
505 
506 	return NT_STATUS_OK;
507 }
508 
509 #else
510 
511 /****************************************************************************
512 core of password checking routine
513 ****************************************************************************/
password_check(const char * username,const char * password,const char * crypted,const char * salt)514 static NTSTATUS password_check(const char *username, const char *password,
515 					const char *crypted, const char *salt)
516 {
517 	bool ret;
518 
519 
520 
521 #ifdef OSF1_ENH_SEC
522 
523 	ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
524 
525 	if (!ret) {
526 		DEBUG(2,
527 		      ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
528 		ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
529 	}
530 	if (ret) {
531 		return NT_STATUS_OK;
532 	} else {
533 		return NT_STATUS_WRONG_PASSWORD;
534 	}
535 
536 #endif /* OSF1_ENH_SEC */
537 
538 #ifdef ULTRIX_AUTH
539 	ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
540 	if (ret) {
541 		return NT_STATUS_OK;
542         } else {
543 		return NT_STATUS_WRONG_PASSWORD;
544 	}
545 
546 #endif /* ULTRIX_AUTH */
547 
548 
549 
550 #ifdef HAVE_BIGCRYPT
551 	ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
552         if (ret) {
553 		return NT_STATUS_OK;
554 	} else {
555 		return NT_STATUS_WRONG_PASSWORD;
556 	}
557 #endif /* HAVE_BIGCRYPT */
558 
559 #ifndef HAVE_CRYPT
560 	DEBUG(1, ("Warning - no crypt available\n"));
561 	return NT_STATUS_LOGON_FAILURE;
562 #else /* HAVE_CRYPT */
563 	ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
564         if (ret) {
565 		return NT_STATUS_OK;
566 	} else {
567 		return NT_STATUS_WRONG_PASSWORD;
568 	}
569 #endif /* HAVE_CRYPT */
570 }
571 
check_unix_password(TALLOC_CTX * ctx,struct loadparm_context * lp_ctx,const struct auth_usersupplied_info * user_info,struct passwd ** ret_passwd)572 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
573 				    const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
574 {
575 	char *username;
576 	char *password;
577 	char *salt;
578 	char *crypted;
579 	struct passwd *pws;
580 	NTSTATUS nt_status;
581 
582 	*ret_passwd = NULL;
583 
584 	username = talloc_strdup(ctx, user_info->mapped.account_name);
585 	password = talloc_strdup(ctx, user_info->password.plaintext);
586 
587 	nt_status = talloc_getpwnam(ctx, username, &pws);
588 	if (!NT_STATUS_IS_OK(nt_status)) {
589 		return nt_status;
590 	}
591 
592 	crypted = pws->pw_passwd;
593 	salt = pws->pw_passwd;
594 
595 #ifdef HAVE_GETSPNAM
596 	{
597 		struct spwd *spass;
598 
599 		/* many shadow systems require you to be root to get
600 		   the password, in most cases this should already be
601 		   the case when this function is called, except
602 		   perhaps for IPC password changing requests */
603 
604 		spass = getspnam(pws->pw_name);
605 		if (spass && spass->sp_pwdp) {
606 			crypted = talloc_strdup(ctx, spass->sp_pwdp);
607 			NT_STATUS_HAVE_NO_MEMORY(crypted);
608 			salt = talloc_strdup(ctx, spass->sp_pwdp);
609 			NT_STATUS_HAVE_NO_MEMORY(salt);
610 		}
611 	}
612 #elif defined(IA_UINFO)
613 	{
614 		char *ia_password;
615 		/* Need to get password with SVR4.2's ia_ functions
616 		   instead of get{sp,pw}ent functions. Required by
617 		   UnixWare 2.x, tested on version
618 		   2.1. (tangent@cyberport.com) */
619 		uinfo_t uinfo;
620 		if (ia_openinfo(pws->pw_name, &uinfo) != -1) {
621 			ia_get_logpwd(uinfo, &ia_password);
622 			crypted = talloc_strdup(ctx, ia_password);
623 			NT_STATUS_HAVE_NO_MEMORY(crypted);
624 		}
625 	}
626 #endif
627 
628 
629 #ifdef HAVE_GETPWANAM
630 	{
631 		struct passwd_adjunct *pwret;
632 		pwret = getpwanam(s);
633 		if (pwret && pwret->pwa_passwd) {
634 			crypted = talloc_strdup(ctx, pwret->pwa_passwd);
635 			NT_STATUS_HAVE_NO_MEMORY(crypted);
636 		}
637 	}
638 #endif
639 
640 #ifdef OSF1_ENH_SEC
641 	{
642 		struct pr_passwd *mypasswd;
643 		DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username));
644 		mypasswd = getprpwnam(username);
645 		if (mypasswd) {
646 			username = talloc_strdup(ctx, mypasswd->ufld.fd_name);
647 			NT_STATUS_HAVE_NO_MEMORY(username);
648 			crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt);
649 			NT_STATUS_HAVE_NO_MEMORY(crypted);
650 		} else {
651 			DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username));
652 		}
653 	}
654 #endif
655 
656 #ifdef ULTRIX_AUTH
657 	{
658 		AUTHORIZATION *ap = getauthuid(pws->pw_uid);
659 		if (ap) {
660 			crypted = talloc_strdup(ctx, ap->a_password);
661 			endauthent();
662 			NT_STATUS_HAVE_NO_MEMORY(crypted);
663 		}
664 	}
665 #endif
666 
667 
668 	if (crypted[0] == '\0') {
669 		if (!lpcfg_null_passwords(lp_ctx)) {
670 			DEBUG(2, ("Disallowing %s with null password\n", username));
671 			return NT_STATUS_LOGON_FAILURE;
672 		}
673 		if (password == NULL) {
674 			DEBUG(3, ("Allowing access to %s with null password\n", username));
675 			*ret_passwd = pws;
676 			return NT_STATUS_OK;
677 		}
678 	}
679 
680 	/* try it as it came to us */
681 	nt_status = password_check(username, password, crypted, salt);
682         if (NT_STATUS_IS_OK(nt_status)) {
683 		*ret_passwd = pws;
684 		return nt_status;
685 	}
686 	else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
687 		/* No point continuing if its not the password thats to blame (ie PAM disabled). */
688 		return nt_status;
689 	}
690 
691 	/* we no longer try different case combinations here. The use
692 	 * of this code is now web auth, where trying different case
693 	 * combinations makes no sense
694 	 */
695 
696 	return NT_STATUS_WRONG_PASSWORD;
697 }
698 
699 #endif
700 
701 /** Check a plaintext username/password
702  *
703  **/
704 
authunix_want_check(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info)705 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
706 				    TALLOC_CTX *mem_ctx,
707 				    const struct auth_usersupplied_info *user_info)
708 {
709 	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
710 		return NT_STATUS_NOT_IMPLEMENTED;
711 	}
712 
713 	return NT_STATUS_OK;
714 }
715 
authunix_check_password(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info,struct auth_user_info_dc ** user_info_dc,bool * authoritative)716 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
717 					TALLOC_CTX *mem_ctx,
718 					const struct auth_usersupplied_info *user_info,
719 					struct auth_user_info_dc **user_info_dc,
720 					bool *authoritative)
721 {
722 	TALLOC_CTX *check_ctx;
723 	NTSTATUS nt_status;
724 	struct passwd *pwd;
725 
726 	if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
727 		return NT_STATUS_INVALID_PARAMETER;
728 	}
729 
730 	check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
731 	if (check_ctx == NULL) {
732 		return NT_STATUS_NO_MEMORY;
733 	}
734 
735 	nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd);
736 	if (!NT_STATUS_IS_OK(nt_status)) {
737 		talloc_free(check_ctx);
738 		return nt_status;
739 	}
740 
741 	nt_status = authunix_make_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
742 					      user_info, pwd, user_info_dc);
743 	if (!NT_STATUS_IS_OK(nt_status)) {
744 		talloc_free(check_ctx);
745 		return nt_status;
746 	}
747 
748 	talloc_free(check_ctx);
749 	return NT_STATUS_OK;
750 }
751 
752 static const struct auth_operations unix_ops = {
753 	.name		= "unix",
754 	.want_check	= authunix_want_check,
755 	.check_password	= authunix_check_password
756 };
757 
auth4_unix_init(TALLOC_CTX * ctx)758 _PUBLIC_ NTSTATUS auth4_unix_init(TALLOC_CTX *ctx)
759 {
760 	NTSTATUS ret;
761 
762 	ret = auth_register(ctx, &unix_ops);
763 	if (!NT_STATUS_IS_OK(ret)) {
764 		DEBUG(0,("Failed to register unix auth backend!\n"));
765 		return ret;
766 	}
767 
768 	return ret;
769 }
770