s3 auth: Add parameter that forces every user through an NSS lookup
[samba.git] / source3 / auth / auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Volker Lendecke 2006
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
28
29 /****************************************************************************
30  Ensure primary group SID is always at position 0 in a 
31  auth_serversupplied_info struct.
32 ****************************************************************************/
33
34 static void sort_sid_array_for_smbd(auth_serversupplied_info *result,
35                                 const DOM_SID *pgroup_sid)
36 {
37         unsigned int i;
38
39         if (!result->sids) {
40                 return;
41         }
42
43         if (sid_compare(&result->sids[0], pgroup_sid)==0) {
44                 return;
45         }
46
47         for (i = 1; i < result->num_sids; i++) {
48                 if (sid_compare(pgroup_sid,
49                                 &result->sids[i]) == 0) {
50                         sid_copy(&result->sids[i], &result->sids[0]);
51                         sid_copy(&result->sids[0], pgroup_sid);
52                         return;
53                 }
54         }
55 }
56
57 /****************************************************************************
58  Create a UNIX user on demand.
59 ****************************************************************************/
60
61 static int smb_create_user(const char *domain, const char *unix_username, const char *homedir)
62 {
63         TALLOC_CTX *ctx = talloc_tos();
64         char *add_script;
65         int ret;
66
67         add_script = talloc_strdup(ctx, lp_adduser_script());
68         if (!add_script || !*add_script) {
69                 return -1;
70         }
71         add_script = talloc_all_string_sub(ctx,
72                                 add_script,
73                                 "%u",
74                                 unix_username);
75         if (!add_script) {
76                 return -1;
77         }
78         if (domain) {
79                 add_script = talloc_all_string_sub(ctx,
80                                         add_script,
81                                         "%D",
82                                         domain);
83                 if (!add_script) {
84                         return -1;
85                 }
86         }
87         if (homedir) {
88                 add_script = talloc_all_string_sub(ctx,
89                                 add_script,
90                                 "%H",
91                                 homedir);
92                 if (!add_script) {
93                         return -1;
94                 }
95         }
96         ret = smbrun(add_script,NULL);
97         flush_pwnam_cache();
98         DEBUG(ret ? 0 : 3,
99                 ("smb_create_user: Running the command `%s' gave %d\n",
100                  add_script,ret));
101         return ret;
102 }
103
104 /****************************************************************************
105  Create an auth_usersupplied_data structure
106 ****************************************************************************/
107
108 static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
109                                const char *smb_name,
110                                const char *internal_username,
111                                const char *client_domain,
112                                const char *domain,
113                                const char *wksta_name,
114                                DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
115                                DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
116                                DATA_BLOB *plaintext,
117                                bool encrypted)
118 {
119
120         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
121
122         *user_info = SMB_MALLOC_P(auth_usersupplied_info);
123         if (*user_info == NULL) {
124                 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
125                 return NT_STATUS_NO_MEMORY;
126         }
127
128         ZERO_STRUCTP(*user_info);
129
130         DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
131
132         (*user_info)->smb_name = SMB_STRDUP(smb_name);
133         if ((*user_info)->smb_name == NULL) { 
134                 free_user_info(user_info);
135                 return NT_STATUS_NO_MEMORY;
136         }
137         
138         (*user_info)->internal_username = SMB_STRDUP(internal_username);
139         if ((*user_info)->internal_username == NULL) { 
140                 free_user_info(user_info);
141                 return NT_STATUS_NO_MEMORY;
142         }
143
144         (*user_info)->domain = SMB_STRDUP(domain);
145         if ((*user_info)->domain == NULL) { 
146                 free_user_info(user_info);
147                 return NT_STATUS_NO_MEMORY;
148         }
149
150         (*user_info)->client_domain = SMB_STRDUP(client_domain);
151         if ((*user_info)->client_domain == NULL) { 
152                 free_user_info(user_info);
153                 return NT_STATUS_NO_MEMORY;
154         }
155
156         (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
157         if ((*user_info)->wksta_name == NULL) { 
158                 free_user_info(user_info);
159                 return NT_STATUS_NO_MEMORY;
160         }
161
162         DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
163
164         if (lm_pwd)
165                 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
166         if (nt_pwd)
167                 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
168         if (lm_interactive_pwd)
169                 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
170         if (nt_interactive_pwd)
171                 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
172
173         if (plaintext)
174                 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
175
176         (*user_info)->encrypted = encrypted;
177
178         (*user_info)->logon_parameters = 0;
179
180         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
181
182         return NT_STATUS_OK;
183 }
184
185 /****************************************************************************
186  Create an auth_usersupplied_data structure after appropriate mapping.
187 ****************************************************************************/
188
189 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
190                             const char *smb_name,
191                             const char *client_domain,
192                             const char *wksta_name,
193                             DATA_BLOB *lm_pwd,
194                             DATA_BLOB *nt_pwd,
195                             DATA_BLOB *lm_interactive_pwd,
196                             DATA_BLOB *nt_interactive_pwd,
197                             DATA_BLOB *plaintext,
198                             bool encrypted)
199 {
200         const char *domain;
201         NTSTATUS result;
202         bool was_mapped;
203         fstring internal_username;
204         fstrcpy(internal_username, smb_name);
205         was_mapped = map_username(internal_username);
206
207         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
208                  client_domain, smb_name, wksta_name));
209
210         /* don't allow "" as a domain, fixes a Win9X bug
211            where it doens't supply a domain for logon script
212            'net use' commands.                                 */
213
214         if ( *client_domain )
215                 domain = client_domain;
216         else
217                 domain = lp_workgroup();
218
219         /* If you connect to a Windows domain member using a bogus domain name,
220          * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
221          * the Windows box is a DC the name will become DOMAIN\user and be
222          * authenticated against AD, if the Windows box is a member server but
223          * not a DC the name will become WORKSTATION\user.  A standalone
224          * non-domain member box will also map to WORKSTATION\user. */
225
226         if (!is_trusted_domain(domain) &&
227             !strequal(domain, get_global_sam_name()) )
228         {
229                 if (lp_map_untrusted_to_domain())
230                         domain = my_sam_name();
231                 else
232                         domain = get_global_sam_name();
233                 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
234                           "workstation [%s]\n",
235                           client_domain, domain, smb_name, wksta_name));
236         }
237
238         /* We know that the given domain is trusted (and we are allowing them),
239          * it is our global SAM name, or for legacy behavior it is our
240          * primary domain name */
241
242         result = make_user_info(user_info, smb_name, internal_username,
243                               client_domain, domain, wksta_name,
244                               lm_pwd, nt_pwd,
245                               lm_interactive_pwd, nt_interactive_pwd,
246                               plaintext, encrypted);
247         if (NT_STATUS_IS_OK(result)) {
248                 (*user_info)->was_mapped = was_mapped;
249         }
250         return result;
251 }
252
253 /****************************************************************************
254  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
255  Decrypt and encrypt the passwords.
256 ****************************************************************************/
257
258 bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
259                                      const char *smb_name, 
260                                      const char *client_domain, 
261                                      const char *wksta_name, 
262                                      uint32 logon_parameters,
263                                      const uchar *lm_network_pwd,
264                                      int lm_pwd_len,
265                                      const uchar *nt_network_pwd,
266                                      int nt_pwd_len)
267 {
268         bool ret;
269         NTSTATUS status;
270         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
271         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
272
273         status = make_user_info_map(user_info,
274                                     smb_name, client_domain, 
275                                     wksta_name, 
276                                     lm_pwd_len ? &lm_blob : NULL, 
277                                     nt_pwd_len ? &nt_blob : NULL,
278                                     NULL, NULL, NULL,
279                                     True);
280
281         if (NT_STATUS_IS_OK(status)) {
282                 (*user_info)->logon_parameters = logon_parameters;
283         }
284         ret = NT_STATUS_IS_OK(status) ? True : False;
285
286         data_blob_free(&lm_blob);
287         data_blob_free(&nt_blob);
288         return ret;
289 }
290
291 /****************************************************************************
292  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
293  Decrypt and encrypt the passwords.
294 ****************************************************************************/
295
296 bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
297                                          const char *smb_name, 
298                                          const char *client_domain, 
299                                          const char *wksta_name, 
300                                          uint32 logon_parameters,
301                                          const uchar chal[8], 
302                                          const uchar lm_interactive_pwd[16], 
303                                          const uchar nt_interactive_pwd[16], 
304                                          const uchar *dc_sess_key)
305 {
306         unsigned char lm_pwd[16];
307         unsigned char nt_pwd[16];
308         unsigned char local_lm_response[24];
309         unsigned char local_nt_response[24];
310         unsigned char key[16];
311         
312         ZERO_STRUCT(key);
313         memcpy(key, dc_sess_key, 8);
314         
315         if (lm_interactive_pwd)
316                 memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
317
318         if (nt_interactive_pwd)
319                 memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
320         
321 #ifdef DEBUG_PASSWORD
322         DEBUG(100,("key:"));
323         dump_data(100, key, sizeof(key));
324         
325         DEBUG(100,("lm owf password:"));
326         dump_data(100, lm_pwd, sizeof(lm_pwd));
327         
328         DEBUG(100,("nt owf password:"));
329         dump_data(100, nt_pwd, sizeof(nt_pwd));
330 #endif
331         
332         if (lm_interactive_pwd)
333                 SamOEMhash(lm_pwd, key, sizeof(lm_pwd));
334         
335         if (nt_interactive_pwd)
336                 SamOEMhash(nt_pwd, key, sizeof(nt_pwd));
337         
338 #ifdef DEBUG_PASSWORD
339         DEBUG(100,("decrypt of lm owf password:"));
340         dump_data(100, lm_pwd, sizeof(lm_pwd));
341         
342         DEBUG(100,("decrypt of nt owf password:"));
343         dump_data(100, nt_pwd, sizeof(nt_pwd));
344 #endif
345         
346         if (lm_interactive_pwd)
347                 SMBOWFencrypt(lm_pwd, chal,
348                               local_lm_response);
349
350         if (nt_interactive_pwd)
351                 SMBOWFencrypt(nt_pwd, chal,
352                               local_nt_response);
353         
354         /* Password info paranoia */
355         ZERO_STRUCT(key);
356
357         {
358                 bool ret;
359                 NTSTATUS nt_status;
360                 DATA_BLOB local_lm_blob;
361                 DATA_BLOB local_nt_blob;
362
363                 DATA_BLOB lm_interactive_blob;
364                 DATA_BLOB nt_interactive_blob;
365                 
366                 if (lm_interactive_pwd) {
367                         local_lm_blob = data_blob(local_lm_response,
368                                                   sizeof(local_lm_response));
369                         lm_interactive_blob = data_blob(lm_pwd,
370                                                         sizeof(lm_pwd));
371                         ZERO_STRUCT(lm_pwd);
372                 }
373                 
374                 if (nt_interactive_pwd) {
375                         local_nt_blob = data_blob(local_nt_response,
376                                                   sizeof(local_nt_response));
377                         nt_interactive_blob = data_blob(nt_pwd,
378                                                         sizeof(nt_pwd));
379                         ZERO_STRUCT(nt_pwd);
380                 }
381
382                 nt_status = make_user_info_map(
383                         user_info, 
384                         smb_name, client_domain, wksta_name, 
385                         lm_interactive_pwd ? &local_lm_blob : NULL,
386                         nt_interactive_pwd ? &local_nt_blob : NULL,
387                         lm_interactive_pwd ? &lm_interactive_blob : NULL,
388                         nt_interactive_pwd ? &nt_interactive_blob : NULL,
389                         NULL, True);
390
391                 if (NT_STATUS_IS_OK(nt_status)) {
392                         (*user_info)->logon_parameters = logon_parameters;
393                 }
394
395                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
396                 data_blob_free(&local_lm_blob);
397                 data_blob_free(&local_nt_blob);
398                 data_blob_free(&lm_interactive_blob);
399                 data_blob_free(&nt_interactive_blob);
400                 return ret;
401         }
402 }
403
404
405 /****************************************************************************
406  Create an auth_usersupplied_data structure
407 ****************************************************************************/
408
409 bool make_user_info_for_reply(auth_usersupplied_info **user_info, 
410                               const char *smb_name, 
411                               const char *client_domain,
412                               const uint8 chal[8],
413                               DATA_BLOB plaintext_password)
414 {
415
416         DATA_BLOB local_lm_blob;
417         DATA_BLOB local_nt_blob;
418         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
419                         
420         /*
421          * Not encrypted - do so.
422          */
423         
424         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
425                  "format.\n"));
426         
427         if (plaintext_password.data) {
428                 unsigned char local_lm_response[24];
429                 
430 #ifdef DEBUG_PASSWORD
431                 DEBUG(10,("Unencrypted password (len %d):\n",
432                           (int)plaintext_password.length));
433                 dump_data(100, plaintext_password.data,
434                           plaintext_password.length);
435 #endif
436
437                 SMBencrypt( (const char *)plaintext_password.data,
438                             (const uchar*)chal, local_lm_response);
439                 local_lm_blob = data_blob(local_lm_response, 24);
440                 
441                 /* We can't do an NT hash here, as the password needs to be
442                    case insensitive */
443                 local_nt_blob = data_blob_null; 
444                 
445         } else {
446                 local_lm_blob = data_blob_null; 
447                 local_nt_blob = data_blob_null; 
448         }
449         
450         ret = make_user_info_map(
451                 user_info, smb_name, client_domain, 
452                 get_remote_machine_name(),
453                 local_lm_blob.data ? &local_lm_blob : NULL,
454                 local_nt_blob.data ? &local_nt_blob : NULL,
455                 NULL, NULL,
456                 plaintext_password.data ? &plaintext_password : NULL, 
457                 False);
458         
459         data_blob_free(&local_lm_blob);
460         return NT_STATUS_IS_OK(ret) ? True : False;
461 }
462
463 /****************************************************************************
464  Create an auth_usersupplied_data structure
465 ****************************************************************************/
466
467 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
468                                       const char *smb_name,
469                                       const char *client_domain, 
470                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
471 {
472         return make_user_info_map(user_info, smb_name, 
473                                   client_domain, 
474                                   get_remote_machine_name(), 
475                                   lm_resp.data ? &lm_resp : NULL, 
476                                   nt_resp.data ? &nt_resp : NULL, 
477                                   NULL, NULL, NULL,
478                                   True);
479 }
480
481 /****************************************************************************
482  Create a guest user_info blob, for anonymous authenticaion.
483 ****************************************************************************/
484
485 bool make_user_info_guest(auth_usersupplied_info **user_info) 
486 {
487         NTSTATUS nt_status;
488
489         nt_status = make_user_info(user_info, 
490                                    "","", 
491                                    "","", 
492                                    "", 
493                                    NULL, NULL, 
494                                    NULL, NULL, 
495                                    NULL,
496                                    True);
497                               
498         return NT_STATUS_IS_OK(nt_status) ? True : False;
499 }
500
501 static int server_info_dtor(auth_serversupplied_info *server_info)
502 {
503         TALLOC_FREE(server_info->sam_account);
504         ZERO_STRUCTP(server_info);
505         return 0;
506 }
507
508 /***************************************************************************
509  Make a server_info struct. Free with TALLOC_FREE().
510 ***************************************************************************/
511
512 static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
513 {
514         struct auth_serversupplied_info *result;
515
516         result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
517         if (result == NULL) {
518                 DEBUG(0, ("talloc failed\n"));
519                 return NULL;
520         }
521
522         talloc_set_destructor(result, server_info_dtor);
523
524         /* Initialise the uid and gid values to something non-zero
525            which may save us from giving away root access if there
526            is a bug in allocating these fields. */
527
528         result->utok.uid = -1;
529         result->utok.gid = -1;
530         return result;
531 }
532
533 static char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
534 {
535         fstring tmp;
536
537         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
538         return talloc_strdup(mem_ctx, tmp);
539 }
540
541 /***************************************************************************
542  Is the incoming username our own machine account ?
543  If so, the connection is almost certainly from winbindd.
544 ***************************************************************************/
545
546 static bool is_our_machine_account(const char *username)
547 {
548         bool ret;
549         char *truncname = NULL;
550         size_t ulen = strlen(username);
551
552         if (ulen == 0 || username[ulen-1] != '$') {
553                 return false;
554         }
555         truncname = SMB_STRDUP(username);
556         if (!truncname) {
557                 return false;
558         }
559         truncname[ulen-1] = '\0';
560         ret = strequal(truncname, global_myname());
561         SAFE_FREE(truncname);
562         return ret;
563 }
564
565 /***************************************************************************
566  Make (and fill) a user_info struct from a struct samu
567 ***************************************************************************/
568
569 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
570                               struct samu *sampass)
571 {
572         struct passwd *pwd;
573         gid_t *gids;
574         auth_serversupplied_info *result;
575         const char *username = pdb_get_username(sampass);
576         NTSTATUS status;
577
578         if ( !(result = make_server_info(NULL)) ) {
579                 return NT_STATUS_NO_MEMORY;
580         }
581
582         if ( !(pwd = getpwnam_alloc(result, username)) ) {
583                 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
584                           pdb_get_username(sampass)));
585                 TALLOC_FREE(result);
586                 return NT_STATUS_NO_SUCH_USER;
587         }
588
589         result->sam_account = sampass;
590         result->unix_name = pwd->pw_name;
591         /* Ensure that we keep pwd->pw_name, because we will free pwd below */
592         talloc_steal(result, pwd->pw_name);
593         result->utok.gid = pwd->pw_gid;
594         result->utok.uid = pwd->pw_uid;
595
596         TALLOC_FREE(pwd);
597
598         result->sanitized_username = sanitize_username(result,
599                                                        result->unix_name);
600         if (result->sanitized_username == NULL) {
601                 TALLOC_FREE(result);
602                 return NT_STATUS_NO_MEMORY;
603         }
604
605         if (IS_DC && is_our_machine_account(username)) {
606                 /*
607                  * Ensure for a connection from our own
608                  * machine account (from winbindd on a DC)
609                  * there are no supplementary groups.
610                  * Prevents loops in calling gid_to_sid().
611                  */
612                 result->sids = NULL;
613                 gids = NULL;
614                 result->num_sids = 0;
615
616                 /*
617                  * This is a hack of monstrous proportions.
618                  * If we know it's winbindd talking to us,
619                  * we know we must never recurse into it,
620                  * so turn off contacting winbindd for this
621                  * entire process. This will get fixed when
622                  * winbindd doesn't need to talk to smbd on
623                  * a PDC. JRA.
624                  */
625
626                 (void)winbind_off();
627
628                 DEBUG(10, ("make_server_info_sam: our machine account %s "
629                         "setting supplementary group list empty and "
630                         "turning off winbindd requests.\n",
631                         username));
632         } else {
633                 status = pdb_enum_group_memberships(result, sampass,
634                                             &result->sids, &gids,
635                                             &result->num_sids);
636
637                 if (!NT_STATUS_IS_OK(status)) {
638                         DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
639                                    nt_errstr(status)));
640                         result->sam_account = NULL; /* Don't free on error exit. */
641                         TALLOC_FREE(result);
642                         return status;
643                 }
644         }
645
646         /* For now we throw away the gids and convert via sid_to_gid
647          * later. This needs fixing, but I'd like to get the code straight and
648          * simple first. */
649          
650         TALLOC_FREE(gids);
651
652         DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
653                  pdb_get_username(sampass), result->unix_name));
654
655         *server_info = result;
656         /* Ensure that the sampass will be freed with the result */
657         talloc_steal(result, sampass);
658
659         return NT_STATUS_OK;
660 }
661
662 static NTSTATUS log_nt_token(NT_USER_TOKEN *token)
663 {
664         TALLOC_CTX *frame = talloc_stackframe();
665         char *command;
666         char *group_sidstr;
667         size_t i;
668
669         if ((lp_log_nt_token_command() == NULL) ||
670             (strlen(lp_log_nt_token_command()) == 0)) {
671                 TALLOC_FREE(frame);
672                 return NT_STATUS_OK;
673         }
674
675         group_sidstr = talloc_strdup(frame, "");
676         for (i=1; i<token->num_sids; i++) {
677                 group_sidstr = talloc_asprintf(
678                         frame, "%s %s", group_sidstr,
679                         sid_string_talloc(frame, &token->user_sids[i]));
680         }
681
682         command = talloc_string_sub(
683                 frame, lp_log_nt_token_command(),
684                 "%s", sid_string_talloc(frame, &token->user_sids[0]));
685         command = talloc_string_sub(frame, command, "%t", group_sidstr);
686
687         if (command == NULL) {
688                 TALLOC_FREE(frame);
689                 return NT_STATUS_NO_MEMORY;
690         }
691
692         DEBUG(8, ("running command: [%s]\n", command));
693         if (smbrun(command, NULL) != 0) {
694                 DEBUG(0, ("Could not log NT token\n"));
695                 TALLOC_FREE(frame);
696                 return NT_STATUS_ACCESS_DENIED;
697         }
698
699         TALLOC_FREE(frame);
700         return NT_STATUS_OK;
701 }
702
703 /*
704  * Create the token to use from server_info->sam_account and
705  * server_info->sids (the info3/sam groups). Find the unix gids.
706  */
707
708 NTSTATUS create_local_token(auth_serversupplied_info *server_info)
709 {
710         NTSTATUS status;
711         size_t i;
712         struct dom_sid tmp_sid;
713         const char *name_to_use;
714         bool force_nss;
715
716         /*
717          * If winbind is not around, we can not make much use of the SIDs the
718          * domain controller provided us with. Likewise if the user name was
719          * mapped to some local unix user.
720          */
721
722         DEBUG(10, ("creating token for %s (SAM: %s)\n", server_info->unix_name,
723                 server_info->sam_account->username));
724
725         force_nss = lp_force_username_map() && !server_info->nss_token;
726         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
727             server_info->nss_token || force_nss) {
728                 if (force_nss)
729                         name_to_use =
730                             pdb_get_username(server_info->sam_account);
731                 else
732                         name_to_use = server_info->unix_name;
733
734                 status = create_token_from_username(server_info,
735                                                     name_to_use,
736                                                     server_info->guest,
737                                                     force_nss,
738                                                     &server_info->utok.uid,
739                                                     &server_info->utok.gid,
740                                                     &server_info->unix_name,
741                                                     &server_info->ptok);
742
743         } else {
744                 server_info->ptok = create_local_nt_token(
745                         server_info,
746                         pdb_get_user_sid(server_info->sam_account),
747                         server_info->guest,
748                         server_info->num_sids, server_info->sids);
749                 status = server_info->ptok ?
750                         NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
751         }
752
753         if (!NT_STATUS_IS_OK(status)) {
754                 return status;
755         }
756
757         /* Convert the SIDs to gids. */
758
759         server_info->utok.ngroups = 0;
760         server_info->utok.groups = NULL;
761
762         /* Start at index 1, where the groups start. */
763
764         for (i=1; i<server_info->ptok->num_sids; i++) {
765                 gid_t gid;
766                 DOM_SID *sid = &server_info->ptok->user_sids[i];
767
768                 if (!sid_to_gid(sid, &gid)) {
769                         DEBUG(10, ("Could not convert SID %s to gid, "
770                                    "ignoring it\n", sid_string_dbg(sid)));
771                         continue;
772                 }
773                 add_gid_to_array_unique(server_info, gid,
774                                         &server_info->utok.groups,
775                                         &server_info->utok.ngroups);
776         }
777
778         /*
779          * Add the "Unix Group" SID for each gid to catch mapped groups
780          * and their Unix equivalent.  This is to solve the backwards
781          * compatibility problem of 'valid users = +ntadmin' where
782          * ntadmin has been paired with "Domain Admins" in the group
783          * mapping table.  Otherwise smb.conf would need to be changed
784          * to 'valid user = "Domain Admins"'.  --jerry
785          *
786          * For consistency we also add the "Unix User" SID,
787          * so that the complete unix token is represented within
788          * the nt token.
789          */
790
791         if (!uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid)) {
792                 DEBUG(1,("create_local_token: Failed to create SID "
793                         "for uid %d!\n", server_info->utok.uid));
794         }
795         add_sid_to_array_unique(server_info->ptok, &tmp_sid,
796                                 &server_info->ptok->user_sids,
797                                 &server_info->ptok->num_sids);
798
799         for ( i=0; i<server_info->utok.ngroups; i++ ) {
800                 if (!gid_to_unix_groups_sid( server_info->utok.groups[i], &tmp_sid ) ) {
801                         DEBUG(1,("create_local_token: Failed to create SID "
802                                 "for gid %d!\n", server_info->utok.groups[i]));
803                         continue;
804                 }
805                 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
806                                         &server_info->ptok->user_sids,
807                                         &server_info->ptok->num_sids);
808         }
809
810         debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
811         debug_unix_user_token(DBGC_AUTH, 10,
812                               server_info->utok.uid,
813                               server_info->utok.gid,
814                               server_info->utok.ngroups,
815                               server_info->utok.groups);
816
817         status = log_nt_token(server_info->ptok);
818         return status;
819 }
820
821 /*
822  * Create an artificial NT token given just a username. (Initially indended
823  * for force user)
824  *
825  * We go through lookup_name() to avoid problems we had with 'winbind use
826  * default domain'.
827  *
828  * We have 3 cases:
829  *
830  * unmapped unix users: Go directly to nss to find the user's group.
831  *
832  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
833  *
834  * If the user is provided by winbind, the primary gid is set to "domain
835  * users" of the user's domain. For an explanation why this is necessary, see
836  * the thread starting at
837  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
838  */
839
840 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
841                                     bool is_guest,
842                                     bool force_nss,
843                                     uid_t *uid, gid_t *gid,
844                                     char **found_username,
845                                     struct nt_user_token **token)
846 {
847         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
848         TALLOC_CTX *tmp_ctx;
849         DOM_SID user_sid;
850         enum lsa_SidType type;
851         gid_t *gids;
852         DOM_SID *group_sids;
853         DOM_SID unix_group_sid;
854         size_t num_group_sids;
855         size_t num_gids;
856         size_t i;
857
858         DEBUG(10, ("creating token for %s,%s guest,%s forcing NSS lookup\n",
859                 username, is_guest ? "" : " not", force_nss ? "" : " not"));
860
861         tmp_ctx = talloc_new(NULL);
862         if (tmp_ctx == NULL) {
863                 DEBUG(0, ("talloc_new failed\n"));
864                 return NT_STATUS_NO_MEMORY;
865         }
866
867         if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
868                          NULL, NULL, &user_sid, &type)) {
869                 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
870                 goto done;
871         }
872
873         if (type != SID_NAME_USER) {
874                 DEBUG(1, ("%s is a %s, not a user\n", username,
875                           sid_type_lookup(type)));
876                 goto done;
877         }
878
879         if (!sid_to_uid(&user_sid, uid)) {
880                 DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
881                           username, sid_string_dbg(&user_sid)));
882                 goto done;
883         }
884
885         if (sid_check_is_in_our_domain(&user_sid) && !force_nss) {
886                 bool ret;
887
888                 /* This is a passdb user, so ask passdb */
889
890                 struct samu *sam_acct = NULL;
891
892                 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
893                         result = NT_STATUS_NO_MEMORY;
894                         goto done;
895                 }
896
897                 become_root();
898                 ret = pdb_getsampwsid(sam_acct, &user_sid);
899                 unbecome_root();
900
901                 if (!ret) {
902                         DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
903                                   sid_string_dbg(&user_sid), username));
904                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
905                         goto unix_user;
906                 }
907
908                 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
909                                                     &group_sids, &gids,
910                                                     &num_group_sids);
911                 if (!NT_STATUS_IS_OK(result)) {
912                         DEBUG(10, ("enum_group_memberships failed for %s\n",
913                                    username));
914                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
915                         goto unix_user;
916                 }
917
918                 /* see the smb_panic() in pdb_default_enum_group_memberships */
919                 SMB_ASSERT(num_group_sids > 0); 
920
921                 *gid = gids[0];
922
923                 /* Ensure we're returning the found_username on the right context. */
924                 *found_username = talloc_strdup(mem_ctx,
925                                                 pdb_get_username(sam_acct));
926
927         } else  if (force_nss || sid_check_is_in_unix_users(&user_sid)) {
928
929                 /* This is a unix user not in passdb. We need to ask nss
930                  * directly, without consulting passdb */
931
932                 struct passwd *pass;
933
934                 /*
935                  * This goto target is used as a fallback for the passdb
936                  * case. The concrete bug report is when passdb gave us an
937                  * unmapped gid.
938                  */
939
940         unix_user:
941
942                 uid_to_unix_users_sid(*uid, &user_sid);
943
944                 pass = getpwuid_alloc(tmp_ctx, *uid);
945                 if (pass == NULL) {
946                         DEBUG(1, ("getpwuid(%d) for user %s failed\n",
947                                   *uid, username));
948                         goto done;
949                 }
950
951                 if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
952                                          &gids, &num_group_sids)) {
953                         DEBUG(1, ("getgroups_unix_user for user %s failed\n",
954                                   username));
955                         goto done;
956                 }
957
958                 if (num_group_sids) {
959                         group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
960                         if (group_sids == NULL) {
961                                 DEBUG(1, ("TALLOC_ARRAY failed\n"));
962                                 result = NT_STATUS_NO_MEMORY;
963                                 goto done;
964                         }
965                 } else {
966                         group_sids = NULL;
967                 }
968
969                 for (i=0; i<num_group_sids; i++) {
970                         gid_to_sid(&group_sids[i], gids[i]);
971                 }
972
973                 /* In getgroups_unix_user we always set the primary gid */
974                 SMB_ASSERT(num_group_sids > 0); 
975
976                 *gid = gids[0];
977
978                 /* Ensure we're returning the found_username on the right context. */
979                 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
980         } else {
981
982                 /* This user is from winbind, force the primary gid to the
983                  * user's "domain users" group. Under certain circumstances
984                  * (user comes from NT4), this might be a loss of
985                  * information. But we can not rely on winbind getting the
986                  * correct info. AD might prohibit winbind looking up that
987                  * information. */
988
989                 uint32 dummy;
990
991                 num_group_sids = 1;
992                 group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
993                 if (group_sids == NULL) {
994                         DEBUG(1, ("TALLOC_ARRAY failed\n"));
995                         result = NT_STATUS_NO_MEMORY;
996                         goto done;
997                 }
998
999                 sid_copy(&group_sids[0], &user_sid);
1000                 sid_split_rid(&group_sids[0], &dummy);
1001                 sid_append_rid(&group_sids[0], DOMAIN_GROUP_RID_USERS);
1002
1003                 if (!sid_to_gid(&group_sids[0], gid)) {
1004                         DEBUG(1, ("sid_to_gid(%s) failed\n",
1005                                   sid_string_dbg(&group_sids[0])));
1006                         goto done;
1007                 }
1008
1009                 gids = gid;
1010
1011                 /* Ensure we're returning the found_username on the right context. */
1012                 *found_username = talloc_strdup(mem_ctx, username);
1013         }
1014
1015         /* Add the "Unix Group" SID for each gid to catch mapped groups
1016            and their Unix equivalent.  This is to solve the backwards
1017            compatibility problem of 'valid users = +ntadmin' where
1018            ntadmin has been paired with "Domain Admins" in the group
1019            mapping table.  Otherwise smb.conf would need to be changed
1020            to 'valid user = "Domain Admins"'.  --jerry */
1021
1022         num_gids = num_group_sids;
1023         for ( i=0; i<num_gids; i++ ) {
1024                 gid_t high, low;
1025
1026                 /* don't pickup anything managed by Winbind */
1027
1028                 if ( lp_idmap_gid(&low, &high) && (gids[i] >= low) && (gids[i] <= high) )
1029                         continue;
1030
1031                 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
1032                         DEBUG(1,("create_token_from_username: Failed to create SID "
1033                                 "for gid %d!\n", gids[i]));
1034                         continue;
1035                 }
1036                 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
1037                                                  &group_sids, &num_group_sids);
1038                 if (!NT_STATUS_IS_OK(result)) {
1039                         goto done;
1040                 }
1041         }
1042
1043         /* Ensure we're creating the nt_token on the right context. */
1044         *token = create_local_nt_token(mem_ctx, &user_sid,
1045                                        is_guest, num_group_sids, group_sids);
1046
1047         if ((*token == NULL) || (*found_username == NULL)) {
1048                 result = NT_STATUS_NO_MEMORY;
1049                 goto done;
1050         }
1051
1052         result = NT_STATUS_OK;
1053  done:
1054         TALLOC_FREE(tmp_ctx);
1055         return result;
1056 }
1057
1058 /***************************************************************************
1059  Build upon create_token_from_username:
1060
1061  Expensive helper function to figure out whether a user given its name is
1062  member of a particular group.
1063 ***************************************************************************/
1064
1065 bool user_in_group_sid(const char *username, const DOM_SID *group_sid)
1066 {
1067         NTSTATUS status;
1068         uid_t uid;
1069         gid_t gid;
1070         char *found_username;
1071         struct nt_user_token *token;
1072         bool result;
1073
1074         TALLOC_CTX *mem_ctx;
1075
1076         mem_ctx = talloc_new(NULL);
1077         if (mem_ctx == NULL) {
1078                 DEBUG(0, ("talloc_new failed\n"));
1079                 return False;
1080         }
1081
1082         status = create_token_from_username(mem_ctx, username, False,
1083                                             lp_force_username_map(),
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