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