Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Authentication utility functions
4 : Copyright (C) Volker Lendecke 2010
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "auth.h"
22 : #include "lib/util_unixsids.h"
23 : #include "../librpc/gen_ndr/netlogon.h"
24 : #include "../libcli/security/security.h"
25 : #include "rpc_client/util_netlogon.h"
26 : #include "nsswitch/libwbclient/wbclient.h"
27 : #include "lib/winbind_util.h"
28 : #include "passdb.h"
29 :
30 : #undef DBGC_CLASS
31 : #define DBGC_CLASS DBGC_AUTH
32 :
33 : /***************************************************************************
34 : Make a server_info struct. Free with TALLOC_FREE().
35 : ***************************************************************************/
36 :
37 1664 : struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
38 : {
39 : struct auth_serversupplied_info *result;
40 :
41 1664 : result = talloc_zero(mem_ctx, struct auth_serversupplied_info);
42 1664 : if (result == NULL) {
43 0 : DEBUG(0, ("talloc failed\n"));
44 0 : return NULL;
45 : }
46 :
47 : /* Initialise the uid and gid values to something non-zero
48 : which may save us from giving away root access if there
49 : is a bug in allocating these fields. */
50 :
51 1664 : result->utok.uid = -1;
52 1664 : result->utok.gid = -1;
53 :
54 1664 : return result;
55 : }
56 :
57 : /****************************************************************************
58 : inits a netr_SamInfo2 structure from an auth_serversupplied_info. sam2 must
59 : already be initialized and is used as the talloc parent for its members.
60 : *****************************************************************************/
61 :
62 0 : NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
63 : struct netr_SamInfo2 *sam2)
64 : {
65 0 : struct netr_SamInfo3 *info3 = NULL;
66 : NTSTATUS status;
67 :
68 0 : status = copy_netr_SamInfo3(sam2,
69 0 : server_info->info3,
70 : &info3);
71 0 : if (!NT_STATUS_IS_OK(status)) {
72 0 : return status;
73 : }
74 :
75 0 : if (server_info->session_key.length) {
76 0 : memcpy(info3->base.key.key,
77 0 : server_info->session_key.data,
78 0 : MIN(sizeof(info3->base.key.key),
79 : server_info->session_key.length));
80 : }
81 0 : if (server_info->lm_session_key.length) {
82 0 : memcpy(info3->base.LMSessKey.key,
83 0 : server_info->lm_session_key.data,
84 0 : MIN(sizeof(info3->base.LMSessKey.key),
85 : server_info->lm_session_key.length));
86 : }
87 :
88 0 : sam2->base = info3->base;
89 :
90 0 : return NT_STATUS_OK;
91 : }
92 :
93 : /****************************************************************************
94 : inits a netr_SamInfo3 structure from an auth_serversupplied_info. sam3 must
95 : already be initialized and is used as the talloc parent for its members.
96 : *****************************************************************************/
97 :
98 2 : NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info,
99 : struct netr_SamInfo3 *sam3)
100 : {
101 2 : struct netr_SamInfo3 *info3 = NULL;
102 : NTSTATUS status;
103 :
104 2 : status = copy_netr_SamInfo3(sam3,
105 2 : server_info->info3,
106 : &info3);
107 2 : if (!NT_STATUS_IS_OK(status)) {
108 0 : return status;
109 : }
110 :
111 2 : if (server_info->session_key.length) {
112 2 : memcpy(info3->base.key.key,
113 2 : server_info->session_key.data,
114 2 : MIN(sizeof(info3->base.key.key),
115 : server_info->session_key.length));
116 : }
117 2 : if (server_info->lm_session_key.length) {
118 1 : memcpy(info3->base.LMSessKey.key,
119 1 : server_info->lm_session_key.data,
120 1 : MIN(sizeof(info3->base.LMSessKey.key),
121 : server_info->lm_session_key.length));
122 : }
123 :
124 2 : sam3->base = info3->base;
125 :
126 2 : sam3->sidcount = 0;
127 2 : sam3->sids = NULL;
128 :
129 2 : return NT_STATUS_OK;
130 : }
131 :
132 : /****************************************************************************
133 : inits a netr_SamInfo6 structure from an auth_serversupplied_info. sam6 must
134 : already be initialized and is used as the talloc parent for its members.
135 : *****************************************************************************/
136 :
137 0 : NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
138 : struct netr_SamInfo6 *sam6)
139 : {
140 : struct pdb_domain_info *dominfo;
141 0 : struct netr_SamInfo3 *info3 = NULL;
142 : NTSTATUS status;
143 :
144 0 : if ((pdb_capabilities() & PDB_CAP_ADS) == 0) {
145 0 : DEBUG(10,("Not adding validation info level 6 "
146 : "without ADS passdb backend\n"));
147 0 : return NT_STATUS_INVALID_INFO_CLASS;
148 : }
149 :
150 0 : dominfo = pdb_get_domain_info(sam6);
151 0 : if (dominfo == NULL) {
152 0 : return NT_STATUS_NO_MEMORY;
153 : }
154 :
155 0 : status = copy_netr_SamInfo3(sam6,
156 0 : server_info->info3,
157 : &info3);
158 0 : if (!NT_STATUS_IS_OK(status)) {
159 0 : return status;
160 : }
161 :
162 0 : if (server_info->session_key.length) {
163 0 : memcpy(info3->base.key.key,
164 0 : server_info->session_key.data,
165 0 : MIN(sizeof(info3->base.key.key),
166 : server_info->session_key.length));
167 : }
168 0 : if (server_info->lm_session_key.length) {
169 0 : memcpy(info3->base.LMSessKey.key,
170 0 : server_info->lm_session_key.data,
171 0 : MIN(sizeof(info3->base.LMSessKey.key),
172 : server_info->lm_session_key.length));
173 : }
174 :
175 0 : sam6->base = info3->base;
176 :
177 0 : sam6->sidcount = 0;
178 0 : sam6->sids = NULL;
179 :
180 0 : sam6->dns_domainname.string = talloc_strdup(sam6, dominfo->dns_domain);
181 0 : if (sam6->dns_domainname.string == NULL) {
182 0 : return NT_STATUS_NO_MEMORY;
183 : }
184 :
185 0 : sam6->principal_name.string = talloc_asprintf(
186 : sam6, "%s@%s", sam6->base.account_name.string,
187 : sam6->dns_domainname.string);
188 0 : if (sam6->principal_name.string == NULL) {
189 0 : return NT_STATUS_NO_MEMORY;
190 : }
191 :
192 0 : return NT_STATUS_OK;
193 : }
194 :
195 902 : static NTSTATUS append_netr_SidAttr(TALLOC_CTX *mem_ctx,
196 : struct netr_SidAttr **sids,
197 : uint32_t *count,
198 : const struct dom_sid2 *asid,
199 : uint32_t attributes)
200 : {
201 902 : uint32_t t = *count;
202 :
203 902 : *sids = talloc_realloc(mem_ctx, *sids, struct netr_SidAttr, t + 1);
204 902 : if (*sids == NULL) {
205 0 : return NT_STATUS_NO_MEMORY;
206 : }
207 902 : (*sids)[t].sid = dom_sid_dup(*sids, asid);
208 902 : if ((*sids)[t].sid == NULL) {
209 0 : return NT_STATUS_NO_MEMORY;
210 : }
211 902 : (*sids)[t].attributes = attributes;
212 902 : *count = t + 1;
213 :
214 902 : return NT_STATUS_OK;
215 : }
216 :
217 : /* Fills the samr_RidWithAttributeArray with the provided sids.
218 : * If it happens that we have additional groups that do not belong
219 : * to the domain, add their sids as extra sids */
220 497 : static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3,
221 : const struct dom_sid *sids,
222 : size_t num_sids)
223 : {
224 497 : uint32_t attributes = SE_GROUP_MANDATORY |
225 : SE_GROUP_ENABLED_BY_DEFAULT |
226 : SE_GROUP_ENABLED;
227 : struct samr_RidWithAttributeArray *groups;
228 : struct dom_sid *domain_sid;
229 : unsigned int i;
230 : NTSTATUS status;
231 : uint32_t rid;
232 : bool ok;
233 :
234 497 : domain_sid = info3->base.domain_sid;
235 497 : groups = &info3->base.groups;
236 :
237 497 : groups->rids = talloc_array(info3,
238 : struct samr_RidWithAttribute, num_sids);
239 497 : if (!groups->rids) {
240 0 : return NT_STATUS_NO_MEMORY;
241 : }
242 :
243 1484 : for (i = 0; i < num_sids; i++) {
244 987 : ok = sid_peek_check_rid(domain_sid, &sids[i], &rid);
245 987 : if (ok) {
246 : /* store domain group rid */
247 85 : groups->rids[groups->count].rid = rid;
248 85 : groups->rids[groups->count].attributes = attributes;
249 85 : groups->count++;
250 85 : continue;
251 : }
252 :
253 : /* if this wasn't a domain sid, add it as extra sid */
254 902 : status = append_netr_SidAttr(info3, &info3->sids,
255 : &info3->sidcount,
256 902 : &sids[i], attributes);
257 902 : if (!NT_STATUS_IS_OK(status)) {
258 0 : return status;
259 : }
260 : }
261 :
262 497 : return NT_STATUS_OK;
263 : }
264 :
265 : /*
266 : * Merge resource SIDs, if any, into the passed in info3 structure.
267 : */
268 :
269 617 : static NTSTATUS merge_resource_sids(const struct PAC_LOGON_INFO *logon_info,
270 : struct netr_SamInfo3 *info3)
271 : {
272 617 : uint32_t i = 0;
273 617 : const struct PAC_DOMAIN_GROUP_MEMBERSHIP *rg = NULL;
274 :
275 617 : if (logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS) {
276 0 : rg = &logon_info->resource_groups;
277 : }
278 :
279 617 : if (rg == NULL) {
280 617 : return NT_STATUS_OK;
281 : }
282 :
283 0 : if (rg->domain_sid == NULL) {
284 0 : DEBUG(10, ("Missing Resource Group Domain SID\n"));
285 0 : return NT_STATUS_INVALID_PARAMETER;
286 : }
287 :
288 : /* The IDL layer would be a better place to check this, but to
289 : * guard the integer addition below, we double-check */
290 0 : if (rg->groups.count > 65535) {
291 0 : DEBUG(10, ("Too much Resource Group RIDs %u\n",
292 : (unsigned)rg->groups.count));
293 0 : return NT_STATUS_INVALID_PARAMETER;
294 : }
295 :
296 : /*
297 : * If there are any resource groups (SID Compression) add
298 : * them to the extra sids portion of the info3 in the PAC.
299 : *
300 : * This makes the info3 look like it would if we got the info
301 : * from the DC rather than the PAC.
302 : */
303 :
304 : /*
305 : * Construct a SID for each RID in the list and then append it
306 : * to the info3.
307 : */
308 0 : for (i = 0; i < rg->groups.count; i++) {
309 : NTSTATUS status;
310 : struct dom_sid new_sid;
311 0 : uint32_t attributes = rg->groups.rids[i].attributes;
312 : struct dom_sid_buf buf;
313 :
314 0 : sid_compose(&new_sid,
315 0 : rg->domain_sid,
316 0 : rg->groups.rids[i].rid);
317 :
318 0 : DEBUG(10, ("Adding SID %s to extra SIDS\n",
319 : dom_sid_str_buf(&new_sid, &buf)));
320 :
321 0 : status = append_netr_SidAttr(info3, &info3->sids,
322 : &info3->sidcount,
323 : &new_sid,
324 : attributes);
325 0 : if (!NT_STATUS_IS_OK(status)) {
326 0 : DEBUG(1, ("failed to append SID %s to extra SIDS: %s\n",
327 : dom_sid_str_buf(&new_sid, &buf),
328 : nt_errstr(status)));
329 0 : return status;
330 : }
331 : }
332 :
333 0 : return NT_STATUS_OK;
334 : }
335 :
336 : /*
337 : * Create a copy of an info3 struct from the struct PAC_LOGON_INFO,
338 : * then merge resource SIDs, if any, into it. If successful return
339 : * the created info3 struct.
340 : */
341 :
342 0 : NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx,
343 : const struct PAC_LOGON_INFO *logon_info,
344 : struct netr_SamInfo3 **pp_info3)
345 : {
346 : NTSTATUS status;
347 0 : struct netr_SamInfo3 *info3 = NULL;
348 :
349 0 : status = copy_netr_SamInfo3(mem_ctx,
350 : &logon_info->info3,
351 : &info3);
352 0 : if (!NT_STATUS_IS_OK(status)) {
353 0 : return status;
354 : }
355 :
356 0 : status = merge_resource_sids(logon_info, info3);
357 0 : if (!NT_STATUS_IS_OK(status)) {
358 0 : TALLOC_FREE(info3);
359 0 : return status;
360 : }
361 0 : *pp_info3 = info3;
362 0 : return NT_STATUS_OK;
363 : }
364 :
365 : /*
366 : * Create a copy of an info6 struct from the PAC_UPN_DNS_INFO and PAC_LOGON_INFO
367 : * then merge resource SIDs, if any, into it. If successful return the created
368 : * info6 struct.
369 : */
370 617 : NTSTATUS create_info6_from_pac(TALLOC_CTX *mem_ctx,
371 : const struct PAC_LOGON_INFO *logon_info,
372 : const struct PAC_UPN_DNS_INFO *upn_dns_info,
373 : struct netr_SamInfo6 **pp_info6)
374 : {
375 : NTSTATUS status;
376 617 : struct netr_SamInfo6 *info6 = NULL;
377 617 : struct netr_SamInfo3 *info3 = NULL;
378 :
379 617 : info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
380 617 : if (info6 == NULL) {
381 0 : return NT_STATUS_NO_MEMORY;
382 : }
383 :
384 617 : status = copy_netr_SamInfo3(info6,
385 : &logon_info->info3,
386 : &info3);
387 617 : if (!NT_STATUS_IS_OK(status)) {
388 0 : TALLOC_FREE(info6);
389 0 : return status;
390 : }
391 :
392 617 : status = merge_resource_sids(logon_info, info3);
393 617 : if (!NT_STATUS_IS_OK(status)) {
394 0 : TALLOC_FREE(info6);
395 0 : return status;
396 : }
397 :
398 617 : info6->base = info3->base;
399 617 : info6->sids = info3->sids;
400 617 : info6->sidcount = info3->sidcount;
401 :
402 617 : if (upn_dns_info != NULL) {
403 801 : info6->dns_domainname.string = talloc_strdup(info6,
404 267 : upn_dns_info->dns_domain_name);
405 534 : if (info6->dns_domainname.string == NULL) {
406 0 : TALLOC_FREE(info6);
407 0 : return NT_STATUS_NO_MEMORY;
408 : }
409 801 : info6->principal_name.string = talloc_strdup(info6,
410 267 : upn_dns_info->upn_name);
411 534 : if (info6->principal_name.string == NULL) {
412 0 : TALLOC_FREE(info6);
413 0 : return NT_STATUS_NO_MEMORY;
414 : }
415 : }
416 :
417 617 : *pp_info6 = info6;
418 617 : return NT_STATUS_OK;
419 : }
420 :
421 : /*
422 : * Check if this is a "Unix Users" domain user, or a
423 : * "Unix Groups" domain group, we need to handle it
424 : * in a special way if that's the case.
425 : */
426 :
427 531 : static NTSTATUS SamInfo3_handle_sids(const char *username,
428 : const struct dom_sid *user_sid,
429 : const struct dom_sid *group_sid,
430 : struct netr_SamInfo3 *info3,
431 : struct dom_sid *domain_sid,
432 : struct extra_auth_info *extra)
433 : {
434 : struct dom_sid_buf buf;
435 :
436 531 : if (sid_check_is_in_unix_users(user_sid)) {
437 : /* in info3 you can only set rids for the user and the
438 : * primary group, and the domain sid must be that of
439 : * the sam domain.
440 : *
441 : * Store a completely bogus value here.
442 : * The real SID is stored in the extra sids.
443 : * Other code will know to look there if (-1) is found
444 : */
445 32 : info3->base.rid = (uint32_t)(-1);
446 32 : sid_copy(&extra->user_sid, user_sid);
447 :
448 32 : DEBUG(10, ("Unix User found. Rid marked as "
449 : "special and sid (%s) saved as extra sid\n",
450 : dom_sid_str_buf(user_sid, &buf)));
451 : } else {
452 499 : sid_copy(domain_sid, user_sid);
453 499 : sid_split_rid(domain_sid, &info3->base.rid);
454 : }
455 :
456 531 : if (is_null_sid(domain_sid)) {
457 32 : sid_copy(domain_sid, get_global_sam_sid());
458 : }
459 :
460 : /* check if this is a "Unix Groups" domain group,
461 : * if so we need special handling */
462 531 : if (sid_check_is_in_unix_groups(group_sid)) {
463 : /* in info3 you can only set rids for the user and the
464 : * primary group, and the domain sid must be that of
465 : * the sam domain.
466 : *
467 : * Store a completely bogus value here.
468 : * The real SID is stored in the extra sids.
469 : * Other code will know to look there if (-1) is found
470 : */
471 0 : info3->base.primary_gid = (uint32_t)(-1);
472 0 : sid_copy(&extra->pgid_sid, group_sid);
473 :
474 0 : DEBUG(10, ("Unix Group found. Rid marked as "
475 : "special and sid (%s) saved as extra sid\n",
476 : dom_sid_str_buf(group_sid, &buf)));
477 : } else {
478 531 : bool ok = sid_peek_check_rid(domain_sid, group_sid,
479 : &info3->base.primary_gid);
480 531 : if (!ok) {
481 : struct dom_sid_buf buf2, buf3;
482 0 : DEBUG(1, ("The primary group domain sid(%s) does not "
483 : "match the domain sid(%s) for %s(%s)\n",
484 : dom_sid_str_buf(group_sid, &buf),
485 : dom_sid_str_buf(domain_sid, &buf2),
486 : username,
487 : dom_sid_str_buf(user_sid, &buf3)));
488 0 : return NT_STATUS_INVALID_SID;
489 : }
490 : }
491 531 : return NT_STATUS_OK;
492 : }
493 :
494 : #define RET_NOMEM(ptr) do { \
495 : if (!ptr) { \
496 : TALLOC_FREE(info3); \
497 : return NT_STATUS_NO_MEMORY; \
498 : } } while(0)
499 :
500 457 : NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
501 : struct samu *samu,
502 : const char *login_server,
503 : struct netr_SamInfo3 **_info3,
504 : struct extra_auth_info *extra)
505 : {
506 : struct netr_SamInfo3 *info3;
507 : const struct dom_sid *user_sid;
508 : const struct dom_sid *group_sid;
509 457 : struct dom_sid domain_sid = {0};
510 : struct dom_sid *group_sids;
511 457 : uint32_t num_group_sids = 0;
512 : const char *tmp;
513 : gid_t *gids;
514 : NTSTATUS status;
515 :
516 457 : user_sid = pdb_get_user_sid(samu);
517 457 : group_sid = pdb_get_group_sid(samu);
518 :
519 457 : if (!user_sid || !group_sid) {
520 0 : DEBUG(1, ("Sam account is missing sids!\n"));
521 0 : return NT_STATUS_UNSUCCESSFUL;
522 : }
523 :
524 457 : info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
525 457 : if (!info3) {
526 0 : return NT_STATUS_NO_MEMORY;
527 : }
528 :
529 457 : status = SamInfo3_handle_sids(pdb_get_username(samu),
530 : user_sid,
531 : group_sid,
532 : info3,
533 : &domain_sid,
534 : extra);
535 :
536 457 : if (!NT_STATUS_IS_OK(status)) {
537 0 : TALLOC_FREE(info3);
538 0 : return status;
539 : }
540 :
541 457 : unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
542 457 : unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
543 457 : unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
544 457 : unix_to_nt_time(&info3->base.last_password_change,
545 : pdb_get_pass_last_set_time(samu));
546 457 : unix_to_nt_time(&info3->base.allow_password_change,
547 : pdb_get_pass_can_change_time(samu));
548 457 : unix_to_nt_time(&info3->base.force_password_change,
549 : pdb_get_pass_must_change_time(samu));
550 :
551 457 : tmp = pdb_get_username(samu);
552 457 : if (tmp) {
553 457 : info3->base.account_name.string = talloc_strdup(info3, tmp);
554 457 : RET_NOMEM(info3->base.account_name.string);
555 : }
556 457 : tmp = pdb_get_fullname(samu);
557 457 : if (tmp) {
558 457 : info3->base.full_name.string = talloc_strdup(info3, tmp);
559 457 : RET_NOMEM(info3->base.full_name.string);
560 : }
561 457 : tmp = pdb_get_logon_script(samu);
562 457 : if (tmp) {
563 457 : info3->base.logon_script.string = talloc_strdup(info3, tmp);
564 457 : RET_NOMEM(info3->base.logon_script.string);
565 : }
566 457 : tmp = pdb_get_profile_path(samu);
567 457 : if (tmp) {
568 457 : info3->base.profile_path.string = talloc_strdup(info3, tmp);
569 457 : RET_NOMEM(info3->base.profile_path.string);
570 : }
571 457 : tmp = pdb_get_homedir(samu);
572 457 : if (tmp) {
573 457 : info3->base.home_directory.string = talloc_strdup(info3, tmp);
574 457 : RET_NOMEM(info3->base.home_directory.string);
575 : }
576 457 : tmp = pdb_get_dir_drive(samu);
577 457 : if (tmp) {
578 456 : info3->base.home_drive.string = talloc_strdup(info3, tmp);
579 456 : RET_NOMEM(info3->base.home_drive.string);
580 : }
581 :
582 457 : info3->base.logon_count = pdb_get_logon_count(samu);
583 457 : info3->base.bad_password_count = pdb_get_bad_password_count(samu);
584 :
585 457 : info3->base.logon_domain.string = talloc_strdup(info3,
586 : pdb_get_domain(samu));
587 457 : RET_NOMEM(info3->base.logon_domain.string);
588 :
589 457 : info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
590 457 : RET_NOMEM(info3->base.domain_sid);
591 :
592 457 : status = pdb_enum_group_memberships(mem_ctx, samu,
593 : &group_sids, &gids,
594 : &num_group_sids);
595 457 : if (!NT_STATUS_IS_OK(status)) {
596 0 : DEBUG(1, ("Failed to get groups from sam account.\n"));
597 0 : TALLOC_FREE(info3);
598 0 : return status;
599 : }
600 :
601 457 : if (num_group_sids) {
602 457 : status = group_sids_to_info3(info3, group_sids, num_group_sids);
603 457 : if (!NT_STATUS_IS_OK(status)) {
604 0 : TALLOC_FREE(info3);
605 0 : return status;
606 : }
607 : }
608 :
609 : /* We don't need sids and gids after the conversion */
610 457 : TALLOC_FREE(group_sids);
611 457 : TALLOC_FREE(gids);
612 457 : num_group_sids = 0;
613 :
614 : /* FIXME: should we add other flags ? */
615 457 : info3->base.user_flags = NETLOGON_EXTRA_SIDS;
616 :
617 457 : if (login_server) {
618 457 : info3->base.logon_server.string = talloc_strdup(info3, login_server);
619 457 : RET_NOMEM(info3->base.logon_server.string);
620 : }
621 :
622 457 : info3->base.acct_flags = pdb_get_acct_ctrl(samu);
623 :
624 457 : *_info3 = info3;
625 457 : return NT_STATUS_OK;
626 : }
627 :
628 74 : NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
629 : const char *unix_username,
630 : const struct passwd *pwd,
631 : struct netr_SamInfo3 **pinfo3,
632 : struct extra_auth_info *extra)
633 : {
634 : struct netr_SamInfo3 *info3;
635 : NTSTATUS status;
636 : TALLOC_CTX *tmp_ctx;
637 74 : const char *domain_name = NULL;
638 74 : const char *user_name = NULL;
639 : struct dom_sid domain_sid;
640 : struct dom_sid user_sid;
641 : struct dom_sid group_sid;
642 : enum lsa_SidType type;
643 74 : uint32_t num_sids = 0;
644 74 : struct dom_sid *user_sids = NULL;
645 : bool is_null;
646 : bool ok;
647 :
648 74 : tmp_ctx = talloc_stackframe();
649 :
650 74 : ok = lookup_name_smbconf(tmp_ctx,
651 : unix_username,
652 : LOOKUP_NAME_ALL,
653 : &domain_name,
654 : &user_name,
655 : &user_sid,
656 : &type);
657 74 : if (!ok) {
658 0 : status = NT_STATUS_NO_SUCH_USER;
659 0 : goto done;
660 : }
661 :
662 74 : if (type != SID_NAME_USER) {
663 0 : status = NT_STATUS_NO_SUCH_USER;
664 0 : goto done;
665 : }
666 :
667 74 : ok = winbind_lookup_usersids(tmp_ctx,
668 : &user_sid,
669 : &num_sids,
670 : &user_sids);
671 : /* Check if winbind is running */
672 74 : if (ok) {
673 : /*
674 : * Winbind is running and the first element of the user_sids
675 : * is the primary group.
676 : */
677 40 : if (num_sids > 0) {
678 40 : group_sid = user_sids[0];
679 : }
680 : } else {
681 : /*
682 : * Winbind is not running, try to create the group_sid from the
683 : * passwd group id.
684 : */
685 :
686 : /*
687 : * This can lead to a primary group of S-1-22-2-XX which
688 : * will be rejected by other Samba code.
689 : */
690 34 : gid_to_sid(&group_sid, pwd->pw_gid);
691 : }
692 :
693 : /*
694 : * If we are a unix group, or a wellknown/builtin alias,
695 : * set the group_sid to the
696 : * 'Domain Users' RID of 513 which will always resolve to a
697 : * name.
698 : */
699 130 : if (sid_check_is_in_unix_groups(&group_sid) ||
700 112 : sid_check_is_in_builtin(&group_sid) ||
701 56 : sid_check_is_in_wellknown_domain(&group_sid)) {
702 34 : if (sid_check_is_in_unix_users(&user_sid)) {
703 32 : sid_compose(&group_sid,
704 32 : get_global_sam_sid(),
705 : DOMAIN_RID_USERS);
706 : } else {
707 2 : sid_copy(&domain_sid, &user_sid);
708 2 : sid_split_rid(&domain_sid, NULL);
709 2 : sid_compose(&group_sid,
710 : &domain_sid,
711 : DOMAIN_RID_USERS);
712 : }
713 : }
714 :
715 : /* Make sure we have a valid group sid */
716 74 : is_null = is_null_sid(&group_sid);
717 74 : if (is_null) {
718 0 : status = NT_STATUS_NO_SUCH_USER;
719 0 : goto done;
720 : }
721 :
722 : /* Construct a netr_SamInfo3 from the information we have */
723 74 : info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3);
724 74 : if (!info3) {
725 0 : status = NT_STATUS_NO_MEMORY;
726 0 : goto done;
727 : }
728 :
729 74 : info3->base.account_name.string = talloc_strdup(info3, unix_username);
730 74 : if (info3->base.account_name.string == NULL) {
731 0 : status = NT_STATUS_NO_MEMORY;
732 0 : goto done;
733 : }
734 :
735 74 : info3->base.logon_domain.string = talloc_strdup(info3, domain_name);
736 74 : if (info3->base.logon_domain.string == NULL) {
737 0 : status = NT_STATUS_NO_MEMORY;
738 0 : goto done;
739 : }
740 :
741 74 : ZERO_STRUCT(domain_sid);
742 :
743 74 : status = SamInfo3_handle_sids(unix_username,
744 : &user_sid,
745 : &group_sid,
746 : info3,
747 : &domain_sid,
748 : extra);
749 :
750 74 : if (!NT_STATUS_IS_OK(status)) {
751 0 : goto done;
752 : }
753 :
754 74 : info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
755 74 : if (info3->base.domain_sid == NULL) {
756 0 : status = NT_STATUS_NO_MEMORY;
757 0 : goto done;
758 : }
759 :
760 74 : ok = sid_peek_check_rid(&domain_sid, &group_sid,
761 74 : &info3->base.primary_gid);
762 74 : if (!ok) {
763 : struct dom_sid_buf buf1, buf2, buf3;
764 :
765 0 : DEBUG(1, ("The primary group domain sid(%s) does not "
766 : "match the domain sid(%s) for %s(%s)\n",
767 : dom_sid_str_buf(&group_sid, &buf1),
768 : dom_sid_str_buf(&domain_sid, &buf2),
769 : unix_username,
770 : dom_sid_str_buf(&user_sid, &buf3)));
771 0 : status = NT_STATUS_INVALID_SID;
772 0 : goto done;
773 : }
774 :
775 74 : info3->base.acct_flags = ACB_NORMAL;
776 :
777 74 : if (num_sids) {
778 40 : status = group_sids_to_info3(info3, user_sids, num_sids);
779 40 : if (!NT_STATUS_IS_OK(status)) {
780 0 : goto done;
781 : }
782 : }
783 :
784 74 : *pinfo3 = talloc_move(mem_ctx, &info3);
785 :
786 74 : status = NT_STATUS_OK;
787 74 : done:
788 74 : talloc_free(tmp_ctx);
789 :
790 74 : return status;
791 : }
|