s3:auth: add S-1-22-X-Y sids to the local token
[samba.git] / source3 / auth / auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Volker Lendecke 2006
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
28
29 /****************************************************************************
30  Ensure primary group SID is always at position 0 in a 
31  auth_serversupplied_info struct.
32 ****************************************************************************/
33
34 static void sort_sid_array_for_smbd(auth_serversupplied_info *result,
35                                 const DOM_SID *pgroup_sid)
36 {
37         unsigned int i;
38
39         if (!result->sids) {
40                 return;
41         }
42
43         if (sid_compare(&result->sids[0], pgroup_sid)==0) {
44                 return;
45         }
46
47         for (i = 1; i < result->num_sids; i++) {
48                 if (sid_compare(pgroup_sid,
49                                 &result->sids[i]) == 0) {
50                         sid_copy(&result->sids[i], &result->sids[0]);
51                         sid_copy(&result->sids[0], pgroup_sid);
52                         return;
53                 }
54         }
55 }
56
57 /****************************************************************************
58  Create a UNIX user on demand.
59 ****************************************************************************/
60
61 static int smb_create_user(const char *domain, const char *unix_username, const char *homedir)
62 {
63         TALLOC_CTX *ctx = talloc_tos();
64         char *add_script;
65         int ret;
66
67         add_script = talloc_strdup(ctx, lp_adduser_script());
68         if (!add_script || !*add_script) {
69                 return -1;
70         }
71         add_script = talloc_all_string_sub(ctx,
72                                 add_script,
73                                 "%u",
74                                 unix_username);
75         if (!add_script) {
76                 return -1;
77         }
78         if (domain) {
79                 add_script = talloc_all_string_sub(ctx,
80                                         add_script,
81                                         "%D",
82                                         domain);
83                 if (!add_script) {
84                         return -1;
85                 }
86         }
87         if (homedir) {
88                 add_script = talloc_all_string_sub(ctx,
89                                 add_script,
90                                 "%H",
91                                 homedir);
92                 if (!add_script) {
93                         return -1;
94                 }
95         }
96         ret = smbrun(add_script,NULL);
97         flush_pwnam_cache();
98         DEBUG(ret ? 0 : 3,
99                 ("smb_create_user: Running the command `%s' gave %d\n",
100                  add_script,ret));
101         return ret;
102 }
103
104 /****************************************************************************
105  Create an auth_usersupplied_data structure
106 ****************************************************************************/
107
108 static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
109                                const char *smb_name,
110                                const char *internal_username,
111                                const char *client_domain,
112                                const char *domain,
113                                const char *wksta_name,
114                                DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
115                                DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
116                                DATA_BLOB *plaintext,
117                                bool encrypted)
118 {
119
120         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
121
122         *user_info = SMB_MALLOC_P(auth_usersupplied_info);
123         if (*user_info == NULL) {
124                 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
125                 return NT_STATUS_NO_MEMORY;
126         }
127
128         ZERO_STRUCTP(*user_info);
129
130         DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
131
132         (*user_info)->smb_name = SMB_STRDUP(smb_name);
133         if ((*user_info)->smb_name == NULL) { 
134                 free_user_info(user_info);
135                 return NT_STATUS_NO_MEMORY;
136         }
137         
138         (*user_info)->internal_username = SMB_STRDUP(internal_username);
139         if ((*user_info)->internal_username == NULL) { 
140                 free_user_info(user_info);
141                 return NT_STATUS_NO_MEMORY;
142         }
143
144         (*user_info)->domain = SMB_STRDUP(domain);
145         if ((*user_info)->domain == NULL) { 
146                 free_user_info(user_info);
147                 return NT_STATUS_NO_MEMORY;
148         }
149
150         (*user_info)->client_domain = SMB_STRDUP(client_domain);
151         if ((*user_info)->client_domain == NULL) { 
152                 free_user_info(user_info);
153                 return NT_STATUS_NO_MEMORY;
154         }
155
156         (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
157         if ((*user_info)->wksta_name == NULL) { 
158                 free_user_info(user_info);
159                 return NT_STATUS_NO_MEMORY;
160         }
161
162         DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
163
164         if (lm_pwd)
165                 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
166         if (nt_pwd)
167                 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
168         if (lm_interactive_pwd)
169                 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
170         if (nt_interactive_pwd)
171                 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
172
173         if (plaintext)
174                 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
175
176         (*user_info)->encrypted = encrypted;
177
178         (*user_info)->logon_parameters = 0;
179
180         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
181
182         return NT_STATUS_OK;
183 }
184
185 /****************************************************************************
186  Create an auth_usersupplied_data structure after appropriate mapping.
187 ****************************************************************************/
188
189 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
190                             const char *smb_name,
191                             const char *client_domain,
192                             const char *wksta_name,
193                             DATA_BLOB *lm_pwd,
194                             DATA_BLOB *nt_pwd,
195                             DATA_BLOB *lm_interactive_pwd,
196                             DATA_BLOB *nt_interactive_pwd,
197                             DATA_BLOB *plaintext,
198                             bool encrypted)
199 {
200         const char *domain;
201         NTSTATUS result;
202         bool was_mapped;
203         fstring internal_username;
204         fstrcpy(internal_username, smb_name);
205         was_mapped = map_username(internal_username);
206
207         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
208                  client_domain, smb_name, wksta_name));
209
210         /* don't allow "" as a domain, fixes a Win9X bug
211            where it doens't supply a domain for logon script
212            'net use' commands.                                 */
213
214         if ( *client_domain )
215                 domain = client_domain;
216         else
217                 domain = lp_workgroup();
218
219         /* If you connect to a Windows domain member using a bogus domain name,
220          * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
221          * the Windows box is a DC the name will become DOMAIN\user and be
222          * authenticated against AD, if the Windows box is a member server but
223          * not a DC the name will become WORKSTATION\user.  A standalone
224          * non-domain member box will also map to WORKSTATION\user. */
225
226         if (!is_trusted_domain(domain) &&
227             !strequal(domain, get_global_sam_name()) )
228         {
229                 if (lp_map_untrusted_to_domain())
230                         domain = my_sam_name();
231                 else
232                         domain = get_global_sam_name();
233                 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
234                           "workstation [%s]\n",
235                           client_domain, domain, smb_name, wksta_name));
236         }
237
238         /* We know that the given domain is trusted (and we are allowing them),
239          * it is our global SAM name, or for legacy behavior it is our
240          * primary domain name */
241
242         result = make_user_info(user_info, smb_name, internal_username,
243                               client_domain, domain, wksta_name,
244                               lm_pwd, nt_pwd,
245                               lm_interactive_pwd, nt_interactive_pwd,
246                               plaintext, encrypted);
247         if (NT_STATUS_IS_OK(result)) {
248                 (*user_info)->was_mapped = was_mapped;
249         }
250         return result;
251 }
252
253 /****************************************************************************
254  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
255  Decrypt and encrypt the passwords.
256 ****************************************************************************/
257
258 bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
259                                      const char *smb_name, 
260                                      const char *client_domain, 
261                                      const char *wksta_name, 
262                                      uint32 logon_parameters,
263                                      const uchar *lm_network_pwd,
264                                      int lm_pwd_len,
265                                      const uchar *nt_network_pwd,
266                                      int nt_pwd_len)
267 {
268         bool ret;
269         NTSTATUS status;
270         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
271         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
272
273         status = make_user_info_map(user_info,
274                                     smb_name, client_domain, 
275                                     wksta_name, 
276                                     lm_pwd_len ? &lm_blob : NULL, 
277                                     nt_pwd_len ? &nt_blob : NULL,
278                                     NULL, NULL, NULL,
279                                     True);
280
281         if (NT_STATUS_IS_OK(status)) {
282                 (*user_info)->logon_parameters = logon_parameters;
283         }
284         ret = NT_STATUS_IS_OK(status) ? True : False;
285
286         data_blob_free(&lm_blob);
287         data_blob_free(&nt_blob);
288         return ret;
289 }
290
291 /****************************************************************************
292  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
293  Decrypt and encrypt the passwords.
294 ****************************************************************************/
295
296 bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
297                                          const char *smb_name, 
298                                          const char *client_domain, 
299                                          const char *wksta_name, 
300                                          uint32 logon_parameters,
301                                          const uchar chal[8], 
302                                          const uchar lm_interactive_pwd[16], 
303                                          const uchar nt_interactive_pwd[16], 
304                                          const uchar *dc_sess_key)
305 {
306         unsigned char lm_pwd[16];
307         unsigned char nt_pwd[16];
308         unsigned char local_lm_response[24];
309         unsigned char local_nt_response[24];
310         unsigned char key[16];
311         
312         ZERO_STRUCT(key);
313         memcpy(key, dc_sess_key, 8);
314         
315         if (lm_interactive_pwd)
316                 memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
317
318         if (nt_interactive_pwd)
319                 memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
320         
321 #ifdef DEBUG_PASSWORD
322         DEBUG(100,("key:"));
323         dump_data(100, key, sizeof(key));
324         
325         DEBUG(100,("lm owf password:"));
326         dump_data(100, lm_pwd, sizeof(lm_pwd));
327         
328         DEBUG(100,("nt owf password:"));
329         dump_data(100, nt_pwd, sizeof(nt_pwd));
330 #endif
331         
332         if (lm_interactive_pwd)
333                 SamOEMhash(lm_pwd, key, sizeof(lm_pwd));
334         
335         if (nt_interactive_pwd)
336                 SamOEMhash(nt_pwd, key, sizeof(nt_pwd));
337         
338 #ifdef DEBUG_PASSWORD
339         DEBUG(100,("decrypt of lm owf password:"));
340         dump_data(100, lm_pwd, sizeof(lm_pwd));
341         
342         DEBUG(100,("decrypt of nt owf password:"));
343         dump_data(100, nt_pwd, sizeof(nt_pwd));
344 #endif
345         
346         if (lm_interactive_pwd)
347                 SMBOWFencrypt(lm_pwd, chal,
348                               local_lm_response);
349
350         if (nt_interactive_pwd)
351                 SMBOWFencrypt(nt_pwd, chal,
352                               local_nt_response);
353         
354         /* Password info paranoia */
355         ZERO_STRUCT(key);
356
357         {
358                 bool ret;
359                 NTSTATUS nt_status;
360                 DATA_BLOB local_lm_blob;
361                 DATA_BLOB local_nt_blob;
362
363                 DATA_BLOB lm_interactive_blob;
364                 DATA_BLOB nt_interactive_blob;
365                 
366                 if (lm_interactive_pwd) {
367                         local_lm_blob = data_blob(local_lm_response,
368                                                   sizeof(local_lm_response));
369                         lm_interactive_blob = data_blob(lm_pwd,
370                                                         sizeof(lm_pwd));
371                         ZERO_STRUCT(lm_pwd);
372                 }
373                 
374                 if (nt_interactive_pwd) {
375                         local_nt_blob = data_blob(local_nt_response,
376                                                   sizeof(local_nt_response));
377                         nt_interactive_blob = data_blob(nt_pwd,
378                                                         sizeof(nt_pwd));
379                         ZERO_STRUCT(nt_pwd);
380                 }
381
382                 nt_status = make_user_info_map(
383                         user_info, 
384                         smb_name, client_domain, wksta_name, 
385                         lm_interactive_pwd ? &local_lm_blob : NULL,
386                         nt_interactive_pwd ? &local_nt_blob : NULL,
387                         lm_interactive_pwd ? &lm_interactive_blob : NULL,
388                         nt_interactive_pwd ? &nt_interactive_blob : NULL,
389                         NULL, True);
390
391                 if (NT_STATUS_IS_OK(nt_status)) {
392                         (*user_info)->logon_parameters = logon_parameters;
393                 }
394
395                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
396                 data_blob_free(&local_lm_blob);
397                 data_blob_free(&local_nt_blob);
398                 data_blob_free(&lm_interactive_blob);
399                 data_blob_free(&nt_interactive_blob);
400                 return ret;
401         }
402 }
403
404
405 /****************************************************************************
406  Create an auth_usersupplied_data structure
407 ****************************************************************************/
408
409 bool make_user_info_for_reply(auth_usersupplied_info **user_info, 
410                               const char *smb_name, 
411                               const char *client_domain,
412                               const uint8 chal[8],
413                               DATA_BLOB plaintext_password)
414 {
415
416         DATA_BLOB local_lm_blob;
417         DATA_BLOB local_nt_blob;
418         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
419                         
420         /*
421          * Not encrypted - do so.
422          */
423         
424         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
425                  "format.\n"));
426         
427         if (plaintext_password.data) {
428                 unsigned char local_lm_response[24];
429                 
430 #ifdef DEBUG_PASSWORD
431                 DEBUG(10,("Unencrypted password (len %d):\n",
432                           (int)plaintext_password.length));
433                 dump_data(100, plaintext_password.data,
434                           plaintext_password.length);
435 #endif
436
437                 SMBencrypt( (const char *)plaintext_password.data,
438                             (const uchar*)chal, local_lm_response);
439                 local_lm_blob = data_blob(local_lm_response, 24);
440                 
441                 /* We can't do an NT hash here, as the password needs to be
442                    case insensitive */
443                 local_nt_blob = data_blob_null; 
444                 
445         } else {
446                 local_lm_blob = data_blob_null; 
447                 local_nt_blob = data_blob_null; 
448         }
449         
450         ret = make_user_info_map(
451                 user_info, smb_name, client_domain, 
452                 get_remote_machine_name(),
453                 local_lm_blob.data ? &local_lm_blob : NULL,
454                 local_nt_blob.data ? &local_nt_blob : NULL,
455                 NULL, NULL,
456                 plaintext_password.data ? &plaintext_password : NULL, 
457                 False);
458         
459         data_blob_free(&local_lm_blob);
460         return NT_STATUS_IS_OK(ret) ? True : False;
461 }
462
463 /****************************************************************************
464  Create an auth_usersupplied_data structure
465 ****************************************************************************/
466
467 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
468                                       const char *smb_name,
469                                       const char *client_domain, 
470                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
471 {
472         return make_user_info_map(user_info, smb_name, 
473                                   client_domain, 
474                                   get_remote_machine_name(), 
475                                   lm_resp.data ? &lm_resp : NULL, 
476                                   nt_resp.data ? &nt_resp : NULL, 
477                                   NULL, NULL, NULL,
478                                   True);
479 }
480
481 /****************************************************************************
482  Create a guest user_info blob, for anonymous authenticaion.
483 ****************************************************************************/
484
485 bool make_user_info_guest(auth_usersupplied_info **user_info) 
486 {
487         NTSTATUS nt_status;
488
489         nt_status = make_user_info(user_info, 
490                                    "","", 
491                                    "","", 
492                                    "", 
493                                    NULL, NULL, 
494                                    NULL, NULL, 
495                                    NULL,
496                                    True);
497                               
498         return NT_STATUS_IS_OK(nt_status) ? True : False;
499 }
500
501 static int server_info_dtor(auth_serversupplied_info *server_info)
502 {
503         TALLOC_FREE(server_info->sam_account);
504         ZERO_STRUCTP(server_info);
505         return 0;
506 }
507
508 /***************************************************************************
509  Make a server_info struct. Free with TALLOC_FREE().
510 ***************************************************************************/
511
512 static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
513 {
514         struct auth_serversupplied_info *result;
515
516         result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
517         if (result == NULL) {
518                 DEBUG(0, ("talloc failed\n"));
519                 return NULL;
520         }
521
522         talloc_set_destructor(result, server_info_dtor);
523
524         /* Initialise the uid and gid values to something non-zero
525            which may save us from giving away root access if there
526            is a bug in allocating these fields. */
527
528         result->utok.uid = -1;
529         result->utok.gid = -1;
530         return result;
531 }
532
533 static char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
534 {
535         fstring tmp;
536
537         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
538         return talloc_strdup(mem_ctx, tmp);
539 }
540
541 /***************************************************************************
542  Is the incoming username our own machine account ?
543  If so, the connection is almost certainly from winbindd.
544 ***************************************************************************/
545
546 static bool is_our_machine_account(const char *username)
547 {
548         bool ret;
549         char *truncname = NULL;
550         size_t ulen = strlen(username);
551
552         if (ulen == 0 || username[ulen-1] != '$') {
553                 return false;
554         }
555         truncname = SMB_STRDUP(username);
556         if (!truncname) {
557                 return false;
558         }
559         truncname[ulen-1] = '\0';
560         ret = strequal(truncname, global_myname());
561         SAFE_FREE(truncname);
562         return ret;
563 }
564
565 /***************************************************************************
566  Make (and fill) a user_info struct from a struct samu
567 ***************************************************************************/
568
569 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
570                               struct samu *sampass)
571 {
572         struct passwd *pwd;
573         gid_t *gids;
574         auth_serversupplied_info *result;
575         int i;
576         size_t num_gids;
577         DOM_SID unix_group_sid;
578         const char *username = pdb_get_username(sampass);
579         NTSTATUS status;
580
581         if ( !(result = make_server_info(NULL)) ) {
582                 return NT_STATUS_NO_MEMORY;
583         }
584
585         if ( !(pwd = getpwnam_alloc(result, username)) ) {
586                 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
587                           pdb_get_username(sampass)));
588                 TALLOC_FREE(result);
589                 return NT_STATUS_NO_SUCH_USER;
590         }
591
592         result->sam_account = sampass;
593         result->unix_name = pwd->pw_name;
594         /* Ensure that we keep pwd->pw_name, because we will free pwd below */
595         talloc_steal(result, pwd->pw_name);
596         result->utok.gid = pwd->pw_gid;
597         result->utok.uid = pwd->pw_uid;
598
599         TALLOC_FREE(pwd);
600
601         result->sanitized_username = sanitize_username(result,
602                                                        result->unix_name);
603         if (result->sanitized_username == NULL) {
604                 TALLOC_FREE(result);
605                 return NT_STATUS_NO_MEMORY;
606         }
607
608         if (IS_DC && is_our_machine_account(username)) {
609                 /*
610                  * Ensure for a connection from our own
611                  * machine account (from winbindd on a DC)
612                  * there are no supplementary groups.
613                  * Prevents loops in calling gid_to_sid().
614                  */
615                 result->sids = NULL;
616                 gids = NULL;
617                 result->num_sids = 0;
618
619                 /*
620                  * This is a hack of monstrous proportions.
621                  * If we know it's winbindd talking to us,
622                  * we know we must never recurse into it,
623                  * so turn off contacting winbindd for this
624                  * entire process. This will get fixed when
625                  * winbindd doesn't need to talk to smbd on
626                  * a PDC. JRA.
627                  */
628
629                 (void)winbind_off();
630
631                 DEBUG(10, ("make_server_info_sam: our machine account %s "
632                         "setting supplementary group list empty and "
633                         "turning off winbindd requests.\n",
634                         username));
635         } else {
636                 status = pdb_enum_group_memberships(result, sampass,
637                                             &result->sids, &gids,
638                                             &result->num_sids);
639
640                 if (!NT_STATUS_IS_OK(status)) {
641                         DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
642                                    nt_errstr(status)));
643                         result->sam_account = NULL; /* Don't free on error exit. */
644                         TALLOC_FREE(result);
645                         return status;
646                 }
647         }
648
649         /* Add the "Unix Group" SID for each gid to catch mapped groups
650            and their Unix equivalent.  This is to solve the backwards 
651            compatibility problem of 'valid users = +ntadmin' where 
652            ntadmin has been paired with "Domain Admins" in the group 
653            mapping table.  Otherwise smb.conf would need to be changed
654            to 'valid user = "Domain Admins"'.  --jerry */
655         
656         num_gids = result->num_sids;
657         for ( i=0; i<num_gids; i++ ) {
658                 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
659                         DEBUG(1,("make_server_info_sam: Failed to create SID "
660                                 "for gid %d!\n", gids[i]));
661                         continue;
662                 }
663                 status = add_sid_to_array_unique(result, &unix_group_sid,
664                                                  &result->sids,
665                                                  &result->num_sids);
666                 if (!NT_STATUS_IS_OK(status)) {
667                         result->sam_account = NULL; /* Don't free on error exit. */
668                         TALLOC_FREE(result);
669                         return status;
670                 }
671         }
672
673         /* For now we throw away the gids and convert via sid_to_gid
674          * later. This needs fixing, but I'd like to get the code straight and
675          * simple first. */
676          
677         TALLOC_FREE(gids);
678
679         DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
680                  pdb_get_username(sampass), result->unix_name));
681
682         *server_info = result;
683         /* Ensure that the sampass will be freed with the result */
684         talloc_steal(result, sampass);
685
686         return NT_STATUS_OK;
687 }
688
689 static NTSTATUS log_nt_token(NT_USER_TOKEN *token)
690 {
691         TALLOC_CTX *frame = talloc_stackframe();
692         char *command;
693         char *group_sidstr;
694         size_t i;
695
696         if ((lp_log_nt_token_command() == NULL) ||
697             (strlen(lp_log_nt_token_command()) == 0)) {
698                 TALLOC_FREE(frame);
699                 return NT_STATUS_OK;
700         }
701
702         group_sidstr = talloc_strdup(frame, "");
703         for (i=1; i<token->num_sids; i++) {
704                 group_sidstr = talloc_asprintf(
705                         frame, "%s %s", group_sidstr,
706                         sid_string_talloc(frame, &token->user_sids[i]));
707         }
708
709         command = talloc_string_sub(
710                 frame, lp_log_nt_token_command(),
711                 "%s", sid_string_talloc(frame, &token->user_sids[0]));
712         command = talloc_string_sub(frame, command, "%t", group_sidstr);
713
714         if (command == NULL) {
715                 TALLOC_FREE(frame);
716                 return NT_STATUS_NO_MEMORY;
717         }
718
719         DEBUG(8, ("running command: [%s]\n", command));
720         if (smbrun(command, NULL) != 0) {
721                 DEBUG(0, ("Could not log NT token\n"));
722                 TALLOC_FREE(frame);
723                 return NT_STATUS_ACCESS_DENIED;
724         }
725
726         TALLOC_FREE(frame);
727         return NT_STATUS_OK;
728 }
729
730 /*
731  * Create the token to use from server_info->sam_account and
732  * server_info->sids (the info3/sam groups). Find the unix gids.
733  */
734
735 NTSTATUS create_local_token(auth_serversupplied_info *server_info)
736 {
737         NTSTATUS status;
738         size_t i;
739         struct dom_sid tmp_sid;
740
741         /*
742          * If winbind is not around, we can not make much use of the SIDs the
743          * domain controller provided us with. Likewise if the user name was
744          * mapped to some local unix user.
745          */
746
747         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
748             (server_info->nss_token)) {
749                 status = create_token_from_username(server_info,
750                                                     server_info->unix_name,
751                                                     server_info->guest,
752                                                     &server_info->utok.uid,
753                                                     &server_info->utok.gid,
754                                                     &server_info->unix_name,
755                                                     &server_info->ptok);
756
757         } else {
758                 server_info->ptok = create_local_nt_token(
759                         server_info,
760                         pdb_get_user_sid(server_info->sam_account),
761                         server_info->guest,
762                         server_info->num_sids, server_info->sids);
763                 status = server_info->ptok ?
764                         NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
765         }
766
767         if (!NT_STATUS_IS_OK(status)) {
768                 return status;
769         }
770
771         /* Convert the SIDs to gids. */
772
773         server_info->utok.ngroups = 0;
774         server_info->utok.groups = NULL;
775
776         /* Start at index 1, where the groups start. */
777
778         for (i=1; i<server_info->ptok->num_sids; i++) {
779                 gid_t gid;
780                 DOM_SID *sid = &server_info->ptok->user_sids[i];
781
782                 if (!sid_to_gid(sid, &gid)) {
783                         DEBUG(10, ("Could not convert SID %s to gid, "
784                                    "ignoring it\n", sid_string_dbg(sid)));
785                         continue;
786                 }
787                 add_gid_to_array_unique(server_info, gid,
788                                         &server_info->utok.groups,
789                                         &server_info->utok.ngroups);
790         }
791
792         /*
793          * Add the "Unix Group" SID for each gid to catch mapped groups
794          * and their Unix equivalent.  This is to solve the backwards
795          * compatibility problem of 'valid users = +ntadmin' where
796          * ntadmin has been paired with "Domain Admins" in the group
797          * mapping table.  Otherwise smb.conf would need to be changed
798          * to 'valid user = "Domain Admins"'.  --jerry
799          *
800          * For consistency we also add the "Unix User" SID,
801          * so that the complete unix token is represented within
802          * the nt token.
803          */
804
805         if (!uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid)) {
806                 DEBUG(1,("create_local_token: Failed to create SID "
807                         "for uid %d!\n", server_info->utok.uid));
808         }
809         add_sid_to_array_unique(server_info->ptok, &tmp_sid,
810                                 &server_info->ptok->user_sids,
811                                 &server_info->ptok->num_sids);
812
813         for ( i=0; i<server_info->utok.ngroups; i++ ) {
814                 if (!gid_to_unix_groups_sid( server_info->utok.groups[i], &tmp_sid ) ) {
815                         DEBUG(1,("create_local_token: Failed to create SID "
816                                 "for gid %d!\n", server_info->utok.groups[i]));
817                         continue;
818                 }
819                 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
820                                         &server_info->ptok->user_sids,
821                                         &server_info->ptok->num_sids);
822         }
823
824         debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
825         debug_unix_user_token(DBGC_AUTH, 10,
826                               server_info->utok.uid,
827                               server_info->utok.gid,
828                               server_info->utok.ngroups,
829                               server_info->utok.groups);
830
831         status = log_nt_token(server_info->ptok);
832         return status;
833 }
834
835 /*
836  * Create an artificial NT token given just a username. (Initially indended
837  * for force user)
838  *
839  * We go through lookup_name() to avoid problems we had with 'winbind use
840  * default domain'.
841  *
842  * We have 3 cases:
843  *
844  * unmapped unix users: Go directly to nss to find the user's group.
845  *
846  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
847  *
848  * If the user is provided by winbind, the primary gid is set to "domain
849  * users" of the user's domain. For an explanation why this is necessary, see
850  * the thread starting at
851  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
852  */
853
854 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
855                                     bool is_guest,
856                                     uid_t *uid, gid_t *gid,
857                                     char **found_username,
858                                     struct nt_user_token **token)
859 {
860         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
861         TALLOC_CTX *tmp_ctx;
862         DOM_SID user_sid;
863         enum lsa_SidType type;
864         gid_t *gids;
865         DOM_SID *group_sids;
866         DOM_SID unix_group_sid;
867         size_t num_group_sids;
868         size_t num_gids;
869         size_t i;
870
871         tmp_ctx = talloc_new(NULL);
872         if (tmp_ctx == NULL) {
873                 DEBUG(0, ("talloc_new failed\n"));
874                 return NT_STATUS_NO_MEMORY;
875         }
876
877         if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
878                          NULL, NULL, &user_sid, &type)) {
879                 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
880                 goto done;
881         }
882
883         if (type != SID_NAME_USER) {
884                 DEBUG(1, ("%s is a %s, not a user\n", username,
885                           sid_type_lookup(type)));
886                 goto done;
887         }
888
889         if (!sid_to_uid(&user_sid, uid)) {
890                 DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
891                           username, sid_string_dbg(&user_sid)));
892                 goto done;
893         }
894
895         if (sid_check_is_in_our_domain(&user_sid)) {
896                 bool ret;
897
898                 /* This is a passdb user, so ask passdb */
899
900                 struct samu *sam_acct = NULL;
901
902                 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
903                         result = NT_STATUS_NO_MEMORY;
904                         goto done;
905                 }
906
907                 become_root();
908                 ret = pdb_getsampwsid(sam_acct, &user_sid);
909                 unbecome_root();
910
911                 if (!ret) {
912                         DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
913                                   sid_string_dbg(&user_sid), username));
914                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
915                         goto unix_user;
916                 }
917
918                 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
919                                                     &group_sids, &gids,
920                                                     &num_group_sids);
921                 if (!NT_STATUS_IS_OK(result)) {
922                         DEBUG(10, ("enum_group_memberships failed for %s\n",
923                                    username));
924                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
925                         goto unix_user;
926                 }
927
928                 /* see the smb_panic() in pdb_default_enum_group_memberships */
929                 SMB_ASSERT(num_group_sids > 0); 
930
931                 *gid = gids[0];
932
933                 /* Ensure we're returning the found_username on the right context. */
934                 *found_username = talloc_strdup(mem_ctx,
935                                                 pdb_get_username(sam_acct));
936
937         } else  if (sid_check_is_in_unix_users(&user_sid)) {
938
939                 /* This is a unix user not in passdb. We need to ask nss
940                  * directly, without consulting passdb */
941
942                 struct passwd *pass;
943
944                 /*
945                  * This goto target is used as a fallback for the passdb
946                  * case. The concrete bug report is when passdb gave us an
947                  * unmapped gid.
948                  */
949
950         unix_user:
951
952                 uid_to_unix_users_sid(*uid, &user_sid);
953
954                 pass = getpwuid_alloc(tmp_ctx, *uid);
955                 if (pass == NULL) {
956                         DEBUG(1, ("getpwuid(%d) for user %s failed\n",
957                                   *uid, username));
958                         goto done;
959                 }
960
961                 if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
962                                          &gids, &num_group_sids)) {
963                         DEBUG(1, ("getgroups_unix_user for user %s failed\n",
964                                   username));
965                         goto done;
966                 }
967
968                 if (num_group_sids) {
969                         group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
970                         if (group_sids == NULL) {
971                                 DEBUG(1, ("TALLOC_ARRAY failed\n"));
972                                 result = NT_STATUS_NO_MEMORY;
973                                 goto done;
974                         }
975                 } else {
976                         group_sids = NULL;
977                 }
978
979                 for (i=0; i<num_group_sids; i++) {
980                         gid_to_sid(&group_sids[i], gids[i]);
981                 }
982
983                 /* In getgroups_unix_user we always set the primary gid */
984                 SMB_ASSERT(num_group_sids > 0); 
985
986                 *gid = gids[0];
987
988                 /* Ensure we're returning the found_username on the right context. */
989                 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
990         } else {
991
992                 /* This user is from winbind, force the primary gid to the
993                  * user's "domain users" group. Under certain circumstances
994                  * (user comes from NT4), this might be a loss of
995                  * information. But we can not rely on winbind getting the
996                  * correct info. AD might prohibit winbind looking up that
997                  * information. */
998
999                 uint32 dummy;
1000
1001                 num_group_sids = 1;
1002                 group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
1003                 if (group_sids == NULL) {
1004                         DEBUG(1, ("TALLOC_ARRAY failed\n"));
1005                         result = NT_STATUS_NO_MEMORY;
1006                         goto done;
1007                 }
1008
1009                 sid_copy(&group_sids[0], &user_sid);
1010                 sid_split_rid(&group_sids[0], &dummy);
1011                 sid_append_rid(&group_sids[0], DOMAIN_GROUP_RID_USERS);
1012
1013                 if (!sid_to_gid(&group_sids[0], gid)) {
1014                         DEBUG(1, ("sid_to_gid(%s) failed\n",
1015                                   sid_string_dbg(&group_sids[0])));
1016                         goto done;
1017                 }
1018
1019                 gids = gid;
1020
1021                 /* Ensure we're returning the found_username on the right context. */
1022                 *found_username = talloc_strdup(mem_ctx, username);
1023         }
1024
1025         /* Add the "Unix Group" SID for each gid to catch mapped groups
1026            and their Unix equivalent.  This is to solve the backwards
1027            compatibility problem of 'valid users = +ntadmin' where
1028            ntadmin has been paired with "Domain Admins" in the group
1029            mapping table.  Otherwise smb.conf would need to be changed
1030            to 'valid user = "Domain Admins"'.  --jerry */
1031
1032         num_gids = num_group_sids;
1033         for ( i=0; i<num_gids; i++ ) {
1034                 gid_t high, low;
1035
1036                 /* don't pickup anything managed by Winbind */
1037
1038                 if ( lp_idmap_gid(&low, &high) && (gids[i] >= low) && (gids[i] <= high) )
1039                         continue;
1040
1041                 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
1042                         DEBUG(1,("create_token_from_username: Failed to create SID "
1043                                 "for gid %d!\n", gids[i]));
1044                         continue;
1045                 }
1046                 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
1047                                                  &group_sids, &num_group_sids);
1048                 if (!NT_STATUS_IS_OK(result)) {
1049                         goto done;
1050                 }
1051         }
1052
1053         /* Ensure we're creating the nt_token on the right context. */
1054         *token = create_local_nt_token(mem_ctx, &user_sid,
1055                                        is_guest, num_group_sids, group_sids);
1056
1057         if ((*token == NULL) || (*found_username == NULL)) {
1058                 result = NT_STATUS_NO_MEMORY;
1059                 goto done;
1060         }
1061
1062         result = NT_STATUS_OK;
1063  done:
1064         TALLOC_FREE(tmp_ctx);
1065         return result;
1066 }
1067
1068 /***************************************************************************
1069  Build upon create_token_from_username:
1070
1071  Expensive helper function to figure out whether a user given its name is
1072  member of a particular group.
1073 ***************************************************************************/
1074
1075 bool user_in_group_sid(const char *username, const DOM_SID *group_sid)
1076 {
1077         NTSTATUS status;
1078         uid_t uid;
1079         gid_t gid;
1080         char *found_username;
1081         struct nt_user_token *token;
1082         bool result;
1083
1084         TALLOC_CTX *mem_ctx;
1085
1086         mem_ctx = talloc_new(NULL);
1087         if (mem_ctx == NULL) {
1088                 DEBUG(0, ("talloc_new failed\n"));
1089                 return False;
1090         }
1091
1092         status = create_token_from_username(mem_ctx, username, False,
1093                                             &uid, &gid, &found_username,
1094                                             &token);
1095
1096         if (!NT_STATUS_IS_OK(status)) {
1097                 DEBUG(10, ("could not create token for %s\n", username));
1098                 return False;
1099         }
1100
1101         result = nt_token_check_sid(group_sid, token);
1102
1103         TALLOC_FREE(mem_ctx);
1104         return result;
1105         
1106 }
1107
1108 bool user_in_group(const char *username, const char *groupname)
1109 {
1110         TALLOC_CTX *mem_ctx;
1111         DOM_SID group_sid;
1112         bool ret;
1113
1114         mem_ctx = talloc_new(NULL);
1115         if (mem_ctx == NULL) {
1116                 DEBUG(0, ("talloc_new failed\n"));
1117                 return False;
1118         }
1119
1120         ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
1121                           NULL, NULL, &group_sid, NULL);
1122         TALLOC_FREE(mem_ctx);
1123
1124         if (!ret) {
1125                 DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
1126                 return False;
1127         }
1128
1129         return user_in_group_sid(username, &group_sid);
1130 }
1131
1132 /***************************************************************************
1133  Make (and fill) a server_info struct from a 'struct passwd' by conversion
1134  to a struct samu
1135 ***************************************************************************/
1136
1137 NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, 
1138                              char *unix_username,
1139                              struct passwd *pwd)
1140 {
1141         NTSTATUS status;
1142         struct samu *sampass = NULL;
1143         gid_t *gids;
1144         char *qualified_name = NULL;
1145         TALLOC_CTX *mem_ctx = NULL;
1146         DOM_SID u_sid;
1147         enum lsa_SidType type;
1148         auth_serversupplied_info *result;
1149         
1150         if ( !(sampass = samu_new( NULL )) ) {
1151                 return NT_STATUS_NO_MEMORY;
1152         }
1153         
1154         status = samu_set_unix( sampass, pwd );
1155         if (!NT_STATUS_IS_OK(status)) {
1156                 return status;
1157         }
1158
1159         result = make_server_info(NULL);
1160         if (result == NULL) {
1161                 TALLOC_FREE(sampass);
1162                 return NT_STATUS_NO_MEMORY;
1163         }
1164
1165         result->sam_account = sampass;
1166
1167         result->unix_name = talloc_strdup(result, unix_username);
1168         result->sanitized_username = sanitize_username(result, unix_username);
1169
1170         if ((result->unix_name == NULL)
1171             || (result->sanitized_username == NULL)) {
1172                 TALLOC_FREE(sampass);
1173                 TALLOC_FREE(result);
1174                 return NT_STATUS_NO_MEMORY;
1175         }
1176
1177         result->utok.uid = pwd->pw_uid;
1178         result->utok.gid = pwd->pw_gid;
1179
1180         status = pdb_enum_group_memberships(result, sampass,
1181                                             &result->sids, &gids,
1182                                             &result->num_sids);
1183
1184         if (!NT_STATUS_IS_OK(status)) {
1185                 DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
1186                            nt_errstr(status)));
1187                 TALLOC_FREE(result);
1188                 return status;
1189         }
1190
1191         /*
1192          * The SID returned in server_info->sam_account is based
1193          * on our SAM sid even though for a pure UNIX account this should
1194          * not be the case as it doesn't really exist in the SAM db.
1195          * This causes lookups on "[in]valid users" to fail as they
1196          * will lookup this name as a "Unix User" SID to check against
1197          * the user token. Fix this by adding the "Unix User"\unix_username
1198          * SID to the sid array. The correct fix should probably be
1199          * changing the server_info->sam_account user SID to be a
1200          * S-1-22 Unix SID, but this might break old configs where
1201          * plaintext passwords were used with no SAM backend.
1202          */
1203
1204         mem_ctx = talloc_init("make_server_info_pw_tmp");
1205         if (!mem_ctx) {
1206                 TALLOC_FREE(result);
1207                 return NT_STATUS_NO_MEMORY;
1208         }
1209
1210         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
1211                                         unix_users_domain_name(),
1212                                         unix_username );
1213         if (!qualified_name) {
1214                 TALLOC_FREE(result);
1215                 TALLOC_FREE(mem_ctx);
1216                 return NT_STATUS_NO_MEMORY;
1217         }
1218
1219         if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
1220                                                 NULL, NULL,
1221                                                 &u_sid, &type)) {
1222                 TALLOC_FREE(result);
1223                 TALLOC_FREE(mem_ctx);
1224                 return NT_STATUS_NO_SUCH_USER;
1225         }
1226
1227         TALLOC_FREE(mem_ctx);
1228
1229         if (type != SID_NAME_USER) {
1230                 TALLOC_FREE(result);
1231                 return NT_STATUS_NO_SUCH_USER;
1232         }
1233
1234         status = add_sid_to_array_unique(result, &u_sid,
1235                                          &result->sids,
1236                                          &result->num_sids);
1237         if (!NT_STATUS_IS_OK(status)) {
1238                 TALLOC_FREE(result);
1239                 return status;
1240         }
1241
1242         /* For now we throw away the gids and convert via sid_to_gid
1243          * later. This needs fixing, but I'd like to get the code straight and
1244          * simple first. */
1245         TALLOC_FREE(gids);
1246
1247         *server_info = result;
1248
1249         return NT_STATUS_OK;
1250 }
1251
1252 /***************************************************************************
1253  Make (and fill) a user_info struct for a guest login.
1254  This *must* succeed for smbd to start. If there is no mapping entry for
1255  the guest gid, then create one.
1256 ***************************************************************************/
1257
1258 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
1259 {
1260         NTSTATUS status;
1261         struct samu *sampass = NULL;
1262         DOM_SID guest_sid;
1263         bool ret;
1264         char zeros[16];
1265         fstring tmp;
1266
1267         if ( !(sampass = samu_new( NULL )) ) {
1268                 return NT_STATUS_NO_MEMORY;
1269         }
1270
1271         sid_copy(&guest_sid, get_global_sam_sid());
1272         sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
1273
1274         become_root();
1275         ret = pdb_getsampwsid(sampass, &guest_sid);
1276         unbecome_root();
1277
1278         if (!ret) {
1279                 TALLOC_FREE(sampass);
1280                 return NT_STATUS_NO_SUCH_USER;
1281         }
1282
1283         status = make_server_info_sam(server_info, sampass);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 TALLOC_FREE(sampass);
1286                 return status;
1287         }
1288         
1289         (*server_info)->guest = True;
1290
1291         status = create_local_token(*server_info);
1292         if (!NT_STATUS_IS_OK(status)) {
1293                 DEBUG(10, ("create_local_token failed: %s\n",
1294                            nt_errstr(status)));
1295                 return status;
1296         }
1297
1298         /* annoying, but the Guest really does have a session key, and it is
1299            all zeros! */
1300         ZERO_STRUCT(zeros);
1301         (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
1302         (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
1303
1304         alpha_strcpy(tmp, pdb_get_username(sampass), ". _-$", sizeof(tmp));
1305         (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
1306
1307         return NT_STATUS_OK;
1308 }
1309
1310 /****************************************************************************
1311   Fake a auth_serversupplied_info just from a username
1312 ****************************************************************************/
1313
1314 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
1315                                        const char *username,
1316                                        bool is_guest,
1317                                        struct auth_serversupplied_info **presult)
1318 {
1319         struct auth_serversupplied_info *result;
1320         struct passwd *pwd;
1321         NTSTATUS status;
1322
1323         pwd = getpwnam_alloc(talloc_tos(), username);
1324         if (pwd == NULL) {
1325                 return NT_STATUS_NO_SUCH_USER;
1326         }
1327
1328         status = make_server_info_pw(&result, pwd->pw_name, pwd);
1329
1330         TALLOC_FREE(pwd);
1331
1332         if (!NT_STATUS_IS_OK(status)) {
1333                 return status;
1334         }
1335
1336         result->nss_token = true;
1337         result->guest = is_guest;
1338
1339         status = create_local_token(result);
1340
1341         if (!NT_STATUS_IS_OK(status)) {
1342                 TALLOC_FREE(result);
1343                 return status;
1344         }
1345
1346         *presult = result;
1347         return NT_STATUS_OK;
1348 }
1349
1350
1351 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
1352                                                  const auth_serversupplied_info *src)
1353 {
1354         auth_serversupplied_info *dst;
1355
1356         dst = make_server_info(mem_ctx);
1357         if (dst == NULL) {
1358                 return NULL;
1359         }
1360
1361         dst->guest = src->guest;
1362         dst->utok.uid = src->utok.uid;
1363         dst->utok.gid = src->utok.gid;
1364         dst->utok.ngroups = src->utok.ngroups;
1365         if (src->utok.ngroups != 0) {
1366                 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
1367                         dst, src->utok.groups,
1368                         sizeof(gid_t)*dst->utok.ngroups);
1369         } else {
1370                 dst->utok.groups = NULL;
1371         }
1372
1373         if (src->ptok) {
1374                 dst->ptok = dup_nt_token(dst, src->ptok);
1375                 if (!dst->ptok) {
1376                         TALLOC_FREE(dst);
1377                         return NULL;
1378                 }
1379         }
1380         
1381         dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
1382                                                 src->user_session_key.length);
1383
1384         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
1385                                                 src->lm_session_key.length);
1386
1387         dst->sam_account = samu_new(NULL);
1388         if (!dst->sam_account) {
1389                 TALLOC_FREE(dst);
1390                 return NULL;
1391         }
1392
1393         if (!pdb_copy_sam_account(dst->sam_account, src->sam_account)) {
1394                 TALLOC_FREE(dst);
1395                 return NULL;
1396         }
1397         
1398         dst->pam_handle = NULL;
1399         dst->unix_name = talloc_strdup(dst, src->unix_name);
1400         if (!dst->unix_name) {
1401                 TALLOC_FREE(dst);
1402                 return NULL;
1403         }
1404
1405         dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
1406         if (!dst->sanitized_username) {
1407                 TALLOC_FREE(dst);
1408                 return NULL;
1409         }
1410
1411         return dst;
1412 }
1413
1414 /*
1415  * Set a new session key. Used in the rpc server where we have to override the
1416  * SMB level session key with SystemLibraryDTC
1417  */
1418
1419 bool server_info_set_session_key(struct auth_serversupplied_info *info,
1420                                  DATA_BLOB session_key)
1421 {
1422         TALLOC_FREE(info->user_session_key.data);
1423
1424         info->user_session_key = data_blob_talloc(
1425                 info, session_key.data, session_key.length);
1426
1427         return (info->user_session_key.data != NULL);
1428 }
1429
1430 static auth_serversupplied_info *guest_info = NULL;
1431
1432 bool init_guest_info(void)
1433 {
1434         if (guest_info != NULL)
1435                 return True;
1436
1437         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1438 }
1439
1440 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1441                                 auth_serversupplied_info **server_info)
1442 {
1443         *server_info = copy_serverinfo(mem_ctx, guest_info);
1444         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1445 }
1446
1447 bool copy_current_user(struct current_user *dst, struct current_user *src)
1448 {
1449         gid_t *groups;
1450         NT_USER_TOKEN *nt_token;
1451
1452         groups = (gid_t *)memdup(src->ut.groups,
1453                                  sizeof(gid_t) * src->ut.ngroups);
1454         if ((src->ut.ngroups != 0) && (groups == NULL)) {
1455                 return False;
1456         }
1457
1458         nt_token = dup_nt_token(NULL, src->nt_user_token);
1459         if (nt_token == NULL) {
1460                 SAFE_FREE(groups);
1461                 return False;
1462         }
1463
1464         dst->conn = src->conn;
1465         dst->vuid = src->vuid;
1466         dst->ut.uid = src->ut.uid;
1467         dst->ut.gid = src->ut.gid;
1468         dst->ut.ngroups = src->ut.ngroups;
1469         dst->ut.groups = groups;
1470         dst->nt_user_token = nt_token;
1471         return True;
1472 }
1473
1474 /***************************************************************************
1475  Purely internal function for make_server_info_info3
1476  Fill the sam account from getpwnam
1477 ***************************************************************************/
1478 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, 
1479                                  const char *domain,
1480                                  const char *username,
1481                                  char **found_username,
1482                                  uid_t *uid, gid_t *gid,
1483                                  struct samu *account,
1484                                  bool *username_was_mapped)
1485 {
1486         NTSTATUS nt_status;
1487         fstring dom_user, lower_username;
1488         fstring real_username;
1489         struct passwd *passwd;
1490
1491         fstrcpy( lower_username, username );
1492         strlower_m( lower_username );
1493
1494         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
1495                 lower_username);
1496
1497         /* Get the passwd struct.  Try to create the account is necessary. */
1498
1499         *username_was_mapped = map_username( dom_user );
1500
1501         if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
1502                 return NT_STATUS_NO_SUCH_USER;
1503
1504         *uid = passwd->pw_uid;
1505         *gid = passwd->pw_gid;
1506
1507         /* This is pointless -- there is no suport for differing 
1508            unix and windows names.  Make sure to always store the 
1509            one we actually looked up and succeeded. Have I mentioned
1510            why I hate the 'winbind use default domain' parameter?   
1511                                          --jerry              */
1512            
1513         *found_username = talloc_strdup( mem_ctx, real_username );
1514         
1515         DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
1516
1517         nt_status = samu_set_unix( account, passwd );
1518         
1519         TALLOC_FREE(passwd);
1520         
1521         return nt_status;
1522 }
1523
1524 /****************************************************************************
1525  Wrapper to allow the getpwnam() call to strip the domain name and 
1526  try again in case a local UNIX user is already there.  Also run through 
1527  the username if we fallback to the username only.
1528  ****************************************************************************/
1529  
1530 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
1531                              fstring save_username, bool create )
1532 {
1533         struct passwd *pw = NULL;
1534         char *p;
1535         fstring username;
1536         
1537         /* we only save a copy of the username it has been mangled 
1538            by winbindd use default domain */
1539            
1540         save_username[0] = '\0';
1541            
1542         /* don't call map_username() here since it has to be done higher 
1543            up the stack so we don't call it mutliple times */
1544
1545         fstrcpy( username, domuser );
1546         
1547         p = strchr_m( username, *lp_winbind_separator() );
1548         
1549         /* code for a DOMAIN\user string */
1550         
1551         if ( p ) {
1552                 fstring strip_username;
1553
1554                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1555                 if ( pw ) {     
1556                         /* make sure we get the case of the username correct */
1557                         /* work around 'winbind use default domain = yes' */
1558
1559                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1560                                 char *domain;
1561                                 
1562                                 /* split the domain and username into 2 strings */
1563                                 *p = '\0';
1564                                 domain = username;
1565
1566                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1567                         }
1568                         else
1569                                 fstrcpy( save_username, pw->pw_name );
1570
1571                         /* whew -- done! */             
1572                         return pw;
1573                 }
1574
1575                 /* setup for lookup of just the username */
1576                 /* remember that p and username are overlapping memory */
1577
1578                 p++;
1579                 fstrcpy( strip_username, p );
1580                 fstrcpy( username, strip_username );
1581         }
1582         
1583         /* just lookup a plain username */
1584         
1585         pw = Get_Pwnam_alloc(mem_ctx, username);
1586                 
1587         /* Create local user if requested but only if winbindd
1588            is not running.  We need to protect against cases
1589            where winbindd is failing and then prematurely
1590            creating users in /etc/passwd */
1591         
1592         if ( !pw && create && !winbind_ping() ) {
1593                 /* Don't add a machine account. */
1594                 if (username[strlen(username)-1] == '$')
1595                         return NULL;
1596
1597                 smb_create_user(NULL, username, NULL);
1598                 pw = Get_Pwnam_alloc(mem_ctx, username);
1599         }
1600         
1601         /* one last check for a valid passwd struct */
1602         
1603         if ( pw )
1604                 fstrcpy( save_username, pw->pw_name );
1605
1606         return pw;
1607 }
1608
1609 /***************************************************************************
1610  Make a server_info struct from the info3 returned by a domain logon 
1611 ***************************************************************************/
1612
1613 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1614                                 const char *sent_nt_username,
1615                                 const char *domain,
1616                                 auth_serversupplied_info **server_info, 
1617                                 struct netr_SamInfo3 *info3)
1618 {
1619         char zeros[16];
1620
1621         NTSTATUS nt_status = NT_STATUS_OK;
1622         char *found_username = NULL;
1623         const char *nt_domain;
1624         const char *nt_username;
1625         struct samu *sam_account = NULL;
1626         DOM_SID user_sid;
1627         DOM_SID group_sid;
1628         bool username_was_mapped;
1629
1630         uid_t uid = (uid_t)-1;
1631         gid_t gid = (gid_t)-1;
1632
1633         auth_serversupplied_info *result;
1634
1635         /* 
1636            Here is where we should check the list of
1637            trusted domains, and verify that the SID 
1638            matches.
1639         */
1640
1641         sid_copy(&user_sid, info3->base.domain_sid);
1642         if (!sid_append_rid(&user_sid, info3->base.rid)) {
1643                 return NT_STATUS_INVALID_PARAMETER;
1644         }
1645         
1646         sid_copy(&group_sid, info3->base.domain_sid);
1647         if (!sid_append_rid(&group_sid, info3->base.primary_gid)) {
1648                 return NT_STATUS_INVALID_PARAMETER;
1649         }
1650
1651         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1652         if (!nt_username) {
1653                 /* If the server didn't give us one, just use the one we sent
1654                  * them */
1655                 nt_username = sent_nt_username;
1656         }
1657
1658         nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1659         if (!nt_domain) {
1660                 /* If the server didn't give us one, just use the one we sent
1661                  * them */
1662                 nt_domain = domain;
1663         }
1664         
1665         /* try to fill the SAM account..  If getpwnam() fails, then try the 
1666            add user script (2.2.x behavior).
1667
1668            We use the _unmapped_ username here in an attempt to provide
1669            consistent username mapping behavior between kerberos and NTLM[SSP]
1670            authentication in domain mode security.  I.E. Username mapping
1671            should be applied to the fully qualified username
1672            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1673            called map_username() unnecessarily in make_user_info_map() but
1674            that is how the current code is designed.  Making the change here
1675            is the least disruptive place.  -- jerry */
1676            
1677         if ( !(sam_account = samu_new( NULL )) ) {
1678                 return NT_STATUS_NO_MEMORY;
1679         }
1680
1681         /* this call will try to create the user if necessary */
1682
1683         nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1684                                      &found_username, &uid, &gid, sam_account,
1685                                      &username_was_mapped);
1686
1687         
1688         /* if we still don't have a valid unix account check for 
1689           'map to guest = bad uid' */
1690           
1691         if (!NT_STATUS_IS_OK(nt_status)) {
1692                 TALLOC_FREE( sam_account );
1693                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1694                         make_server_info_guest(NULL, server_info);
1695                         return NT_STATUS_OK;
1696                 }
1697                 return nt_status;
1698         }
1699                 
1700         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1701                 TALLOC_FREE(sam_account);
1702                 return NT_STATUS_NO_MEMORY;
1703         }
1704
1705         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1706                 TALLOC_FREE(sam_account);
1707                 return NT_STATUS_NO_MEMORY;
1708         }
1709
1710         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1711                 TALLOC_FREE(sam_account);
1712                 return NT_STATUS_NO_MEMORY;
1713         }
1714
1715         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1716                 TALLOC_FREE(sam_account);
1717                 return NT_STATUS_UNSUCCESSFUL;
1718         }
1719
1720         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1721                 TALLOC_FREE(sam_account);
1722                 return NT_STATUS_UNSUCCESSFUL;
1723         }
1724
1725         if (!pdb_set_fullname(sam_account,
1726                               info3->base.full_name.string,
1727                               PDB_CHANGED)) {
1728                 TALLOC_FREE(sam_account);
1729                 return NT_STATUS_NO_MEMORY;
1730         }
1731
1732         if (!pdb_set_logon_script(sam_account,
1733                                   info3->base.logon_script.string,
1734                                   PDB_CHANGED)) {
1735                 TALLOC_FREE(sam_account);
1736                 return NT_STATUS_NO_MEMORY;
1737         }
1738
1739         if (!pdb_set_profile_path(sam_account,
1740                                   info3->base.profile_path.string,
1741                                   PDB_CHANGED)) {
1742                 TALLOC_FREE(sam_account);
1743                 return NT_STATUS_NO_MEMORY;
1744         }
1745
1746         if (!pdb_set_homedir(sam_account,
1747                              info3->base.home_directory.string,
1748                              PDB_CHANGED)) {
1749                 TALLOC_FREE(sam_account);
1750                 return NT_STATUS_NO_MEMORY;
1751         }
1752
1753         if (!pdb_set_dir_drive(sam_account,
1754                                info3->base.home_drive.string,
1755                                PDB_CHANGED)) {
1756                 TALLOC_FREE(sam_account);
1757                 return NT_STATUS_NO_MEMORY;
1758         }
1759
1760         if (!pdb_set_acct_ctrl(sam_account, info3->base.acct_flags, PDB_CHANGED)) {
1761                 TALLOC_FREE(sam_account);
1762                 return NT_STATUS_NO_MEMORY;
1763         }
1764
1765         if (!pdb_set_pass_last_set_time(
1766                     sam_account,
1767                     nt_time_to_unix(info3->base.last_password_change),
1768                     PDB_CHANGED)) {
1769                 TALLOC_FREE(sam_account);
1770                 return NT_STATUS_NO_MEMORY;
1771         }
1772
1773         if (!pdb_set_pass_can_change_time(
1774                     sam_account,
1775                     nt_time_to_unix(info3->base.allow_password_change),
1776                     PDB_CHANGED)) {
1777                 TALLOC_FREE(sam_account);
1778                 return NT_STATUS_NO_MEMORY;
1779         }
1780
1781         if (!pdb_set_pass_must_change_time(
1782                     sam_account,
1783                     nt_time_to_unix(info3->base.force_password_change),
1784                     PDB_CHANGED)) {
1785                 TALLOC_FREE(sam_account);
1786                 return NT_STATUS_NO_MEMORY;
1787         }
1788
1789         result = make_server_info(NULL);
1790         if (result == NULL) {
1791                 DEBUG(4, ("make_server_info failed!\n"));
1792                 TALLOC_FREE(sam_account);
1793                 return NT_STATUS_NO_MEMORY;
1794         }
1795
1796         /* save this here to _net_sam_logon() doesn't fail (it assumes a 
1797            valid struct samu) */
1798                    
1799         result->sam_account = sam_account;
1800         result->unix_name = talloc_strdup(result, found_username);
1801
1802         result->sanitized_username = sanitize_username(result,
1803                                                        result->unix_name);
1804         if (result->sanitized_username == NULL) {
1805                 TALLOC_FREE(result);
1806                 return NT_STATUS_NO_MEMORY;
1807         }
1808
1809         /* Fill in the unix info we found on the way */
1810
1811         result->utok.uid = uid;
1812         result->utok.gid = gid;
1813
1814         /* Create a 'combined' list of all SIDs we might want in the SD */
1815
1816         result->num_sids = 0;
1817         result->sids = NULL;
1818
1819         nt_status = sid_array_from_info3(result, info3,
1820                                          &result->sids,
1821                                          &result->num_sids,
1822                                          false, false);
1823         if (!NT_STATUS_IS_OK(nt_status)) {
1824                 TALLOC_FREE(result);
1825                 return nt_status;
1826         }
1827
1828         /* Ensure the primary group sid is at position 0. */
1829         sort_sid_array_for_smbd(result, &group_sid);
1830
1831         result->login_server = talloc_strdup(result,
1832                                              info3->base.logon_server.string);
1833
1834         /* ensure we are never given NULL session keys */
1835
1836         ZERO_STRUCT(zeros);
1837
1838         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1839                 result->user_session_key = data_blob_null;
1840         } else {
1841                 result->user_session_key = data_blob_talloc(
1842                         result, info3->base.key.key,
1843                         sizeof(info3->base.key.key));
1844         }
1845
1846         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1847                 result->lm_session_key = data_blob_null;
1848         } else {
1849                 result->lm_session_key = data_blob_talloc(
1850                         result, info3->base.LMSessKey.key,
1851                         sizeof(info3->base.LMSessKey.key));
1852         }
1853
1854         result->nss_token |= username_was_mapped;
1855
1856         *server_info = result;
1857
1858         return NT_STATUS_OK;
1859 }
1860
1861 /*****************************************************************************
1862  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1863 ******************************************************************************/
1864
1865 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1866                                           const char *sent_nt_username,
1867                                           const char *domain,
1868                                           const struct wbcAuthUserInfo *info,
1869                                           auth_serversupplied_info **server_info)
1870 {
1871         char zeros[16];
1872
1873         NTSTATUS nt_status = NT_STATUS_OK;
1874         char *found_username = NULL;
1875         const char *nt_domain;
1876         const char *nt_username;
1877         struct samu *sam_account = NULL;
1878         DOM_SID user_sid;
1879         DOM_SID group_sid;
1880         bool username_was_mapped;
1881         uint32_t i;
1882
1883         uid_t uid = (uid_t)-1;
1884         gid_t gid = (gid_t)-1;
1885
1886         auth_serversupplied_info *result;
1887
1888         result = make_server_info(NULL);
1889         if (result == NULL) {
1890                 DEBUG(4, ("make_server_info failed!\n"));
1891                 return NT_STATUS_NO_MEMORY;
1892         }
1893
1894         /*
1895            Here is where we should check the list of
1896            trusted domains, and verify that the SID
1897            matches.
1898         */
1899
1900         memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
1901         memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
1902
1903         if (info->account_name) {
1904                 nt_username = talloc_strdup(result, info->account_name);
1905         } else {
1906                 /* If the server didn't give us one, just use the one we sent
1907                  * them */
1908                 nt_username = talloc_strdup(result, sent_nt_username);
1909         }
1910         if (!nt_username) {
1911                 TALLOC_FREE(result);
1912                 return NT_STATUS_NO_MEMORY;
1913         }
1914
1915         if (info->domain_name) {
1916                 nt_domain = talloc_strdup(result, info->domain_name);
1917         } else {
1918                 /* If the server didn't give us one, just use the one we sent
1919                  * them */
1920                 nt_domain = talloc_strdup(result, domain);
1921         }
1922         if (!nt_domain) {
1923                 TALLOC_FREE(result);
1924                 return NT_STATUS_NO_MEMORY;
1925         }
1926
1927         /* try to fill the SAM account..  If getpwnam() fails, then try the
1928            add user script (2.2.x behavior).
1929
1930            We use the _unmapped_ username here in an attempt to provide
1931            consistent username mapping behavior between kerberos and NTLM[SSP]
1932            authentication in domain mode security.  I.E. Username mapping
1933            should be applied to the fully qualified username
1934            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1935            called map_username() unnecessarily in make_user_info_map() but
1936            that is how the current code is designed.  Making the change here
1937            is the least disruptive place.  -- jerry */
1938
1939         if ( !(sam_account = samu_new( result )) ) {
1940                 TALLOC_FREE(result);
1941                 return NT_STATUS_NO_MEMORY;
1942         }
1943
1944         /* this call will try to create the user if necessary */
1945
1946         nt_status = fill_sam_account(result, nt_domain, sent_nt_username,
1947                                      &found_username, &uid, &gid, sam_account,
1948                                      &username_was_mapped);
1949
1950         /* if we still don't have a valid unix account check for
1951           'map to guest = bad uid' */
1952
1953         if (!NT_STATUS_IS_OK(nt_status)) {
1954                 TALLOC_FREE( result );
1955                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1956                         make_server_info_guest(NULL, server_info);
1957                         return NT_STATUS_OK;
1958                 }
1959                 return nt_status;
1960         }
1961
1962         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1963                 TALLOC_FREE(result);
1964                 return NT_STATUS_NO_MEMORY;
1965         }
1966
1967         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1968                 TALLOC_FREE(result);
1969                 return NT_STATUS_NO_MEMORY;
1970         }
1971
1972         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1973                 TALLOC_FREE(result);
1974                 return NT_STATUS_NO_MEMORY;
1975         }
1976
1977         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1978                 TALLOC_FREE(result);
1979                 return NT_STATUS_UNSUCCESSFUL;
1980         }
1981
1982         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1983                 TALLOC_FREE(result);
1984                 return NT_STATUS_UNSUCCESSFUL;
1985         }
1986
1987         if (!pdb_set_fullname(sam_account, info->full_name, PDB_CHANGED)) {
1988                 TALLOC_FREE(result);
1989                 return NT_STATUS_NO_MEMORY;
1990         }
1991
1992         if (!pdb_set_logon_script(sam_account, info->logon_script, PDB_CHANGED)) {
1993                 TALLOC_FREE(result);
1994                 return NT_STATUS_NO_MEMORY;
1995         }
1996
1997         if (!pdb_set_profile_path(sam_account, info->profile_path, PDB_CHANGED)) {
1998                 TALLOC_FREE(result);
1999                 return NT_STATUS_NO_MEMORY;
2000         }
2001
2002         if (!pdb_set_homedir(sam_account, info->home_directory, PDB_CHANGED)) {
2003                 TALLOC_FREE(result);
2004                 return NT_STATUS_NO_MEMORY;
2005         }
2006
2007         if (!pdb_set_dir_drive(sam_account, info->home_drive, PDB_CHANGED)) {
2008                 TALLOC_FREE(result);
2009                 return NT_STATUS_NO_MEMORY;
2010         }
2011
2012         if (!pdb_set_acct_ctrl(sam_account, info->acct_flags, PDB_CHANGED)) {
2013                 TALLOC_FREE(result);
2014                 return NT_STATUS_NO_MEMORY;
2015         }
2016
2017         if (!pdb_set_pass_last_set_time(
2018                     sam_account,
2019                     nt_time_to_unix(info->pass_last_set_time),
2020                     PDB_CHANGED)) {
2021                 TALLOC_FREE(result);
2022                 return NT_STATUS_NO_MEMORY;
2023         }
2024
2025         if (!pdb_set_pass_can_change_time(
2026                     sam_account,
2027                     nt_time_to_unix(info->pass_can_change_time),
2028                     PDB_CHANGED)) {
2029                 TALLOC_FREE(result);
2030                 return NT_STATUS_NO_MEMORY;
2031         }
2032
2033         if (!pdb_set_pass_must_change_time(
2034                     sam_account,
2035                     nt_time_to_unix(info->pass_must_change_time),
2036                     PDB_CHANGED)) {
2037                 TALLOC_FREE(result);
2038                 return NT_STATUS_NO_MEMORY;
2039         }
2040
2041         /* save this here to _net_sam_logon() doesn't fail (it assumes a
2042            valid struct samu) */
2043
2044         result->sam_account = sam_account;
2045         result->unix_name = talloc_strdup(result, found_username);
2046
2047         result->sanitized_username = sanitize_username(result,
2048                                                        result->unix_name);
2049         result->login_server = talloc_strdup(result, info->logon_server);
2050
2051         if ((result->unix_name == NULL)
2052             || (result->sanitized_username == NULL)
2053             || (result->login_server == NULL)) {
2054                 TALLOC_FREE(result);
2055                 return NT_STATUS_NO_MEMORY;
2056         }
2057
2058         /* Fill in the unix info we found on the way */
2059
2060         result->utok.uid = uid;
2061         result->utok.gid = gid;
2062
2063         /* Create a 'combined' list of all SIDs we might want in the SD */
2064
2065         result->num_sids = info->num_sids - 2;
2066         result->sids = talloc_array(result, DOM_SID, result->num_sids);
2067         if (result->sids == NULL) {
2068                 TALLOC_FREE(result);
2069                 return NT_STATUS_NO_MEMORY;
2070         }
2071
2072         for (i=0; i < result->num_sids; i++) {
2073                 memcpy(&result->sids[i], &info->sids[i+2].sid, sizeof(result->sids[i]));
2074         }
2075
2076         /* Ensure the primary group sid is at position 0. */
2077         sort_sid_array_for_smbd(result, &group_sid);
2078
2079         /* ensure we are never given NULL session keys */
2080
2081         ZERO_STRUCT(zeros);
2082
2083         if (memcmp(info->user_session_key, zeros, sizeof(zeros)) == 0) {
2084                 result->user_session_key = data_blob_null;
2085         } else {
2086                 result->user_session_key = data_blob_talloc(
2087                         result, info->user_session_key,
2088                         sizeof(info->user_session_key));
2089         }
2090
2091         if (memcmp(info->lm_session_key, zeros, 8) == 0) {
2092                 result->lm_session_key = data_blob_null;
2093         } else {
2094                 result->lm_session_key = data_blob_talloc(
2095                         result, info->lm_session_key,
2096                         sizeof(info->lm_session_key));
2097         }
2098
2099         result->nss_token |= username_was_mapped;
2100
2101         *server_info = result;
2102
2103         return NT_STATUS_OK;
2104 }
2105
2106 /***************************************************************************
2107  Free a user_info struct
2108 ***************************************************************************/
2109
2110 void free_user_info(auth_usersupplied_info **user_info)
2111 {
2112         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
2113         if (*user_info != NULL) {
2114                 if ((*user_info)->smb_name) {
2115                         DEBUG(10,("structure was created for %s\n",
2116                                   (*user_info)->smb_name));
2117                 }
2118                 SAFE_FREE((*user_info)->smb_name);
2119                 SAFE_FREE((*user_info)->internal_username);
2120                 SAFE_FREE((*user_info)->client_domain);
2121                 SAFE_FREE((*user_info)->domain);
2122                 SAFE_FREE((*user_info)->wksta_name);
2123                 data_blob_free(&(*user_info)->lm_resp);
2124                 data_blob_free(&(*user_info)->nt_resp);
2125                 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
2126                 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
2127                 data_blob_clear_free(&(*user_info)->plaintext_password);
2128                 ZERO_STRUCT(**user_info);
2129         }
2130         SAFE_FREE(*user_info);
2131 }
2132
2133 /***************************************************************************
2134  Make an auth_methods struct
2135 ***************************************************************************/
2136
2137 bool make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
2138 {
2139         if (!auth_context) {
2140                 smb_panic("no auth_context supplied to "
2141                           "make_auth_methods()!\n");
2142         }
2143
2144         if (!auth_method) {
2145                 smb_panic("make_auth_methods: pointer to auth_method pointer "
2146                           "is NULL!\n");
2147         }
2148
2149         *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
2150         if (!*auth_method) {
2151                 DEBUG(0,("make_auth_method: malloc failed!\n"));
2152                 return False;
2153         }
2154         ZERO_STRUCTP(*auth_method);
2155         
2156         return True;
2157 }
2158
2159 /**
2160  * Verify whether or not given domain is trusted.
2161  *
2162  * @param domain_name name of the domain to be verified
2163  * @return true if domain is one of the trusted once or
2164  *         false if otherwise
2165  **/
2166
2167 bool is_trusted_domain(const char* dom_name)
2168 {
2169         DOM_SID trustdom_sid;
2170         bool ret;
2171
2172         /* no trusted domains for a standalone server */
2173
2174         if ( lp_server_role() == ROLE_STANDALONE )
2175                 return False;
2176
2177         /* if we are a DC, then check for a direct trust relationships */
2178
2179         if ( IS_DC ) {
2180                 become_root();
2181                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2182                           "[%s]\n", dom_name ));
2183                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2184                 unbecome_root();
2185                 if (ret)
2186                         return True;
2187         }
2188         else {
2189                 wbcErr result;
2190
2191                 /* If winbind is around, ask it */
2192
2193                 result = wb_is_trusted_domain(dom_name);
2194
2195                 if (result == WBC_ERR_SUCCESS) {
2196                         return True;
2197                 }
2198
2199                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
2200                         /* winbind could not find the domain */
2201                         return False;
2202                 }
2203
2204                 /* The only other possible result is that winbind is not up
2205                    and running. We need to update the trustdom_cache
2206                    ourselves */
2207                 
2208                 update_trustdom_cache();
2209         }
2210
2211         /* now the trustdom cache should be available a DC could still
2212          * have a transitive trust so fall back to the cache of trusted
2213          * domains (like a domain member would use  */
2214
2215         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
2216                 return True;
2217         }
2218
2219         return False;
2220 }
2221