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