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