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