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