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