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