1 /*
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2009
5    Copyright (C) Gerald Carter                             2003
6    Copyright (C) Stefan Metzmacher                         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 "system/time.h"
24 #include <ldb.h>
25 #include "libcli/ldap/ldap_ndr.h"
26 #include "libcli/security/security.h"
27 #include "auth/auth.h"
28 #include "../libcli/auth/ntlm_check.h"
29 #include "auth/ntlm/auth_proto.h"
30 #include "auth/auth_sam.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "dsdb/common/util.h"
33 #include "param/param.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "librpc/gen_ndr/ndr_winbind_c.h"
36 #include "lib/messaging/irpc.h"
37 #include "libcli/auth/libcli_auth.h"
38 #include "libds/common/roles.h"
39 
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_AUTH
42 
43 NTSTATUS auth_sam_init(void);
44 
45 extern const char *user_attrs[];
46 extern const char *domain_ref_attrs[];
47 
48 /****************************************************************************
49  Do a specific test for an smb password being correct, given a smb_password and
50  the lanman and NT responses.
51 ****************************************************************************/
authsam_password_ok(struct auth4_context * auth_context,TALLOC_CTX * mem_ctx,uint16_t acct_flags,const struct samr_Password * lm_pwd,const struct samr_Password * nt_pwd,const struct auth_usersupplied_info * user_info,DATA_BLOB * user_sess_key,DATA_BLOB * lm_sess_key)52 static NTSTATUS authsam_password_ok(struct auth4_context *auth_context,
53 				    TALLOC_CTX *mem_ctx,
54 				    uint16_t acct_flags,
55 				    const struct samr_Password *lm_pwd,
56 				    const struct samr_Password *nt_pwd,
57 				    const struct auth_usersupplied_info *user_info,
58 				    DATA_BLOB *user_sess_key,
59 				    DATA_BLOB *lm_sess_key)
60 {
61 	NTSTATUS status;
62 
63 	switch (user_info->password_state) {
64 	case AUTH_PASSWORD_PLAIN:
65 	{
66 		const struct auth_usersupplied_info *user_info_temp;
67 		status = encrypt_user_info(mem_ctx, auth_context,
68 					   AUTH_PASSWORD_HASH,
69 					   user_info, &user_info_temp);
70 		if (!NT_STATUS_IS_OK(status)) {
71 			DEBUG(1, ("Failed to convert plaintext password to password HASH: %s\n", nt_errstr(status)));
72 			return status;
73 		}
74 		user_info = user_info_temp;
75 
76 		FALL_THROUGH;
77 	}
78 	case AUTH_PASSWORD_HASH:
79 		*lm_sess_key = data_blob(NULL, 0);
80 		*user_sess_key = data_blob(NULL, 0);
81 		status = hash_password_check(mem_ctx,
82 					     lpcfg_lanman_auth(auth_context->lp_ctx),
83 					     user_info->password.hash.lanman,
84 					     user_info->password.hash.nt,
85 					     user_info->mapped.account_name,
86 					     lm_pwd, nt_pwd);
87 		NT_STATUS_NOT_OK_RETURN(status);
88 		break;
89 
90 	case AUTH_PASSWORD_RESPONSE:
91 		status = ntlm_password_check(mem_ctx,
92 					     lpcfg_lanman_auth(auth_context->lp_ctx),
93 						 lpcfg_ntlm_auth(auth_context->lp_ctx),
94 					     user_info->logon_parameters,
95 					     &auth_context->challenge.data,
96 					     &user_info->password.response.lanman,
97 					     &user_info->password.response.nt,
98 					     user_info->mapped.account_name,
99 					     user_info->client.account_name,
100 					     user_info->client.domain_name,
101 					     lm_pwd, nt_pwd,
102 					     user_sess_key, lm_sess_key);
103 		NT_STATUS_NOT_OK_RETURN(status);
104 		break;
105 	}
106 
107 	return NT_STATUS_OK;
108 }
109 
auth_sam_trigger_zero_password(TALLOC_CTX * mem_ctx,struct imessaging_context * msg_ctx,struct tevent_context * event_ctx,struct netr_SendToSamBase * send_to_sam)110 static void auth_sam_trigger_zero_password(TALLOC_CTX *mem_ctx,
111 					   struct imessaging_context *msg_ctx,
112 					   struct tevent_context *event_ctx,
113 					   struct netr_SendToSamBase *send_to_sam)
114 {
115 	struct dcerpc_binding_handle *irpc_handle;
116 	struct winbind_SendToSam r;
117 	struct tevent_req *req;
118 	TALLOC_CTX *tmp_ctx;
119 
120 	tmp_ctx = talloc_new(mem_ctx);
121 	if (tmp_ctx == NULL) {
122 		return;
123 	}
124 
125 	irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
126 						  "winbind_server",
127 						  &ndr_table_winbind);
128 	if (irpc_handle == NULL) {
129 		DEBUG(1,(__location__ ": Unable to get binding handle for winbind\n"));
130 		TALLOC_FREE(tmp_ctx);
131 		return;
132 	}
133 
134 	r.in.message = *send_to_sam;
135 
136 	/*
137 	 * This seem to rely on the current IRPC implementation,
138 	 * which delivers the message in the _send function.
139 	 *
140 	 * TODO: we need a ONE_WAY IRPC handle and register
141 	 * a callback and wait for it to be triggered!
142 	 */
143 	req = dcerpc_winbind_SendToSam_r_send(tmp_ctx,
144 					      event_ctx,
145 					      irpc_handle,
146 					      &r);
147 
148 	/* we aren't interested in a reply */
149 	talloc_free(req);
150 	TALLOC_FREE(tmp_ctx);
151 
152 }
153 
154 /*
155   send a message to the drepl server telling it to initiate a
156   REPL_SECRET getncchanges extended op to fetch the users secrets
157  */
auth_sam_trigger_repl_secret(TALLOC_CTX * mem_ctx,struct imessaging_context * msg_ctx,struct tevent_context * event_ctx,struct ldb_dn * user_dn)158 static void auth_sam_trigger_repl_secret(TALLOC_CTX *mem_ctx,
159 					 struct imessaging_context *msg_ctx,
160 					 struct tevent_context *event_ctx,
161 					 struct ldb_dn *user_dn)
162 {
163 	struct dcerpc_binding_handle *irpc_handle;
164 	struct drepl_trigger_repl_secret r;
165 	struct tevent_req *req;
166 	TALLOC_CTX *tmp_ctx;
167 
168 	tmp_ctx = talloc_new(mem_ctx);
169 	if (tmp_ctx == NULL) {
170 		return;
171 	}
172 
173 	irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
174 						  "dreplsrv",
175 						  &ndr_table_irpc);
176 	if (irpc_handle == NULL) {
177 		DEBUG(1,(__location__ ": Unable to get binding handle for dreplsrv\n"));
178 		TALLOC_FREE(tmp_ctx);
179 		return;
180 	}
181 
182 	r.in.user_dn = ldb_dn_get_linearized(user_dn);
183 
184 	/*
185 	 * This seem to rely on the current IRPC implementation,
186 	 * which delivers the message in the _send function.
187 	 *
188 	 * TODO: we need a ONE_WAY IRPC handle and register
189 	 * a callback and wait for it to be triggered!
190 	 */
191 	req = dcerpc_drepl_trigger_repl_secret_r_send(tmp_ctx,
192 						      event_ctx,
193 						      irpc_handle,
194 						      &r);
195 
196 	/* we aren't interested in a reply */
197 	talloc_free(req);
198 	TALLOC_FREE(tmp_ctx);
199 }
200 
201 
202 /*
203  * Check that a password is OK, and update badPwdCount if required.
204  */
205 
authsam_password_check_and_record(struct auth4_context * auth_context,TALLOC_CTX * mem_ctx,struct ldb_dn * domain_dn,struct ldb_message * msg,uint16_t acct_flags,const struct auth_usersupplied_info * user_info,DATA_BLOB * user_sess_key,DATA_BLOB * lm_sess_key,bool * authoritative)206 static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_context,
207 						  TALLOC_CTX *mem_ctx,
208 						  struct ldb_dn *domain_dn,
209 						  struct ldb_message *msg,
210 						  uint16_t acct_flags,
211 						  const struct auth_usersupplied_info *user_info,
212 						  DATA_BLOB *user_sess_key,
213 						  DATA_BLOB *lm_sess_key,
214 						  bool *authoritative)
215 {
216 	NTSTATUS nt_status;
217 	NTSTATUS auth_status;
218 	TALLOC_CTX *tmp_ctx;
219 	int i, ret;
220 	int history_len = 0;
221 	struct ldb_context *sam_ctx = auth_context->sam_ctx;
222 	const char * const attrs[] = { "pwdHistoryLength", NULL };
223 	struct ldb_message *dom_msg;
224 	struct samr_Password *lm_pwd;
225 	struct samr_Password *nt_pwd;
226 	bool am_rodc;
227 
228 	tmp_ctx = talloc_new(mem_ctx);
229 	if (tmp_ctx == NULL) {
230 		return NT_STATUS_NO_MEMORY;
231 	}
232 
233 	/*
234 	 * This call does more than what it appears to do, it also
235 	 * checks for the account lockout.
236 	 *
237 	 * It is done here so that all parts of Samba that read the
238 	 * password refuse to even operate on it if the account is
239 	 * locked out, to avoid mistakes like CVE-2013-4496.
240 	 */
241 	nt_status = samdb_result_passwords(tmp_ctx, auth_context->lp_ctx,
242 					   msg, &lm_pwd, &nt_pwd);
243 	if (!NT_STATUS_IS_OK(nt_status)) {
244 		TALLOC_FREE(tmp_ctx);
245 		return nt_status;
246 	}
247 
248 	if (lm_pwd == NULL && nt_pwd == NULL) {
249 		if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) {
250 			/*
251 			 * we don't have passwords for this
252 			 * account. We are an RODC, and this account
253 			 * may be one for which we either are denied
254 			 * REPL_SECRET replication or we haven't yet
255 			 * done the replication. We return
256 			 * NT_STATUS_NOT_IMPLEMENTED which tells the
257 			 * auth code to try the next authentication
258 			 * mechanism. We also send a message to our
259 			 * drepl server to tell it to try and
260 			 * replicate the secrets for this account.
261 			 *
262 			 * TODO: Should we only trigger this is detected
263 			 * there's a chance that the password might be
264 			 * replicated, we should be able to detect this
265 			 * based on msDS-NeverRevealGroup.
266 			 */
267 			auth_sam_trigger_repl_secret(auth_context,
268 						     auth_context->msg_ctx,
269 						     auth_context->event_ctx,
270 						     msg->dn);
271 			TALLOC_FREE(tmp_ctx);
272 			return NT_STATUS_NOT_IMPLEMENTED;
273 		}
274 	}
275 
276 	auth_status = authsam_password_ok(auth_context, tmp_ctx,
277 					  acct_flags,
278 					  lm_pwd, nt_pwd,
279 					  user_info,
280 					  user_sess_key, lm_sess_key);
281 	if (NT_STATUS_IS_OK(auth_status)) {
282 		if (user_sess_key->data) {
283 			talloc_steal(mem_ctx, user_sess_key->data);
284 		}
285 		if (lm_sess_key->data) {
286 			talloc_steal(mem_ctx, lm_sess_key->data);
287 		}
288 		TALLOC_FREE(tmp_ctx);
289 		return NT_STATUS_OK;
290 	}
291 	*user_sess_key = data_blob_null;
292 	*lm_sess_key = data_blob_null;
293 
294 	if (!NT_STATUS_EQUAL(auth_status, NT_STATUS_WRONG_PASSWORD)) {
295 		TALLOC_FREE(tmp_ctx);
296 		return auth_status;
297 	}
298 
299 	/*
300 	 * We only continue if this was a wrong password
301 	 * and we'll always return NT_STATUS_WRONG_PASSWORD
302 	 * no matter what error happens.
303 	 */
304 
305 	/* pull the domain password property attributes */
306 	ret = dsdb_search_one(sam_ctx, tmp_ctx, &dom_msg, domain_dn, LDB_SCOPE_BASE,
307 			      attrs, 0, "objectClass=domain");
308 	if (ret == LDB_SUCCESS) {
309 		history_len = ldb_msg_find_attr_as_uint(dom_msg, "pwdHistoryLength", 0);
310 	} else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
311 		DEBUG(3,("Couldn't find domain %s: %s!\n",
312 			 ldb_dn_get_linearized(domain_dn),
313 			 ldb_errstring(sam_ctx)));
314 	} else {
315 		DEBUG(3,("error finding domain %s: %s!\n",
316 			 ldb_dn_get_linearized(domain_dn),
317 			 ldb_errstring(sam_ctx)));
318 	}
319 
320 	for (i = 1; i < MIN(history_len, 3); i++) {
321 		struct samr_Password zero_string_hash;
322 		struct samr_Password zero_string_des_hash;
323 		struct samr_Password *nt_history_pwd = NULL;
324 		struct samr_Password *lm_history_pwd = NULL;
325 		NTTIME pwdLastSet;
326 		struct timeval tv_now;
327 		NTTIME now;
328 		int allowed_period_mins;
329 		NTTIME allowed_period;
330 
331 		nt_status = samdb_result_passwords_from_history(tmp_ctx,
332 							auth_context->lp_ctx,
333 							msg, i,
334 							&lm_history_pwd,
335 							&nt_history_pwd);
336 		if (!NT_STATUS_IS_OK(nt_status)) {
337 			/*
338 			 * If we don't find element 'i' we won't find
339 			 * 'i+1' ...
340 			 */
341 			break;
342 		}
343 
344 		/*
345 		 * We choose to avoid any issues
346 		 * around different LM and NT history
347 		 * lengths by only checking the NT
348 		 * history
349 		 */
350 		if (nt_history_pwd == NULL) {
351 			/*
352 			 * If we don't find element 'i' we won't find
353 			 * 'i+1' ...
354 			 */
355 			break;
356 		}
357 
358 		/* Skip over all-zero hashes in the history */
359 		if (all_zero(nt_history_pwd->hash,
360 			     sizeof(nt_history_pwd->hash))) {
361 			continue;
362 		}
363 
364 		/*
365 		 * This looks odd, but the password_hash module writes this in if
366 		 * (somehow) we didn't have an old NT hash
367 		 */
368 
369 		E_md4hash("", zero_string_hash.hash);
370 		if (memcmp(nt_history_pwd->hash, zero_string_hash.hash, 16) == 0) {
371 			continue;
372 		}
373 
374 		E_deshash("", zero_string_des_hash.hash);
375 		if (!lm_history_pwd || memcmp(lm_history_pwd->hash, zero_string_des_hash.hash, 16) == 0) {
376 			lm_history_pwd = NULL;
377 		}
378 
379 		auth_status = authsam_password_ok(auth_context, tmp_ctx,
380 						  acct_flags,
381 						  lm_history_pwd,
382 						  nt_history_pwd,
383 						  user_info,
384 						  user_sess_key,
385 						  lm_sess_key);
386 		if (!NT_STATUS_IS_OK(auth_status)) {
387 			/*
388 			 * If this was not a correct password, try the next
389 			 * one from the history
390 			 */
391 			*user_sess_key = data_blob_null;
392 			*lm_sess_key = data_blob_null;
393 			continue;
394 		}
395 
396 		if (i != 1) {
397 			/*
398 			 * The authentication was OK, but not against
399 			 * the previous password, which is stored at index 1.
400 			 *
401 			 * We just return the original wrong password.
402 			 * This skips the update of the bad pwd count,
403 			 * because this is almost certainly user error
404 			 * (or automatic login on a computer using a cached
405 			 * password from before the password change),
406 			 * not an attack.
407 			 */
408 			TALLOC_FREE(tmp_ctx);
409 			return NT_STATUS_WRONG_PASSWORD;
410 		}
411 
412 		if (user_info->password_state != AUTH_PASSWORD_RESPONSE) {
413 			/*
414 			 * The authentication was OK against the previous password,
415 			 * but it's not a NTLM network authentication.
416 			 *
417 			 * We just return the original wrong password.
418 			 * This skips the update of the bad pwd count,
419 			 * because this is almost certainly user error
420 			 * (or automatic login on a computer using a cached
421 			 * password from before the password change),
422 			 * not an attack.
423 			 */
424 			TALLOC_FREE(tmp_ctx);
425 			return NT_STATUS_WRONG_PASSWORD;
426 		}
427 
428 		/*
429 		 * If the password was OK, it's a NTLM network authentication
430 		 * and it was the previous password.
431 		 *
432 		 * Now we see if it is within the grace period,
433 		 * so that we don't break cached sessions on other computers
434 		 * before the user can lock and unlock their other screens
435 		 * (resetting their cached password).
436 		 *
437 		 * See http://support.microsoft.com/kb/906305
438 		 * OldPasswordAllowedPeriod ("old password allowed period")
439 		 * is specified in minutes. The default is 60.
440 		 */
441 		allowed_period_mins = lpcfg_old_password_allowed_period(auth_context->lp_ctx);
442 		/*
443 		 * NTTIME uses 100ns units
444 		 */
445 		allowed_period = allowed_period_mins * 60 * 1000*1000*10;
446 		pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0);
447 		tv_now = timeval_current();
448 		now = timeval_to_nttime(&tv_now);
449 
450 		if (now < pwdLastSet) {
451 			/*
452 			 * time jump?
453 			 *
454 			 * We just return the original wrong password.
455 			 * This skips the update of the bad pwd count,
456 			 * because this is almost certainly user error
457 			 * (or automatic login on a computer using a cached
458 			 * password from before the password change),
459 			 * not an attack.
460 			 */
461 			TALLOC_FREE(tmp_ctx);
462 			return NT_STATUS_WRONG_PASSWORD;
463 		}
464 
465 		if ((now - pwdLastSet) >= allowed_period) {
466 			/*
467 			 * The allowed period is over.
468 			 *
469 			 * We just return the original wrong password.
470 			 * This skips the update of the bad pwd count,
471 			 * because this is almost certainly user error
472 			 * (or automatic login on a computer using a cached
473 			 * password from before the password change),
474 			 * not an attack.
475 			 */
476 			TALLOC_FREE(tmp_ctx);
477 			return NT_STATUS_WRONG_PASSWORD;
478 		}
479 
480 		/*
481 		 * We finally allow the authentication with the
482 		 * previous password within the allowed period.
483 		 */
484 		if (user_sess_key->data) {
485 			talloc_steal(mem_ctx, user_sess_key->data);
486 		}
487 		if (lm_sess_key->data) {
488 			talloc_steal(mem_ctx, lm_sess_key->data);
489 		}
490 
491 		TALLOC_FREE(tmp_ctx);
492 		return auth_status;
493 	}
494 
495 	/*
496 	 * If we are not in the allowed period or match an old password,
497 	 * we didn't return early. Now update the badPwdCount et al.
498 	 */
499 	nt_status = authsam_update_bad_pwd_count(auth_context->sam_ctx,
500 						 msg, domain_dn);
501 	if (!NT_STATUS_IS_OK(nt_status)) {
502 		/*
503 		 * We need to return the original
504 		 * NT_STATUS_WRONG_PASSWORD error, so there isn't
505 		 * anything more we can do than write something into
506 		 * the log
507 		 */
508 		DEBUG(0, ("Failed to note bad password for user [%s]: %s\n",
509 			  user_info->mapped.account_name,
510 			  nt_errstr(nt_status)));
511 	}
512 
513 	if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) {
514 		*authoritative = false;
515 	}
516 
517 	TALLOC_FREE(tmp_ctx);
518 	return NT_STATUS_WRONG_PASSWORD;
519 }
520 
authsam_authenticate(struct auth4_context * auth_context,TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct ldb_dn * domain_dn,struct ldb_message * msg,const struct auth_usersupplied_info * user_info,DATA_BLOB * user_sess_key,DATA_BLOB * lm_sess_key,bool * authoritative)521 static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
522 				     TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx,
523 				     struct ldb_dn *domain_dn,
524 				     struct ldb_message *msg,
525 				     const struct auth_usersupplied_info *user_info,
526 				     DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key,
527 				     bool *authoritative)
528 {
529 	NTSTATUS nt_status;
530 	bool interactive = (user_info->password_state == AUTH_PASSWORD_HASH);
531 	uint32_t acct_flags = samdb_result_acct_flags(msg, NULL);
532 	struct netr_SendToSamBase *send_to_sam = NULL;
533 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
534 	if (!tmp_ctx) {
535 		return NT_STATUS_NO_MEMORY;
536 	}
537 
538 	/* You can only do an interactive login to normal accounts */
539 	if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
540 		if (!(acct_flags & ACB_NORMAL)) {
541 			TALLOC_FREE(tmp_ctx);
542 			return NT_STATUS_NO_SUCH_USER;
543 		}
544 		if (acct_flags & ACB_SMARTCARD_REQUIRED) {
545 			if (acct_flags & ACB_DISABLED) {
546 				DEBUG(2,("authsam_authenticate: Account for user '%s' "
547 					 "was disabled.\n",
548 					 user_info->mapped.account_name));
549 				TALLOC_FREE(tmp_ctx);
550 				return NT_STATUS_ACCOUNT_DISABLED;
551 			}
552 			DEBUG(2,("authsam_authenticate: Account for user '%s' "
553 				 "requires interactive smartcard logon.\n",
554 				 user_info->mapped.account_name));
555 			TALLOC_FREE(tmp_ctx);
556 			return NT_STATUS_SMARTCARD_LOGON_REQUIRED;
557 		}
558 	}
559 
560 	nt_status = authsam_password_check_and_record(auth_context, tmp_ctx,
561 						      domain_dn, msg, acct_flags,
562 						      user_info,
563 						      user_sess_key, lm_sess_key,
564 						      authoritative);
565 	if (!NT_STATUS_IS_OK(nt_status)) {
566 		TALLOC_FREE(tmp_ctx);
567 		return nt_status;
568 	}
569 
570 	nt_status = authsam_account_ok(tmp_ctx, auth_context->sam_ctx,
571 				       user_info->logon_parameters,
572 				       domain_dn,
573 				       msg,
574 				       user_info->workstation_name,
575 				       user_info->mapped.account_name,
576 				       false, false);
577 	if (!NT_STATUS_IS_OK(nt_status)) {
578 		TALLOC_FREE(tmp_ctx);
579 		return nt_status;
580 	}
581 
582 	nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
583 						     msg, domain_dn,
584 						     interactive,
585 						     &send_to_sam);
586 
587 	if (send_to_sam != NULL) {
588 		auth_sam_trigger_zero_password(tmp_ctx,
589 					       auth_context->msg_ctx,
590 					       auth_context->event_ctx,
591 					       send_to_sam);
592 	}
593 
594 	if (!NT_STATUS_IS_OK(nt_status)) {
595 		TALLOC_FREE(tmp_ctx);
596 		return nt_status;
597 	}
598 
599 	if (user_sess_key && user_sess_key->data) {
600 		talloc_steal(mem_ctx, user_sess_key->data);
601 	}
602 	if (lm_sess_key && lm_sess_key->data) {
603 		talloc_steal(mem_ctx, lm_sess_key->data);
604 	}
605 
606 	TALLOC_FREE(tmp_ctx);
607 	return nt_status;
608 }
609 
610 
611 
authsam_check_password_internals(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)612 static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
613 						 TALLOC_CTX *mem_ctx,
614 						 const struct auth_usersupplied_info *user_info,
615 						 struct auth_user_info_dc **user_info_dc,
616 						 bool *authoritative)
617 {
618 	NTSTATUS nt_status;
619 	const char *account_name = user_info->mapped.account_name;
620 	struct ldb_message *msg;
621 	struct ldb_dn *domain_dn;
622 	DATA_BLOB user_sess_key, lm_sess_key;
623 	TALLOC_CTX *tmp_ctx;
624 	const char *p = NULL;
625 
626 	if (ctx->auth_ctx->sam_ctx == NULL) {
627 		DEBUG(0, ("No SAM available, cannot log in users\n"));
628 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
629 	}
630 
631 	if (!account_name || !*account_name) {
632 		/* 'not for me' */
633 		return NT_STATUS_NOT_IMPLEMENTED;
634 	}
635 
636 	tmp_ctx = talloc_new(mem_ctx);
637 	if (!tmp_ctx) {
638 		return NT_STATUS_NO_MEMORY;
639 	}
640 
641 	domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
642 	if (domain_dn == NULL) {
643 		talloc_free(tmp_ctx);
644 		return NT_STATUS_NO_SUCH_DOMAIN;
645 	}
646 
647 	p = strchr_m(account_name, '@');
648 	if (p != NULL) {
649 		const char *nt4_domain = NULL;
650 		const char *nt4_account = NULL;
651 		bool is_my_domain = false;
652 
653 		nt_status = crack_name_to_nt4_name(mem_ctx,
654 						   ctx->auth_ctx->sam_ctx,
655 						   /*
656 						    * DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON ?
657 						    */
658 						   DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
659 						   account_name,
660 						   &nt4_domain, &nt4_account);
661 		if (!NT_STATUS_IS_OK(nt_status)) {
662 			talloc_free(tmp_ctx);
663 			return NT_STATUS_NO_SUCH_USER;
664 		}
665 
666 		is_my_domain = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain);
667 		if (!is_my_domain) {
668 			/*
669 			 * This is a user within our forest,
670 			 * but in a different domain,
671 			 * we're not authoritative
672 			 */
673 			talloc_free(tmp_ctx);
674 			return NT_STATUS_NOT_IMPLEMENTED;
675 		}
676 
677 		/*
678 		 * Let's use the NT4 account name for the lookup.
679 		 */
680 		account_name = nt4_account;
681 	}
682 
683 	nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
684 	if (!NT_STATUS_IS_OK(nt_status)) {
685 		talloc_free(tmp_ctx);
686 		return nt_status;
687 	}
688 
689 	nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, ctx->auth_ctx->sam_ctx, domain_dn, msg, user_info,
690 					 &user_sess_key, &lm_sess_key, authoritative);
691 	if (!NT_STATUS_IS_OK(nt_status)) {
692 		talloc_free(tmp_ctx);
693 		return nt_status;
694 	}
695 
696 	nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx,
697 					     lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
698 					     lpcfg_sam_name(ctx->auth_ctx->lp_ctx),
699 					     lpcfg_sam_dnsname(ctx->auth_ctx->lp_ctx),
700 					     domain_dn,
701 					     msg,
702 					     user_sess_key, lm_sess_key,
703 					     user_info_dc);
704 	if (!NT_STATUS_IS_OK(nt_status)) {
705 		talloc_free(tmp_ctx);
706 		return nt_status;
707 	}
708 
709 	talloc_steal(mem_ctx, *user_info_dc);
710 	talloc_free(tmp_ctx);
711 
712 	return NT_STATUS_OK;
713 }
714 
authsam_ignoredomain_want_check(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info)715 static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx,
716 						TALLOC_CTX *mem_ctx,
717 						const struct auth_usersupplied_info *user_info)
718 {
719 	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
720 		return NT_STATUS_NOT_IMPLEMENTED;
721 	}
722 
723 	return NT_STATUS_OK;
724 }
725 
726 /****************************************************************************
727 Check SAM security (above) but with a few extra checks.
728 ****************************************************************************/
authsam_want_check(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info)729 static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
730 				   TALLOC_CTX *mem_ctx,
731 				   const struct auth_usersupplied_info *user_info)
732 {
733 	const char *effective_domain = user_info->mapped.domain_name;
734 	bool is_local_name = false;
735 	bool is_my_domain = false;
736 	const char *p = NULL;
737 	struct dsdb_trust_routing_table *trt = NULL;
738 	const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
739 	NTSTATUS status;
740 
741 	if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
742 		return NT_STATUS_NOT_IMPLEMENTED;
743 	}
744 
745 	if (effective_domain == NULL) {
746 		effective_domain = "";
747 	}
748 
749 	is_local_name = lpcfg_is_myname(ctx->auth_ctx->lp_ctx,
750 					effective_domain);
751 
752 	/* check whether or not we service this domain/workgroup name */
753 	switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
754 	case ROLE_STANDALONE:
755 		return NT_STATUS_OK;
756 
757 	case ROLE_DOMAIN_MEMBER:
758 		if (is_local_name) {
759 			return NT_STATUS_OK;
760 		}
761 
762 		DBG_DEBUG("%s is not one of my local names (DOMAIN_MEMBER)\n",
763 			  effective_domain);
764 		return NT_STATUS_NOT_IMPLEMENTED;
765 
766 	case ROLE_ACTIVE_DIRECTORY_DC:
767 		/* handled later */
768 		break;
769 
770 	default:
771 		DBG_ERR("lpcfg_server_role() has an undefined value\n");
772 		return NT_STATUS_INVALID_SERVER_STATE;
773 	}
774 
775 	/*
776 	 * Now we handle the AD DC case...
777 	 */
778 
779 	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
780 						   effective_domain);
781 	if (is_my_domain) {
782 		return NT_STATUS_OK;
783 	}
784 
785 	if (user_info->mapped_state) {
786 		/*
787 		 * The caller already did a cracknames call.
788 		 */
789 		DBG_DEBUG("%s is not one domain name (DC)\n",
790 			  effective_domain);
791 		return NT_STATUS_NOT_IMPLEMENTED;
792 	}
793 
794 	if (!strequal(effective_domain, "")) {
795 		DBG_DEBUG("%s is not one domain name (DC)\n",
796 			  effective_domain);
797 		return NT_STATUS_NOT_IMPLEMENTED;
798 	}
799 
800 	p = strchr_m(user_info->mapped.account_name, '@');
801 	if (p == NULL) {
802 		/*
803 		 * An empty to domain name should be handled
804 		 * as the local domain name.
805 		 */
806 		return NT_STATUS_OK;
807 	}
808 
809 	effective_domain = p + 1;
810 	is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
811 						   effective_domain);
812 	if (is_my_domain) {
813 		return NT_STATUS_OK;
814 	}
815 
816 	if (strequal(effective_domain, "")) {
817 		DBG_DEBUG("authsam_check_password: upn without realm (DC)\n");
818 		return NT_STATUS_NOT_IMPLEMENTED;
819 	}
820 
821 	/*
822 	 * as last option we check the routing table if the
823 	 * domain is within our forest.
824 	 */
825 	status = dsdb_trust_routing_table_load(ctx->auth_ctx->sam_ctx,
826 					       mem_ctx, &trt);
827 	if (!NT_STATUS_IS_OK(status)) {
828 		DBG_ERR("authsam_check_password: dsdb_trust_routing_table_load() %s\n",
829 			 nt_errstr(status));
830 		return status;
831 	}
832 
833 	tdo = dsdb_trust_routing_by_name(trt, effective_domain);
834 	if (tdo == NULL) {
835 		DBG_DEBUG("%s is not a known TLN (DC)\n",
836 			  effective_domain);
837 		TALLOC_FREE(trt);
838 		return NT_STATUS_NOT_IMPLEMENTED;
839 	}
840 
841 	if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
842 		DBG_DEBUG("%s is not a TLN in our forest (DC)\n",
843 			  effective_domain);
844 		TALLOC_FREE(trt);
845 		return NT_STATUS_NOT_IMPLEMENTED;
846 	}
847 
848 	/*
849 	 * This principal is within our forest.
850 	 * we'll later do a crack_name_to_nt4_name()
851 	 * to check if it's in our domain.
852 	 */
853 	TALLOC_FREE(trt);
854 	return NT_STATUS_OK;
855 }
856 
857 /* Wrapper for the auth subsystem pointer */
authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX * mem_ctx,struct auth4_context * auth_context,const char * principal,struct ldb_dn * user_dn,struct auth_user_info_dc ** user_info_dc)858 static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx,
859 							  struct auth4_context *auth_context,
860 							  const char *principal,
861 							  struct ldb_dn *user_dn,
862 							  struct auth_user_info_dc **user_info_dc)
863 {
864 	return authsam_get_user_info_dc_principal(mem_ctx, auth_context->lp_ctx, auth_context->sam_ctx,
865 						 principal, user_dn, user_info_dc);
866 }
867 static const struct auth_operations sam_ignoredomain_ops = {
868 	.name		           = "sam_ignoredomain",
869 	.want_check	           = authsam_ignoredomain_want_check,
870 	.check_password	           = authsam_check_password_internals,
871 	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
872 };
873 
874 static const struct auth_operations sam_ops = {
875 	.name		           = "sam",
876 	.want_check	           = authsam_want_check,
877 	.check_password	           = authsam_check_password_internals,
878 	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
879 };
880 
881 _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *);
auth4_sam_init(TALLOC_CTX * ctx)882 _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *ctx)
883 {
884 	NTSTATUS ret;
885 
886 	ret = auth_register(ctx, &sam_ops);
887 	if (!NT_STATUS_IS_OK(ret)) {
888 		DEBUG(0,("Failed to register 'sam' auth backend!\n"));
889 		return ret;
890 	}
891 
892 	ret = auth_register(ctx, &sam_ignoredomain_ops);
893 	if (!NT_STATUS_IS_OK(ret)) {
894 		DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
895 		return ret;
896 	}
897 
898 	return ret;
899 }
900