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