Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Convert a server info struct into the form for PAC and NETLOGON replies
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2011
7 : Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "librpc/gen_ndr/auth.h"
25 : #include "libcli/security/security.h"
26 : #include "auth/auth_sam_reply.h"
27 :
28 : /* Returns true if this SID belongs in SamBaseInfo, otherwise false. */
29 1197074 : static bool is_base_sid(const struct auth_SidAttr *sid,
30 : const struct dom_sid *domain_sid)
31 : {
32 1197074 : if (sid->attrs & SE_GROUP_RESOURCE) {
33 : /*
34 : * Resource groups don't belong in the base
35 : * RIDs, they're handled elsewhere.
36 : */
37 140144 : return false;
38 : }
39 :
40 : /*
41 : * This SID belongs in the base structure only if it's in the account's
42 : * domain.
43 : */
44 1049204 : return dom_sid_in_domain(domain_sid, &sid->sid);
45 : }
46 :
47 : /* Stores a SID in a previously allocated array. */
48 174679 : static NTSTATUS store_extra_sid(struct netr_SidAttr *sids,
49 : uint32_t *sidcount,
50 : const uint32_t allocated_sids,
51 : const struct auth_SidAttr *sid)
52 : {
53 : /* Check we aren't about to overflow our allocation. */
54 174679 : if (*sidcount >= allocated_sids) {
55 0 : return NT_STATUS_INVALID_PARAMETER;
56 : }
57 :
58 174679 : sids[*sidcount].sid = dom_sid_dup(sids, &sid->sid);
59 174679 : if (sids[*sidcount].sid == NULL) {
60 0 : return NT_STATUS_NO_MEMORY;
61 : }
62 174679 : sids[*sidcount].attributes = sid->attrs;
63 174679 : *sidcount += 1;
64 :
65 174679 : return NT_STATUS_OK;
66 : }
67 :
68 : /*
69 : * Stores a resource SID in a previously allocated array, either Extra SIDs or
70 : * Resource SIDs. Any SID within the domain of the first SID so added is stored
71 : * there, while remaining SIDs are stored in Extra SIDs.
72 : */
73 16526 : static NTSTATUS store_resource_sid(struct netr_SidAttr *sids,
74 : uint32_t *sidcount,
75 : const uint32_t allocated_sids,
76 : const struct auth_SidAttr *sid,
77 : struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups,
78 : const uint32_t allocated_resource_groups)
79 : {
80 581 : NTSTATUS status;
81 :
82 16526 : struct dom_sid *resource_domain = NULL;
83 581 : uint32_t rid;
84 :
85 16526 : if (resource_groups == NULL) {
86 0 : return NT_STATUS_INVALID_PARAMETER;
87 : }
88 :
89 : /* Split the SID into domain and RID. */
90 16526 : status = dom_sid_split_rid(resource_groups, &sid->sid, &resource_domain, &rid);
91 16526 : if (!NT_STATUS_IS_OK(status)) {
92 0 : return status;
93 : }
94 :
95 16526 : if (resource_groups->domain_sid == NULL) {
96 : /*
97 : * There is no domain SID set. Set it to the domain of this SID.
98 : */
99 16506 : resource_groups->domain_sid = resource_domain;
100 : } else {
101 : /*
102 : * A domain SID has already been set. Check whether this SID's
103 : * domain matches.
104 : *
105 : * Assuming that resource SIDs have been obtained with
106 : * dsdb_expand_nested_groups(), they should all be within the
107 : * same domain (ours), so unless something has gone horribly
108 : * wrong, we should always find that they match.
109 : */
110 20 : bool match = dom_sid_equal(resource_groups->domain_sid, resource_domain);
111 20 : talloc_free(resource_domain);
112 20 : if (!match) {
113 : /*
114 : * It doesn't match, so we can't store this SID here. It
115 : * will have to go in Extra SIDs.
116 : */
117 0 : return store_extra_sid(sids, sidcount, allocated_sids, sid);
118 : }
119 : }
120 :
121 : /* Store the SID in Resource SIDs. */
122 :
123 : /* Check we aren't about to overflow our allocation. */
124 16526 : if (resource_groups->groups.count >= allocated_resource_groups) {
125 0 : return NT_STATUS_INVALID_PARAMETER;
126 : }
127 :
128 16526 : resource_groups->groups.rids[resource_groups->groups.count].rid = rid;
129 16526 : resource_groups->groups.rids[resource_groups->groups.count].attributes = sid->attrs;
130 16526 : resource_groups->groups.count++;
131 :
132 16526 : return NT_STATUS_OK;
133 : }
134 :
135 : /*
136 : * Stores a SID in a previously allocated array, or excludes it if we are not
137 : * storing resource groups. It will be placed in either Extra SIDs or Resource
138 : * SIDs, depending on which is appropriate.
139 : */
140 239854 : static NTSTATUS store_sid(struct netr_SidAttr *sids,
141 : uint32_t *sidcount,
142 : const uint32_t allocated_sids,
143 : const struct auth_SidAttr *sid,
144 : struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups,
145 : const uint32_t allocated_resource_groups,
146 : const enum auth_group_inclusion group_inclusion)
147 : {
148 : /* See if it's a resource SID. */
149 239854 : if (sid->attrs & SE_GROUP_RESOURCE) {
150 : /*
151 : * If this is the SID of a resource group, determine whether it
152 : * should be included or filtered out.
153 : */
154 73935 : switch (group_inclusion) {
155 7486 : case AUTH_INCLUDE_RESOURCE_GROUPS:
156 : /* Include this SID in Extra SIDs. */
157 7486 : break;
158 16526 : case AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED:
159 : /*
160 : * Try to include this SID in Resource Groups. If this
161 : * can't be arranged, we shall fall back to Extra
162 : * SIDs.
163 : */
164 63167 : return store_resource_sid(sids,
165 : sidcount,
166 : allocated_sids,
167 : sid,
168 : resource_groups,
169 : allocated_resource_groups);
170 48649 : case AUTH_EXCLUDE_RESOURCE_GROUPS:
171 : /* Ignore this SID. */
172 48649 : return NT_STATUS_OK;
173 0 : default:
174 : /* This means we have a bug. */
175 0 : DBG_ERR("invalid group inclusion parameter: %u\n", group_inclusion);
176 0 : return NT_STATUS_INVALID_PARAMETER;
177 : }
178 : }
179 :
180 : /* Just store the SID in Extra SIDs. */
181 174679 : return store_extra_sid(sids,
182 : sidcount,
183 : allocated_sids,
184 : sid);
185 : }
186 :
187 90646 : static NTSTATUS auth_convert_user_info_dc_sambaseinfo(TALLOC_CTX *mem_ctx,
188 : const struct auth_user_info_dc *user_info_dc,
189 : struct netr_SamBaseInfo *sam)
190 : {
191 4104 : NTSTATUS status;
192 4104 : const struct auth_user_info *info;
193 :
194 90646 : ZERO_STRUCTP(sam);
195 :
196 90646 : if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX) {
197 90646 : status = dom_sid_split_rid(sam, &user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid,
198 : &sam->domain_sid, &sam->rid);
199 90646 : if (!NT_STATUS_IS_OK(status)) {
200 0 : return status;
201 : }
202 : } else {
203 0 : return NT_STATUS_INVALID_PARAMETER;
204 : }
205 :
206 90646 : if (user_info_dc->num_sids > PRIMARY_GROUP_SID_INDEX) {
207 90645 : status = dom_sid_split_rid(NULL, &user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid,
208 : NULL, &sam->primary_gid);
209 90645 : if (!NT_STATUS_IS_OK(status)) {
210 0 : return status;
211 : }
212 : } else {
213 : /* if we have to encode something like SYSTEM (with no
214 : * second SID in the token) then this is the only
215 : * choice */
216 1 : sam->primary_gid = sam->rid;
217 : }
218 :
219 90646 : info = user_info_dc->info;
220 :
221 90646 : sam->logon_time = info->last_logon;
222 90646 : sam->logoff_time = info->last_logoff;
223 90646 : sam->kickoff_time = info->acct_expiry;
224 90646 : sam->last_password_change = info->last_password_change;
225 90646 : sam->allow_password_change = info->allow_password_change;
226 90646 : sam->force_password_change = info->force_password_change;
227 :
228 : #define _COPY_STRING_TALLOC(src_name, dst_name) do { \
229 : if (info->src_name != NULL) {\
230 : sam->dst_name.string = talloc_strdup(mem_ctx, info->src_name); \
231 : if (sam->dst_name.string == NULL) { \
232 : return NT_STATUS_NO_MEMORY; \
233 : } \
234 : } \
235 : } while(0)
236 90646 : _COPY_STRING_TALLOC(account_name, account_name);
237 90646 : _COPY_STRING_TALLOC(full_name, full_name);
238 90646 : _COPY_STRING_TALLOC(logon_script, logon_script);
239 90646 : _COPY_STRING_TALLOC(profile_path, profile_path);
240 90646 : _COPY_STRING_TALLOC(home_directory, home_directory);
241 90646 : _COPY_STRING_TALLOC(home_drive, home_drive);
242 90646 : _COPY_STRING_TALLOC(logon_server, logon_server);
243 90646 : _COPY_STRING_TALLOC(domain_name, logon_domain);
244 : #undef _COPY_STRING_TALLOC
245 :
246 90646 : sam->logon_count = info->logon_count;
247 90646 : sam->bad_password_count = info->bad_password_count;
248 90646 : sam->groups.count = 0;
249 90646 : sam->groups.rids = NULL;
250 :
251 90646 : if (user_info_dc->num_sids > REMAINING_SIDS_INDEX) {
252 4103 : size_t i;
253 90645 : sam->groups.rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
254 : user_info_dc->num_sids);
255 :
256 90645 : if (sam->groups.rids == NULL)
257 0 : return NT_STATUS_NO_MEMORY;
258 :
259 689182 : for (i=REMAINING_SIDS_INDEX; i<user_info_dc->num_sids; i++) {
260 598537 : struct auth_SidAttr *group_sid = &user_info_dc->sids[i];
261 :
262 598537 : bool belongs_in_base = is_base_sid(group_sid, sam->domain_sid);
263 594674 : if (!belongs_in_base) {
264 : /* We handle this elsewhere */
265 239854 : continue;
266 : }
267 358683 : sam->groups.rids[sam->groups.count].rid =
268 358683 : group_sid->sid.sub_auths[group_sid->sid.num_auths-1];
269 :
270 358683 : sam->groups.rids[sam->groups.count].attributes = group_sid->attrs;
271 358683 : sam->groups.count += 1;
272 : }
273 :
274 90645 : if (sam->groups.count == 0) {
275 0 : TALLOC_FREE(sam->groups.rids);
276 : }
277 : }
278 :
279 90646 : sam->user_flags = info->user_flags; /* w2k3 uses NETLOGON_EXTRA_SIDS | NETLOGON_NTLMV2_ENABLED */
280 90646 : sam->acct_flags = user_info_dc->info->acct_flags;
281 90646 : sam->sub_auth_status = 0;
282 90646 : sam->last_successful_logon = 0;
283 90646 : sam->last_failed_logon = 0;
284 90646 : sam->failed_logon_count = 0;
285 90646 : sam->reserved = 0;
286 :
287 90646 : ZERO_STRUCT(sam->key);
288 90646 : if (user_info_dc->user_session_key.length == sizeof(sam->key.key)) {
289 9957 : memcpy(sam->key.key, user_info_dc->user_session_key.data, sizeof(sam->key.key));
290 : }
291 :
292 90646 : ZERO_STRUCT(sam->LMSessKey);
293 90646 : if (user_info_dc->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
294 8682 : memcpy(sam->LMSessKey.key, user_info_dc->lm_session_key.data,
295 : sizeof(sam->LMSessKey.key));
296 : }
297 :
298 90646 : return NT_STATUS_OK;
299 : }
300 :
301 : /* Note that the validity of the _sam6 and resource_groups structures is only as
302 : * long as the user_info_dc it was generated from */
303 90646 : NTSTATUS auth_convert_user_info_dc_saminfo6(TALLOC_CTX *mem_ctx,
304 : const struct auth_user_info_dc *user_info_dc,
305 : enum auth_group_inclusion group_inclusion,
306 : struct netr_SamInfo6 **_sam6,
307 : struct PAC_DOMAIN_GROUP_MEMBERSHIP **_resource_groups)
308 : {
309 4104 : NTSTATUS status;
310 90646 : struct netr_SamInfo6 *sam6 = NULL;
311 90646 : struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups = NULL;
312 4104 : size_t i;
313 :
314 90646 : const uint32_t allocated_sids = user_info_dc->num_sids;
315 90646 : uint32_t allocated_resource_groups = 0;
316 :
317 90646 : sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
318 90646 : if (sam6 == NULL) {
319 0 : return NT_STATUS_NO_MEMORY;
320 : }
321 :
322 90646 : if (_resource_groups == NULL) {
323 11041 : if (group_inclusion == AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED) {
324 0 : DBG_ERR("_resource_groups parameter not provided to receive resource groups!\n");
325 0 : TALLOC_FREE(sam6);
326 0 : return NT_STATUS_INVALID_PARAMETER;
327 : }
328 79605 : } else if (group_inclusion == AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED) {
329 23794 : *_resource_groups = NULL;
330 :
331 : /* Allocate resource groups structure. */
332 23794 : resource_groups = talloc_zero(mem_ctx, struct PAC_DOMAIN_GROUP_MEMBERSHIP);
333 23794 : if (resource_groups == NULL) {
334 0 : TALLOC_FREE(sam6);
335 0 : return NT_STATUS_NO_MEMORY;
336 : }
337 :
338 : /*
339 : * Allocate enough space to store user_info_dc->num_sids
340 : * RIDs in the worst case.
341 : */
342 23794 : allocated_resource_groups = user_info_dc->num_sids;
343 23794 : resource_groups->groups.rids = talloc_zero_array(resource_groups,
344 : struct samr_RidWithAttribute,
345 : allocated_resource_groups);
346 23794 : if (resource_groups->groups.rids == NULL) {
347 0 : TALLOC_FREE(sam6);
348 0 : TALLOC_FREE(resource_groups);
349 0 : return NT_STATUS_NO_MEMORY;
350 : }
351 : } else {
352 : /* No resource groups will be provided. */
353 55811 : *_resource_groups = NULL;
354 : }
355 :
356 90646 : status = auth_convert_user_info_dc_sambaseinfo(sam6,
357 : user_info_dc,
358 : &sam6->base);
359 90646 : if (!NT_STATUS_IS_OK(status)) {
360 0 : TALLOC_FREE(sam6);
361 0 : TALLOC_FREE(resource_groups);
362 0 : return status;
363 : }
364 :
365 : /*
366 : * Allocate enough space to store user_info_dc->num_sids SIDs in the
367 : * worst case.
368 : */
369 90646 : sam6->sids = talloc_zero_array(sam6, struct netr_SidAttr,
370 : allocated_sids);
371 90646 : if (sam6->sids == NULL) {
372 0 : TALLOC_FREE(sam6);
373 0 : TALLOC_FREE(resource_groups);
374 0 : return NT_STATUS_NO_MEMORY;
375 : }
376 :
377 : /* We don't put the user and group SIDs in there */
378 689183 : for (i=REMAINING_SIDS_INDEX; i<user_info_dc->num_sids; i++) {
379 598537 : struct auth_SidAttr *group_sid = &user_info_dc->sids[i];
380 598537 : bool belongs_in_base = is_base_sid(group_sid, sam6->base.domain_sid);
381 594674 : if (belongs_in_base) {
382 : /* We already handled this in the base. */
383 358683 : continue;
384 : }
385 :
386 239854 : status = store_sid(sam6->sids,
387 : &sam6->sidcount,
388 : allocated_sids,
389 : group_sid,
390 : resource_groups,
391 : allocated_resource_groups,
392 : group_inclusion);
393 239854 : if (!NT_STATUS_IS_OK(status)) {
394 0 : TALLOC_FREE(sam6);
395 0 : TALLOC_FREE(resource_groups);
396 0 : return status;
397 : }
398 : }
399 90646 : if (sam6->sidcount) {
400 88330 : sam6->base.user_flags |= NETLOGON_EXTRA_SIDS;
401 : } else {
402 2316 : sam6->base.user_flags &= ~NETLOGON_EXTRA_SIDS;
403 2316 : TALLOC_FREE(sam6->sids);
404 : }
405 :
406 90646 : if (user_info_dc->info->dns_domain_name != NULL) {
407 177186 : sam6->dns_domainname.string = talloc_strdup(sam6,
408 86542 : user_info_dc->info->dns_domain_name);
409 90644 : if (sam6->dns_domainname.string == NULL) {
410 0 : TALLOC_FREE(sam6);
411 0 : TALLOC_FREE(resource_groups);
412 0 : return NT_STATUS_NO_MEMORY;
413 : }
414 : }
415 :
416 90646 : if (user_info_dc->info->user_principal_name != NULL) {
417 177186 : sam6->principal_name.string = talloc_strdup(sam6,
418 86542 : user_info_dc->info->user_principal_name);
419 90644 : if (sam6->principal_name.string == NULL) {
420 0 : TALLOC_FREE(sam6);
421 0 : TALLOC_FREE(resource_groups);
422 0 : return NT_STATUS_NO_MEMORY;
423 : }
424 : }
425 :
426 90646 : *_sam6 = sam6;
427 90646 : if (resource_groups != NULL) {
428 23794 : if (resource_groups->groups.count > 0) {
429 16506 : *_resource_groups = resource_groups;
430 : } else {
431 7288 : TALLOC_FREE(resource_groups);
432 : }
433 : }
434 90646 : return NT_STATUS_OK;
435 : }
436 :
437 : /* Note that the validity of the _sam2 structure is only as long as
438 : * the user_info_dc it was generated from */
439 4254 : NTSTATUS auth_convert_user_info_dc_saminfo2(TALLOC_CTX *mem_ctx,
440 : const struct auth_user_info_dc *user_info_dc,
441 : enum auth_group_inclusion group_inclusion,
442 : struct netr_SamInfo2 **_sam2)
443 : {
444 601 : NTSTATUS status;
445 4254 : struct netr_SamInfo6 *sam6 = NULL;
446 4254 : struct netr_SamInfo2 *sam2 = NULL;
447 :
448 4254 : sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
449 4254 : if (sam2 == NULL) {
450 0 : return NT_STATUS_NO_MEMORY;
451 : }
452 :
453 4254 : status = auth_convert_user_info_dc_saminfo6(sam2, user_info_dc,
454 : group_inclusion, &sam6,
455 : NULL);
456 4254 : if (!NT_STATUS_IS_OK(status)) {
457 0 : TALLOC_FREE(sam2);
458 0 : return status;
459 : }
460 4254 : sam2->base = sam6->base;
461 : /*
462 : * We have nowhere to put sam6->sids, so we follow Windows here and drop
463 : * it. Any resource groups it happened to contain are lost.
464 : */
465 4254 : sam2->base.user_flags &= ~NETLOGON_EXTRA_SIDS;
466 4254 : TALLOC_FREE(sam6->sids);
467 :
468 4254 : *_sam2 = sam2;
469 4254 : return NT_STATUS_OK;
470 : }
471 :
472 : /* Note that the validity of the _sam3 structure is only as long as
473 : * the user_info_dc it was generated from */
474 83977 : NTSTATUS auth_convert_user_info_dc_saminfo3(TALLOC_CTX *mem_ctx,
475 : const struct auth_user_info_dc *user_info_dc,
476 : enum auth_group_inclusion group_inclusion,
477 : struct netr_SamInfo3 **_sam3,
478 : struct PAC_DOMAIN_GROUP_MEMBERSHIP **_resource_groups)
479 : {
480 3431 : NTSTATUS status;
481 83977 : struct netr_SamInfo6 *sam6 = NULL;
482 83977 : struct netr_SamInfo3 *sam3 = NULL;
483 :
484 83977 : sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
485 83977 : if (sam3 == NULL) {
486 0 : return NT_STATUS_NO_MEMORY;
487 : }
488 :
489 83977 : status = auth_convert_user_info_dc_saminfo6(sam3, user_info_dc,
490 : group_inclusion, &sam6,
491 : _resource_groups);
492 83977 : if (!NT_STATUS_IS_OK(status)) {
493 0 : TALLOC_FREE(sam3);
494 0 : return status;
495 : }
496 83977 : sam3->base = sam6->base;
497 83977 : sam3->sidcount = sam6->sidcount;
498 83977 : sam3->sids = sam6->sids;
499 :
500 83977 : *_sam3 = sam3;
501 83977 : return NT_STATUS_OK;
502 : }
503 :
504 : /**
505 : * Make a user_info struct from the info3 or similar returned by a domain logon.
506 : *
507 : * The netr_SamInfo3 is also a key structure in the source3 auth subsystem
508 : */
509 :
510 104552 : NTSTATUS make_user_info_SamBaseInfo(TALLOC_CTX *mem_ctx,
511 : const char *account_name,
512 : const struct netr_SamBaseInfo *base,
513 : bool authenticated,
514 : struct auth_user_info **_user_info)
515 : {
516 2543 : struct auth_user_info *info;
517 :
518 104552 : info = talloc_zero(mem_ctx, struct auth_user_info);
519 104552 : if (info == NULL) {
520 0 : return NT_STATUS_NO_MEMORY;
521 : }
522 :
523 104552 : if (base->account_name.string) {
524 104552 : info->account_name = talloc_strdup(info, base->account_name.string);
525 : } else {
526 0 : info->account_name = talloc_strdup(info, account_name);
527 : }
528 104552 : if (info->account_name == NULL) {
529 0 : talloc_free(info);
530 0 : return NT_STATUS_NO_MEMORY;
531 : }
532 :
533 104552 : if (base->logon_domain.string) {
534 104552 : info->domain_name = talloc_strdup(info, base->logon_domain.string);
535 104552 : if (info->domain_name == NULL) {
536 0 : talloc_free(info);
537 0 : return NT_STATUS_NO_MEMORY;
538 : }
539 : }
540 :
541 104552 : if (base->full_name.string) {
542 103546 : info->full_name = talloc_strdup(info, base->full_name.string);
543 103546 : if (info->full_name == NULL) {
544 0 : talloc_free(info);
545 0 : return NT_STATUS_NO_MEMORY;
546 : }
547 : }
548 104552 : if (base->logon_script.string) {
549 103546 : info->logon_script = talloc_strdup(info, base->logon_script.string);
550 103546 : if (info->logon_script == NULL) {
551 0 : talloc_free(info);
552 0 : return NT_STATUS_NO_MEMORY;
553 : }
554 : }
555 104552 : if (base->profile_path.string) {
556 103546 : info->profile_path = talloc_strdup(info, base->profile_path.string);
557 103546 : if (info->profile_path == NULL) {
558 0 : talloc_free(info);
559 0 : return NT_STATUS_NO_MEMORY;
560 : }
561 : }
562 104552 : if (base->home_directory.string) {
563 103546 : info->home_directory = talloc_strdup(info, base->home_directory.string);
564 103546 : if (info->home_directory == NULL) {
565 0 : talloc_free(info);
566 0 : return NT_STATUS_NO_MEMORY;
567 : }
568 : }
569 104552 : if (base->home_drive.string) {
570 103546 : info->home_drive = talloc_strdup(info, base->home_drive.string);
571 103546 : if (info->home_drive == NULL) {
572 0 : talloc_free(info);
573 0 : return NT_STATUS_NO_MEMORY;
574 : }
575 : }
576 104552 : if (base->logon_server.string) {
577 103546 : info->logon_server = talloc_strdup(info, base->logon_server.string);
578 103546 : if (info->logon_server == NULL) {
579 0 : talloc_free(info);
580 0 : return NT_STATUS_NO_MEMORY;
581 : }
582 : }
583 104552 : info->last_logon = base->logon_time;
584 104552 : info->last_logoff = base->logoff_time;
585 104552 : info->acct_expiry = base->kickoff_time;
586 104552 : info->last_password_change = base->last_password_change;
587 104552 : info->allow_password_change = base->allow_password_change;
588 104552 : info->force_password_change = base->force_password_change;
589 104552 : info->logon_count = base->logon_count;
590 104552 : info->bad_password_count = base->bad_password_count;
591 104552 : info->acct_flags = base->acct_flags;
592 :
593 104552 : info->user_flags = base->user_flags;
594 104552 : if (!authenticated) {
595 : /*
596 : * We only consider the user authenticated if NETLOGON_GUEST is
597 : * not set, and authenticated is set
598 : */
599 825 : info->user_flags |= NETLOGON_GUEST;
600 : }
601 :
602 104552 : *_user_info = info;
603 104552 : return NT_STATUS_OK;
604 : }
605 :
606 1338 : struct auth_user_info *auth_user_info_copy(TALLOC_CTX *mem_ctx,
607 : const struct auth_user_info *src)
608 : {
609 1338 : struct auth_user_info *dst = NULL;
610 :
611 1338 : dst = talloc_zero(mem_ctx, struct auth_user_info);
612 1338 : if (dst == NULL) {
613 0 : return NULL;
614 : }
615 :
616 1338 : *dst = *src;
617 : #define _COPY_STRING(_mem, _str) do { \
618 : if ((_str) != NULL) { \
619 : (_str) = talloc_strdup((_mem), (_str)); \
620 : if ((_str) == NULL) { \
621 : TALLOC_FREE(dst); \
622 : return NULL; \
623 : } \
624 : } \
625 : } while(0)
626 1338 : _COPY_STRING(dst, dst->account_name);
627 1338 : _COPY_STRING(dst, dst->user_principal_name);
628 1338 : _COPY_STRING(dst, dst->domain_name);
629 1338 : _COPY_STRING(dst, dst->dns_domain_name);
630 1338 : _COPY_STRING(dst, dst->full_name);
631 1338 : _COPY_STRING(dst, dst->logon_script);
632 1338 : _COPY_STRING(dst, dst->profile_path);
633 1338 : _COPY_STRING(dst, dst->home_directory);
634 1338 : _COPY_STRING(dst, dst->home_drive);
635 1338 : _COPY_STRING(dst, dst->logon_server);
636 : #undef _COPY_STRING
637 :
638 1338 : return dst;
639 : }
640 :
641 : /**
642 : * Make a user_info_dc struct from the info3 returned by a domain logon
643 : */
644 82631 : NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx,
645 : const char *account_name,
646 : uint16_t validation_level,
647 : const union netr_Validation *validation,
648 : bool authenticated,
649 : struct auth_user_info_dc **_user_info_dc)
650 : {
651 2543 : NTSTATUS status;
652 82631 : struct auth_user_info_dc *user_info_dc = NULL;
653 82631 : const struct netr_SamBaseInfo *base = NULL;
654 82631 : uint32_t sidcount = 0;
655 82631 : const struct netr_SidAttr *sids = NULL;
656 82631 : const char *dns_domainname = NULL;
657 82631 : const char *principal = NULL;
658 2543 : uint32_t i;
659 :
660 82631 : switch (validation_level) {
661 0 : case 2:
662 0 : if (!validation || !validation->sam2) {
663 0 : return NT_STATUS_INVALID_PARAMETER;
664 : }
665 0 : base = &validation->sam2->base;
666 0 : break;
667 82343 : case 3:
668 82343 : if (!validation || !validation->sam3) {
669 0 : return NT_STATUS_INVALID_PARAMETER;
670 : }
671 82343 : base = &validation->sam3->base;
672 82343 : sidcount = validation->sam3->sidcount;
673 82343 : sids = validation->sam3->sids;
674 82343 : break;
675 288 : case 6:
676 288 : if (!validation || !validation->sam6) {
677 0 : return NT_STATUS_INVALID_PARAMETER;
678 : }
679 288 : base = &validation->sam6->base;
680 288 : sidcount = validation->sam6->sidcount;
681 288 : sids = validation->sam6->sids;
682 288 : dns_domainname = validation->sam6->dns_domainname.string;
683 288 : principal = validation->sam6->principal_name.string;
684 288 : break;
685 0 : default:
686 0 : return NT_STATUS_INVALID_LEVEL;
687 : }
688 :
689 82631 : user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
690 82631 : if (user_info_dc == NULL) {
691 0 : return NT_STATUS_NO_MEMORY;
692 : }
693 :
694 : /*
695 : Here is where we should check the list of
696 : trusted domains, and verify that the SID
697 : matches.
698 : */
699 82631 : if (!base->domain_sid) {
700 0 : DEBUG(0, ("Cannot operate on a Netlogon Validation without a domain SID\n"));
701 0 : talloc_free(user_info_dc);
702 0 : return NT_STATUS_INVALID_PARAMETER;
703 : }
704 :
705 : /* The IDL layer would be a better place to check this, but to
706 : * guard the integer addition below, we double-check */
707 82631 : if (base->groups.count > 65535) {
708 0 : talloc_free(user_info_dc);
709 0 : return NT_STATUS_INVALID_PARAMETER;
710 : }
711 :
712 82631 : user_info_dc->num_sids = PRIMARY_SIDS_COUNT;
713 :
714 82631 : user_info_dc->sids = talloc_array(user_info_dc, struct auth_SidAttr, user_info_dc->num_sids + base->groups.count);
715 82631 : if (user_info_dc->sids == NULL) {
716 0 : talloc_free(user_info_dc);
717 0 : return NT_STATUS_NO_MEMORY;
718 : }
719 :
720 82631 : user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid = *base->domain_sid;
721 82631 : if (!sid_append_rid(&user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid, base->rid)) {
722 0 : talloc_free(user_info_dc);
723 0 : return NT_STATUS_INVALID_PARAMETER;
724 : }
725 82631 : user_info_dc->sids[PRIMARY_USER_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
726 :
727 82631 : user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid = *base->domain_sid;
728 82631 : if (!sid_append_rid(&user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid, base->primary_gid)) {
729 0 : talloc_free(user_info_dc);
730 0 : return NT_STATUS_INVALID_PARAMETER;
731 : }
732 : /*
733 : * This attribute value might be wrong if the primary group is a
734 : * resource group. But a resource group is not meant to be in a primary
735 : * group in the first place, and besides, these attributes will never
736 : * make their way into a PAC.
737 : */
738 82631 : user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
739 :
740 423637 : for (i = 0; i < base->groups.count; i++) {
741 341006 : user_info_dc->sids[user_info_dc->num_sids].sid = *base->domain_sid;
742 341006 : if (!sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids].sid, base->groups.rids[i].rid)) {
743 0 : talloc_free(user_info_dc);
744 0 : return NT_STATUS_INVALID_PARAMETER;
745 : }
746 341006 : user_info_dc->sids[user_info_dc->num_sids].attrs = base->groups.rids[i].attributes;
747 341006 : user_info_dc->num_sids++;
748 : }
749 :
750 : /* Copy 'other' sids. We need to do sid filtering here to
751 : prevent possible elevation of privileges. See:
752 :
753 : http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
754 : */
755 :
756 : /*
757 : * The IDL layer would be a better place to check this, but to
758 : * guard the integer addition below, we double-check
759 : */
760 82631 : if (sidcount > UINT16_MAX) {
761 0 : talloc_free(user_info_dc);
762 0 : return NT_STATUS_INVALID_PARAMETER;
763 : }
764 :
765 82631 : if (sidcount > 0) {
766 82554 : struct auth_SidAttr *dgrps = user_info_dc->sids;
767 2541 : size_t dgrps_count;
768 :
769 82554 : dgrps_count = user_info_dc->num_sids + sidcount;
770 82554 : dgrps = talloc_realloc(user_info_dc, dgrps, struct auth_SidAttr,
771 : dgrps_count);
772 82554 : if (dgrps == NULL) {
773 0 : talloc_free(user_info_dc);
774 0 : return NT_STATUS_NO_MEMORY;
775 : }
776 :
777 253963 : for (i = 0; i < sidcount; i++) {
778 171409 : if (sids[i].sid) {
779 171409 : dgrps[user_info_dc->num_sids].sid = *sids[i].sid;
780 171409 : dgrps[user_info_dc->num_sids].attrs = sids[i].attributes;
781 171409 : user_info_dc->num_sids++;
782 : }
783 : }
784 :
785 82554 : user_info_dc->sids = dgrps;
786 :
787 : /* Where are the 'global' sids?... */
788 : }
789 :
790 82631 : status = make_user_info_SamBaseInfo(user_info_dc, account_name, base, authenticated, &user_info_dc->info);
791 82631 : if (!NT_STATUS_IS_OK(status)) {
792 0 : talloc_free(user_info_dc);
793 0 : return status;
794 : }
795 :
796 82631 : if (dns_domainname != NULL) {
797 288 : user_info_dc->info->dns_domain_name = talloc_strdup(user_info_dc->info,
798 : dns_domainname);
799 288 : if (user_info_dc->info->dns_domain_name == NULL) {
800 0 : talloc_free(user_info_dc);
801 0 : return NT_STATUS_NO_MEMORY;
802 : }
803 : }
804 :
805 82631 : if (principal != NULL) {
806 288 : user_info_dc->info->user_principal_name = talloc_strdup(user_info_dc->info,
807 : principal);
808 288 : if (user_info_dc->info->user_principal_name == NULL) {
809 0 : talloc_free(user_info_dc);
810 0 : return NT_STATUS_NO_MEMORY;
811 : }
812 : }
813 :
814 : /* ensure we are never given NULL session keys */
815 :
816 82631 : if (all_zero(base->key.key, sizeof(base->key.key))) {
817 82409 : user_info_dc->user_session_key = data_blob(NULL, 0);
818 : } else {
819 222 : user_info_dc->user_session_key = data_blob_talloc(user_info_dc, base->key.key, sizeof(base->key.key));
820 222 : if (user_info_dc->user_session_key.data == NULL) {
821 0 : talloc_free(user_info_dc);
822 0 : return NT_STATUS_NO_MEMORY;
823 : }
824 : }
825 :
826 82631 : if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
827 82419 : user_info_dc->lm_session_key = data_blob(NULL, 0);
828 : } else {
829 212 : user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, base->LMSessKey.key, sizeof(base->LMSessKey.key));
830 212 : if (user_info_dc->lm_session_key.data == NULL) {
831 0 : talloc_free(user_info_dc);
832 0 : return NT_STATUS_NO_MEMORY;
833 : }
834 : }
835 :
836 82631 : *_user_info_dc = user_info_dc;
837 82631 : return NT_STATUS_OK;
838 : }
839 :
840 : /**
841 : * Make a user_info_dc struct from the PAC_LOGON_INFO supplied in the krb5
842 : * logon. For group_inclusion, pass AUTH_INCLUDE_RESOURCE_GROUPS if SIDs from
843 : * the resource groups are to be included in the resulting structure, and pass
844 : * AUTH_EXCLUDE_RESOURCE_GROUPS otherwise.
845 : */
846 82257 : NTSTATUS make_user_info_dc_pac(TALLOC_CTX *mem_ctx,
847 : const struct PAC_LOGON_INFO *pac_logon_info,
848 : const struct PAC_UPN_DNS_INFO *pac_upn_dns_info,
849 : const enum auth_group_inclusion group_inclusion,
850 : struct auth_user_info_dc **_user_info_dc)
851 : {
852 2541 : uint32_t i;
853 2541 : NTSTATUS nt_status;
854 2541 : union netr_Validation validation;
855 2541 : struct auth_user_info_dc *user_info_dc;
856 82257 : const struct PAC_DOMAIN_GROUP_MEMBERSHIP *rg = NULL;
857 2541 : size_t sidcount;
858 :
859 82257 : validation.sam3 = discard_const_p(struct netr_SamInfo3, &pac_logon_info->info3);
860 :
861 82257 : nt_status = make_user_info_dc_netlogon_validation(mem_ctx, "", 3, &validation,
862 : true, /* This user was authenticated */
863 : &user_info_dc);
864 82257 : if (!NT_STATUS_IS_OK(nt_status)) {
865 0 : return nt_status;
866 : }
867 :
868 82257 : if (pac_logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS) {
869 30631 : switch (group_inclusion) {
870 30583 : case AUTH_INCLUDE_RESOURCE_GROUPS:
871 : /* Take resource groups from the PAC. */
872 30583 : rg = &pac_logon_info->resource_groups;
873 30631 : break;
874 48 : case AUTH_EXCLUDE_RESOURCE_GROUPS:
875 : /*
876 : * The PAC is from a TGT, or we don't want to process
877 : * its resource groups.
878 : */
879 48 : break;
880 0 : default:
881 0 : DBG_ERR("invalid group inclusion parameter: %u\n", group_inclusion);
882 0 : talloc_free(user_info_dc);
883 0 : return NT_STATUS_INVALID_PARAMETER;
884 : }
885 : }
886 :
887 80482 : if (rg != NULL && rg->groups.count > 0) {
888 : /* The IDL layer would be a better place to check this, but to
889 : * guard the integer addition below, we double-check */
890 30583 : if (rg->groups.count > 65535) {
891 0 : talloc_free(user_info_dc);
892 0 : return NT_STATUS_INVALID_PARAMETER;
893 : }
894 :
895 : /*
896 : Here is where we should check the list of
897 : trusted domains, and verify that the SID
898 : matches.
899 : */
900 30583 : if (rg->domain_sid == NULL) {
901 0 : talloc_free(user_info_dc);
902 0 : DEBUG(0, ("Cannot operate on a PAC without a resource domain SID\n"));
903 0 : return NT_STATUS_INVALID_PARAMETER;
904 : }
905 :
906 30583 : sidcount = user_info_dc->num_sids + rg->groups.count;
907 30583 : user_info_dc->sids
908 30583 : = talloc_realloc(user_info_dc, user_info_dc->sids, struct auth_SidAttr, sidcount);
909 30583 : if (user_info_dc->sids == NULL) {
910 0 : TALLOC_FREE(user_info_dc);
911 0 : return NT_STATUS_NO_MEMORY;
912 : }
913 :
914 61182 : for (i = 0; i < rg->groups.count; i++) {
915 766 : bool ok;
916 :
917 30599 : user_info_dc->sids[user_info_dc->num_sids].sid = *rg->domain_sid;
918 31365 : ok = sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids].sid,
919 30599 : rg->groups.rids[i].rid);
920 30599 : if (!ok) {
921 0 : talloc_free(user_info_dc);
922 0 : return NT_STATUS_INVALID_PARAMETER;
923 : }
924 30599 : user_info_dc->sids[user_info_dc->num_sids].attrs = rg->groups.rids[i].attributes;
925 30599 : user_info_dc->num_sids++;
926 : }
927 : }
928 :
929 82257 : if (pac_upn_dns_info != NULL) {
930 82255 : if (pac_upn_dns_info->upn_name != NULL) {
931 164510 : user_info_dc->info->user_principal_name =
932 82255 : talloc_strdup(user_info_dc->info,
933 79716 : pac_upn_dns_info->upn_name);
934 82255 : if (user_info_dc->info->user_principal_name == NULL) {
935 0 : talloc_free(user_info_dc);
936 0 : return NT_STATUS_NO_MEMORY;
937 : }
938 : }
939 :
940 164510 : user_info_dc->info->dns_domain_name =
941 82255 : talloc_strdup(user_info_dc->info,
942 82255 : pac_upn_dns_info->dns_domain_name);
943 82255 : if (user_info_dc->info->dns_domain_name == NULL) {
944 0 : talloc_free(user_info_dc);
945 0 : return NT_STATUS_NO_MEMORY;
946 : }
947 :
948 82255 : if (pac_upn_dns_info->flags & PAC_UPN_DNS_FLAG_CONSTRUCTED) {
949 78585 : user_info_dc->info->user_principal_constructed = true;
950 : }
951 : }
952 :
953 82257 : *_user_info_dc = user_info_dc;
954 82257 : return NT_STATUS_OK;
955 : }
|