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