Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Winbind daemon - pam auth funcions
5 :
6 : Copyright (C) Andrew Tridgell 2000
7 : Copyright (C) Tim Potter 2001
8 : Copyright (C) Andrew Bartlett 2001-2002
9 : Copyright (C) Guenther Deschner 2005
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include "ntdomain.h"
27 : #include "winbindd.h"
28 : #include "libsmb/namequery.h"
29 : #include "../libcli/auth/libcli_auth.h"
30 : #include "libcli/auth/pam_errors.h"
31 : #include "../librpc/gen_ndr/ndr_samr_c.h"
32 : #include "librpc/rpc/dcesrv_core.h"
33 : #include "librpc/gen_ndr/ndr_winbind.h"
34 : #include "rpc_client/cli_pipe.h"
35 : #include "rpc_client/cli_samr.h"
36 : #include "../librpc/gen_ndr/ndr_netlogon.h"
37 : #include "rpc_client/cli_netlogon.h"
38 : #include "smb_krb5.h"
39 : #include "../libcli/security/security.h"
40 : #include "ads.h"
41 : #include "../librpc/gen_ndr/krb5pac.h"
42 : #include "passdb/machine_sid.h"
43 : #include "auth.h"
44 : #include "../lib/tsocket/tsocket.h"
45 : #include "auth/kerberos/pac_utils.h"
46 : #include "auth/gensec/gensec.h"
47 : #include "librpc/crypto/gse_krb5.h"
48 : #include "lib/afs/afs_funcs.h"
49 : #include "libsmb/samlogon_cache.h"
50 : #include "rpc_client/util_netlogon.h"
51 : #include "param/param.h"
52 : #include "messaging/messaging.h"
53 : #include "lib/util/string_wrappers.h"
54 : #include "lib/crypto/gnutls_helpers.h"
55 :
56 : #include "lib/crypto/gnutls_helpers.h"
57 : #include <gnutls/crypto.h>
58 : #include "lib/global_contexts.h"
59 :
60 : #undef DBGC_CLASS
61 : #define DBGC_CLASS DBGC_WINBIND
62 :
63 : #define LOGON_KRB5_FAIL_CLOCK_SKEW 0x02000000
64 :
65 1105 : static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
66 : struct winbindd_response *resp,
67 : uint16_t validation_level,
68 : union netr_Validation *validation)
69 : {
70 1105 : struct netr_SamInfo3 *info3 = NULL;
71 1105 : char *ex = NULL;
72 : uint32_t i;
73 1105 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
74 1105 : TALLOC_CTX *frame = talloc_stackframe();
75 :
76 1105 : status = map_validation_to_info3(frame,
77 : validation_level,
78 : validation,
79 : &info3);
80 1105 : if (!NT_STATUS_IS_OK(status)) {
81 0 : goto out;
82 : }
83 :
84 1105 : resp->data.auth.info3.logon_time =
85 1105 : nt_time_to_unix(info3->base.logon_time);
86 1105 : resp->data.auth.info3.logoff_time =
87 1105 : nt_time_to_unix(info3->base.logoff_time);
88 1105 : resp->data.auth.info3.kickoff_time =
89 1105 : nt_time_to_unix(info3->base.kickoff_time);
90 1105 : resp->data.auth.info3.pass_last_set_time =
91 1105 : nt_time_to_unix(info3->base.last_password_change);
92 1105 : resp->data.auth.info3.pass_can_change_time =
93 1105 : nt_time_to_unix(info3->base.allow_password_change);
94 1105 : resp->data.auth.info3.pass_must_change_time =
95 1105 : nt_time_to_unix(info3->base.force_password_change);
96 :
97 1105 : resp->data.auth.info3.logon_count = info3->base.logon_count;
98 1105 : resp->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
99 :
100 1105 : resp->data.auth.info3.user_rid = info3->base.rid;
101 1105 : resp->data.auth.info3.group_rid = info3->base.primary_gid;
102 1105 : sid_to_fstring(resp->data.auth.info3.dom_sid, info3->base.domain_sid);
103 :
104 1105 : resp->data.auth.info3.num_groups = info3->base.groups.count;
105 1105 : resp->data.auth.info3.user_flgs = info3->base.user_flags;
106 :
107 1105 : resp->data.auth.info3.acct_flags = info3->base.acct_flags;
108 1105 : resp->data.auth.info3.num_other_sids = info3->sidcount;
109 :
110 1105 : fstrcpy(resp->data.auth.info3.user_name,
111 : info3->base.account_name.string);
112 1105 : fstrcpy(resp->data.auth.info3.full_name,
113 : info3->base.full_name.string);
114 1105 : fstrcpy(resp->data.auth.info3.logon_script,
115 : info3->base.logon_script.string);
116 1105 : fstrcpy(resp->data.auth.info3.profile_path,
117 : info3->base.profile_path.string);
118 1105 : fstrcpy(resp->data.auth.info3.home_dir,
119 : info3->base.home_directory.string);
120 1105 : fstrcpy(resp->data.auth.info3.dir_drive,
121 : info3->base.home_drive.string);
122 :
123 1105 : fstrcpy(resp->data.auth.info3.logon_srv,
124 : info3->base.logon_server.string);
125 1105 : fstrcpy(resp->data.auth.info3.logon_dom,
126 : info3->base.logon_domain.string);
127 :
128 1105 : resp->data.auth.validation_level = validation_level;
129 1105 : if (validation_level == 6) {
130 1045 : fstrcpy(resp->data.auth.info6.dns_domainname,
131 : validation->sam6->dns_domainname.string);
132 1045 : fstrcpy(resp->data.auth.info6.principal_name,
133 : validation->sam6->principal_name.string);
134 : }
135 :
136 1105 : ex = talloc_strdup(frame, "");
137 1105 : if (ex == NULL) {
138 0 : status = NT_STATUS_NO_MEMORY;
139 0 : goto out;
140 : }
141 :
142 7129 : for (i=0; i < info3->base.groups.count; i++) {
143 12048 : ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
144 6024 : info3->base.groups.rids[i].rid,
145 6024 : info3->base.groups.rids[i].attributes);
146 6024 : if (ex == NULL) {
147 0 : status = NT_STATUS_NO_MEMORY;
148 0 : goto out;
149 : }
150 : }
151 :
152 1712 : for (i=0; i < info3->sidcount; i++) {
153 : struct dom_sid_buf sidbuf;
154 :
155 904 : ex = talloc_asprintf_append_buffer(
156 : ex,
157 : "%s:0x%08X\n",
158 607 : dom_sid_str_buf(info3->sids[i].sid, &sidbuf),
159 607 : info3->sids[i].attributes);
160 607 : if (ex == NULL) {
161 0 : status = NT_STATUS_NO_MEMORY;
162 0 : goto out;
163 : }
164 : }
165 :
166 1105 : resp->length += talloc_get_size(ex);
167 1105 : resp->extra_data.data = talloc_move(mem_ctx, &ex);
168 :
169 1105 : status = NT_STATUS_OK;
170 1105 : out:
171 1105 : TALLOC_FREE(frame);
172 1105 : return status;
173 : }
174 :
175 0 : static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
176 : struct winbindd_response *resp,
177 : struct netr_SamInfo3 *info3)
178 : {
179 : DATA_BLOB blob;
180 : enum ndr_err_code ndr_err;
181 :
182 0 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3,
183 : (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
184 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
185 0 : DEBUG(0,("append_info3_as_ndr: failed to append\n"));
186 0 : return ndr_map_error2ntstatus(ndr_err);
187 : }
188 :
189 0 : resp->extra_data.data = blob.data;
190 0 : resp->length += blob.length;
191 :
192 0 : return NT_STATUS_OK;
193 : }
194 :
195 181 : static NTSTATUS append_unix_username(uint16_t validation_level,
196 : union netr_Validation *validation,
197 : const char *name_domain,
198 : const char *name_user,
199 : TALLOC_CTX *mem_ctx,
200 : char **_unix_username)
201 : {
202 181 : TALLOC_CTX *tmp_ctx = NULL;
203 181 : const char *nt_username = NULL;
204 181 : const char *nt_domain = NULL;
205 181 : char *unix_username = NULL;
206 181 : struct netr_SamBaseInfo *base_info = NULL;
207 : NTSTATUS status;
208 :
209 181 : tmp_ctx = talloc_new(mem_ctx);
210 181 : if (tmp_ctx == NULL) {
211 0 : return NT_STATUS_NO_MEMORY;
212 : }
213 :
214 : /* We've been asked to return the unix username, per
215 : 'winbind use default domain' settings and the like */
216 :
217 181 : switch (validation_level) {
218 14 : case 3:
219 14 : base_info = &validation->sam3->base;
220 14 : break;
221 167 : case 6:
222 167 : base_info = &validation->sam6->base;
223 167 : break;
224 0 : default:
225 0 : DBG_ERR("Invalid validation level %d\n", validation_level);
226 0 : status = NT_STATUS_INTERNAL_ERROR;
227 0 : goto out;
228 : }
229 :
230 181 : nt_domain = talloc_strdup(tmp_ctx, base_info->logon_domain.string);
231 181 : if (!nt_domain) {
232 : /* If the server didn't give us one, just use the one
233 : * we sent them */
234 0 : nt_domain = name_domain;
235 : }
236 :
237 181 : nt_username = talloc_strdup(tmp_ctx, base_info->account_name.string);
238 181 : if (!nt_username) {
239 : /* If the server didn't give us one, just use the one
240 : * we sent them */
241 0 : nt_username = name_user;
242 : }
243 :
244 181 : unix_username = fill_domain_username_talloc(tmp_ctx,
245 : nt_domain,
246 : nt_username,
247 : true);
248 181 : if (unix_username == NULL) {
249 0 : status = NT_STATUS_NO_MEMORY;
250 0 : goto out;
251 : }
252 :
253 181 : DBG_INFO("Setting unix username to [%s]\n", unix_username);
254 :
255 181 : *_unix_username = talloc_move(mem_ctx, &unix_username);
256 :
257 181 : status = NT_STATUS_OK;
258 181 : out:
259 181 : TALLOC_FREE(tmp_ctx);
260 :
261 181 : return status;
262 : }
263 :
264 0 : static NTSTATUS append_afs_token(uint16_t validation_level,
265 : union netr_Validation *validation,
266 : const char *name_domain,
267 : const char *name_user,
268 : TALLOC_CTX *mem_ctx,
269 : DATA_BLOB *_blob)
270 : {
271 0 : TALLOC_CTX *tmp_ctx = NULL;
272 0 : char *afsname = NULL;
273 : char *cell;
274 : char *token;
275 0 : struct netr_SamBaseInfo *base_info = NULL;
276 : NTSTATUS status;
277 :
278 0 : tmp_ctx = talloc_new(mem_ctx);
279 0 : if (tmp_ctx == NULL) {
280 0 : return NT_STATUS_NO_MEMORY;
281 : }
282 :
283 0 : switch (validation_level) {
284 0 : case 3:
285 0 : base_info = &validation->sam3->base;
286 0 : break;
287 0 : case 6:
288 0 : base_info = &validation->sam6->base;
289 0 : break;
290 0 : default:
291 0 : DBG_ERR("Invalid validation level %d\n", validation_level);
292 0 : status = NT_STATUS_INTERNAL_ERROR;
293 0 : goto out;
294 : }
295 :
296 0 : afsname = talloc_strdup(tmp_ctx, lp_afs_username_map());
297 0 : if (afsname == NULL) {
298 0 : status = NT_STATUS_NO_MEMORY;
299 0 : goto out;
300 : }
301 :
302 0 : afsname = talloc_string_sub(tmp_ctx,
303 : lp_afs_username_map(),
304 : "%D", name_domain);
305 0 : afsname = talloc_string_sub(tmp_ctx, afsname,
306 : "%u", name_user);
307 0 : afsname = talloc_string_sub(tmp_ctx, afsname,
308 : "%U", name_user);
309 :
310 : {
311 : struct dom_sid user_sid;
312 : struct dom_sid_buf sidstr;
313 :
314 0 : sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
315 0 : afsname = talloc_string_sub(
316 : tmp_ctx,
317 : afsname,
318 : "%s",
319 0 : dom_sid_str_buf(&user_sid, &sidstr));
320 : }
321 :
322 0 : if (afsname == NULL) {
323 0 : status = NT_STATUS_NO_MEMORY;
324 0 : goto out;
325 : }
326 :
327 0 : if (!strlower_m(afsname)) {
328 0 : status = NT_STATUS_INVALID_PARAMETER;
329 0 : goto out;
330 : }
331 :
332 0 : DEBUG(10, ("Generating token for user %s\n", afsname));
333 :
334 0 : cell = strchr(afsname, '@');
335 :
336 0 : if (cell == NULL) {
337 0 : status = NT_STATUS_NO_MEMORY;
338 0 : goto out;
339 : }
340 :
341 0 : *cell = '\0';
342 0 : cell += 1;
343 :
344 0 : token = afs_createtoken_str(afsname, cell);
345 0 : if (token == NULL) {
346 0 : status = NT_STATUS_OK;
347 0 : goto out;
348 : }
349 :
350 0 : talloc_steal(mem_ctx, token);
351 0 : *_blob = data_blob_string_const_null(token);
352 :
353 0 : status = NT_STATUS_OK;
354 0 : out:
355 0 : TALLOC_FREE(tmp_ctx);
356 :
357 0 : return status;
358 : }
359 :
360 850 : NTSTATUS extra_data_to_sid_array(const char *group_sid,
361 : TALLOC_CTX *mem_ctx,
362 : struct wbint_SidArray **_sid_array)
363 : {
364 850 : TALLOC_CTX *tmp_ctx = NULL;
365 850 : struct wbint_SidArray *sid_array = NULL;
366 850 : struct dom_sid *require_membership_of_sid = NULL;
367 850 : uint32_t num_require_membership_of_sid = 0;
368 850 : char *req_sid = NULL;
369 850 : const char *p = NULL;
370 : NTSTATUS status;
371 :
372 850 : if (_sid_array == NULL) {
373 0 : return NT_STATUS_INVALID_PARAMETER;
374 : }
375 :
376 850 : *_sid_array = NULL;
377 :
378 850 : tmp_ctx = talloc_new(mem_ctx);
379 850 : if (tmp_ctx == NULL) {
380 0 : return NT_STATUS_NO_MEMORY;
381 : }
382 :
383 850 : sid_array = talloc_zero(tmp_ctx, struct wbint_SidArray);
384 850 : if (sid_array == NULL) {
385 0 : status = NT_STATUS_NO_MEMORY;
386 0 : goto fail;
387 : }
388 :
389 850 : if (!group_sid || !group_sid[0]) {
390 : /* NO sid supplied, all users may access */
391 816 : status = NT_STATUS_OK;
392 : /*
393 : * Always return an allocated wbint_SidArray,
394 : * even if the array is empty.
395 : */
396 816 : goto out;
397 : }
398 :
399 34 : num_require_membership_of_sid = 0;
400 34 : require_membership_of_sid = NULL;
401 34 : p = group_sid;
402 :
403 94 : while (next_token_talloc(tmp_ctx, &p, &req_sid, ",")) {
404 : struct dom_sid sid;
405 :
406 34 : if (!string_to_sid(&sid, req_sid)) {
407 0 : DBG_ERR("check_info3_in_group: could not parse %s "
408 : "as a SID!\n", req_sid);
409 0 : status = NT_STATUS_INVALID_PARAMETER;
410 0 : goto fail;
411 : }
412 :
413 34 : status = add_sid_to_array(tmp_ctx, &sid,
414 : &require_membership_of_sid,
415 : &num_require_membership_of_sid);
416 34 : if (!NT_STATUS_IS_OK(status)) {
417 0 : DBG_ERR("add_sid_to_array failed\n");
418 0 : goto fail;
419 : }
420 : }
421 :
422 34 : sid_array->num_sids = num_require_membership_of_sid;
423 34 : sid_array->sids = talloc_move(sid_array, &require_membership_of_sid);
424 :
425 34 : status = NT_STATUS_OK;
426 850 : out:
427 850 : *_sid_array = talloc_move(mem_ctx, &sid_array);
428 :
429 850 : fail:
430 850 : TALLOC_FREE(tmp_ctx);
431 :
432 850 : return status;
433 : }
434 :
435 0 : static NTSTATUS check_info3_in_group(struct netr_SamInfo3 *info3,
436 : struct wbint_SidArray *sid_array)
437 : /**
438 : * Check whether a user belongs to a group or list of groups.
439 : *
440 : * @param mem_ctx talloc memory context.
441 : * @param info3 user information, including group membership info.
442 : * @param group_sid One or more groups , separated by commas.
443 : *
444 : * @return NT_STATUS_OK on success,
445 : * NT_STATUS_LOGON_FAILURE if the user does not belong,
446 : * or other NT_STATUS_IS_ERR(status) for other kinds of failure.
447 : */
448 : {
449 : size_t i;
450 : struct security_token *token;
451 : NTSTATUS status;
452 :
453 : /* Parse the 'required group' SID */
454 :
455 0 : if (sid_array == NULL || sid_array->num_sids == 0) {
456 : /* NO sid supplied, all users may access */
457 0 : return NT_STATUS_OK;
458 : }
459 :
460 0 : token = talloc_zero(talloc_tos(), struct security_token);
461 0 : if (token == NULL) {
462 0 : DEBUG(0, ("talloc failed\n"));
463 0 : return NT_STATUS_NO_MEMORY;
464 : }
465 :
466 0 : status = sid_array_from_info3(talloc_tos(), info3,
467 : &token->sids,
468 : &token->num_sids,
469 : true);
470 0 : if (!NT_STATUS_IS_OK(status)) {
471 0 : return status;
472 : }
473 :
474 0 : if (!NT_STATUS_IS_OK(status = add_aliases(get_global_sam_sid(),
475 : token))
476 0 : || !NT_STATUS_IS_OK(status = add_aliases(&global_sid_Builtin,
477 : token))) {
478 0 : DEBUG(3, ("could not add aliases: %s\n",
479 : nt_errstr(status)));
480 0 : return status;
481 : }
482 :
483 0 : security_token_debug(DBGC_CLASS, 10, token);
484 :
485 0 : for (i=0; i<sid_array->num_sids; i++) {
486 : struct dom_sid_buf buf;
487 0 : DEBUG(10, ("Checking SID %s\n",
488 : dom_sid_str_buf(&sid_array->sids[i],
489 : &buf)));
490 0 : if (nt_token_check_sid(&sid_array->sids[i],
491 : token)) {
492 0 : DEBUG(10, ("Access ok\n"));
493 0 : return NT_STATUS_OK;
494 : }
495 : }
496 :
497 : /* Do not distinguish this error from a wrong username/pw */
498 :
499 0 : return NT_STATUS_LOGON_FAILURE;
500 : }
501 :
502 1281 : struct winbindd_domain *find_auth_domain(uint8_t flags,
503 : const char *domain_name)
504 : {
505 : struct winbindd_domain *domain;
506 :
507 1281 : if (IS_DC) {
508 566 : domain = find_domain_from_name_noinit(domain_name);
509 566 : if (domain == NULL) {
510 135 : DEBUG(3, ("Authentication for domain [%s] refused "
511 : "as it is not a trusted domain\n",
512 : domain_name));
513 135 : return NULL;
514 : }
515 :
516 431 : if (domain->secure_channel_type != SEC_CHAN_NULL) {
517 431 : return domain;
518 : }
519 :
520 0 : return domain->routing_domain;
521 : }
522 :
523 715 : if (strequal(domain_name, get_global_sam_name())) {
524 46 : return find_domain_from_name_noinit(domain_name);
525 : }
526 :
527 669 : if (lp_winbind_use_krb5_enterprise_principals()) {
528 : /*
529 : * If we use enterprise principals
530 : * we always go trough our primary domain
531 : * and follow the WRONG_REALM replies.
532 : */
533 669 : flags &= ~WBFLAG_PAM_CONTACT_TRUSTDOM;
534 : }
535 :
536 : /* we can auth against trusted domains */
537 669 : if (flags & WBFLAG_PAM_CONTACT_TRUSTDOM) {
538 0 : domain = find_domain_from_name_noinit(domain_name);
539 0 : if (domain == NULL) {
540 0 : DEBUG(3, ("Authentication for domain [%s] skipped "
541 : "as it is not a trusted domain\n",
542 : domain_name));
543 : } else {
544 0 : return domain;
545 : }
546 : }
547 :
548 669 : return find_our_domain();
549 : }
550 :
551 0 : static NTSTATUS get_password_policy(struct winbindd_domain *domain,
552 : TALLOC_CTX *mem_ctx,
553 : struct samr_DomInfo1 **_policy)
554 : {
555 : NTSTATUS status;
556 0 : struct samr_DomInfo1 *policy = NULL;
557 :
558 0 : if ( !winbindd_can_contact_domain( domain ) ) {
559 0 : DBG_INFO("No inbound trust to contact domain %s\n",
560 : domain->name);
561 0 : return NT_STATUS_NOT_SUPPORTED;
562 : }
563 :
564 0 : policy = talloc_zero(mem_ctx, struct samr_DomInfo1);
565 0 : if (policy == NULL) {
566 0 : return NT_STATUS_NO_MEMORY;
567 : }
568 :
569 0 : status = wb_cache_password_policy(domain, mem_ctx, policy);
570 0 : if (NT_STATUS_IS_ERR(status)) {
571 0 : TALLOC_FREE(policy);
572 0 : return status;
573 : }
574 :
575 0 : *_policy = talloc_move(mem_ctx, &policy);
576 :
577 0 : return NT_STATUS_OK;
578 : }
579 :
580 0 : static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
581 : TALLOC_CTX *mem_ctx,
582 : uint16_t *lockout_threshold)
583 : {
584 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
585 : struct samr_DomInfo12 lockout_policy;
586 :
587 0 : *lockout_threshold = 0;
588 :
589 0 : status = wb_cache_lockout_policy(domain, mem_ctx, &lockout_policy);
590 0 : if (NT_STATUS_IS_ERR(status)) {
591 0 : return status;
592 : }
593 :
594 0 : *lockout_threshold = lockout_policy.lockout_threshold;
595 :
596 0 : return NT_STATUS_OK;
597 : }
598 :
599 0 : static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
600 : TALLOC_CTX *mem_ctx,
601 : uint32_t *password_properties)
602 : {
603 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
604 : struct samr_DomInfo1 password_policy;
605 :
606 0 : *password_properties = 0;
607 :
608 0 : status = wb_cache_password_policy(domain, mem_ctx, &password_policy);
609 0 : if (NT_STATUS_IS_ERR(status)) {
610 0 : return status;
611 : }
612 :
613 0 : *password_properties = password_policy.password_properties;
614 :
615 0 : return NT_STATUS_OK;
616 : }
617 :
618 : #ifdef HAVE_KRB5
619 :
620 0 : static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx,
621 : const char *type,
622 : uid_t uid,
623 : const char **user_ccache_file)
624 : {
625 : /* accept FILE and WRFILE as krb5_cc_type from the client and then
626 : * build the full ccname string based on the user's uid here -
627 : * Guenther*/
628 :
629 0 : const char *gen_cc = NULL;
630 :
631 0 : if (uid != -1) {
632 0 : if (strequal(type, "FILE")) {
633 0 : gen_cc = talloc_asprintf(
634 : mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
635 : }
636 0 : if (strequal(type, "WRFILE")) {
637 0 : gen_cc = talloc_asprintf(
638 : mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
639 : }
640 0 : if (strequal(type, "KEYRING")) {
641 0 : gen_cc = talloc_asprintf(
642 : mem_ctx, "KEYRING:persistent:%d", uid);
643 : }
644 0 : if (strequal(type, "KCM")) {
645 0 : gen_cc = talloc_asprintf(mem_ctx,
646 : "KCM:%d",
647 : uid);
648 : }
649 :
650 0 : if (strnequal(type, "FILE:/", 6) ||
651 0 : strnequal(type, "WRFILE:/", 8) ||
652 0 : strnequal(type, "DIR:/", 5)) {
653 :
654 : /* we allow only one "%u" substitution */
655 :
656 : char *p;
657 :
658 0 : p = strchr(type, '%');
659 0 : if (p != NULL) {
660 :
661 0 : p++;
662 :
663 0 : if (p != NULL && *p == 'u' && strchr(p, '%') == NULL) {
664 : char uid_str[sizeof("18446744073709551615")];
665 :
666 0 : snprintf(uid_str, sizeof(uid_str), "%u", uid);
667 :
668 0 : gen_cc = talloc_string_sub2(mem_ctx,
669 : type,
670 : "%u",
671 : uid_str,
672 : /* remove_unsafe_characters */
673 : false,
674 : /* replace_once */
675 : true,
676 : /* allow_trailing_dollar */
677 : false);
678 : }
679 : }
680 : }
681 : }
682 :
683 0 : *user_ccache_file = gen_cc;
684 :
685 0 : if (gen_cc == NULL) {
686 0 : gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache");
687 : }
688 0 : if (gen_cc == NULL) {
689 0 : DEBUG(0,("out of memory\n"));
690 0 : return NULL;
691 : }
692 :
693 0 : DEBUG(10, ("using ccache: %s%s\n", gen_cc,
694 : (*user_ccache_file == NULL) ? " (internal)":""));
695 :
696 0 : return gen_cc;
697 : }
698 :
699 : #endif
700 :
701 0 : uid_t get_uid_from_request(struct winbindd_request *request)
702 : {
703 : uid_t uid;
704 :
705 0 : uid = request->data.auth.uid;
706 :
707 0 : if (uid == (uid_t)-1) {
708 0 : DEBUG(1,("invalid uid: '%u'\n", (unsigned int)uid));
709 0 : return -1;
710 : }
711 0 : return uid;
712 : }
713 :
714 : /**********************************************************************
715 : Authenticate a user with a clear text password using Kerberos and fill up
716 : ccache if required
717 : **********************************************************************/
718 :
719 0 : static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
720 : struct winbindd_domain *domain,
721 : const char *user,
722 : const char *pass,
723 : const char *krb5_cc_type,
724 : uid_t uid,
725 : struct netr_SamInfo6 **info6,
726 : const char **_krb5ccname)
727 : {
728 : #ifdef HAVE_KRB5
729 0 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
730 : krb5_error_code krb5_ret;
731 0 : const char *cc = NULL;
732 0 : const char *principal_s = NULL;
733 0 : char *realm = NULL;
734 : fstring name_namespace, name_domain, name_user;
735 0 : time_t ticket_lifetime = 0;
736 0 : time_t renewal_until = 0;
737 0 : time_t time_offset = 0;
738 : const char *user_ccache_file;
739 0 : struct PAC_LOGON_INFO *logon_info = NULL;
740 0 : struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
741 0 : struct PAC_DATA *pac_data = NULL;
742 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
743 : const char *local_service;
744 : uint32_t i;
745 0 : struct netr_SamInfo6 *info6_copy = NULL;
746 0 : char *canon_principal = NULL;
747 0 : char *canon_realm = NULL;
748 : bool ok;
749 :
750 0 : *info6 = NULL;
751 :
752 0 : if (domain->alt_name == NULL) {
753 0 : return NT_STATUS_INVALID_PARAMETER;
754 : }
755 :
756 0 : if (_krb5ccname != NULL) {
757 0 : *_krb5ccname = NULL;
758 : }
759 :
760 : /* 1st step:
761 : * prepare a krb5_cc_cache string for the user */
762 :
763 0 : if (uid == -1) {
764 0 : DEBUG(0,("no valid uid\n"));
765 : }
766 :
767 0 : cc = generate_krb5_ccache(mem_ctx,
768 : krb5_cc_type,
769 : uid,
770 : &user_ccache_file);
771 0 : if (cc == NULL) {
772 0 : return NT_STATUS_NO_MEMORY;
773 : }
774 :
775 :
776 : /* 2nd step:
777 : * get kerberos properties */
778 :
779 0 : if (domain->backend_data.ads_conn != NULL) {
780 0 : time_offset = domain->backend_data.ads_conn->auth.time_offset;
781 : }
782 :
783 :
784 : /* 3rd step:
785 : * do kerberos auth and setup ccache as the user */
786 :
787 0 : ok = parse_domain_user(user, name_namespace, name_domain, name_user);
788 0 : if (!ok) {
789 0 : return NT_STATUS_INVALID_PARAMETER;
790 : }
791 :
792 0 : realm = talloc_strdup(mem_ctx, domain->alt_name);
793 0 : if (realm == NULL) {
794 0 : return NT_STATUS_NO_MEMORY;
795 : }
796 :
797 0 : if (!strupper_m(realm)) {
798 0 : return NT_STATUS_INVALID_PARAMETER;
799 : }
800 :
801 0 : if (lp_winbind_use_krb5_enterprise_principals() &&
802 0 : name_namespace[0] != '\0')
803 : {
804 0 : principal_s = talloc_asprintf(mem_ctx,
805 : "%s@%s@%s",
806 : name_user,
807 : name_namespace,
808 : realm);
809 : } else {
810 0 : principal_s = talloc_asprintf(mem_ctx,
811 : "%s@%s",
812 : name_user,
813 : realm);
814 : }
815 0 : if (principal_s == NULL) {
816 0 : return NT_STATUS_NO_MEMORY;
817 : }
818 :
819 0 : local_service = talloc_asprintf(mem_ctx, "%s$@%s",
820 : lp_netbios_name(), lp_realm());
821 0 : if (local_service == NULL) {
822 0 : return NT_STATUS_NO_MEMORY;
823 : }
824 :
825 :
826 : /* if this is a user ccache, we need to act as the user to let the krb5
827 : * library handle the chown, etc. */
828 :
829 : /************************ ENTERING NON-ROOT **********************/
830 :
831 0 : if (user_ccache_file != NULL) {
832 0 : set_effective_uid(uid);
833 0 : DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
834 : }
835 :
836 0 : result = kerberos_return_pac(mem_ctx,
837 : principal_s,
838 : pass,
839 : time_offset,
840 : &ticket_lifetime,
841 : &renewal_until,
842 : cc,
843 : true,
844 : true,
845 : WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
846 : NULL,
847 : local_service,
848 : &canon_principal,
849 : &canon_realm,
850 : &pac_data_ctr);
851 0 : if (user_ccache_file != NULL) {
852 0 : gain_root_privilege();
853 : }
854 :
855 : /************************ RETURNED TO ROOT **********************/
856 :
857 0 : if (!NT_STATUS_IS_OK(result)) {
858 0 : goto failed;
859 : }
860 :
861 0 : if (pac_data_ctr == NULL) {
862 0 : goto failed;
863 : }
864 :
865 0 : pac_data = pac_data_ctr->pac_data;
866 0 : if (pac_data == NULL) {
867 0 : goto failed;
868 : }
869 :
870 0 : for (i=0; i < pac_data->num_buffers; i++) {
871 :
872 0 : if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
873 0 : logon_info = pac_data->buffers[i].info->logon_info.info;
874 0 : continue;
875 : }
876 :
877 0 : if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
878 0 : upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
879 0 : continue;
880 : }
881 : }
882 :
883 0 : if (logon_info == NULL) {
884 0 : DEBUG(10,("Missing logon_info in ticket of %s\n",
885 : principal_s));
886 0 : return NT_STATUS_INVALID_PARAMETER;
887 : }
888 :
889 0 : DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
890 : principal_s));
891 :
892 0 : result = create_info6_from_pac(mem_ctx, logon_info,
893 : upn_dns_info, &info6_copy);
894 0 : if (!NT_STATUS_IS_OK(result)) {
895 0 : goto failed;
896 : }
897 :
898 : /* if we had a user's ccache then return that string for the pam
899 : * environment */
900 :
901 0 : if (user_ccache_file != NULL) {
902 :
903 0 : if (_krb5ccname != NULL) {
904 0 : *_krb5ccname = talloc_steal(mem_ctx, user_ccache_file);
905 : }
906 :
907 0 : result = add_ccache_to_list(principal_s,
908 : cc,
909 : user,
910 : pass,
911 : realm,
912 : uid,
913 : time(NULL),
914 : ticket_lifetime,
915 : renewal_until,
916 : false,
917 : canon_principal,
918 : canon_realm);
919 :
920 0 : if (!NT_STATUS_IS_OK(result)) {
921 0 : DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
922 : nt_errstr(result)));
923 : }
924 : } else {
925 :
926 : /* need to delete the memory cred cache, it is not used anymore */
927 :
928 0 : krb5_ret = ads_kdestroy(cc);
929 0 : if (krb5_ret) {
930 0 : DEBUG(3,("winbindd_raw_kerberos_login: "
931 : "could not destroy krb5 credential cache: "
932 : "%s\n", error_message(krb5_ret)));
933 : }
934 :
935 : }
936 0 : *info6 = info6_copy;
937 0 : return NT_STATUS_OK;
938 :
939 0 : failed:
940 : /*
941 : * Do not delete an existing valid credential cache, if the user
942 : * e.g. enters a wrong password
943 : */
944 0 : if ((strequal(krb5_cc_type, "FILE") || strequal(krb5_cc_type, "WRFILE"))
945 0 : && user_ccache_file != NULL) {
946 0 : return result;
947 : }
948 :
949 : /* we could have created a new credential cache with a valid tgt in it
950 : * but we werent able to get or verify the service ticket for this
951 : * local host and therefor didn't get the PAC, we need to remove that
952 : * cache entirely now */
953 :
954 0 : krb5_ret = ads_kdestroy(cc);
955 0 : if (krb5_ret) {
956 0 : DEBUG(3,("winbindd_raw_kerberos_login: "
957 : "could not destroy krb5 credential cache: "
958 : "%s\n", error_message(krb5_ret)));
959 : }
960 :
961 0 : if (!NT_STATUS_IS_OK(remove_ccache(user))) {
962 0 : DEBUG(3,("winbindd_raw_kerberos_login: "
963 : "could not remove ccache for user %s\n",
964 : user));
965 : }
966 :
967 0 : return result;
968 : #else
969 : return NT_STATUS_NOT_SUPPORTED;
970 : #endif /* HAVE_KRB5 */
971 : }
972 :
973 : /****************************************************************
974 : ****************************************************************/
975 :
976 856 : bool check_request_flags(uint32_t flags)
977 : {
978 856 : uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN |
979 : WBFLAG_PAM_INFO3_TEXT |
980 : WBFLAG_PAM_INFO3_NDR;
981 :
982 1377 : if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) ||
983 1377 : ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) ||
984 995 : ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)||
985 185 : !(flags & flags_edata) ) {
986 856 : return true;
987 : }
988 :
989 0 : DEBUG(1, ("check_request_flags: invalid request flags[0x%08X]\n",
990 : flags));
991 :
992 0 : return false;
993 : }
994 :
995 : /****************************************************************
996 : ****************************************************************/
997 :
998 1238 : NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx,
999 : struct winbindd_response *resp,
1000 : uint32_t request_flags,
1001 : uint16_t validation_level,
1002 : union netr_Validation *validation,
1003 : const char *name_domain,
1004 : const char *name_user)
1005 : {
1006 1238 : struct netr_SamInfo3 *info3 = NULL;
1007 1238 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1008 :
1009 1238 : result = map_validation_to_info3(talloc_tos(),
1010 : validation_level,
1011 : validation,
1012 : &info3);
1013 1238 : if (!NT_STATUS_IS_OK(result)) {
1014 0 : goto out;
1015 : }
1016 :
1017 1238 : if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) {
1018 614 : memcpy(resp->data.auth.user_session_key,
1019 614 : info3->base.key.key,
1020 : sizeof(resp->data.auth.user_session_key)
1021 : /* 16 */);
1022 : }
1023 :
1024 1238 : if (request_flags & WBFLAG_PAM_LMKEY) {
1025 574 : memcpy(resp->data.auth.first_8_lm_hash,
1026 574 : info3->base.LMSessKey.key,
1027 : sizeof(resp->data.auth.first_8_lm_hash)
1028 : /* 8 */);
1029 : }
1030 :
1031 1238 : if (request_flags & WBFLAG_PAM_UNIX_NAME) {
1032 181 : char *unix_username = NULL;
1033 181 : result = append_unix_username(validation_level,
1034 : validation,
1035 : name_domain,
1036 : name_user,
1037 : mem_ctx,
1038 : &unix_username);
1039 181 : if (!NT_STATUS_IS_OK(result)) {
1040 0 : DEBUG(10,("Failed to append Unix Username: %s\n",
1041 : nt_errstr(result)));
1042 0 : goto out;
1043 : }
1044 181 : fstrcpy(resp->data.auth.unix_username, unix_username);
1045 181 : TALLOC_FREE(unix_username);
1046 : }
1047 :
1048 : /* currently, anything from here on potentially overwrites extra_data. */
1049 :
1050 1238 : if (request_flags & WBFLAG_PAM_INFO3_NDR) {
1051 0 : result = append_info3_as_ndr(mem_ctx, resp, info3);
1052 0 : if (!NT_STATUS_IS_OK(result)) {
1053 0 : DEBUG(10,("Failed to append INFO3 (NDR): %s\n",
1054 : nt_errstr(result)));
1055 0 : goto out;
1056 : }
1057 : }
1058 :
1059 1238 : if (request_flags & WBFLAG_PAM_INFO3_TEXT) {
1060 1105 : result = append_info3_as_txt(mem_ctx, resp,
1061 : validation_level,
1062 : validation);
1063 1105 : if (!NT_STATUS_IS_OK(result)) {
1064 0 : DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
1065 : nt_errstr(result)));
1066 0 : goto out;
1067 : }
1068 : }
1069 :
1070 1238 : if (request_flags & WBFLAG_PAM_AFS_TOKEN) {
1071 0 : DATA_BLOB blob = data_blob_null;
1072 0 : result = append_afs_token(validation_level,
1073 : validation,
1074 : name_domain,
1075 : name_user,
1076 : mem_ctx,
1077 : &blob);
1078 0 : if (!NT_STATUS_IS_OK(result)) {
1079 0 : DEBUG(10,("Failed to append AFS token: %s\n",
1080 : nt_errstr(result)));
1081 0 : goto out;
1082 : }
1083 0 : resp->extra_data.data = blob.data;
1084 0 : resp->length += blob.length;
1085 : }
1086 :
1087 1238 : result = NT_STATUS_OK;
1088 1238 : out:
1089 1238 : TALLOC_FREE(info3);
1090 1238 : return result;
1091 : }
1092 :
1093 0 : static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
1094 : bool krb5_auth,
1095 : const char *user,
1096 : const char *pass,
1097 : const char *krb5_cc_type,
1098 : uid_t uid,
1099 : TALLOC_CTX *mem_ctx,
1100 : uint16_t *_validation_level,
1101 : union netr_Validation **_validation,
1102 : const char **_krb5ccname)
1103 : {
1104 0 : TALLOC_CTX *tmp_ctx = NULL;
1105 0 : NTSTATUS result = NT_STATUS_LOGON_FAILURE;
1106 : uint16_t max_allowed_bad_attempts;
1107 : fstring name_namespace, name_domain, name_user;
1108 : struct dom_sid sid;
1109 : enum lsa_SidType type;
1110 : uchar new_nt_pass[NT_HASH_LEN];
1111 : const uint8_t *cached_nt_pass;
1112 : const uint8_t *cached_salt;
1113 : struct netr_SamInfo3 *my_info3;
1114 : time_t kickoff_time, must_change_time;
1115 0 : bool password_good = false;
1116 : bool ok;
1117 : #ifdef HAVE_KRB5
1118 0 : struct winbindd_tdc_domain *tdc_domain = NULL;
1119 : #endif
1120 :
1121 0 : if (_validation == NULL) {
1122 0 : return NT_STATUS_INVALID_PARAMETER;
1123 : }
1124 0 : *_validation = NULL;
1125 :
1126 0 : if (_krb5ccname != NULL) {
1127 0 : *_krb5ccname = NULL;
1128 : }
1129 :
1130 0 : DEBUG(10,("winbindd_dual_pam_auth_cached\n"));
1131 :
1132 0 : tmp_ctx = talloc_new(mem_ctx);
1133 0 : if (tmp_ctx == NULL) {
1134 0 : return NT_STATUS_NO_MEMORY;
1135 : }
1136 :
1137 : /* Parse domain and username */
1138 :
1139 0 : ok = parse_domain_user(user, name_namespace, name_domain, name_user);
1140 0 : if (!ok) {
1141 0 : DBG_DEBUG("parse_domain_user failed\n");
1142 0 : result = NT_STATUS_NO_SUCH_USER;
1143 0 : goto out;
1144 : }
1145 :
1146 0 : if (!lookup_cached_name(name_namespace,
1147 : name_domain,
1148 : name_user,
1149 : &sid,
1150 : &type)) {
1151 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n"));
1152 0 : result = NT_STATUS_NO_SUCH_USER;
1153 0 : goto out;
1154 : }
1155 :
1156 0 : if (type != SID_NAME_USER) {
1157 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type)));
1158 0 : result = NT_STATUS_LOGON_FAILURE;
1159 0 : goto out;
1160 : }
1161 :
1162 0 : result = winbindd_get_creds(domain,
1163 : tmp_ctx,
1164 : &sid,
1165 : &my_info3,
1166 : &cached_nt_pass,
1167 : &cached_salt);
1168 0 : if (!NT_STATUS_IS_OK(result)) {
1169 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
1170 0 : goto out;
1171 : }
1172 :
1173 0 : E_md4hash(pass, new_nt_pass);
1174 :
1175 0 : dump_data_pw("new_nt_pass", new_nt_pass, NT_HASH_LEN);
1176 0 : dump_data_pw("cached_nt_pass", cached_nt_pass, NT_HASH_LEN);
1177 0 : if (cached_salt) {
1178 0 : dump_data_pw("cached_salt", cached_salt, NT_HASH_LEN);
1179 : }
1180 :
1181 0 : if (cached_salt) {
1182 : /* In this case we didn't store the nt_hash itself,
1183 : but the MD5 combination of salt + nt_hash. */
1184 : uchar salted_hash[NT_HASH_LEN];
1185 0 : gnutls_hash_hd_t hash_hnd = NULL;
1186 : int rc;
1187 :
1188 0 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1189 0 : if (rc < 0) {
1190 0 : result = gnutls_error_to_ntstatus(
1191 : rc, NT_STATUS_HASH_NOT_SUPPORTED);
1192 0 : goto out;
1193 : }
1194 :
1195 0 : rc = gnutls_hash(hash_hnd, cached_salt, 16);
1196 0 : if (rc < 0) {
1197 0 : gnutls_hash_deinit(hash_hnd, NULL);
1198 0 : result = gnutls_error_to_ntstatus(
1199 : rc, NT_STATUS_HASH_NOT_SUPPORTED);
1200 0 : goto out;
1201 : }
1202 0 : rc = gnutls_hash(hash_hnd, new_nt_pass, 16);
1203 0 : if (rc < 0) {
1204 0 : gnutls_hash_deinit(hash_hnd, NULL);
1205 0 : result = gnutls_error_to_ntstatus(
1206 : rc, NT_STATUS_HASH_NOT_SUPPORTED);
1207 0 : goto out;
1208 : }
1209 0 : gnutls_hash_deinit(hash_hnd, salted_hash);
1210 :
1211 0 : password_good = mem_equal_const_time(cached_nt_pass, salted_hash,
1212 : NT_HASH_LEN);
1213 : } else {
1214 : /* Old cached cred - direct store of nt_hash (bad bad bad !). */
1215 0 : password_good = mem_equal_const_time(cached_nt_pass, new_nt_pass,
1216 : NT_HASH_LEN);
1217 : }
1218 :
1219 0 : if (password_good) {
1220 :
1221 : /* User *DOES* know the password, update logon_time and reset
1222 : * bad_pw_count */
1223 :
1224 0 : my_info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT;
1225 :
1226 0 : if (my_info3->base.acct_flags & ACB_AUTOLOCK) {
1227 0 : result = NT_STATUS_ACCOUNT_LOCKED_OUT;
1228 0 : goto out;
1229 : }
1230 :
1231 0 : if (my_info3->base.acct_flags & ACB_DISABLED) {
1232 0 : result = NT_STATUS_ACCOUNT_DISABLED;
1233 0 : goto out;
1234 : }
1235 :
1236 0 : if (my_info3->base.acct_flags & ACB_WSTRUST) {
1237 0 : result = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
1238 0 : goto out;
1239 : }
1240 :
1241 0 : if (my_info3->base.acct_flags & ACB_SVRTRUST) {
1242 0 : result = NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
1243 0 : goto out;
1244 : }
1245 :
1246 0 : if (my_info3->base.acct_flags & ACB_DOMTRUST) {
1247 0 : result = NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
1248 0 : goto out;
1249 : }
1250 :
1251 0 : if (!(my_info3->base.acct_flags & ACB_NORMAL)) {
1252 0 : DEBUG(0,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n",
1253 : my_info3->base.acct_flags));
1254 0 : result = NT_STATUS_LOGON_FAILURE;
1255 0 : goto out;
1256 : }
1257 :
1258 0 : kickoff_time = nt_time_to_unix(my_info3->base.kickoff_time);
1259 0 : if (kickoff_time != 0 && time(NULL) > kickoff_time) {
1260 0 : result = NT_STATUS_ACCOUNT_EXPIRED;
1261 0 : goto out;
1262 : }
1263 :
1264 0 : must_change_time = nt_time_to_unix(my_info3->base.force_password_change);
1265 0 : if (must_change_time != 0 && must_change_time < time(NULL)) {
1266 : /* we allow grace logons when the password has expired */
1267 0 : my_info3->base.user_flags |= NETLOGON_GRACE_LOGON;
1268 : /* return NT_STATUS_PASSWORD_EXPIRED; */
1269 0 : goto success;
1270 : }
1271 :
1272 : #ifdef HAVE_KRB5
1273 0 : if ((krb5_auth) &&
1274 0 : ((tdc_domain = wcache_tdc_fetch_domain(tmp_ctx, name_domain)) != NULL) &&
1275 0 : ((tdc_domain->trust_type & LSA_TRUST_TYPE_UPLEVEL) ||
1276 : /* used to cope with the case winbindd starting without network. */
1277 0 : !strequal(tdc_domain->domain_name, tdc_domain->dns_name))) {
1278 0 : const char *cc = NULL;
1279 0 : char *realm = NULL;
1280 0 : const char *principal_s = NULL;
1281 : const char *user_ccache_file;
1282 :
1283 0 : if (domain->alt_name == NULL) {
1284 0 : result = NT_STATUS_INVALID_PARAMETER;
1285 0 : goto out;
1286 : }
1287 :
1288 0 : if (uid == -1) {
1289 0 : DEBUG(0,("winbindd_dual_pam_auth_cached: invalid uid\n"));
1290 0 : result = NT_STATUS_INVALID_PARAMETER;
1291 0 : goto out;
1292 : }
1293 :
1294 0 : cc = generate_krb5_ccache(tmp_ctx,
1295 : krb5_cc_type,
1296 : uid,
1297 : &user_ccache_file);
1298 0 : if (cc == NULL) {
1299 0 : result = NT_STATUS_NO_MEMORY;
1300 0 : goto out;
1301 : }
1302 :
1303 0 : realm = talloc_strdup(tmp_ctx, domain->alt_name);
1304 0 : if (realm == NULL) {
1305 0 : result = NT_STATUS_NO_MEMORY;
1306 0 : goto out;
1307 : }
1308 :
1309 0 : if (!strupper_m(realm)) {
1310 0 : result = NT_STATUS_INVALID_PARAMETER;
1311 0 : goto out;
1312 : }
1313 :
1314 0 : principal_s = talloc_asprintf(tmp_ctx, "%s@%s", name_user, realm);
1315 0 : if (principal_s == NULL) {
1316 0 : result = NT_STATUS_NO_MEMORY;
1317 0 : goto out;
1318 : }
1319 :
1320 0 : if (user_ccache_file != NULL) {
1321 :
1322 0 : if (_krb5ccname != NULL) {
1323 0 : *_krb5ccname = talloc_move(mem_ctx,
1324 : &user_ccache_file);
1325 : }
1326 :
1327 0 : result = add_ccache_to_list(principal_s,
1328 : cc,
1329 : user,
1330 : pass,
1331 : realm,
1332 : uid,
1333 : time(NULL),
1334 0 : time(NULL) + lp_winbind_cache_time(),
1335 0 : time(NULL) + WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
1336 : true,
1337 : principal_s,
1338 : realm);
1339 :
1340 0 : if (!NT_STATUS_IS_OK(result)) {
1341 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: failed "
1342 : "to add ccache to list: %s\n",
1343 : nt_errstr(result)));
1344 : }
1345 : }
1346 : }
1347 : #endif /* HAVE_KRB5 */
1348 0 : success:
1349 : /* FIXME: we possibly should handle logon hours as well (does xp when
1350 : * offline?) see auth/auth_sam.c:sam_account_ok for details */
1351 :
1352 0 : unix_to_nt_time(&my_info3->base.logon_time, time(NULL));
1353 0 : my_info3->base.bad_password_count = 0;
1354 :
1355 0 : result = winbindd_update_creds_by_info3(domain,
1356 : user,
1357 : pass,
1358 : my_info3);
1359 0 : if (!NT_STATUS_IS_OK(result)) {
1360 0 : DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
1361 : nt_errstr(result)));
1362 0 : goto out;
1363 : }
1364 :
1365 0 : result = map_info3_to_validation(mem_ctx,
1366 : my_info3,
1367 : _validation_level,
1368 : _validation);
1369 0 : if (!NT_STATUS_IS_OK(result)) {
1370 0 : DBG_ERR("map_info3_to_validation failed: %s\n",
1371 : nt_errstr(result));
1372 0 : goto out;
1373 : }
1374 :
1375 0 : result = NT_STATUS_OK;
1376 0 : goto out;
1377 : }
1378 :
1379 : /* User does *NOT* know the correct password, modify info3 accordingly, but only if online */
1380 0 : if (domain->online == false) {
1381 0 : goto failed;
1382 : }
1383 :
1384 : /* failure of this is not critical */
1385 0 : result = get_max_bad_attempts_from_lockout_policy(domain, tmp_ctx, &max_allowed_bad_attempts);
1386 0 : if (!NT_STATUS_IS_OK(result)) {
1387 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. "
1388 : "Won't be able to honour account lockout policies\n"));
1389 : }
1390 :
1391 : /* increase counter */
1392 0 : my_info3->base.bad_password_count++;
1393 :
1394 0 : if (max_allowed_bad_attempts == 0) {
1395 0 : goto failed;
1396 : }
1397 :
1398 : /* lockout user */
1399 0 : if (my_info3->base.bad_password_count >= max_allowed_bad_attempts) {
1400 :
1401 : uint32_t password_properties;
1402 :
1403 0 : result = get_pwd_properties(domain, tmp_ctx, &password_properties);
1404 0 : if (!NT_STATUS_IS_OK(result)) {
1405 0 : DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n"));
1406 : }
1407 :
1408 0 : if ((my_info3->base.rid != DOMAIN_RID_ADMINISTRATOR) ||
1409 0 : (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
1410 0 : my_info3->base.acct_flags |= ACB_AUTOLOCK;
1411 : }
1412 : }
1413 :
1414 0 : failed:
1415 0 : result = winbindd_update_creds_by_info3(domain, user, NULL, my_info3);
1416 0 : if (!NT_STATUS_IS_OK(result)) {
1417 0 : DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n",
1418 : nt_errstr(result)));
1419 : }
1420 :
1421 0 : result = NT_STATUS_LOGON_FAILURE;
1422 :
1423 0 : out:
1424 0 : TALLOC_FREE(tmp_ctx);
1425 :
1426 0 : return result;
1427 : }
1428 :
1429 0 : static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
1430 : const char *user,
1431 : const char *pass,
1432 : const char *krb5_cc_type,
1433 : uid_t uid,
1434 : TALLOC_CTX *mem_ctx,
1435 : uint16_t *_validation_level,
1436 : union netr_Validation **_validation,
1437 : const char **_krb5ccname)
1438 : {
1439 0 : struct netr_SamInfo6 *info6 = NULL;
1440 : struct winbindd_domain *contact_domain;
1441 : fstring name_namespace, name_domain, name_user;
1442 : NTSTATUS result;
1443 : bool ok;
1444 :
1445 0 : DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
1446 :
1447 : /* Parse domain and username */
1448 :
1449 0 : ok = parse_domain_user(user,
1450 : name_namespace,
1451 : name_domain,
1452 : name_user);
1453 0 : if (!ok) {
1454 0 : result = NT_STATUS_INVALID_PARAMETER;
1455 0 : goto done;
1456 : }
1457 :
1458 : /* what domain should we contact? */
1459 :
1460 0 : if (lp_winbind_use_krb5_enterprise_principals()) {
1461 0 : contact_domain = find_auth_domain(0, name_namespace);
1462 : } else {
1463 0 : contact_domain = find_domain_from_name(name_namespace);
1464 : }
1465 0 : if (contact_domain == NULL) {
1466 0 : DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
1467 : user, name_domain, name_user, name_namespace));
1468 0 : result = NT_STATUS_NO_SUCH_USER;
1469 0 : goto done;
1470 : }
1471 :
1472 0 : if (contact_domain->initialized &&
1473 0 : contact_domain->active_directory) {
1474 0 : goto try_login;
1475 : }
1476 :
1477 0 : if (!contact_domain->initialized) {
1478 0 : init_dc_connection(contact_domain, false);
1479 : }
1480 :
1481 0 : if (!contact_domain->active_directory) {
1482 0 : DEBUG(3,("krb5 auth requested but domain (%s) is not Active Directory\n",
1483 : contact_domain->name));
1484 0 : return NT_STATUS_INVALID_LOGON_TYPE;
1485 : }
1486 0 : try_login:
1487 0 : result = winbindd_raw_kerberos_login(
1488 : mem_ctx,
1489 : contact_domain,
1490 : user,
1491 : pass,
1492 : krb5_cc_type,
1493 : uid,
1494 : &info6,
1495 : _krb5ccname);
1496 0 : if (!NT_STATUS_IS_OK(result)) {
1497 0 : goto done;
1498 : }
1499 :
1500 0 : result = map_info6_to_validation(mem_ctx,
1501 : info6,
1502 : _validation_level,
1503 : _validation);
1504 0 : TALLOC_FREE(info6);
1505 0 : if (!NT_STATUS_IS_OK(result)) {
1506 0 : DBG_ERR("map_info6_to_validation failed: %s\n",
1507 : nt_errstr(result));
1508 : }
1509 :
1510 0 : done:
1511 0 : return result;
1512 : }
1513 :
1514 0 : static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
1515 : uint32_t logon_parameters,
1516 : const char *domain,
1517 : const char *user,
1518 : const uint64_t logon_id,
1519 : const char *client_name,
1520 : const int client_pid,
1521 : const DATA_BLOB *challenge,
1522 : const DATA_BLOB *lm_resp,
1523 : const DATA_BLOB *nt_resp,
1524 : const struct tsocket_address *remote,
1525 : const struct tsocket_address *local,
1526 : bool interactive,
1527 : uint8_t *pauthoritative,
1528 : struct netr_SamInfo3 **pinfo3)
1529 : {
1530 : struct auth_context *auth_context;
1531 : struct auth_serversupplied_info *server_info;
1532 0 : struct auth_usersupplied_info *user_info = NULL;
1533 : struct netr_SamInfo3 *info3;
1534 : NTSTATUS status;
1535 : bool ok;
1536 0 : TALLOC_CTX *frame = talloc_stackframe();
1537 :
1538 : /*
1539 : * We are authoritative by default
1540 : */
1541 0 : *pauthoritative = 1;
1542 :
1543 0 : status = make_user_info(frame, &user_info, user, user, domain, domain,
1544 : lp_netbios_name(), remote, local,
1545 : "winbind",
1546 : lm_resp, nt_resp, NULL, NULL,
1547 : NULL, AUTH_PASSWORD_RESPONSE);
1548 0 : if (!NT_STATUS_IS_OK(status)) {
1549 0 : DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status)));
1550 0 : TALLOC_FREE(frame);
1551 0 : return status;
1552 : }
1553 :
1554 0 : user_info->logon_parameters = logon_parameters;
1555 0 : user_info->logon_id = logon_id;
1556 0 : user_info->auth_description = talloc_asprintf(
1557 : frame, "PASSDB, %s, %d", client_name, client_pid);
1558 0 : if (user_info->auth_description == NULL) {
1559 0 : TALLOC_FREE(frame);
1560 0 : return NT_STATUS_NO_MEMORY;
1561 : }
1562 :
1563 : /* We don't want to come back to winbindd or to do PAM account checks */
1564 0 : user_info->flags |= USER_INFO_INFO3_AND_NO_AUTHZ;
1565 :
1566 0 : if (interactive) {
1567 0 : user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1568 : }
1569 :
1570 0 : status = make_auth3_context_for_winbind(frame, &auth_context);
1571 0 : if (!NT_STATUS_IS_OK(status)) {
1572 0 : DBG_ERR("make_auth3_context_for_winbind failed: %s\n",
1573 : nt_errstr(status));
1574 0 : TALLOC_FREE(frame);
1575 0 : return status;
1576 : }
1577 :
1578 0 : ok = auth3_context_set_challenge(auth_context,
1579 0 : challenge->data, "fixed");
1580 0 : if (!ok) {
1581 0 : TALLOC_FREE(frame);
1582 0 : return NT_STATUS_NO_MEMORY;
1583 : }
1584 :
1585 0 : status = auth_check_ntlm_password(mem_ctx,
1586 : auth_context,
1587 : user_info,
1588 : &server_info,
1589 : pauthoritative);
1590 0 : if (!NT_STATUS_IS_OK(status)) {
1591 0 : TALLOC_FREE(frame);
1592 0 : return status;
1593 : }
1594 :
1595 0 : info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
1596 0 : if (info3 == NULL) {
1597 0 : TALLOC_FREE(frame);
1598 0 : return NT_STATUS_NO_MEMORY;
1599 : }
1600 :
1601 0 : status = serverinfo_to_SamInfo3(server_info, info3);
1602 0 : if (!NT_STATUS_IS_OK(status)) {
1603 0 : TALLOC_FREE(frame);
1604 0 : TALLOC_FREE(info3);
1605 0 : DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
1606 : nt_errstr(status)));
1607 0 : return status;
1608 : }
1609 :
1610 0 : *pinfo3 = info3;
1611 0 : DBG_DEBUG("Authenticating user %s\\%s returned %s\n",
1612 : domain,
1613 : user,
1614 : nt_errstr(status));
1615 0 : TALLOC_FREE(frame);
1616 0 : return status;
1617 : }
1618 :
1619 0 : static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain,
1620 : TALLOC_CTX *mem_ctx,
1621 : uint32_t logon_parameters,
1622 : const char *username,
1623 : const char *password,
1624 : const char *domainname,
1625 : const char *workstation,
1626 : const uint64_t logon_id,
1627 : bool plaintext_given,
1628 : DATA_BLOB chal,
1629 : DATA_BLOB lm_response,
1630 : DATA_BLOB nt_response,
1631 : bool interactive,
1632 : uint8_t *authoritative,
1633 : uint32_t *flags,
1634 : uint16_t *_validation_level,
1635 : union netr_Validation **_validation)
1636 : {
1637 0 : int attempts = 0;
1638 0 : int netr_attempts = 0;
1639 0 : bool retry = false;
1640 0 : bool valid_result = false;
1641 : NTSTATUS result;
1642 : enum netr_LogonInfoClass logon_type_i;
1643 : enum netr_LogonInfoClass logon_type_n;
1644 0 : uint16_t validation_level = UINT16_MAX;
1645 0 : union netr_Validation *validation = NULL;
1646 0 : TALLOC_CTX *base_ctx = NULL;
1647 0 : struct netr_SamBaseInfo *base_info = NULL;
1648 :
1649 : do {
1650 : struct rpc_pipe_client *netlogon_pipe;
1651 0 : struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1652 :
1653 : /*
1654 : * We should always reset authoritative to 1
1655 : * before calling a server again.
1656 : *
1657 : * Otherwise we could treat a local problem as
1658 : * non-authoritative.
1659 : */
1660 0 : *authoritative = 1;
1661 :
1662 0 : retry = false;
1663 :
1664 0 : result = cm_connect_netlogon_secure(domain, &netlogon_pipe,
1665 : &netlogon_creds_ctx);
1666 :
1667 0 : if (NT_STATUS_EQUAL(result,
1668 : NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
1669 : /*
1670 : * This means we don't have a trust account.
1671 : */
1672 0 : *authoritative = 0;
1673 0 : result = NT_STATUS_NO_SUCH_USER;
1674 0 : break;
1675 : }
1676 :
1677 0 : if (!NT_STATUS_IS_OK(result)) {
1678 0 : DEBUG(3,("Could not open handle to NETLOGON pipe "
1679 : "(error: %s, attempts: %d)\n",
1680 : nt_errstr(result), netr_attempts));
1681 :
1682 0 : reset_cm_connection_on_error(domain, NULL, result);
1683 :
1684 : /* After the first retry always close the connection */
1685 0 : if (netr_attempts > 0) {
1686 0 : DEBUG(3, ("This is again a problem for this "
1687 : "particular call, forcing the close "
1688 : "of this connection\n"));
1689 0 : invalidate_cm_connection(domain);
1690 : }
1691 :
1692 : /* After the second retry failover to the next DC */
1693 0 : if (netr_attempts > 1) {
1694 : /*
1695 : * If the netlogon server is not reachable then
1696 : * it is possible that the DC is rebuilding
1697 : * sysvol and shutdown netlogon for that time.
1698 : * We should failover to the next dc.
1699 : */
1700 0 : DEBUG(3, ("This is the third problem for this "
1701 : "particular call, adding DC to the "
1702 : "negative cache list: %s %s\n", domain->name, domain->dcname));
1703 0 : add_failed_connection_entry(domain->name,
1704 0 : domain->dcname,
1705 : result);
1706 0 : saf_delete(domain->name);
1707 : }
1708 :
1709 : /* Only allow 3 retries */
1710 0 : if (netr_attempts < 3) {
1711 0 : DEBUG(3, ("The connection to netlogon "
1712 : "failed, retrying\n"));
1713 0 : netr_attempts++;
1714 0 : retry = true;
1715 0 : continue;
1716 : }
1717 0 : return result;
1718 : }
1719 :
1720 0 : logon_type_i = NetlogonInteractiveInformation;
1721 0 : logon_type_n = NetlogonNetworkInformation;
1722 0 : if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
1723 0 : logon_type_i = NetlogonInteractiveTransitiveInformation;
1724 0 : logon_type_n = NetlogonNetworkTransitiveInformation;
1725 : }
1726 :
1727 0 : if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1728 0 : logon_type_i = NetlogonInteractiveTransitiveInformation;
1729 0 : logon_type_n = NetlogonNetworkTransitiveInformation;
1730 : }
1731 :
1732 0 : if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
1733 0 : logon_type_i = NetlogonInteractiveInformation;
1734 0 : logon_type_n = NetlogonNetworkInformation;
1735 : }
1736 :
1737 0 : if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
1738 0 : logon_type_i = NetlogonInteractiveInformation;
1739 0 : logon_type_n = NetlogonNetworkInformation;
1740 : }
1741 :
1742 0 : netr_attempts = 0;
1743 0 : if (plaintext_given) {
1744 0 : result = rpccli_netlogon_password_logon(
1745 : netlogon_creds_ctx,
1746 0 : netlogon_pipe->binding_handle,
1747 : mem_ctx,
1748 : logon_parameters,
1749 : domainname,
1750 : username,
1751 : password,
1752 : workstation,
1753 : logon_id,
1754 : logon_type_i,
1755 : authoritative,
1756 : flags,
1757 : &validation_level,
1758 : &validation);
1759 0 : } else if (interactive) {
1760 0 : result = rpccli_netlogon_interactive_logon(
1761 : netlogon_creds_ctx,
1762 0 : netlogon_pipe->binding_handle,
1763 : mem_ctx,
1764 : logon_parameters,
1765 : username,
1766 : domainname,
1767 : workstation,
1768 : logon_id,
1769 : lm_response,
1770 : nt_response,
1771 : logon_type_i,
1772 : authoritative,
1773 : flags,
1774 : &validation_level,
1775 : &validation);
1776 : } else {
1777 0 : result = rpccli_netlogon_network_logon(
1778 : netlogon_creds_ctx,
1779 0 : netlogon_pipe->binding_handle,
1780 : mem_ctx,
1781 : logon_parameters,
1782 : username,
1783 : domainname,
1784 : workstation,
1785 : logon_id,
1786 : chal,
1787 : lm_response,
1788 : nt_response,
1789 : logon_type_n,
1790 : authoritative,
1791 : flags,
1792 : &validation_level,
1793 : &validation);
1794 : }
1795 :
1796 : /*
1797 : * we increment this after the "feature negotiation"
1798 : * for can_do_samlogon_ex and can_do_validation6
1799 : */
1800 0 : attempts += 1;
1801 :
1802 : /* We have to try a second time as cm_connect_netlogon
1803 : might not yet have noticed that the DC has killed
1804 : our connection. */
1805 :
1806 0 : retry = reset_cm_connection_on_error(domain,
1807 0 : netlogon_pipe->binding_handle,
1808 : result);
1809 0 : if (retry) {
1810 0 : DBG_PREFIX(attempts > 1 ? DBGLVL_NOTICE : DBGLVL_INFO, (
1811 : "This is problem %d for this "
1812 : "particular call,"
1813 : "DOMAIN[%s] DC[%s] - %s\n",
1814 : attempts,
1815 : domain->name,
1816 : domain->dcname,
1817 : nt_errstr(result)));
1818 0 : continue;
1819 : }
1820 :
1821 0 : valid_result = true;
1822 :
1823 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1824 : /*
1825 : * Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon
1826 : * (no Ex). This happens against old Samba
1827 : * DCs, if LogonSamLogonEx() fails with an error
1828 : * e.g. NT_STATUS_NO_SUCH_USER or NT_STATUS_WRONG_PASSWORD.
1829 : *
1830 : * The server will log something like this:
1831 : * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.
1832 : *
1833 : * This sets the whole connection into a fault_state mode
1834 : * and all following request get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
1835 : *
1836 : * This also happens to our retry with LogonSamLogonWithFlags()
1837 : * and LogonSamLogon().
1838 : *
1839 : * In order to recover from this situation, we need to
1840 : * drop the connection.
1841 : */
1842 0 : invalidate_cm_connection(domain);
1843 0 : result = NT_STATUS_LOGON_FAILURE;
1844 0 : break;
1845 : }
1846 :
1847 0 : } while ( (attempts < 3) && retry );
1848 :
1849 0 : if (!valid_result) {
1850 : /*
1851 : * This matches what windows does. In a chain of transitive
1852 : * trusts the ACCESS_DENIED/authoritative=0 is not propagated
1853 : * instead of NT_STATUS_NO_LOGON_SERVERS/authoritative=1 is
1854 : * passed along the chain if there's no other DC is available.
1855 : */
1856 0 : DBG_WARNING("Mapping %s/authoritative=%u to "
1857 : "NT_STATUS_NO_LOGON_SERVERS/authoritative=1 for"
1858 : "USERNAME[%s] USERDOMAIN[%s] REMOTE-DOMAIN[%s] \n",
1859 : nt_errstr(result),
1860 : *authoritative,
1861 : username,
1862 : domainname,
1863 : domain->name);
1864 0 : *authoritative = 1;
1865 0 : return NT_STATUS_NO_LOGON_SERVERS;
1866 : }
1867 :
1868 0 : if (!NT_STATUS_IS_OK(result)) {
1869 0 : return result;
1870 : }
1871 :
1872 0 : switch (validation_level) {
1873 0 : case 3:
1874 0 : base_ctx = validation->sam3;
1875 0 : base_info = &validation->sam3->base;
1876 0 : break;
1877 0 : case 6:
1878 0 : base_ctx = validation->sam6;
1879 0 : base_info = &validation->sam6->base;
1880 0 : break;
1881 0 : default:
1882 0 : smb_panic(__location__);
1883 : }
1884 :
1885 0 : if (base_info->acct_flags == 0 || base_info->account_name.string == NULL) {
1886 : struct dom_sid user_sid;
1887 : struct dom_sid_buf sid_buf;
1888 0 : const char *acct_flags_src = "server";
1889 0 : const char *acct_name_src = "server";
1890 :
1891 : /*
1892 : * Handle the case where a NT4 DC does not fill in the acct_flags in
1893 : * the samlogon reply info3. Yes, in 2021, there are still admins
1894 : * arround with real NT4 DCs.
1895 : *
1896 : * We used to call dcerpc_samr_QueryUserInfo(level=16) to fetch
1897 : * acct_flags, but as NT4 DCs reject authentication with workstation
1898 : * accounts with NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, even if
1899 : * MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT is specified, we only ever got
1900 : * ACB_NORMAL back (maybe with ACB_PWNOEXP in addition).
1901 : *
1902 : * For network logons NT4 DCs also skip the
1903 : * account_name, so we have to fallback to the
1904 : * one given by the client.
1905 : */
1906 :
1907 0 : if (base_info->acct_flags == 0) {
1908 0 : base_info->acct_flags = ACB_NORMAL;
1909 0 : if (base_info->force_password_change == NTTIME_MAX) {
1910 0 : base_info->acct_flags |= ACB_PWNOEXP;
1911 : }
1912 0 : acct_flags_src = "calculated";
1913 : }
1914 :
1915 0 : if (base_info->account_name.string == NULL) {
1916 0 : base_info->account_name.string = talloc_strdup(base_ctx,
1917 : username);
1918 0 : if (base_info->account_name.string == NULL) {
1919 0 : TALLOC_FREE(validation);
1920 0 : return NT_STATUS_NO_MEMORY;
1921 : }
1922 0 : acct_name_src = "client";
1923 : }
1924 :
1925 0 : sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
1926 :
1927 0 : DBG_DEBUG("Fallback to %s_acct_flags[0x%x] %s_acct_name[%s] for %s\n",
1928 : acct_flags_src,
1929 : base_info->acct_flags,
1930 : acct_name_src,
1931 : base_info->account_name.string,
1932 : dom_sid_str_buf(&user_sid, &sid_buf));
1933 : }
1934 :
1935 0 : *_validation_level = validation_level;
1936 0 : *_validation = validation;
1937 0 : return NT_STATUS_OK;
1938 : }
1939 :
1940 0 : static NTSTATUS nt_dual_auth_passdb(TALLOC_CTX *mem_ctx,
1941 : fstring name_user,
1942 : fstring name_domain,
1943 : const char *pass,
1944 : uint64_t logon_id,
1945 : const char *client_name,
1946 : const int client_pid,
1947 : const struct tsocket_address *remote,
1948 : const struct tsocket_address *local,
1949 : uint8_t *authoritative,
1950 : struct netr_SamInfo3 **info3)
1951 : {
1952 : unsigned char local_nt_response[24];
1953 : uchar chal[8];
1954 : DATA_BLOB chal_blob;
1955 : DATA_BLOB lm_resp;
1956 : DATA_BLOB nt_resp;
1957 :
1958 : /* do password magic */
1959 :
1960 0 : generate_random_buffer(chal, sizeof(chal));
1961 0 : chal_blob = data_blob_const(chal, sizeof(chal));
1962 :
1963 0 : if (lp_client_ntlmv2_auth()) {
1964 : DATA_BLOB server_chal;
1965 : DATA_BLOB names_blob;
1966 0 : server_chal = data_blob_const(chal, 8);
1967 :
1968 : /* note that the 'workgroup' here is for the local
1969 : machine. The 'server name' must match the
1970 : 'workstation' passed to the actual SamLogon call.
1971 : */
1972 0 : names_blob = NTLMv2_generate_names_blob(mem_ctx,
1973 : lp_netbios_name(),
1974 : lp_workgroup());
1975 :
1976 0 : if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
1977 : pass, &server_chal, &names_blob,
1978 : &lm_resp, &nt_resp, NULL, NULL)) {
1979 0 : data_blob_free(&names_blob);
1980 0 : DEBUG(0, ("SMBNTLMv2encrypt() failed!\n"));
1981 0 : return NT_STATUS_NO_MEMORY;
1982 : }
1983 0 : data_blob_free(&names_blob);
1984 : } else {
1985 : int rc;
1986 0 : lm_resp = data_blob_null;
1987 :
1988 0 : rc = SMBNTencrypt(pass, chal, local_nt_response);
1989 0 : if (rc != 0) {
1990 0 : DEBUG(0, ("SMBNTencrypt() failed!\n"));
1991 0 : return gnutls_error_to_ntstatus(rc,
1992 : NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
1993 : }
1994 :
1995 0 : nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
1996 : sizeof(local_nt_response));
1997 : }
1998 :
1999 0 : return winbindd_dual_auth_passdb(talloc_tos(), 0, name_domain,
2000 : name_user, logon_id, client_name,
2001 : client_pid, &chal_blob, &lm_resp,
2002 : &nt_resp, remote, local,
2003 : true, /* interactive */
2004 : authoritative, info3);
2005 : }
2006 :
2007 0 : static NTSTATUS winbindd_dual_pam_auth_samlogon(
2008 : TALLOC_CTX *mem_ctx,
2009 : struct winbindd_domain *domain,
2010 : const char *user,
2011 : const char *pass,
2012 : uint64_t logon_id,
2013 : const char *client_name,
2014 : const int client_pid,
2015 : uint32_t request_flags,
2016 : const struct tsocket_address *remote,
2017 : const struct tsocket_address *local,
2018 : uint16_t *_validation_level,
2019 : union netr_Validation **_validation)
2020 : {
2021 : fstring name_namespace, name_domain, name_user;
2022 : NTSTATUS result;
2023 0 : uint8_t authoritative = 1;
2024 0 : uint32_t flags = 0;
2025 0 : uint16_t validation_level = 0;
2026 0 : union netr_Validation *validation = NULL;
2027 : bool ok;
2028 :
2029 0 : DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
2030 :
2031 : /* Parse domain and username */
2032 :
2033 0 : ok = parse_domain_user(user, name_namespace, name_domain, name_user);
2034 0 : if (!ok) {
2035 0 : return NT_STATUS_INVALID_PARAMETER;
2036 : }
2037 :
2038 : /*
2039 : * We check against domain->name instead of
2040 : * name_domain, as find_auth_domain() ->
2041 : * find_domain_from_name_noinit() already decided
2042 : * that we are in a child for the correct domain.
2043 : *
2044 : * name_domain can also be lp_realm()
2045 : * we need to check against domain->name.
2046 : */
2047 0 : if (strequal(domain->name, get_global_sam_name())) {
2048 0 : struct netr_SamInfo3 *info3 = NULL;
2049 :
2050 0 : result = nt_dual_auth_passdb(mem_ctx, name_user, name_domain,
2051 : pass, logon_id, client_name,
2052 : client_pid, remote, local,
2053 : &authoritative, &info3);
2054 :
2055 : /*
2056 : * We need to try the remote NETLOGON server if this is
2057 : * not authoritative (for example on the RODC).
2058 : */
2059 0 : if (authoritative != 0) {
2060 0 : if (!NT_STATUS_IS_OK(result)) {
2061 0 : return result;
2062 : }
2063 0 : result = map_info3_to_validation(mem_ctx,
2064 : info3,
2065 : &validation_level,
2066 : &validation);
2067 0 : TALLOC_FREE(info3);
2068 0 : if (!NT_STATUS_IS_OK(result)) {
2069 0 : return result;
2070 : }
2071 :
2072 0 : goto done;
2073 : }
2074 : }
2075 :
2076 : /* check authentication loop */
2077 :
2078 0 : result = winbind_samlogon_retry_loop(domain,
2079 : mem_ctx,
2080 : 0,
2081 : name_user,
2082 : pass,
2083 : name_domain,
2084 : lp_netbios_name(),
2085 : logon_id,
2086 : true, /* plaintext_given */
2087 : data_blob_null,
2088 : data_blob_null, data_blob_null,
2089 : true, /* interactive */
2090 : &authoritative,
2091 : &flags,
2092 : &validation_level,
2093 : &validation);
2094 0 : if (!NT_STATUS_IS_OK(result)) {
2095 0 : return result;
2096 : }
2097 :
2098 0 : done:
2099 0 : *_validation_level = validation_level;
2100 0 : *_validation = validation;
2101 :
2102 0 : return NT_STATUS_OK;
2103 : }
2104 :
2105 : /*
2106 : * @brief generate an authentication message in the logs.
2107 : *
2108 : */
2109 0 : static void log_authentication(
2110 : TALLOC_CTX *mem_ctx,
2111 : const struct winbindd_domain *domain,
2112 : const char *client_name,
2113 : pid_t client_pid,
2114 : uint16_t validation_level,
2115 : union netr_Validation *validation,
2116 : const struct timeval start_time,
2117 : const uint64_t logon_id,
2118 : const char *command,
2119 : const char *user_name,
2120 : const char *domain_name,
2121 : const char *workstation,
2122 : const DATA_BLOB lm_resp,
2123 : const DATA_BLOB nt_resp,
2124 : const struct tsocket_address *remote,
2125 : const struct tsocket_address *local,
2126 : NTSTATUS result)
2127 : {
2128 0 : struct auth_usersupplied_info *ui = NULL;
2129 0 : struct dom_sid *sid = NULL;
2130 0 : struct loadparm_context *lp_ctx = NULL;
2131 0 : struct imessaging_context *msg_ctx = NULL;
2132 0 : struct netr_SamBaseInfo *base_info = NULL;
2133 :
2134 0 : if (validation != NULL) {
2135 0 : switch (validation_level) {
2136 0 : case 3:
2137 0 : base_info = &validation->sam3->base;
2138 0 : break;
2139 0 : case 6:
2140 0 : base_info = &validation->sam6->base;
2141 0 : break;
2142 0 : default:
2143 0 : DBG_WARNING("Unexpected validation level '%d'\n",
2144 : validation_level);
2145 0 : break;
2146 : }
2147 0 : }
2148 :
2149 0 : ui = talloc_zero(mem_ctx, struct auth_usersupplied_info);
2150 0 : ui->logon_id = logon_id;
2151 0 : ui->service_description = "winbind";
2152 0 : ui->password.response.nt.length = nt_resp.length;
2153 0 : ui->password.response.nt.data = nt_resp.data;
2154 0 : ui->password.response.lanman.length = lm_resp.length;
2155 0 : ui->password.response.lanman.data = lm_resp.data;
2156 0 : if (nt_resp.length == 0 && lm_resp.length == 0) {
2157 0 : ui->password_state = AUTH_PASSWORD_PLAIN;
2158 : } else {
2159 0 : ui->password_state = AUTH_PASSWORD_RESPONSE;
2160 : }
2161 : /*
2162 : * In the event of a failure ui->auth_description will be null,
2163 : * the logging code handles this correctly so it can be ignored.
2164 : */
2165 0 : ui->auth_description = talloc_asprintf(
2166 : ui,
2167 : "%s, %s, %d",
2168 : command,
2169 : client_name,
2170 : client_pid);
2171 0 : if (ui->auth_description == NULL) {
2172 0 : DBG_ERR("OOM Unable to create auth_description");
2173 : }
2174 0 : ui->client.account_name = user_name;
2175 0 : ui->client.domain_name = domain_name;
2176 0 : ui->workstation_name = workstation;
2177 0 : ui->remote_host = remote;
2178 0 : ui->local_host = local;
2179 :
2180 0 : if (base_info != NULL) {
2181 0 : sid = dom_sid_dup(ui, base_info->domain_sid);
2182 0 : if (sid != NULL) {
2183 0 : sid_append_rid(sid, base_info->rid);
2184 : }
2185 : }
2186 :
2187 0 : if (lp_auth_event_notification()) {
2188 0 : lp_ctx = loadparm_init_s3(ui, loadparm_s3_helpers());
2189 0 : msg_ctx = imessaging_client_init(
2190 : ui, lp_ctx, global_event_context());
2191 : }
2192 0 : log_authentication_event(
2193 : msg_ctx,
2194 : lp_ctx,
2195 : &start_time,
2196 : ui,
2197 : result,
2198 : base_info != NULL ? base_info->logon_domain.string : "",
2199 : base_info != NULL ? base_info->account_name.string : "",
2200 : sid);
2201 0 : TALLOC_FREE(ui);
2202 0 : }
2203 :
2204 0 : NTSTATUS _wbint_PamAuth(struct pipes_struct *p,
2205 : struct wbint_PamAuth *r)
2206 : {
2207 0 : struct winbindd_domain *domain = wb_child_domain();
2208 0 : NTSTATUS result = NT_STATUS_LOGON_FAILURE;
2209 0 : NTSTATUS krb5_result = NT_STATUS_OK;
2210 : fstring name_namespace, name_domain, name_user;
2211 0 : char *mapped_user = NULL;
2212 0 : const char *domain_user = NULL;
2213 0 : uint16_t validation_level = UINT16_MAX;
2214 0 : union netr_Validation *validation = NULL;
2215 0 : struct netr_SamBaseInfo *base_info = NULL;
2216 0 : NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
2217 : bool ok;
2218 0 : uint64_t logon_id = 0;
2219 0 : const struct timeval start_time = timeval_current();
2220 0 : const struct tsocket_address *remote = NULL;
2221 0 : const struct tsocket_address *local = NULL;
2222 0 : const char *krb5ccname = NULL;
2223 : uid_t uid;
2224 : pid_t client_pid;
2225 :
2226 0 : if (domain == NULL) {
2227 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
2228 : }
2229 :
2230 : /* Cut client_pid to 32bit */
2231 0 : client_pid = r->in.client_pid;
2232 0 : if ((uint64_t)client_pid != r->in.client_pid) {
2233 0 : DBG_DEBUG("pid out of range\n");
2234 0 : return NT_STATUS_INVALID_PARAMETER;
2235 : }
2236 :
2237 : /* Cut uid to 32bit */
2238 0 : uid = r->in.info->uid;
2239 0 : if ((uint64_t)uid != r->in.info->uid) {
2240 0 : DBG_DEBUG("uid out of range\n");
2241 0 : return NT_STATUS_INVALID_PARAMETER;
2242 : }
2243 :
2244 : /*
2245 : * Generate a logon_id for this session.
2246 : */
2247 0 : logon_id = generate_random_u64();
2248 0 : remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
2249 0 : local = dcesrv_connection_get_local_address(p->dce_call->conn);
2250 0 : DEBUG(3, ("[%"PRIu32"]: dual pam auth %s\n", client_pid,
2251 : r->in.info->username));
2252 :
2253 : /* Parse domain and username */
2254 :
2255 0 : name_map_status = normalize_name_unmap(p->mem_ctx,
2256 0 : r->in.info->username,
2257 : &mapped_user);
2258 :
2259 : /* If the name normalization didn't actually do anything,
2260 : just use the original name */
2261 :
2262 0 : if (!NT_STATUS_IS_OK(name_map_status) &&
2263 0 : !NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
2264 : {
2265 0 : mapped_user = discard_const(r->in.info->username);
2266 : }
2267 :
2268 0 : ok = parse_domain_user(mapped_user,
2269 : name_namespace,
2270 : name_domain,
2271 : name_user);
2272 0 : if (!ok) {
2273 0 : result = NT_STATUS_INVALID_PARAMETER;
2274 0 : goto done;
2275 : }
2276 :
2277 0 : if (mapped_user != r->in.info->username) {
2278 0 : domain_user = talloc_asprintf(talloc_tos(),
2279 : "%s%c%s",
2280 : name_domain,
2281 0 : *lp_winbind_separator(),
2282 : name_user);
2283 0 : if (domain_user == NULL) {
2284 0 : result = NT_STATUS_NO_MEMORY;
2285 0 : goto done;
2286 : }
2287 0 : r->in.info->username = domain_user;
2288 : }
2289 :
2290 0 : if (!domain->online) {
2291 0 : result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2292 0 : if (domain->startup) {
2293 : /* Logons are very important to users. If we're offline and
2294 : we get a request within the first 30 seconds of startup,
2295 : try very hard to find a DC and go online. */
2296 :
2297 0 : DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth "
2298 : "request in startup mode.\n", domain->name ));
2299 :
2300 0 : winbindd_flush_negative_conn_cache(domain);
2301 0 : result = init_dc_connection(domain, false);
2302 : }
2303 : }
2304 :
2305 0 : DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
2306 :
2307 : /* Check for Kerberos authentication */
2308 0 : if (domain->online && (r->in.flags & WBFLAG_PAM_KRB5)) {
2309 0 : result = winbindd_dual_pam_auth_kerberos(
2310 : domain,
2311 0 : r->in.info->username,
2312 0 : r->in.info->password,
2313 0 : r->in.info->krb5_cc_type,
2314 : uid,
2315 : p->mem_ctx,
2316 : &validation_level,
2317 : &validation,
2318 : &krb5ccname);
2319 :
2320 : /* save for later */
2321 0 : krb5_result = result;
2322 :
2323 0 : if (NT_STATUS_IS_OK(result)) {
2324 0 : DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
2325 0 : goto process_result;
2326 : }
2327 :
2328 0 : DBG_DEBUG("winbindd_dual_pam_auth_kerberos failed: %s\n",
2329 : nt_errstr(result));
2330 :
2331 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
2332 0 : NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
2333 0 : NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
2334 0 : DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
2335 0 : set_domain_offline( domain );
2336 0 : goto cached_logon;
2337 : }
2338 :
2339 : /* there are quite some NT_STATUS errors where there is no
2340 : * point in retrying with a samlogon, we explictly have to take
2341 : * care not to increase the bad logon counter on the DC */
2342 :
2343 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) ||
2344 0 : NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) ||
2345 0 : NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) ||
2346 0 : NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) ||
2347 0 : NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) ||
2348 0 : NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) ||
2349 0 : NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) ||
2350 0 : NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) ||
2351 0 : NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
2352 0 : NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
2353 0 : goto done;
2354 : }
2355 :
2356 0 : if (r->in.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
2357 0 : DEBUG(3,("falling back to samlogon\n"));
2358 0 : goto sam_logon;
2359 : } else {
2360 0 : goto cached_logon;
2361 : }
2362 : }
2363 :
2364 0 : sam_logon:
2365 : /* Check for Samlogon authentication */
2366 0 : if (domain->online) {
2367 0 : result = winbindd_dual_pam_auth_samlogon(
2368 : p->mem_ctx,
2369 : domain,
2370 0 : r->in.info->username,
2371 0 : r->in.info->password,
2372 : logon_id,
2373 : r->in.client_name,
2374 : client_pid,
2375 : r->in.flags,
2376 : remote,
2377 : local,
2378 : &validation_level,
2379 : &validation);
2380 :
2381 0 : if (NT_STATUS_IS_OK(result)) {
2382 0 : DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
2383 :
2384 0 : switch (validation_level) {
2385 0 : case 3:
2386 0 : base_info = &validation->sam3->base;
2387 0 : break;
2388 0 : case 6:
2389 0 : base_info = &validation->sam6->base;
2390 0 : break;
2391 0 : default:
2392 0 : DBG_ERR("Bad validation level %d\n",
2393 : validation_level);
2394 0 : result = NT_STATUS_INTERNAL_ERROR;
2395 0 : goto done;
2396 : }
2397 :
2398 : /* add the Krb5 err if we have one */
2399 0 : if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) {
2400 0 : base_info->user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW;
2401 : }
2402 :
2403 0 : goto process_result;
2404 : }
2405 :
2406 0 : DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n",
2407 : nt_errstr(result)));
2408 :
2409 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
2410 0 : NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
2411 0 : NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND))
2412 : {
2413 0 : DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n"));
2414 0 : set_domain_offline( domain );
2415 0 : goto cached_logon;
2416 : }
2417 :
2418 0 : if (domain->online) {
2419 : /* We're still online - fail. */
2420 0 : goto done;
2421 : }
2422 : }
2423 :
2424 0 : cached_logon:
2425 : /* Check for Cached logons */
2426 0 : if (!domain->online && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN) &&
2427 0 : lp_winbind_offline_logon()) {
2428 0 : result = winbindd_dual_pam_auth_cached(domain,
2429 0 : (r->in.flags & WBFLAG_PAM_KRB5),
2430 0 : r->in.info->username,
2431 0 : r->in.info->password,
2432 0 : r->in.info->krb5_cc_type,
2433 : uid,
2434 : p->mem_ctx,
2435 : &validation_level,
2436 : &validation,
2437 : &krb5ccname);
2438 :
2439 0 : if (!NT_STATUS_IS_OK(result)) {
2440 0 : DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
2441 0 : goto done;
2442 : }
2443 0 : DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
2444 : }
2445 :
2446 0 : process_result:
2447 :
2448 0 : if (NT_STATUS_IS_OK(result)) {
2449 : struct dom_sid user_sid;
2450 0 : TALLOC_CTX *base_ctx = NULL;
2451 0 : struct netr_SamInfo3 *info3 = NULL;
2452 :
2453 0 : switch (validation_level) {
2454 0 : case 3:
2455 0 : base_ctx = validation->sam3;
2456 0 : base_info = &validation->sam3->base;
2457 0 : break;
2458 0 : case 6:
2459 0 : base_ctx = validation->sam6;
2460 0 : base_info = &validation->sam6->base;
2461 0 : break;
2462 0 : default:
2463 0 : DBG_ERR("Bad validation level %d\n", validation_level);
2464 0 : result = NT_STATUS_INTERNAL_ERROR;
2465 0 : goto done;
2466 : }
2467 :
2468 0 : sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
2469 :
2470 0 : if (base_info->full_name.string == NULL) {
2471 : struct netr_SamInfo3 *cached_info3;
2472 :
2473 0 : cached_info3 = netsamlogon_cache_get(p->mem_ctx,
2474 : &user_sid);
2475 0 : if (cached_info3 != NULL &&
2476 0 : cached_info3->base.full_name.string != NULL) {
2477 0 : base_info->full_name.string = talloc_strdup(
2478 : base_ctx,
2479 : cached_info3->base.full_name.string);
2480 0 : if (base_info->full_name.string == NULL) {
2481 0 : result = NT_STATUS_NO_MEMORY;
2482 0 : goto done;
2483 : }
2484 : } else {
2485 :
2486 : /* this might fail so we don't check the return code */
2487 0 : wcache_query_user_fullname(domain,
2488 : base_ctx,
2489 : &user_sid,
2490 : &base_info->full_name.string);
2491 : }
2492 : }
2493 :
2494 0 : result = map_validation_to_info3(talloc_tos(),
2495 : validation_level,
2496 : validation,
2497 : &info3);
2498 0 : if (!NT_STATUS_IS_OK(result)) {
2499 0 : goto done;
2500 : }
2501 :
2502 0 : wcache_invalidate_samlogon(find_domain_from_name(name_domain),
2503 : &user_sid);
2504 0 : netsamlogon_cache_store(name_user, info3);
2505 :
2506 : /* save name_to_sid info as early as possible (only if
2507 : this is our primary domain so we don't invalidate
2508 : the cache entry by storing the seq_num for the wrong
2509 : domain). */
2510 0 : if ( domain->primary ) {
2511 0 : cache_name2sid(domain, name_domain, name_user,
2512 : SID_NAME_USER, &user_sid);
2513 : }
2514 :
2515 : /* Check if the user is in the right group */
2516 :
2517 0 : result = check_info3_in_group(info3,
2518 : r->in.require_membership_of_sid);
2519 0 : if (!NT_STATUS_IS_OK(result)) {
2520 0 : char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
2521 : wbint_SidArray,
2522 : r->in.require_membership_of_sid);
2523 0 : DBG_NOTICE("User %s is not in the required groups:\n",
2524 : r->in.info->username);
2525 0 : DEBUGADD(DBGLVL_NOTICE, ("%s", s));
2526 0 : DEBUGADD(DBGLVL_NOTICE,
2527 : ("Plaintext authentication is rejected\n"));
2528 0 : goto done;
2529 : }
2530 :
2531 0 : if (!is_allowed_domain(info3->base.logon_domain.string)) {
2532 0 : DBG_NOTICE("Authentication failed for user [%s] "
2533 : "from firewalled domain [%s]\n",
2534 : info3->base.account_name.string,
2535 : info3->base.logon_domain.string);
2536 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
2537 0 : goto done;
2538 : }
2539 :
2540 0 : r->out.validation = talloc_zero(p->mem_ctx,
2541 : struct wbint_Validation);
2542 0 : if (r->out.validation == NULL) {
2543 0 : result = NT_STATUS_NO_MEMORY;
2544 0 : goto done;
2545 : }
2546 :
2547 0 : r->out.validation->level = validation_level;
2548 0 : r->out.validation->validation = talloc_steal(r->out.validation,
2549 : validation);
2550 0 : r->out.validation->krb5ccname = talloc_steal(r->out.validation,
2551 : krb5ccname);
2552 0 : if ((r->in.flags & WBFLAG_PAM_CACHED_LOGIN)
2553 0 : && lp_winbind_offline_logon()) {
2554 :
2555 0 : result = winbindd_store_creds(domain,
2556 0 : r->in.info->username,
2557 0 : r->in.info->password,
2558 : info3);
2559 : }
2560 :
2561 0 : result = NT_STATUS_OK;
2562 : }
2563 :
2564 0 : done:
2565 : /* give us a more useful (more correct?) error code */
2566 0 : if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
2567 0 : (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
2568 0 : result = NT_STATUS_NO_LOGON_SERVERS;
2569 : }
2570 :
2571 0 : DBG_PREFIX(NT_STATUS_IS_OK(result) ? 5 : 2,
2572 : ("Plain-text authentication for user %s returned %s"
2573 : " (PAM: %d)\n",
2574 : r->in.info->username,
2575 : nt_errstr(result),
2576 : nt_status_to_pam(result)));
2577 :
2578 : /*
2579 : * Log the winbind pam authentication, the logon_id will tie this to
2580 : * any of the logons invoked from this request.
2581 : */
2582 :
2583 0 : log_authentication(
2584 : p->mem_ctx,
2585 : domain,
2586 : r->in.client_name,
2587 : client_pid,
2588 : validation_level,
2589 : validation,
2590 : start_time,
2591 : logon_id,
2592 : "PAM_AUTH",
2593 : name_user,
2594 : name_domain,
2595 : NULL,
2596 : data_blob_null,
2597 : data_blob_null,
2598 : remote,
2599 : local,
2600 : result);
2601 :
2602 0 : return result;
2603 : }
2604 :
2605 0 : NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
2606 : TALLOC_CTX *mem_ctx,
2607 : bool interactive,
2608 : uint32_t logon_parameters,
2609 : const char *name_user,
2610 : const char *name_domain,
2611 : const char *workstation,
2612 : const uint64_t logon_id,
2613 : const char* client_name,
2614 : const int client_pid,
2615 : DATA_BLOB chal_blob,
2616 : DATA_BLOB lm_response,
2617 : DATA_BLOB nt_response,
2618 : const struct tsocket_address *remote,
2619 : const struct tsocket_address *local,
2620 : uint8_t *authoritative,
2621 : bool skip_sam,
2622 : uint32_t *flags,
2623 : uint16_t *_validation_level,
2624 : union netr_Validation **_validation)
2625 : {
2626 0 : uint16_t validation_level = 0;
2627 0 : union netr_Validation *validation = NULL;
2628 : NTSTATUS result;
2629 :
2630 : /*
2631 : * We check against domain->name instead of
2632 : * name_domain, as find_auth_domain() ->
2633 : * find_domain_from_name_noinit() already decided
2634 : * that we are in a child for the correct domain.
2635 : *
2636 : * name_domain can also be lp_realm()
2637 : * we need to check against domain->name.
2638 : */
2639 0 : if (!skip_sam && strequal(domain->name, get_global_sam_name())) {
2640 0 : struct netr_SamInfo3 *info3 = NULL;
2641 :
2642 0 : result = winbindd_dual_auth_passdb(
2643 : talloc_tos(),
2644 : logon_parameters,
2645 : name_domain, name_user,
2646 : logon_id,
2647 : client_name,
2648 : client_pid,
2649 : &chal_blob, &lm_response, &nt_response,
2650 : remote,
2651 : local,
2652 : interactive,
2653 : authoritative,
2654 : &info3);
2655 0 : if (NT_STATUS_IS_OK(result)) {
2656 0 : result = map_info3_to_validation(mem_ctx,
2657 : info3,
2658 : &validation_level,
2659 : &validation);
2660 0 : TALLOC_FREE(info3);
2661 0 : if (!NT_STATUS_IS_OK(result)) {
2662 0 : goto done;
2663 : }
2664 : }
2665 :
2666 : /*
2667 : * We need to try the remote NETLOGON server if this is
2668 : * not authoritative.
2669 : */
2670 0 : if (*authoritative != 0) {
2671 0 : *flags = 0;
2672 0 : goto process_result;
2673 : }
2674 : }
2675 :
2676 0 : result = winbind_samlogon_retry_loop(domain,
2677 : mem_ctx,
2678 : logon_parameters,
2679 : name_user,
2680 : NULL, /* password */
2681 : name_domain,
2682 : /* Bug #3248 - found by Stefan Burkei. */
2683 : workstation, /* We carefully set this above so use it... */
2684 : logon_id,
2685 : false, /* plaintext_given */
2686 : chal_blob,
2687 : lm_response,
2688 : nt_response,
2689 : interactive,
2690 : authoritative,
2691 : flags,
2692 : &validation_level,
2693 : &validation);
2694 0 : if (!NT_STATUS_IS_OK(result)) {
2695 0 : goto done;
2696 : }
2697 :
2698 0 : process_result:
2699 :
2700 0 : if (NT_STATUS_IS_OK(result)) {
2701 : struct dom_sid user_sid;
2702 0 : TALLOC_CTX *base_ctx = NULL;
2703 0 : struct netr_SamBaseInfo *base_info = NULL;
2704 0 : struct netr_SamInfo3 *info3 = NULL;
2705 :
2706 0 : switch (validation_level) {
2707 0 : case 3:
2708 0 : base_ctx = validation->sam3;
2709 0 : base_info = &validation->sam3->base;
2710 0 : break;
2711 0 : case 6:
2712 0 : base_ctx = validation->sam6;
2713 0 : base_info = &validation->sam6->base;
2714 0 : break;
2715 0 : default:
2716 0 : result = NT_STATUS_INTERNAL_ERROR;
2717 0 : goto done;
2718 : }
2719 :
2720 0 : sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
2721 :
2722 0 : if (base_info->full_name.string == NULL) {
2723 : struct netr_SamInfo3 *cached_info3;
2724 :
2725 0 : cached_info3 = netsamlogon_cache_get(mem_ctx,
2726 : &user_sid);
2727 0 : if (cached_info3 != NULL &&
2728 0 : cached_info3->base.full_name.string != NULL)
2729 : {
2730 0 : base_info->full_name.string = talloc_strdup(
2731 : base_ctx,
2732 : cached_info3->base.full_name.string);
2733 : } else {
2734 :
2735 : /* this might fail so we don't check the return code */
2736 0 : wcache_query_user_fullname(domain,
2737 : base_ctx,
2738 : &user_sid,
2739 : &base_info->full_name.string);
2740 : }
2741 : }
2742 :
2743 0 : result = map_validation_to_info3(talloc_tos(),
2744 : validation_level,
2745 : validation,
2746 : &info3);
2747 0 : if (!NT_STATUS_IS_OK(result)) {
2748 0 : goto done;
2749 : }
2750 0 : wcache_invalidate_samlogon(find_domain_from_name(name_domain),
2751 : &user_sid);
2752 0 : netsamlogon_cache_store(name_user, info3);
2753 0 : TALLOC_FREE(info3);
2754 : }
2755 :
2756 0 : done:
2757 :
2758 : /* give us a more useful (more correct?) error code */
2759 0 : if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
2760 0 : (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
2761 0 : result = NT_STATUS_NO_LOGON_SERVERS;
2762 : }
2763 :
2764 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
2765 : ("NTLM CRAP authentication for user [%s]\\[%s] returned %s\n",
2766 : name_domain,
2767 : name_user,
2768 : nt_errstr(result)));
2769 :
2770 0 : if (!NT_STATUS_IS_OK(result)) {
2771 0 : return result;
2772 : }
2773 :
2774 0 : *_validation_level = validation_level;
2775 0 : *_validation = validation;
2776 0 : return NT_STATUS_OK;
2777 : }
2778 :
2779 0 : NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, struct wbint_PamAuthCrap *r)
2780 : {
2781 0 : struct winbindd_domain *domain = wb_child_domain();
2782 : NTSTATUS result;
2783 0 : uint64_t logon_id = 0;
2784 0 : uint8_t authoritative = 1;
2785 0 : uint32_t flags = 0;
2786 0 : uint16_t validation_level = UINT16_MAX;
2787 0 : union netr_Validation *validation = NULL;
2788 0 : const struct timeval start_time = timeval_current();
2789 0 : const struct tsocket_address *remote = NULL;
2790 0 : const struct tsocket_address *local = NULL;
2791 0 : struct netr_SamInfo3 *info3 = NULL;
2792 : pid_t client_pid;
2793 :
2794 0 : if (domain == NULL) {
2795 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
2796 : }
2797 :
2798 : /* Cut client_pid to 32bit */
2799 0 : client_pid = r->in.client_pid;
2800 0 : if ((uint64_t)client_pid != r->in.client_pid) {
2801 0 : DBG_DEBUG("pid out of range\n");
2802 0 : return NT_STATUS_INVALID_PARAMETER;
2803 : }
2804 :
2805 0 : logon_id = generate_random_u64();
2806 0 : remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
2807 0 : local = dcesrv_connection_get_local_address(p->dce_call->conn);
2808 :
2809 0 : DBG_NOTICE("[%"PRIu32"]: pam auth crap domain: %s user: %s\n",
2810 : client_pid, r->in.domain, r->in.user);
2811 :
2812 0 : result = winbind_dual_SamLogon(domain,
2813 : p->mem_ctx,
2814 : false, /* interactive */
2815 : r->in.logon_parameters,
2816 : r->in.user,
2817 : r->in.domain,
2818 : r->in.workstation,
2819 : logon_id,
2820 : r->in.client_name,
2821 : client_pid,
2822 : r->in.chal,
2823 : r->in.lm_resp,
2824 : r->in.nt_resp,
2825 : remote,
2826 : local,
2827 : &authoritative,
2828 : false,
2829 : &flags,
2830 : &validation_level,
2831 : &validation);
2832 0 : if (!NT_STATUS_IS_OK(result)) {
2833 0 : goto done;
2834 : }
2835 :
2836 0 : result = map_validation_to_info3(p->mem_ctx,
2837 : validation_level,
2838 : validation,
2839 : &info3);
2840 0 : if (!NT_STATUS_IS_OK(result)) {
2841 0 : goto done;
2842 : }
2843 :
2844 : /* Check if the user is in the right group */
2845 0 : result = check_info3_in_group(info3, r->in.require_membership_of_sid);
2846 0 : if (!NT_STATUS_IS_OK(result)) {
2847 0 : char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
2848 : wbint_SidArray,
2849 : r->in.require_membership_of_sid);
2850 0 : DBG_NOTICE("User %s is not in the required groups:\n",
2851 : r->in.user);
2852 0 : DEBUGADD(DBGLVL_NOTICE, ("%s", s));
2853 0 : DEBUGADD(DBGLVL_NOTICE,
2854 : ("CRAP authentication is rejected\n"));
2855 0 : goto done;
2856 : }
2857 :
2858 0 : if (!is_allowed_domain(info3->base.logon_domain.string)) {
2859 0 : DBG_NOTICE("Authentication failed for user [%s] "
2860 : "from firewalled domain [%s]\n",
2861 : info3->base.account_name.string,
2862 : info3->base.logon_domain.string);
2863 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
2864 0 : goto done;
2865 : }
2866 :
2867 0 : r->out.validation = talloc_zero(p->mem_ctx,
2868 : struct wbint_PamAuthCrapValidation);
2869 0 : if (r->out.validation == NULL) {
2870 0 : result = NT_STATUS_NO_MEMORY;
2871 0 : goto done;
2872 : }
2873 :
2874 0 : r->out.validation->level = validation_level;
2875 0 : r->out.validation->validation = talloc_move(r->out.validation,
2876 : &validation);
2877 0 : done:
2878 :
2879 0 : if (r->in.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
2880 0 : result = nt_status_squash(result);
2881 : }
2882 :
2883 0 : *r->out.authoritative = authoritative;
2884 :
2885 : /*
2886 : * Log the winbind pam authentication, the logon_id will tie this to
2887 : * any of the logons invoked from this request.
2888 : */
2889 0 : log_authentication(
2890 : p->mem_ctx,
2891 : domain,
2892 : r->in.client_name,
2893 : client_pid,
2894 0 : r->out.validation->level,
2895 0 : r->out.validation->validation,
2896 : start_time,
2897 : logon_id,
2898 : "NTLM_AUTH",
2899 : r->in.user,
2900 : r->in.domain,
2901 : r->in.workstation,
2902 : r->in.lm_resp,
2903 : r->in.nt_resp,
2904 : remote,
2905 : local,
2906 : result);
2907 :
2908 0 : return result;
2909 : }
2910 :
2911 0 : NTSTATUS _wbint_PamAuthChangePassword(struct pipes_struct *p,
2912 : struct wbint_PamAuthChangePassword *r)
2913 : {
2914 0 : struct winbindd_domain *contact_domain = wb_child_domain();
2915 : struct policy_handle dom_pol;
2916 0 : struct rpc_pipe_client *cli = NULL;
2917 0 : bool got_info = false;
2918 0 : struct samr_DomInfo1 *info = NULL;
2919 0 : struct userPwdChangeFailureInformation *reject = NULL;
2920 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2921 0 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2922 : fstring namespace, domain, user;
2923 0 : struct dcerpc_binding_handle *b = NULL;
2924 : bool ok;
2925 : pid_t client_pid;
2926 :
2927 0 : ZERO_STRUCT(dom_pol);
2928 :
2929 0 : if (contact_domain == NULL) {
2930 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
2931 : }
2932 :
2933 : /* Cut client_pid to 32bit */
2934 0 : client_pid = r->in.client_pid;
2935 0 : if ((uint64_t)client_pid != r->in.client_pid) {
2936 0 : DBG_DEBUG("pid out of range\n");
2937 0 : return NT_STATUS_INVALID_PARAMETER;
2938 : }
2939 :
2940 0 : DBG_NOTICE("[%"PRIu32"]: dual pam chauthtok %s\n",
2941 : client_pid, r->in.user);
2942 :
2943 0 : ok = parse_domain_user(r->in.user,
2944 : namespace,
2945 : domain,
2946 : user);
2947 0 : if (!ok) {
2948 0 : goto done;
2949 : }
2950 :
2951 0 : if (!is_allowed_domain(domain)) {
2952 0 : DBG_NOTICE("Authentication failed for user [%s] "
2953 : "from firewalled domain [%s]\n",
2954 : user, domain);
2955 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
2956 0 : goto done;
2957 : }
2958 :
2959 : /* Initialize reject reason */
2960 0 : *r->out.reject_reason = Undefined;
2961 :
2962 : /* Get sam handle */
2963 :
2964 0 : result = cm_connect_sam(contact_domain,
2965 : p->mem_ctx,
2966 : true,
2967 : &cli,
2968 : &dom_pol);
2969 0 : if (!NT_STATUS_IS_OK(result)) {
2970 0 : DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
2971 0 : goto done;
2972 : }
2973 :
2974 0 : b = cli->binding_handle;
2975 :
2976 0 : status = dcerpc_samr_chgpasswd_user4(cli->binding_handle,
2977 : p->mem_ctx,
2978 0 : cli->srv_name_slash,
2979 : user,
2980 : r->in.old_password,
2981 : r->in.new_password,
2982 : &result);
2983 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2984 : /* Password successfully changed. */
2985 0 : goto done;
2986 : }
2987 0 : if (!NT_STATUS_IS_OK(status)) {
2988 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
2989 0 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
2990 0 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
2991 : /* DO NOT FALLBACK TO RC4 */
2992 0 : if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) {
2993 0 : result = NT_STATUS_STRONG_CRYPTO_NOT_SUPPORTED;
2994 0 : goto process_result;
2995 : }
2996 : }
2997 : } else {
2998 : /* Password change was unsuccessful. */
2999 0 : if (!NT_STATUS_IS_OK(result)) {
3000 0 : goto done;
3001 : }
3002 : }
3003 :
3004 0 : result = rpccli_samr_chgpasswd_user3(cli,
3005 : p->mem_ctx,
3006 : user,
3007 : r->in.new_password,
3008 : r->in.old_password,
3009 : &info,
3010 : &reject);
3011 :
3012 : /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */
3013 :
3014 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) {
3015 :
3016 0 : *r->out.dominfo = talloc_steal(p->mem_ctx, info);
3017 0 : *r->out.reject_reason = reject->extendedFailureReason;
3018 :
3019 0 : got_info = true;
3020 : }
3021 :
3022 : /* atm the pidl generated rpccli_samr_ChangePasswordUser3 function will
3023 : * return with NT_STATUS_BUFFER_TOO_SMALL for w2k dcs as w2k just
3024 : * returns with 4byte error code (NT_STATUS_NOT_SUPPORTED) which is too
3025 : * short to comply with the samr_ChangePasswordUser3 idl - gd */
3026 :
3027 : /* only fallback when the chgpasswd_user3 call is not supported */
3028 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
3029 0 : NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ||
3030 0 : NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) ||
3031 0 : NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
3032 :
3033 0 : DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n",
3034 : nt_errstr(result)));
3035 :
3036 0 : result = rpccli_samr_chgpasswd_user2(cli,
3037 : p->mem_ctx,
3038 : user,
3039 : r->in.new_password,
3040 : r->in.old_password);
3041 :
3042 : /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION.
3043 : Map to the same status code as Windows 2003. */
3044 :
3045 0 : if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) {
3046 0 : result = NT_STATUS_PASSWORD_RESTRICTION;
3047 : }
3048 : }
3049 :
3050 0 : done:
3051 :
3052 0 : if (NT_STATUS_IS_OK(result)
3053 0 : && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN)
3054 0 : && lp_winbind_offline_logon()) {
3055 0 : result = winbindd_update_creds_by_name(contact_domain, user,
3056 : r->in.new_password);
3057 : /* Again, this happens when we login from gdm or xdm
3058 : * and the password expires, *BUT* cached crendentials
3059 : * doesn't exist. winbindd_update_creds_by_name()
3060 : * returns NT_STATUS_NO_SUCH_USER.
3061 : * This is not a failure.
3062 : * --- BoYang
3063 : * */
3064 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
3065 0 : result = NT_STATUS_OK;
3066 : }
3067 :
3068 0 : if (!NT_STATUS_IS_OK(result)) {
3069 0 : DEBUG(10, ("Failed to store creds: %s\n",
3070 : nt_errstr(result)));
3071 0 : goto process_result;
3072 : }
3073 : }
3074 :
3075 0 : if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) {
3076 :
3077 : NTSTATUS policy_ret;
3078 :
3079 0 : policy_ret = get_password_policy(contact_domain,
3080 : p->mem_ctx,
3081 : &info);
3082 :
3083 : /* failure of this is non critical, it will just provide no
3084 : * additional information to the client why the change has
3085 : * failed - Guenther */
3086 :
3087 0 : if (!NT_STATUS_IS_OK(policy_ret)) {
3088 0 : DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
3089 0 : goto process_result;
3090 : }
3091 :
3092 0 : *r->out.dominfo = talloc_steal(p->mem_ctx, info);
3093 : }
3094 :
3095 0 : process_result:
3096 :
3097 0 : if (strequal(contact_domain->name, get_global_sam_name())) {
3098 : /* FIXME: internal rpc pipe does not cache handles yet */
3099 0 : if (b) {
3100 0 : if (is_valid_policy_hnd(&dom_pol)) {
3101 : NTSTATUS _result;
3102 0 : dcerpc_samr_Close(b,
3103 : p->mem_ctx,
3104 : &dom_pol,
3105 : &_result);
3106 : }
3107 0 : TALLOC_FREE(cli);
3108 : }
3109 : }
3110 :
3111 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
3112 : ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
3113 : domain,
3114 : user,
3115 : nt_errstr(result),
3116 : nt_status_to_pam(result)));
3117 :
3118 0 : return result;
3119 : }
3120 :
3121 0 : NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r)
3122 : {
3123 0 : struct winbindd_domain *domain = wb_child_domain();
3124 0 : NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
3125 : pid_t client_pid;
3126 : uid_t user_uid;
3127 :
3128 0 : if (domain == NULL) {
3129 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
3130 : }
3131 :
3132 : /* Cut client_pid to 32bit */
3133 0 : client_pid = r->in.client_pid;
3134 0 : if ((uint64_t)client_pid != r->in.client_pid) {
3135 0 : DBG_DEBUG("pid out of range\n");
3136 0 : return NT_STATUS_INVALID_PARAMETER;
3137 : }
3138 :
3139 : /* Cut uid to 32bit */
3140 0 : user_uid = r->in.uid;
3141 0 : if ((uint64_t)user_uid != r->in.uid) {
3142 0 : DBG_DEBUG("uid out of range\n");
3143 0 : return NT_STATUS_INVALID_PARAMETER;
3144 : }
3145 :
3146 0 : DBG_NOTICE("[%"PRIu32"]: pam dual logoff %s\n", client_pid, r->in.user);
3147 :
3148 0 : if (!(r->in.flags & WBFLAG_PAM_KRB5)) {
3149 0 : result = NT_STATUS_OK;
3150 0 : goto process_result;
3151 : }
3152 :
3153 0 : if ((r->in.krb5ccname == NULL) || (strlen(r->in.krb5ccname) == 0)) {
3154 0 : result = NT_STATUS_OK;
3155 0 : goto process_result;
3156 : }
3157 :
3158 : #ifdef HAVE_KRB5
3159 :
3160 0 : if (user_uid == (uid_t)-1) {
3161 0 : DBG_DEBUG("Invalid uid for user '%s'\n", r->in.user);
3162 0 : goto process_result;
3163 : }
3164 :
3165 : /* what we need here is to find the corresponding krb5 ccache name *we*
3166 : * created for a given username and destroy it */
3167 :
3168 0 : if (!ccache_entry_exists(r->in.user)) {
3169 0 : result = NT_STATUS_OK;
3170 0 : DBG_DEBUG("No entry found for user '%s'.\n", r->in.user);
3171 0 : goto process_result;
3172 : }
3173 :
3174 0 : if (!ccache_entry_identical(r->in.user, user_uid, r->in.krb5ccname)) {
3175 0 : DBG_DEBUG("Cached entry differs for user '%s'\n", r->in.user);
3176 0 : goto process_result;
3177 : }
3178 :
3179 0 : result = remove_ccache(r->in.user);
3180 0 : if (!NT_STATUS_IS_OK(result)) {
3181 0 : DBG_DEBUG("Failed to remove ccache for user '%s': %s\n",
3182 : r->in.user, nt_errstr(result));
3183 0 : goto process_result;
3184 : }
3185 :
3186 : /*
3187 : * Remove any mlock'ed memory creds in the child
3188 : * we might be using for krb5 ticket renewal.
3189 : */
3190 :
3191 0 : winbindd_delete_memory_creds(r->in.user);
3192 :
3193 : #else
3194 : result = NT_STATUS_NOT_SUPPORTED;
3195 : #endif
3196 :
3197 0 : process_result:
3198 :
3199 0 : return result;
3200 : }
3201 :
3202 : /* Change user password with auth crap*/
3203 :
3204 0 : NTSTATUS _wbint_PamAuthCrapChangePassword(struct pipes_struct *p,
3205 : struct wbint_PamAuthCrapChangePassword *r)
3206 : {
3207 : NTSTATUS result;
3208 : fstring namespace, domain, user;
3209 : struct policy_handle dom_pol;
3210 0 : struct winbindd_domain *contact_domain = wb_child_domain();
3211 0 : struct rpc_pipe_client *cli = NULL;
3212 0 : struct dcerpc_binding_handle *b = NULL;
3213 : pid_t client_pid;
3214 :
3215 0 : ZERO_STRUCT(dom_pol);
3216 :
3217 0 : if (contact_domain == NULL) {
3218 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
3219 : }
3220 :
3221 : /* Cut client_pid to 32bit */
3222 0 : client_pid = r->in.client_pid;
3223 0 : if ((uint64_t)client_pid != r->in.client_pid) {
3224 0 : DBG_DEBUG("pid out of range\n");
3225 0 : return NT_STATUS_INVALID_PARAMETER;
3226 : }
3227 :
3228 0 : domain[0] = '\0';
3229 0 : namespace[0] = '\0';
3230 0 : user[0] = '\0';
3231 :
3232 0 : DBG_NOTICE("[%"PRIu32"]: pam change pswd auth crap domain: %s "
3233 : "user: %s\n", client_pid, r->in.domain, r->in.user);
3234 :
3235 0 : if (lp_winbind_offline_logon()) {
3236 0 : DEBUG(0,("Refusing password change as winbind offline logons are enabled. "));
3237 0 : DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n"));
3238 0 : result = NT_STATUS_ACCESS_DENIED;
3239 0 : goto done;
3240 : }
3241 :
3242 0 : if (r->in.domain != NULL && strlen(r->in.domain) > 0) {
3243 0 : fstrcpy(domain, r->in.domain);
3244 : } else {
3245 : bool ok;
3246 :
3247 0 : ok = parse_domain_user(r->in.user,
3248 : namespace,
3249 : domain,
3250 : user);
3251 0 : if (!ok) {
3252 0 : result = NT_STATUS_INVALID_PARAMETER;
3253 0 : goto done;
3254 : }
3255 :
3256 0 : if (strlen(domain) == 0) {
3257 0 : DBG_NOTICE("no domain specified with username (%s) - "
3258 : "failing auth\n", r->in.user);
3259 0 : result = NT_STATUS_NO_SUCH_USER;
3260 0 : goto done;
3261 : }
3262 : }
3263 :
3264 0 : if (!*domain && lp_winbind_use_default_domain()) {
3265 0 : fstrcpy(domain,lp_workgroup());
3266 : }
3267 :
3268 0 : if (!is_allowed_domain(domain)) {
3269 0 : DBG_NOTICE("Authentication failed for user [%s] "
3270 : "from firewalled domain [%s]\n",
3271 : r->in.user,
3272 : domain);
3273 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
3274 0 : goto done;
3275 : }
3276 :
3277 0 : if(!*user) {
3278 0 : fstrcpy(user, r->in.user);
3279 : }
3280 :
3281 : /* Get sam handle */
3282 :
3283 0 : result = cm_connect_sam(contact_domain,
3284 : p->mem_ctx,
3285 : true,
3286 : &cli,
3287 : &dom_pol);
3288 0 : if (!NT_STATUS_IS_OK(result)) {
3289 0 : DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
3290 0 : goto done;
3291 : }
3292 :
3293 0 : b = cli->binding_handle;
3294 :
3295 0 : result = rpccli_samr_chng_pswd_auth_crap(cli,
3296 : p->mem_ctx,
3297 : user,
3298 : r->in.new_nt_pswd,
3299 : r->in.old_nt_hash_enc,
3300 : r->in.new_lm_pswd,
3301 : r->in.old_lm_hash_enc);
3302 :
3303 0 : done:
3304 :
3305 0 : if (strequal(contact_domain->name, get_global_sam_name())) {
3306 : /* FIXME: internal rpc pipe does not cache handles yet */
3307 0 : if (b) {
3308 0 : if (is_valid_policy_hnd(&dom_pol)) {
3309 : NTSTATUS _result;
3310 0 : dcerpc_samr_Close(b,
3311 : p->mem_ctx,
3312 : &dom_pol,
3313 : &_result);
3314 : }
3315 0 : TALLOC_FREE(cli);
3316 : }
3317 : }
3318 :
3319 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
3320 : ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
3321 : domain, user,
3322 : nt_errstr(result),
3323 : nt_status_to_pam(result)));
3324 :
3325 0 : return result;
3326 : }
3327 :
3328 : #ifdef HAVE_KRB5
3329 617 : static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
3330 : struct PAC_DATA **p_pac_data)
3331 : {
3332 617 : krb5_context krbctx = NULL;
3333 : krb5_error_code k5ret;
3334 : krb5_keytab keytab;
3335 : krb5_kt_cursor cursor;
3336 : krb5_keytab_entry entry;
3337 617 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
3338 :
3339 617 : ZERO_STRUCT(entry);
3340 617 : ZERO_STRUCT(cursor);
3341 :
3342 617 : k5ret = smb_krb5_init_context_common(&krbctx);
3343 617 : if (k5ret) {
3344 0 : DBG_ERR("kerberos init context failed (%s)\n",
3345 : error_message(k5ret));
3346 0 : status = krb5_to_nt_status(k5ret);
3347 0 : goto out;
3348 : }
3349 :
3350 617 : k5ret = gse_krb5_get_server_keytab(krbctx, &keytab);
3351 617 : if (k5ret) {
3352 0 : DEBUG(1, ("Failed to get keytab: %s\n",
3353 : error_message(k5ret)));
3354 0 : status = krb5_to_nt_status(k5ret);
3355 0 : goto out_free;
3356 : }
3357 :
3358 617 : k5ret = krb5_kt_start_seq_get(krbctx, keytab, &cursor);
3359 617 : if (k5ret) {
3360 0 : DEBUG(1, ("Failed to start seq: %s\n",
3361 : error_message(k5ret)));
3362 0 : status = krb5_to_nt_status(k5ret);
3363 0 : goto out_keytab;
3364 : }
3365 :
3366 617 : k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
3367 2515 : while (k5ret == 0) {
3368 2206 : status = kerberos_decode_pac(mem_ctx,
3369 : pac_blob,
3370 : krbctx,
3371 : NULL, /* krbtgt_keyblock */
3372 : KRB5_KT_KEY(&entry), /* service_keyblock */
3373 : NULL, /* client_principal */
3374 : 0, /* tgs_authtime */
3375 : p_pac_data);
3376 2206 : if (NT_STATUS_IS_OK(status)) {
3377 617 : break;
3378 : }
3379 1589 : k5ret = smb_krb5_kt_free_entry(krbctx, &entry);
3380 1589 : k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
3381 : }
3382 :
3383 617 : k5ret = krb5_kt_end_seq_get(krbctx, keytab, &cursor);
3384 617 : if (k5ret) {
3385 0 : DEBUG(1, ("Failed to end seq: %s\n",
3386 : error_message(k5ret)));
3387 : }
3388 926 : out_keytab:
3389 617 : k5ret = krb5_kt_close(krbctx, keytab);
3390 617 : if (k5ret) {
3391 0 : DEBUG(1, ("Failed to close keytab: %s\n",
3392 : error_message(k5ret)));
3393 : }
3394 926 : out_free:
3395 617 : krb5_free_context(krbctx);
3396 617 : out:
3397 617 : return status;
3398 : }
3399 :
3400 617 : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
3401 : TALLOC_CTX *mem_ctx,
3402 : bool *p_is_trusted,
3403 : uint16_t *p_validation_level,
3404 : union netr_Validation **p_validation)
3405 : {
3406 617 : struct winbindd_request *req = state->request;
3407 : DATA_BLOB pac_blob;
3408 617 : struct PAC_DATA *pac_data = NULL;
3409 617 : struct PAC_LOGON_INFO *logon_info = NULL;
3410 617 : struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
3411 617 : struct netr_SamInfo6 *info6 = NULL;
3412 617 : uint16_t validation_level = 0;
3413 617 : union netr_Validation *validation = NULL;
3414 617 : struct netr_SamInfo3 *info3_copy = NULL;
3415 : NTSTATUS result;
3416 617 : bool is_trusted = false;
3417 : uint32_t i;
3418 617 : TALLOC_CTX *tmp_ctx = NULL;
3419 :
3420 617 : tmp_ctx = talloc_new(mem_ctx);
3421 617 : if (tmp_ctx == NULL) {
3422 0 : return NT_STATUS_NO_MEMORY;
3423 : }
3424 :
3425 617 : *p_is_trusted = false;
3426 617 : *p_validation_level = 0;
3427 617 : *p_validation = NULL;
3428 :
3429 617 : pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
3430 617 : result = extract_pac_vrfy_sigs(tmp_ctx, pac_blob, &pac_data);
3431 617 : if (NT_STATUS_IS_OK(result)) {
3432 617 : is_trusted = true;
3433 : }
3434 617 : if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
3435 : /* Try without signature verification */
3436 0 : result = kerberos_decode_pac(tmp_ctx,
3437 : pac_blob,
3438 : NULL, /* krb5_context */
3439 : NULL, /* krbtgt_keyblock */
3440 : NULL, /* service_keyblock */
3441 : NULL, /* client_principal */
3442 : 0, /* tgs_authtime */
3443 : &pac_data);
3444 : }
3445 617 : if (!NT_STATUS_IS_OK(result)) {
3446 0 : DEBUG(1, ("Error during PAC signature verification: %s\n",
3447 : nt_errstr(result)));
3448 0 : goto out;
3449 : }
3450 :
3451 4153 : for (i=0; i < pac_data->num_buffers; i++) {
3452 3536 : if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
3453 617 : logon_info = pac_data->buffers[i].info->logon_info.info;
3454 617 : continue;
3455 : }
3456 2919 : if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
3457 534 : upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
3458 534 : continue;
3459 : }
3460 : }
3461 :
3462 617 : result = create_info6_from_pac(tmp_ctx,
3463 : logon_info,
3464 : upn_dns_info,
3465 : &info6);
3466 617 : if (!NT_STATUS_IS_OK(result)) {
3467 0 : goto out;
3468 : }
3469 :
3470 617 : if (!is_allowed_domain(info6->base.logon_domain.string)) {
3471 2 : DBG_NOTICE("Authentication failed for user [%s] "
3472 : "from firewalled domain [%s]\n",
3473 : info6->base.account_name.string,
3474 : info6->base.logon_domain.string);
3475 2 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
3476 2 : goto out;
3477 : }
3478 :
3479 615 : result = map_info6_to_validation(tmp_ctx,
3480 : info6,
3481 : &validation_level,
3482 : &validation);
3483 615 : if (!NT_STATUS_IS_OK(result)) {
3484 0 : goto out;
3485 : }
3486 :
3487 615 : result = map_validation_to_info3(tmp_ctx,
3488 : validation_level,
3489 : validation,
3490 : &info3_copy);
3491 615 : if (!NT_STATUS_IS_OK(result)) {
3492 0 : goto out;
3493 : }
3494 :
3495 615 : if (is_trusted) {
3496 : /*
3497 : * Signature verification succeeded, we can
3498 : * trust the PAC and prime the netsamlogon
3499 : * and name2sid caches. DO NOT DO THIS
3500 : * in the signature verification failed
3501 : * code path.
3502 : */
3503 615 : struct winbindd_domain *domain = NULL;
3504 :
3505 615 : netsamlogon_cache_store(NULL, info3_copy);
3506 :
3507 : /*
3508 : * We're in the parent here, so find the child
3509 : * pointer from the PAC domain name.
3510 : */
3511 615 : domain = find_lookup_domain_from_name(
3512 615 : info3_copy->base.logon_domain.string);
3513 615 : if (domain && domain->primary ) {
3514 : struct dom_sid user_sid;
3515 : struct dom_sid_buf buf;
3516 :
3517 923 : sid_compose(&user_sid,
3518 615 : info3_copy->base.domain_sid,
3519 615 : info3_copy->base.rid);
3520 :
3521 923 : cache_name2sid_trusted(domain,
3522 615 : info3_copy->base.logon_domain.string,
3523 615 : info3_copy->base.account_name.string,
3524 : SID_NAME_USER,
3525 : &user_sid);
3526 :
3527 615 : DBG_INFO("PAC for user %s\\%s SID %s primed cache\n",
3528 : info3_copy->base.logon_domain.string,
3529 : info3_copy->base.account_name.string,
3530 : dom_sid_str_buf(&user_sid, &buf));
3531 : }
3532 : }
3533 :
3534 615 : *p_is_trusted = is_trusted;
3535 615 : *p_validation_level = validation_level;
3536 615 : *p_validation = talloc_move(mem_ctx, &validation);
3537 :
3538 615 : result = NT_STATUS_OK;
3539 617 : out:
3540 617 : TALLOC_FREE(tmp_ctx);
3541 617 : return result;
3542 : }
3543 : #else /* HAVE_KRB5 */
3544 : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
3545 : TALLOC_CTX *mem_ctx,
3546 : bool *p_is_trusted,
3547 : uint16_t *p_validation_level,
3548 : union netr_Validation **p_validation);
3549 : {
3550 :
3551 : *p_is_trusted = false;
3552 : *p_validation_level = 0;
3553 : *p_validation = NULL;
3554 : return NT_STATUS_NO_SUCH_USER;
3555 : }
3556 : #endif /* HAVE_KRB5 */
|