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