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 1039 : 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 1039 : struct netr_SamInfo3 *info3 = NULL;
71 1039 : char *ex = NULL;
72 : uint32_t i;
73 1039 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
74 1039 : TALLOC_CTX *frame = talloc_stackframe();
75 :
76 1039 : status = map_validation_to_info3(frame,
77 : validation_level,
78 : validation,
79 : &info3);
80 1039 : if (!NT_STATUS_IS_OK(status)) {
81 0 : goto out;
82 : }
83 :
84 1039 : resp->data.auth.info3.logon_time =
85 1039 : nt_time_to_unix(info3->base.logon_time);
86 1039 : resp->data.auth.info3.logoff_time =
87 1039 : nt_time_to_unix(info3->base.logoff_time);
88 1039 : resp->data.auth.info3.kickoff_time =
89 1039 : nt_time_to_unix(info3->base.kickoff_time);
90 1039 : resp->data.auth.info3.pass_last_set_time =
91 1039 : nt_time_to_unix(info3->base.last_password_change);
92 1039 : resp->data.auth.info3.pass_can_change_time =
93 1039 : nt_time_to_unix(info3->base.allow_password_change);
94 1039 : resp->data.auth.info3.pass_must_change_time =
95 1039 : nt_time_to_unix(info3->base.force_password_change);
96 :
97 1039 : resp->data.auth.info3.logon_count = info3->base.logon_count;
98 1039 : resp->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
99 :
100 1039 : resp->data.auth.info3.user_rid = info3->base.rid;
101 1039 : resp->data.auth.info3.group_rid = info3->base.primary_gid;
102 1039 : sid_to_fstring(resp->data.auth.info3.dom_sid, info3->base.domain_sid);
103 :
104 1039 : resp->data.auth.info3.num_groups = info3->base.groups.count;
105 1039 : resp->data.auth.info3.user_flgs = info3->base.user_flags;
106 :
107 1039 : resp->data.auth.info3.acct_flags = info3->base.acct_flags;
108 1039 : resp->data.auth.info3.num_other_sids = info3->sidcount;
109 :
110 1039 : fstrcpy(resp->data.auth.info3.user_name,
111 : info3->base.account_name.string);
112 1039 : fstrcpy(resp->data.auth.info3.full_name,
113 : info3->base.full_name.string);
114 1039 : fstrcpy(resp->data.auth.info3.logon_script,
115 : info3->base.logon_script.string);
116 1039 : fstrcpy(resp->data.auth.info3.profile_path,
117 : info3->base.profile_path.string);
118 1039 : fstrcpy(resp->data.auth.info3.home_dir,
119 : info3->base.home_directory.string);
120 1039 : fstrcpy(resp->data.auth.info3.dir_drive,
121 : info3->base.home_drive.string);
122 :
123 1039 : fstrcpy(resp->data.auth.info3.logon_srv,
124 : info3->base.logon_server.string);
125 1039 : fstrcpy(resp->data.auth.info3.logon_dom,
126 : info3->base.logon_domain.string);
127 :
128 1039 : resp->data.auth.validation_level = validation_level;
129 1039 : if (validation_level == 6) {
130 1007 : fstrcpy(resp->data.auth.info6.dns_domainname,
131 : validation->sam6->dns_domainname.string);
132 1007 : fstrcpy(resp->data.auth.info6.principal_name,
133 : validation->sam6->principal_name.string);
134 : }
135 :
136 1039 : ex = talloc_strdup(frame, "");
137 1039 : if (ex == NULL) {
138 0 : status = NT_STATUS_NO_MEMORY;
139 0 : goto out;
140 : }
141 :
142 6672 : for (i=0; i < info3->base.groups.count; i++) {
143 11266 : ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
144 5633 : info3->base.groups.rids[i].rid,
145 5633 : info3->base.groups.rids[i].attributes);
146 5633 : if (ex == NULL) {
147 0 : status = NT_STATUS_NO_MEMORY;
148 0 : goto out;
149 : }
150 : }
151 :
152 1633 : for (i=0; i < info3->sidcount; i++) {
153 : struct dom_sid_buf sidbuf;
154 :
155 594 : ex = talloc_asprintf_append_buffer(
156 : ex,
157 : "%s:0x%08X\n",
158 594 : dom_sid_str_buf(info3->sids[i].sid, &sidbuf),
159 594 : info3->sids[i].attributes);
160 594 : if (ex == NULL) {
161 0 : status = NT_STATUS_NO_MEMORY;
162 0 : goto out;
163 : }
164 : }
165 :
166 1039 : resp->length += talloc_get_size(ex);
167 1039 : resp->extra_data.data = talloc_move(mem_ctx, &ex);
168 :
169 1039 : status = NT_STATUS_OK;
170 1039 : out:
171 1039 : TALLOC_FREE(frame);
172 1039 : 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 170 : 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 170 : TALLOC_CTX *tmp_ctx = NULL;
203 170 : const char *nt_username = NULL;
204 170 : const char *nt_domain = NULL;
205 170 : char *unix_username = NULL;
206 170 : struct netr_SamBaseInfo *base_info = NULL;
207 : NTSTATUS status;
208 :
209 170 : tmp_ctx = talloc_new(mem_ctx);
210 170 : 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 170 : switch (validation_level) {
218 8 : case 3:
219 8 : base_info = &validation->sam3->base;
220 8 : break;
221 162 : case 6:
222 162 : base_info = &validation->sam6->base;
223 162 : 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 170 : nt_domain = talloc_strdup(tmp_ctx, base_info->logon_domain.string);
231 170 : 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 170 : nt_username = talloc_strdup(tmp_ctx, base_info->account_name.string);
238 170 : 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 170 : unix_username = fill_domain_username_talloc(tmp_ctx,
245 : nt_domain,
246 : nt_username,
247 : true);
248 170 : if (unix_username == NULL) {
249 0 : status = NT_STATUS_NO_MEMORY;
250 0 : goto out;
251 : }
252 :
253 170 : DBG_INFO("Setting unix username to [%s]\n", unix_username);
254 :
255 170 : *_unix_username = talloc_move(mem_ctx, &unix_username);
256 :
257 170 : status = NT_STATUS_OK;
258 170 : out:
259 170 : TALLOC_FREE(tmp_ctx);
260 :
261 170 : 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 675 : NTSTATUS extra_data_to_sid_array(const char *group_sid,
361 : TALLOC_CTX *mem_ctx,
362 : struct wbint_SidArray **_sid_array)
363 : {
364 675 : TALLOC_CTX *tmp_ctx = NULL;
365 675 : struct wbint_SidArray *sid_array = NULL;
366 675 : struct dom_sid *require_membership_of_sid = NULL;
367 675 : uint32_t num_require_membership_of_sid = 0;
368 675 : char *req_sid = NULL;
369 675 : const char *p = NULL;
370 : NTSTATUS status;
371 :
372 675 : if (_sid_array == NULL) {
373 0 : return NT_STATUS_INVALID_PARAMETER;
374 : }
375 :
376 675 : *_sid_array = NULL;
377 :
378 675 : tmp_ctx = talloc_new(mem_ctx);
379 675 : if (tmp_ctx == NULL) {
380 0 : return NT_STATUS_NO_MEMORY;
381 : }
382 :
383 675 : sid_array = talloc_zero(tmp_ctx, struct wbint_SidArray);
384 675 : if (sid_array == NULL) {
385 0 : status = NT_STATUS_NO_MEMORY;
386 0 : goto fail;
387 : }
388 :
389 675 : if (!group_sid || !group_sid[0]) {
390 : /* NO sid supplied, all users may access */
391 659 : status = NT_STATUS_OK;
392 : /*
393 : * Always return an allocated wbint_SidArray,
394 : * even if the array is empty.
395 : */
396 659 : goto out;
397 : }
398 :
399 16 : num_require_membership_of_sid = 0;
400 16 : require_membership_of_sid = NULL;
401 16 : p = group_sid;
402 :
403 32 : while (next_token_talloc(tmp_ctx, &p, &req_sid, ",")) {
404 : struct dom_sid sid;
405 :
406 16 : 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 16 : status = add_sid_to_array(tmp_ctx, &sid,
414 : &require_membership_of_sid,
415 : &num_require_membership_of_sid);
416 16 : if (!NT_STATUS_IS_OK(status)) {
417 0 : DBG_ERR("add_sid_to_array failed\n");
418 0 : goto fail;
419 : }
420 : }
421 :
422 16 : sid_array->num_sids = num_require_membership_of_sid;
423 16 : sid_array->sids = talloc_move(sid_array, &require_membership_of_sid);
424 :
425 16 : status = NT_STATUS_OK;
426 675 : out:
427 675 : *_sid_array = talloc_move(mem_ctx, &sid_array);
428 :
429 675 : fail:
430 675 : TALLOC_FREE(tmp_ctx);
431 :
432 675 : 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 713 : struct winbindd_domain *find_auth_domain(uint8_t flags,
503 : const char *domain_name)
504 : {
505 : struct winbindd_domain *domain;
506 :
507 713 : if (IS_DC) {
508 0 : domain = find_domain_from_name_noinit(domain_name);
509 0 : if (domain == NULL) {
510 0 : DEBUG(3, ("Authentication for domain [%s] refused "
511 : "as it is not a trusted domain\n",
512 : domain_name));
513 0 : return NULL;
514 : }
515 :
516 0 : if (domain->secure_channel_type != SEC_CHAN_NULL) {
517 0 : return domain;
518 : }
519 :
520 0 : return domain->routing_domain;
521 : }
522 :
523 713 : if (strequal(domain_name, get_global_sam_name())) {
524 46 : return find_domain_from_name_noinit(domain_name);
525 : }
526 :
527 667 : 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 667 : flags &= ~WBFLAG_PAM_CONTACT_TRUSTDOM;
534 : }
535 :
536 : /* we can auth against trusted domains */
537 667 : 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 667 : 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 675 : bool check_request_flags(uint32_t flags)
977 : {
978 675 : uint32_t flags_edata = WBFLAG_PAM_AFS_TOKEN |
979 : WBFLAG_PAM_INFO3_TEXT |
980 : WBFLAG_PAM_INFO3_NDR;
981 :
982 675 : if ( ( (flags & flags_edata) == WBFLAG_PAM_AFS_TOKEN) ||
983 675 : ( (flags & flags_edata) == WBFLAG_PAM_INFO3_NDR) ||
984 675 : ( (flags & flags_edata) == WBFLAG_PAM_INFO3_TEXT)||
985 93 : !(flags & flags_edata) ) {
986 675 : 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 1106 : 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 1106 : struct netr_SamInfo3 *info3 = NULL;
1007 1106 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1008 :
1009 1106 : result = map_validation_to_info3(talloc_tos(),
1010 : validation_level,
1011 : validation,
1012 : &info3);
1013 1106 : if (!NT_STATUS_IS_OK(result)) {
1014 0 : goto out;
1015 : }
1016 :
1017 1106 : if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) {
1018 486 : memcpy(resp->data.auth.user_session_key,
1019 486 : info3->base.key.key,
1020 : sizeof(resp->data.auth.user_session_key)
1021 : /* 16 */);
1022 : }
1023 :
1024 1106 : if (request_flags & WBFLAG_PAM_LMKEY) {
1025 466 : memcpy(resp->data.auth.first_8_lm_hash,
1026 466 : info3->base.LMSessKey.key,
1027 : sizeof(resp->data.auth.first_8_lm_hash)
1028 : /* 8 */);
1029 : }
1030 :
1031 1106 : if (request_flags & WBFLAG_PAM_UNIX_NAME) {
1032 170 : char *unix_username = NULL;
1033 170 : result = append_unix_username(validation_level,
1034 : validation,
1035 : name_domain,
1036 : name_user,
1037 : mem_ctx,
1038 : &unix_username);
1039 170 : 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 170 : fstrcpy(resp->data.auth.unix_username, unix_username);
1045 170 : TALLOC_FREE(unix_username);
1046 : }
1047 :
1048 : /* currently, anything from here on potentially overwrites extra_data. */
1049 :
1050 1106 : 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 1106 : if (request_flags & WBFLAG_PAM_INFO3_TEXT) {
1060 1039 : result = append_info3_as_txt(mem_ctx, resp,
1061 : validation_level,
1062 : validation);
1063 1039 : 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 1106 : 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 1106 : result = NT_STATUS_OK;
1088 1106 : out:
1089 1106 : TALLOC_FREE(info3);
1090 1106 : 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 : }
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 : if (NT_STATUS_IS_OK(result)) {
2603 0 : gpupdate_user_init(r->in.info->username);
2604 : }
2605 :
2606 0 : return result;
2607 : }
2608 :
2609 0 : NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
2610 : TALLOC_CTX *mem_ctx,
2611 : bool interactive,
2612 : uint32_t logon_parameters,
2613 : const char *name_user,
2614 : const char *name_domain,
2615 : const char *workstation,
2616 : const uint64_t logon_id,
2617 : const char* client_name,
2618 : const int client_pid,
2619 : DATA_BLOB chal_blob,
2620 : DATA_BLOB lm_response,
2621 : DATA_BLOB nt_response,
2622 : const struct tsocket_address *remote,
2623 : const struct tsocket_address *local,
2624 : uint8_t *authoritative,
2625 : bool skip_sam,
2626 : uint32_t *flags,
2627 : uint16_t *_validation_level,
2628 : union netr_Validation **_validation)
2629 : {
2630 0 : uint16_t validation_level = 0;
2631 0 : union netr_Validation *validation = NULL;
2632 : NTSTATUS result;
2633 :
2634 : /*
2635 : * We check against domain->name instead of
2636 : * name_domain, as find_auth_domain() ->
2637 : * find_domain_from_name_noinit() already decided
2638 : * that we are in a child for the correct domain.
2639 : *
2640 : * name_domain can also be lp_realm()
2641 : * we need to check against domain->name.
2642 : */
2643 0 : if (!skip_sam && strequal(domain->name, get_global_sam_name())) {
2644 0 : struct netr_SamInfo3 *info3 = NULL;
2645 :
2646 0 : result = winbindd_dual_auth_passdb(
2647 : talloc_tos(),
2648 : logon_parameters,
2649 : name_domain, name_user,
2650 : logon_id,
2651 : client_name,
2652 : client_pid,
2653 : &chal_blob, &lm_response, &nt_response,
2654 : remote,
2655 : local,
2656 : interactive,
2657 : authoritative,
2658 : &info3);
2659 0 : if (NT_STATUS_IS_OK(result)) {
2660 0 : result = map_info3_to_validation(mem_ctx,
2661 : info3,
2662 : &validation_level,
2663 : &validation);
2664 0 : TALLOC_FREE(info3);
2665 0 : if (!NT_STATUS_IS_OK(result)) {
2666 0 : goto done;
2667 : }
2668 : }
2669 :
2670 : /*
2671 : * We need to try the remote NETLOGON server if this is
2672 : * not authoritative.
2673 : */
2674 0 : if (*authoritative != 0) {
2675 0 : *flags = 0;
2676 0 : goto process_result;
2677 : }
2678 : }
2679 :
2680 0 : result = winbind_samlogon_retry_loop(domain,
2681 : mem_ctx,
2682 : logon_parameters,
2683 : name_user,
2684 : NULL, /* password */
2685 : name_domain,
2686 : /* Bug #3248 - found by Stefan Burkei. */
2687 : workstation, /* We carefully set this above so use it... */
2688 : logon_id,
2689 : false, /* plaintext_given */
2690 : chal_blob,
2691 : lm_response,
2692 : nt_response,
2693 : interactive,
2694 : authoritative,
2695 : flags,
2696 : &validation_level,
2697 : &validation);
2698 0 : if (!NT_STATUS_IS_OK(result)) {
2699 0 : goto done;
2700 : }
2701 :
2702 0 : process_result:
2703 :
2704 0 : if (NT_STATUS_IS_OK(result)) {
2705 : struct dom_sid user_sid;
2706 0 : TALLOC_CTX *base_ctx = NULL;
2707 0 : struct netr_SamBaseInfo *base_info = NULL;
2708 0 : struct netr_SamInfo3 *info3 = NULL;
2709 :
2710 0 : switch (validation_level) {
2711 0 : case 3:
2712 0 : base_ctx = validation->sam3;
2713 0 : base_info = &validation->sam3->base;
2714 0 : break;
2715 0 : case 6:
2716 0 : base_ctx = validation->sam6;
2717 0 : base_info = &validation->sam6->base;
2718 0 : break;
2719 0 : default:
2720 0 : result = NT_STATUS_INTERNAL_ERROR;
2721 0 : goto done;
2722 : }
2723 :
2724 0 : sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
2725 :
2726 0 : if (base_info->full_name.string == NULL) {
2727 : struct netr_SamInfo3 *cached_info3;
2728 :
2729 0 : cached_info3 = netsamlogon_cache_get(mem_ctx,
2730 : &user_sid);
2731 0 : if (cached_info3 != NULL &&
2732 0 : cached_info3->base.full_name.string != NULL)
2733 : {
2734 0 : base_info->full_name.string = talloc_strdup(
2735 : base_ctx,
2736 : cached_info3->base.full_name.string);
2737 : } else {
2738 :
2739 : /* this might fail so we don't check the return code */
2740 0 : wcache_query_user_fullname(domain,
2741 : base_ctx,
2742 : &user_sid,
2743 : &base_info->full_name.string);
2744 : }
2745 : }
2746 :
2747 0 : result = map_validation_to_info3(talloc_tos(),
2748 : validation_level,
2749 : validation,
2750 : &info3);
2751 0 : if (!NT_STATUS_IS_OK(result)) {
2752 0 : goto done;
2753 : }
2754 0 : wcache_invalidate_samlogon(find_domain_from_name(name_domain),
2755 : &user_sid);
2756 0 : netsamlogon_cache_store(name_user, info3);
2757 0 : TALLOC_FREE(info3);
2758 : }
2759 :
2760 0 : done:
2761 :
2762 : /* give us a more useful (more correct?) error code */
2763 0 : if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
2764 0 : (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
2765 0 : result = NT_STATUS_NO_LOGON_SERVERS;
2766 : }
2767 :
2768 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
2769 : ("NTLM CRAP authentication for user [%s]\\[%s] returned %s\n",
2770 : name_domain,
2771 : name_user,
2772 : nt_errstr(result)));
2773 :
2774 0 : if (!NT_STATUS_IS_OK(result)) {
2775 0 : return result;
2776 : }
2777 :
2778 0 : *_validation_level = validation_level;
2779 0 : *_validation = validation;
2780 0 : return NT_STATUS_OK;
2781 : }
2782 :
2783 0 : NTSTATUS _wbint_PamAuthCrap(struct pipes_struct *p, struct wbint_PamAuthCrap *r)
2784 : {
2785 0 : struct winbindd_domain *domain = wb_child_domain();
2786 : NTSTATUS result;
2787 0 : uint64_t logon_id = 0;
2788 0 : uint8_t authoritative = 1;
2789 0 : uint32_t flags = 0;
2790 0 : uint16_t validation_level = UINT16_MAX;
2791 0 : union netr_Validation *validation = NULL;
2792 0 : const struct timeval start_time = timeval_current();
2793 0 : const struct tsocket_address *remote = NULL;
2794 0 : const struct tsocket_address *local = NULL;
2795 0 : struct netr_SamInfo3 *info3 = NULL;
2796 : pid_t client_pid;
2797 :
2798 0 : if (domain == NULL) {
2799 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
2800 : }
2801 :
2802 : /* Cut client_pid to 32bit */
2803 0 : client_pid = r->in.client_pid;
2804 0 : if ((uint64_t)client_pid != r->in.client_pid) {
2805 0 : DBG_DEBUG("pid out of range\n");
2806 0 : return NT_STATUS_INVALID_PARAMETER;
2807 : }
2808 :
2809 0 : logon_id = generate_random_u64();
2810 0 : remote = dcesrv_connection_get_remote_address(p->dce_call->conn);
2811 0 : local = dcesrv_connection_get_local_address(p->dce_call->conn);
2812 :
2813 0 : DBG_NOTICE("[%"PRIu32"]: pam auth crap domain: %s user: %s\n",
2814 : client_pid, r->in.domain, r->in.user);
2815 :
2816 0 : result = winbind_dual_SamLogon(domain,
2817 : p->mem_ctx,
2818 : false, /* interactive */
2819 : r->in.logon_parameters,
2820 : r->in.user,
2821 : r->in.domain,
2822 : r->in.workstation,
2823 : logon_id,
2824 : r->in.client_name,
2825 : client_pid,
2826 : r->in.chal,
2827 : r->in.lm_resp,
2828 : r->in.nt_resp,
2829 : remote,
2830 : local,
2831 : &authoritative,
2832 : false,
2833 : &flags,
2834 : &validation_level,
2835 : &validation);
2836 0 : if (!NT_STATUS_IS_OK(result)) {
2837 0 : goto done;
2838 : }
2839 :
2840 0 : result = map_validation_to_info3(p->mem_ctx,
2841 : validation_level,
2842 : validation,
2843 : &info3);
2844 0 : if (!NT_STATUS_IS_OK(result)) {
2845 0 : goto done;
2846 : }
2847 :
2848 : /* Check if the user is in the right group */
2849 0 : result = check_info3_in_group(info3, r->in.require_membership_of_sid);
2850 0 : if (!NT_STATUS_IS_OK(result)) {
2851 0 : char *s = NDR_PRINT_STRUCT_STRING(p->mem_ctx,
2852 : wbint_SidArray,
2853 : r->in.require_membership_of_sid);
2854 0 : DBG_NOTICE("User %s is not in the required groups:\n",
2855 : r->in.user);
2856 0 : DEBUGADD(DBGLVL_NOTICE, ("%s", s));
2857 0 : DEBUGADD(DBGLVL_NOTICE,
2858 : ("CRAP authentication is rejected\n"));
2859 0 : goto done;
2860 : }
2861 :
2862 0 : if (!is_allowed_domain(info3->base.logon_domain.string)) {
2863 0 : DBG_NOTICE("Authentication failed for user [%s] "
2864 : "from firewalled domain [%s]\n",
2865 : info3->base.account_name.string,
2866 : info3->base.logon_domain.string);
2867 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
2868 0 : goto done;
2869 : }
2870 :
2871 0 : r->out.validation = talloc_zero(p->mem_ctx,
2872 : struct wbint_PamAuthCrapValidation);
2873 0 : if (r->out.validation == NULL) {
2874 0 : result = NT_STATUS_NO_MEMORY;
2875 0 : goto done;
2876 : }
2877 :
2878 0 : r->out.validation->level = validation_level;
2879 0 : r->out.validation->validation = talloc_move(r->out.validation,
2880 : &validation);
2881 0 : done:
2882 :
2883 0 : if (r->in.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
2884 0 : result = nt_status_squash(result);
2885 : }
2886 :
2887 0 : *r->out.authoritative = authoritative;
2888 :
2889 : /*
2890 : * Log the winbind pam authentication, the logon_id will tie this to
2891 : * any of the logons invoked from this request.
2892 : */
2893 0 : log_authentication(
2894 : p->mem_ctx,
2895 : domain,
2896 : r->in.client_name,
2897 : client_pid,
2898 0 : r->out.validation->level,
2899 0 : r->out.validation->validation,
2900 : start_time,
2901 : logon_id,
2902 : "NTLM_AUTH",
2903 : r->in.user,
2904 : r->in.domain,
2905 : r->in.workstation,
2906 : r->in.lm_resp,
2907 : r->in.nt_resp,
2908 : remote,
2909 : local,
2910 : result);
2911 :
2912 0 : return result;
2913 : }
2914 :
2915 0 : NTSTATUS _wbint_PamAuthChangePassword(struct pipes_struct *p,
2916 : struct wbint_PamAuthChangePassword *r)
2917 : {
2918 0 : struct winbindd_domain *contact_domain = wb_child_domain();
2919 : struct policy_handle dom_pol;
2920 0 : struct rpc_pipe_client *cli = NULL;
2921 0 : bool got_info = false;
2922 0 : struct samr_DomInfo1 *info = NULL;
2923 0 : struct userPwdChangeFailureInformation *reject = NULL;
2924 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2925 0 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2926 : fstring namespace, domain, user;
2927 0 : struct dcerpc_binding_handle *b = NULL;
2928 : bool ok;
2929 : pid_t client_pid;
2930 :
2931 0 : ZERO_STRUCT(dom_pol);
2932 :
2933 0 : if (contact_domain == NULL) {
2934 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
2935 : }
2936 :
2937 : /* Cut client_pid to 32bit */
2938 0 : client_pid = r->in.client_pid;
2939 0 : if ((uint64_t)client_pid != r->in.client_pid) {
2940 0 : DBG_DEBUG("pid out of range\n");
2941 0 : return NT_STATUS_INVALID_PARAMETER;
2942 : }
2943 :
2944 0 : DBG_NOTICE("[%"PRIu32"]: dual pam chauthtok %s\n",
2945 : client_pid, r->in.user);
2946 :
2947 0 : ok = parse_domain_user(r->in.user,
2948 : namespace,
2949 : domain,
2950 : user);
2951 0 : if (!ok) {
2952 0 : goto done;
2953 : }
2954 :
2955 0 : if (!is_allowed_domain(domain)) {
2956 0 : DBG_NOTICE("Authentication failed for user [%s] "
2957 : "from firewalled domain [%s]\n",
2958 : user, domain);
2959 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
2960 0 : goto done;
2961 : }
2962 :
2963 : /* Initialize reject reason */
2964 0 : *r->out.reject_reason = Undefined;
2965 :
2966 : /* Get sam handle */
2967 :
2968 0 : result = cm_connect_sam(contact_domain,
2969 : p->mem_ctx,
2970 : true,
2971 : &cli,
2972 : &dom_pol);
2973 0 : if (!NT_STATUS_IS_OK(result)) {
2974 0 : DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
2975 0 : goto done;
2976 : }
2977 :
2978 0 : b = cli->binding_handle;
2979 :
2980 0 : status = dcerpc_samr_chgpasswd_user4(cli->binding_handle,
2981 : p->mem_ctx,
2982 0 : cli->srv_name_slash,
2983 : user,
2984 : r->in.old_password,
2985 : r->in.new_password,
2986 : &result);
2987 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
2988 : /* Password successfully changed. */
2989 0 : goto done;
2990 : }
2991 0 : if (!NT_STATUS_IS_OK(status)) {
2992 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
2993 0 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
2994 0 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
2995 : /* DO NOT FALLBACK TO RC4 */
2996 0 : if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) {
2997 0 : result = NT_STATUS_STRONG_CRYPTO_NOT_SUPPORTED;
2998 0 : goto process_result;
2999 : }
3000 : }
3001 : } else {
3002 : /* Password change was unsuccessful. */
3003 0 : if (!NT_STATUS_IS_OK(result)) {
3004 0 : goto done;
3005 : }
3006 : }
3007 :
3008 0 : result = rpccli_samr_chgpasswd_user3(cli,
3009 : p->mem_ctx,
3010 : user,
3011 : r->in.new_password,
3012 : r->in.old_password,
3013 : &info,
3014 : &reject);
3015 :
3016 : /* Windows 2003 returns NT_STATUS_PASSWORD_RESTRICTION */
3017 :
3018 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) ) {
3019 :
3020 0 : *r->out.dominfo = talloc_steal(p->mem_ctx, info);
3021 0 : *r->out.reject_reason = reject->extendedFailureReason;
3022 :
3023 0 : got_info = true;
3024 : }
3025 :
3026 : /* atm the pidl generated rpccli_samr_ChangePasswordUser3 function will
3027 : * return with NT_STATUS_BUFFER_TOO_SMALL for w2k dcs as w2k just
3028 : * returns with 4byte error code (NT_STATUS_NOT_SUPPORTED) which is too
3029 : * short to comply with the samr_ChangePasswordUser3 idl - gd */
3030 :
3031 : /* only fallback when the chgpasswd_user3 call is not supported */
3032 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
3033 0 : NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ||
3034 0 : NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) ||
3035 0 : NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
3036 :
3037 0 : DEBUG(10,("Password change with chgpasswd_user3 failed with: %s, retrying chgpasswd_user2\n",
3038 : nt_errstr(result)));
3039 :
3040 0 : result = rpccli_samr_chgpasswd_user2(cli,
3041 : p->mem_ctx,
3042 : user,
3043 : r->in.new_password,
3044 : r->in.old_password);
3045 :
3046 : /* Windows 2000 returns NT_STATUS_ACCOUNT_RESTRICTION.
3047 : Map to the same status code as Windows 2003. */
3048 :
3049 0 : if ( NT_STATUS_EQUAL(NT_STATUS_ACCOUNT_RESTRICTION, result ) ) {
3050 0 : result = NT_STATUS_PASSWORD_RESTRICTION;
3051 : }
3052 : }
3053 :
3054 0 : done:
3055 :
3056 0 : if (NT_STATUS_IS_OK(result)
3057 0 : && (r->in.flags & WBFLAG_PAM_CACHED_LOGIN)
3058 0 : && lp_winbind_offline_logon()) {
3059 0 : result = winbindd_update_creds_by_name(contact_domain, user,
3060 : r->in.new_password);
3061 : /* Again, this happens when we login from gdm or xdm
3062 : * and the password expires, *BUT* cached crendentials
3063 : * doesn't exist. winbindd_update_creds_by_name()
3064 : * returns NT_STATUS_NO_SUCH_USER.
3065 : * This is not a failure.
3066 : * --- BoYang
3067 : * */
3068 0 : if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
3069 0 : result = NT_STATUS_OK;
3070 : }
3071 :
3072 0 : if (!NT_STATUS_IS_OK(result)) {
3073 0 : DEBUG(10, ("Failed to store creds: %s\n",
3074 : nt_errstr(result)));
3075 0 : goto process_result;
3076 : }
3077 : }
3078 :
3079 0 : if (!NT_STATUS_IS_OK(result) && !got_info && contact_domain) {
3080 :
3081 : NTSTATUS policy_ret;
3082 :
3083 0 : policy_ret = get_password_policy(contact_domain,
3084 : p->mem_ctx,
3085 : &info);
3086 :
3087 : /* failure of this is non critical, it will just provide no
3088 : * additional information to the client why the change has
3089 : * failed - Guenther */
3090 :
3091 0 : if (!NT_STATUS_IS_OK(policy_ret)) {
3092 0 : DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
3093 0 : goto process_result;
3094 : }
3095 :
3096 0 : *r->out.dominfo = talloc_steal(p->mem_ctx, info);
3097 : }
3098 :
3099 0 : process_result:
3100 :
3101 0 : if (strequal(contact_domain->name, get_global_sam_name())) {
3102 : /* FIXME: internal rpc pipe does not cache handles yet */
3103 0 : if (b) {
3104 0 : if (is_valid_policy_hnd(&dom_pol)) {
3105 : NTSTATUS _result;
3106 0 : dcerpc_samr_Close(b,
3107 : p->mem_ctx,
3108 : &dom_pol,
3109 : &_result);
3110 : }
3111 0 : TALLOC_FREE(cli);
3112 : }
3113 : }
3114 :
3115 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
3116 : ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
3117 : domain,
3118 : user,
3119 : nt_errstr(result),
3120 : nt_status_to_pam(result)));
3121 :
3122 0 : return result;
3123 : }
3124 :
3125 0 : NTSTATUS _wbint_PamLogOff(struct pipes_struct *p, struct wbint_PamLogOff *r)
3126 : {
3127 0 : struct winbindd_domain *domain = wb_child_domain();
3128 0 : NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
3129 : pid_t client_pid;
3130 : uid_t user_uid;
3131 :
3132 0 : if (domain == NULL) {
3133 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
3134 : }
3135 :
3136 : /* Cut client_pid to 32bit */
3137 0 : client_pid = r->in.client_pid;
3138 0 : if ((uint64_t)client_pid != r->in.client_pid) {
3139 0 : DBG_DEBUG("pid out of range\n");
3140 0 : return NT_STATUS_INVALID_PARAMETER;
3141 : }
3142 :
3143 : /* Cut uid to 32bit */
3144 0 : user_uid = r->in.uid;
3145 0 : if ((uint64_t)user_uid != r->in.uid) {
3146 0 : DBG_DEBUG("uid out of range\n");
3147 0 : return NT_STATUS_INVALID_PARAMETER;
3148 : }
3149 :
3150 0 : DBG_NOTICE("[%"PRIu32"]: pam dual logoff %s\n", client_pid, r->in.user);
3151 :
3152 0 : if (!(r->in.flags & WBFLAG_PAM_KRB5)) {
3153 0 : result = NT_STATUS_OK;
3154 0 : goto process_result;
3155 : }
3156 :
3157 0 : if ((r->in.krb5ccname == NULL) || (strlen(r->in.krb5ccname) == 0)) {
3158 0 : result = NT_STATUS_OK;
3159 0 : goto process_result;
3160 : }
3161 :
3162 : #ifdef HAVE_KRB5
3163 :
3164 0 : if (user_uid == (uid_t)-1) {
3165 0 : DBG_DEBUG("Invalid uid for user '%s'\n", r->in.user);
3166 0 : goto process_result;
3167 : }
3168 :
3169 : /* what we need here is to find the corresponding krb5 ccache name *we*
3170 : * created for a given username and destroy it */
3171 :
3172 0 : if (!ccache_entry_exists(r->in.user)) {
3173 0 : result = NT_STATUS_OK;
3174 0 : DBG_DEBUG("No entry found for user '%s'.\n", r->in.user);
3175 0 : goto process_result;
3176 : }
3177 :
3178 0 : if (!ccache_entry_identical(r->in.user, user_uid, r->in.krb5ccname)) {
3179 0 : DBG_DEBUG("Cached entry differs for user '%s'\n", r->in.user);
3180 0 : goto process_result;
3181 : }
3182 :
3183 0 : result = remove_ccache(r->in.user);
3184 0 : if (!NT_STATUS_IS_OK(result)) {
3185 0 : DBG_DEBUG("Failed to remove ccache for user '%s': %s\n",
3186 : r->in.user, nt_errstr(result));
3187 0 : goto process_result;
3188 : }
3189 :
3190 : /*
3191 : * Remove any mlock'ed memory creds in the child
3192 : * we might be using for krb5 ticket renewal.
3193 : */
3194 :
3195 0 : winbindd_delete_memory_creds(r->in.user);
3196 :
3197 : #else
3198 : result = NT_STATUS_NOT_SUPPORTED;
3199 : #endif
3200 :
3201 0 : process_result:
3202 :
3203 0 : return result;
3204 : }
3205 :
3206 : /* Change user password with auth crap*/
3207 :
3208 0 : NTSTATUS _wbint_PamAuthCrapChangePassword(struct pipes_struct *p,
3209 : struct wbint_PamAuthCrapChangePassword *r)
3210 : {
3211 : NTSTATUS result;
3212 : fstring namespace, domain, user;
3213 : struct policy_handle dom_pol;
3214 0 : struct winbindd_domain *contact_domain = wb_child_domain();
3215 0 : struct rpc_pipe_client *cli = NULL;
3216 0 : struct dcerpc_binding_handle *b = NULL;
3217 : pid_t client_pid;
3218 :
3219 0 : ZERO_STRUCT(dom_pol);
3220 :
3221 0 : if (contact_domain == NULL) {
3222 0 : return NT_STATUS_REQUEST_NOT_ACCEPTED;
3223 : }
3224 :
3225 : /* Cut client_pid to 32bit */
3226 0 : client_pid = r->in.client_pid;
3227 0 : if ((uint64_t)client_pid != r->in.client_pid) {
3228 0 : DBG_DEBUG("pid out of range\n");
3229 0 : return NT_STATUS_INVALID_PARAMETER;
3230 : }
3231 :
3232 0 : domain[0] = '\0';
3233 0 : namespace[0] = '\0';
3234 0 : user[0] = '\0';
3235 :
3236 0 : DBG_NOTICE("[%"PRIu32"]: pam change pswd auth crap domain: %s "
3237 : "user: %s\n", client_pid, r->in.domain, r->in.user);
3238 :
3239 0 : if (lp_winbind_offline_logon()) {
3240 0 : DEBUG(0,("Refusing password change as winbind offline logons are enabled. "));
3241 0 : DEBUGADD(0,("Changing passwords here would risk inconsistent logons\n"));
3242 0 : result = NT_STATUS_ACCESS_DENIED;
3243 0 : goto done;
3244 : }
3245 :
3246 0 : if (r->in.domain != NULL && strlen(r->in.domain) > 0) {
3247 0 : fstrcpy(domain, r->in.domain);
3248 : } else {
3249 : bool ok;
3250 :
3251 0 : ok = parse_domain_user(r->in.user,
3252 : namespace,
3253 : domain,
3254 : user);
3255 0 : if (!ok) {
3256 0 : result = NT_STATUS_INVALID_PARAMETER;
3257 0 : goto done;
3258 : }
3259 :
3260 0 : if (strlen(domain) == 0) {
3261 0 : DBG_NOTICE("no domain specified with username (%s) - "
3262 : "failing auth\n", r->in.user);
3263 0 : result = NT_STATUS_NO_SUCH_USER;
3264 0 : goto done;
3265 : }
3266 : }
3267 :
3268 0 : if (!*domain && lp_winbind_use_default_domain()) {
3269 0 : fstrcpy(domain,lp_workgroup());
3270 : }
3271 :
3272 0 : if (!is_allowed_domain(domain)) {
3273 0 : DBG_NOTICE("Authentication failed for user [%s] "
3274 : "from firewalled domain [%s]\n",
3275 : r->in.user,
3276 : domain);
3277 0 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
3278 0 : goto done;
3279 : }
3280 :
3281 0 : if(!*user) {
3282 0 : fstrcpy(user, r->in.user);
3283 : }
3284 :
3285 : /* Get sam handle */
3286 :
3287 0 : result = cm_connect_sam(contact_domain,
3288 : p->mem_ctx,
3289 : true,
3290 : &cli,
3291 : &dom_pol);
3292 0 : if (!NT_STATUS_IS_OK(result)) {
3293 0 : DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
3294 0 : goto done;
3295 : }
3296 :
3297 0 : b = cli->binding_handle;
3298 :
3299 0 : result = rpccli_samr_chng_pswd_auth_crap(cli,
3300 : p->mem_ctx,
3301 : user,
3302 : r->in.new_nt_pswd,
3303 : r->in.old_nt_hash_enc,
3304 : r->in.new_lm_pswd,
3305 : r->in.old_lm_hash_enc);
3306 :
3307 0 : done:
3308 :
3309 0 : if (strequal(contact_domain->name, get_global_sam_name())) {
3310 : /* FIXME: internal rpc pipe does not cache handles yet */
3311 0 : if (b) {
3312 0 : if (is_valid_policy_hnd(&dom_pol)) {
3313 : NTSTATUS _result;
3314 0 : dcerpc_samr_Close(b,
3315 : p->mem_ctx,
3316 : &dom_pol,
3317 : &_result);
3318 : }
3319 0 : TALLOC_FREE(cli);
3320 : }
3321 : }
3322 :
3323 0 : DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
3324 : ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
3325 : domain, user,
3326 : nt_errstr(result),
3327 : nt_status_to_pam(result)));
3328 :
3329 0 : return result;
3330 : }
3331 :
3332 : #ifdef HAVE_KRB5
3333 617 : static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
3334 : struct PAC_DATA **p_pac_data)
3335 : {
3336 617 : krb5_context krbctx = NULL;
3337 : krb5_error_code k5ret;
3338 : krb5_keytab keytab;
3339 : krb5_kt_cursor cursor;
3340 : krb5_keytab_entry entry;
3341 617 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
3342 :
3343 617 : ZERO_STRUCT(entry);
3344 617 : ZERO_STRUCT(cursor);
3345 :
3346 617 : k5ret = smb_krb5_init_context_common(&krbctx);
3347 617 : if (k5ret) {
3348 0 : DBG_ERR("kerberos init context failed (%s)\n",
3349 : error_message(k5ret));
3350 0 : status = krb5_to_nt_status(k5ret);
3351 0 : goto out;
3352 : }
3353 :
3354 617 : k5ret = gse_krb5_get_server_keytab(krbctx, &keytab);
3355 617 : if (k5ret) {
3356 0 : DEBUG(1, ("Failed to get keytab: %s\n",
3357 : error_message(k5ret)));
3358 0 : status = krb5_to_nt_status(k5ret);
3359 0 : goto out_free;
3360 : }
3361 :
3362 617 : k5ret = krb5_kt_start_seq_get(krbctx, keytab, &cursor);
3363 617 : if (k5ret) {
3364 0 : DEBUG(1, ("Failed to start seq: %s\n",
3365 : error_message(k5ret)));
3366 0 : status = krb5_to_nt_status(k5ret);
3367 0 : goto out_keytab;
3368 : }
3369 :
3370 617 : k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
3371 2206 : while (k5ret == 0) {
3372 2206 : status = kerberos_decode_pac(mem_ctx,
3373 : pac_blob,
3374 : krbctx,
3375 : NULL, /* krbtgt_keyblock */
3376 : KRB5_KT_KEY(&entry), /* service_keyblock */
3377 : NULL, /* client_principal */
3378 : 0, /* tgs_authtime */
3379 : p_pac_data);
3380 2206 : if (NT_STATUS_IS_OK(status)) {
3381 617 : break;
3382 : }
3383 1589 : k5ret = smb_krb5_kt_free_entry(krbctx, &entry);
3384 1589 : k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
3385 : }
3386 :
3387 617 : k5ret = krb5_kt_end_seq_get(krbctx, keytab, &cursor);
3388 617 : if (k5ret) {
3389 0 : DEBUG(1, ("Failed to end seq: %s\n",
3390 : error_message(k5ret)));
3391 : }
3392 617 : out_keytab:
3393 617 : k5ret = krb5_kt_close(krbctx, keytab);
3394 617 : if (k5ret) {
3395 0 : DEBUG(1, ("Failed to close keytab: %s\n",
3396 : error_message(k5ret)));
3397 : }
3398 617 : out_free:
3399 617 : krb5_free_context(krbctx);
3400 617 : out:
3401 617 : return status;
3402 : }
3403 :
3404 617 : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
3405 : TALLOC_CTX *mem_ctx,
3406 : bool *p_is_trusted,
3407 : uint16_t *p_validation_level,
3408 : union netr_Validation **p_validation)
3409 : {
3410 617 : struct winbindd_request *req = state->request;
3411 : DATA_BLOB pac_blob;
3412 617 : struct PAC_DATA *pac_data = NULL;
3413 617 : struct PAC_LOGON_INFO *logon_info = NULL;
3414 617 : struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
3415 617 : struct netr_SamInfo6 *info6 = NULL;
3416 617 : uint16_t validation_level = 0;
3417 617 : union netr_Validation *validation = NULL;
3418 617 : struct netr_SamInfo3 *info3_copy = NULL;
3419 : NTSTATUS result;
3420 617 : bool is_trusted = false;
3421 : uint32_t i;
3422 617 : TALLOC_CTX *tmp_ctx = NULL;
3423 :
3424 617 : tmp_ctx = talloc_new(mem_ctx);
3425 617 : if (tmp_ctx == NULL) {
3426 0 : return NT_STATUS_NO_MEMORY;
3427 : }
3428 :
3429 617 : *p_is_trusted = false;
3430 617 : *p_validation_level = 0;
3431 617 : *p_validation = NULL;
3432 :
3433 617 : pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
3434 617 : result = extract_pac_vrfy_sigs(tmp_ctx, pac_blob, &pac_data);
3435 617 : if (NT_STATUS_IS_OK(result)) {
3436 617 : is_trusted = true;
3437 : }
3438 617 : if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
3439 : /* Try without signature verification */
3440 0 : result = kerberos_decode_pac(tmp_ctx,
3441 : pac_blob,
3442 : NULL, /* krb5_context */
3443 : NULL, /* krbtgt_keyblock */
3444 : NULL, /* service_keyblock */
3445 : NULL, /* client_principal */
3446 : 0, /* tgs_authtime */
3447 : &pac_data);
3448 : }
3449 617 : if (!NT_STATUS_IS_OK(result)) {
3450 0 : DEBUG(1, ("Error during PAC signature verification: %s\n",
3451 : nt_errstr(result)));
3452 0 : goto out;
3453 : }
3454 :
3455 4153 : for (i=0; i < pac_data->num_buffers; i++) {
3456 3536 : if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
3457 617 : logon_info = pac_data->buffers[i].info->logon_info.info;
3458 617 : continue;
3459 : }
3460 2919 : if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
3461 534 : upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
3462 534 : continue;
3463 : }
3464 : }
3465 :
3466 617 : result = create_info6_from_pac(tmp_ctx,
3467 : logon_info,
3468 : upn_dns_info,
3469 : &info6);
3470 617 : if (!NT_STATUS_IS_OK(result)) {
3471 0 : goto out;
3472 : }
3473 :
3474 617 : if (!is_allowed_domain(info6->base.logon_domain.string)) {
3475 2 : DBG_NOTICE("Authentication failed for user [%s] "
3476 : "from firewalled domain [%s]\n",
3477 : info6->base.account_name.string,
3478 : info6->base.logon_domain.string);
3479 2 : result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
3480 2 : goto out;
3481 : }
3482 :
3483 615 : result = map_info6_to_validation(tmp_ctx,
3484 : info6,
3485 : &validation_level,
3486 : &validation);
3487 615 : if (!NT_STATUS_IS_OK(result)) {
3488 0 : goto out;
3489 : }
3490 :
3491 615 : result = map_validation_to_info3(tmp_ctx,
3492 : validation_level,
3493 : validation,
3494 : &info3_copy);
3495 615 : if (!NT_STATUS_IS_OK(result)) {
3496 0 : goto out;
3497 : }
3498 :
3499 615 : if (is_trusted) {
3500 : /*
3501 : * Signature verification succeeded, we can
3502 : * trust the PAC and prime the netsamlogon
3503 : * and name2sid caches. DO NOT DO THIS
3504 : * in the signature verification failed
3505 : * code path.
3506 : */
3507 615 : struct winbindd_domain *domain = NULL;
3508 :
3509 615 : netsamlogon_cache_store(NULL, info3_copy);
3510 :
3511 : /*
3512 : * We're in the parent here, so find the child
3513 : * pointer from the PAC domain name.
3514 : */
3515 615 : domain = find_lookup_domain_from_name(
3516 615 : info3_copy->base.logon_domain.string);
3517 615 : if (domain && domain->primary ) {
3518 : struct dom_sid user_sid;
3519 : struct dom_sid_buf buf;
3520 :
3521 615 : sid_compose(&user_sid,
3522 615 : info3_copy->base.domain_sid,
3523 615 : info3_copy->base.rid);
3524 :
3525 615 : cache_name2sid_trusted(domain,
3526 615 : info3_copy->base.logon_domain.string,
3527 615 : info3_copy->base.account_name.string,
3528 : SID_NAME_USER,
3529 : &user_sid);
3530 :
3531 615 : DBG_INFO("PAC for user %s\\%s SID %s primed cache\n",
3532 : info3_copy->base.logon_domain.string,
3533 : info3_copy->base.account_name.string,
3534 : dom_sid_str_buf(&user_sid, &buf));
3535 : }
3536 : }
3537 :
3538 615 : *p_is_trusted = is_trusted;
3539 615 : *p_validation_level = validation_level;
3540 615 : *p_validation = talloc_move(mem_ctx, &validation);
3541 :
3542 615 : result = NT_STATUS_OK;
3543 617 : out:
3544 617 : TALLOC_FREE(tmp_ctx);
3545 617 : return result;
3546 : }
3547 : #else /* HAVE_KRB5 */
3548 : NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
3549 : TALLOC_CTX *mem_ctx,
3550 : bool *p_is_trusted,
3551 : uint16_t *p_validation_level,
3552 : union netr_Validation **p_validation);
3553 : {
3554 :
3555 : *p_is_trusted = false;
3556 : *p_validation_level = 0;
3557 : *p_validation = NULL;
3558 : return NT_STATUS_NO_SUCH_USER;
3559 : }
3560 : #endif /* HAVE_KRB5 */
|