r5431: couple of cimpile fixes from Jason Mader <jason@ncac.gwu.edu> -- BUGS 2341...
[tprouty/samba.git] / source / auth / auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
28
29 extern DOM_SID global_sid_World;
30 extern DOM_SID global_sid_Network;
31 extern DOM_SID global_sid_Builtin_Guests;
32 extern DOM_SID global_sid_Authenticated_Users;
33
34
35 /****************************************************************************
36  Create a UNIX user on demand.
37 ****************************************************************************/
38
39 static int smb_create_user(const char *domain, const char *unix_username, const char *homedir)
40 {
41         pstring add_script;
42         int ret;
43
44         pstrcpy(add_script, lp_adduser_script());
45         if (! *add_script)
46                 return -1;
47         all_string_sub(add_script, "%u", unix_username, sizeof(pstring));
48         if (domain)
49                 all_string_sub(add_script, "%D", domain, sizeof(pstring));
50         if (homedir)
51                 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
52         ret = smbrun(add_script,NULL);
53         DEBUG(ret ? 0 : 3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
54         return ret;
55 }
56
57 /****************************************************************************
58  Add and Delete UNIX users on demand, based on NTSTATUS codes.
59  We don't care about RID's here so ignore.
60 ****************************************************************************/
61
62 void auth_add_user_script(const char *domain, const char *username)
63 {
64         /*
65          * User validated ok against Domain controller.
66          * If the admin wants us to try and create a UNIX
67          * user on the fly, do so.
68          */
69         
70         if ( *lp_adduser_script() )
71                 smb_create_user(domain, username, NULL);
72         else {
73                 DEBUG(10,("auth_add_user_script: no 'add user script'.  Asking winbindd\n"));
74                 
75                 /* should never get here is we a re a domain member running winbindd
76                    However, a host set for 'security = server' might run winbindd for 
77                    account allocation */
78                    
79                 if ( !winbind_create_user(username, NULL) ) {
80                         DEBUG(5,("auth_add_user_script: winbindd_create_user() failed\n"));
81                 }
82         }
83 }
84
85 /****************************************************************************
86  Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from
87  unix info.
88 ****************************************************************************/
89
90 NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account) 
91 {
92         BOOL pdb_ret;
93         NTSTATUS nt_status;
94         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) {
95                 return nt_status;
96         }
97         
98         become_root();
99         pdb_ret = pdb_getsampwnam(*account, user);
100         unbecome_root();
101
102         if (!pdb_ret) {
103                 
104                 struct passwd *pass = Get_Pwnam(user);
105                 if (!pass) 
106                         return NT_STATUS_NO_SUCH_USER;
107
108                 if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) {
109                         return nt_status;
110                 }
111         }
112         return NT_STATUS_OK;
113 }
114
115 /****************************************************************************
116  Create an auth_usersupplied_data structure
117 ****************************************************************************/
118
119 static NTSTATUS make_user_info(auth_usersupplied_info **user_info, 
120                                const char *smb_name, 
121                                const char *internal_username,
122                                const char *client_domain, 
123                                const char *domain,
124                                const char *wksta_name, 
125                                DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
126                                DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
127                                DATA_BLOB *plaintext, 
128                                BOOL encrypted)
129 {
130
131         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
132
133         *user_info = SMB_MALLOC_P(auth_usersupplied_info);
134         if (!user_info) {
135                 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
136                 return NT_STATUS_NO_MEMORY;
137         }
138
139         ZERO_STRUCTP(*user_info);
140
141         DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
142
143         (*user_info)->smb_name.str = SMB_STRDUP(smb_name);
144         if ((*user_info)->smb_name.str) { 
145                 (*user_info)->smb_name.len = strlen(smb_name);
146         } else {
147                 free_user_info(user_info);
148                 return NT_STATUS_NO_MEMORY;
149         }
150         
151         (*user_info)->internal_username.str = SMB_STRDUP(internal_username);
152         if ((*user_info)->internal_username.str) { 
153                 (*user_info)->internal_username.len = strlen(internal_username);
154         } else {
155                 free_user_info(user_info);
156                 return NT_STATUS_NO_MEMORY;
157         }
158
159         (*user_info)->domain.str = SMB_STRDUP(domain);
160         if ((*user_info)->domain.str) { 
161                 (*user_info)->domain.len = strlen(domain);
162         } else {
163                 free_user_info(user_info);
164                 return NT_STATUS_NO_MEMORY;
165         }
166
167         (*user_info)->client_domain.str = SMB_STRDUP(client_domain);
168         if ((*user_info)->client_domain.str) { 
169                 (*user_info)->client_domain.len = strlen(client_domain);
170         } else {
171                 free_user_info(user_info);
172                 return NT_STATUS_NO_MEMORY;
173         }
174
175         (*user_info)->wksta_name.str = SMB_STRDUP(wksta_name);
176         if ((*user_info)->wksta_name.str) { 
177                 (*user_info)->wksta_name.len = strlen(wksta_name);
178         } else {
179                 free_user_info(user_info);
180                 return NT_STATUS_NO_MEMORY;
181         }
182
183         DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
184
185         if (lm_pwd)
186                 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
187         if (nt_pwd)
188                 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
189         if (lm_interactive_pwd)
190                 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
191         if (nt_interactive_pwd)
192                 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
193
194         if (plaintext)
195                 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
196
197         (*user_info)->encrypted = encrypted;
198
199         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
200
201         return NT_STATUS_OK;
202 }
203
204 /****************************************************************************
205  Create an auth_usersupplied_data structure after appropriate mapping.
206 ****************************************************************************/
207
208 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, 
209                             const char *smb_name, 
210                             const char *client_domain, 
211                             const char *wksta_name, 
212                             DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
213                             DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
214                             DATA_BLOB *plaintext, 
215                             BOOL encrypted)
216 {
217         const char *domain;
218         fstring internal_username;
219         fstrcpy(internal_username, smb_name);
220         map_username(internal_username); 
221         
222         DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
223               client_domain, smb_name, wksta_name));
224         
225         /* don't allow "" as a domain, fixes a Win9X bug 
226            where it doens't supply a domain for logon script
227            'net use' commands.                                 */
228
229         if ( *client_domain )
230                 domain = client_domain;
231         else
232                 domain = lp_workgroup();
233
234         /* do what win2k does.  Always map unknown domains to our own
235            and let the "passdb backend" handle unknown users. */
236
237         if ( !is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) ) 
238                 domain = get_default_sam_name();
239         
240         /* we know that it is a trusted domain (and we are allowing them) or it is our domain */
241         
242         return 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 }
248
249 /****************************************************************************
250  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
251  Decrypt and encrypt the passwords.
252 ****************************************************************************/
253
254 BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
255                                      const char *smb_name, 
256                                      const char *client_domain, 
257                                      const char *wksta_name, 
258                                      const uchar *lm_network_pwd, int lm_pwd_len,
259                                      const uchar *nt_network_pwd, int nt_pwd_len)
260 {
261         BOOL ret;
262         NTSTATUS nt_status;
263         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
264         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
265
266         nt_status = make_user_info_map(user_info,
267                                        smb_name, client_domain, 
268                                        wksta_name, 
269                                        lm_pwd_len ? &lm_blob : NULL, 
270                                        nt_pwd_len ? &nt_blob : NULL,
271                                        NULL, NULL, NULL,
272                                        True);
273         
274         ret = NT_STATUS_IS_OK(nt_status) ? True : False;
275                 
276         data_blob_free(&lm_blob);
277         data_blob_free(&nt_blob);
278         return ret;
279 }
280
281 /****************************************************************************
282  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
283  Decrypt and encrypt the passwords.
284 ****************************************************************************/
285
286 BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
287                                          const char *smb_name, 
288                                          const char *client_domain, 
289                                          const char *wksta_name, 
290                                          const uchar chal[8], 
291                                          const uchar lm_interactive_pwd[16], 
292                                          const uchar nt_interactive_pwd[16], 
293                                          const uchar *dc_sess_key)
294 {
295         char lm_pwd[16];
296         char nt_pwd[16];
297         unsigned char local_lm_response[24];
298         unsigned char local_nt_response[24];
299         unsigned char key[16];
300         
301         ZERO_STRUCT(key);
302         memcpy(key, dc_sess_key, 8);
303         
304         if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
305         if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
306         
307 #ifdef DEBUG_PASSWORD
308         DEBUG(100,("key:"));
309         dump_data(100, (char *)key, sizeof(key));
310         
311         DEBUG(100,("lm owf password:"));
312         dump_data(100, lm_pwd, sizeof(lm_pwd));
313         
314         DEBUG(100,("nt owf password:"));
315         dump_data(100, nt_pwd, sizeof(nt_pwd));
316 #endif
317         
318         if (lm_interactive_pwd)
319                 SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
320         
321         if (nt_interactive_pwd)
322                 SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
323         
324 #ifdef DEBUG_PASSWORD
325         DEBUG(100,("decrypt of lm owf password:"));
326         dump_data(100, lm_pwd, sizeof(lm_pwd));
327         
328         DEBUG(100,("decrypt of nt owf password:"));
329         dump_data(100, nt_pwd, sizeof(nt_pwd));
330 #endif
331         
332         if (lm_interactive_pwd)
333                 SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
334
335         if (nt_interactive_pwd)
336                 SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
337         
338         /* Password info paranoia */
339         ZERO_STRUCT(key);
340
341         {
342                 BOOL ret;
343                 NTSTATUS nt_status;
344                 DATA_BLOB local_lm_blob;
345                 DATA_BLOB local_nt_blob;
346
347                 DATA_BLOB lm_interactive_blob;
348                 DATA_BLOB nt_interactive_blob;
349                 
350                 if (lm_interactive_pwd) {
351                         local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
352                         lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
353                         ZERO_STRUCT(lm_pwd);
354                 }
355                 
356                 if (nt_interactive_pwd) {
357                         local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
358                         nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
359                         ZERO_STRUCT(nt_pwd);
360                 }
361
362                 nt_status = make_user_info_map(user_info, 
363                                                smb_name, client_domain, 
364                                                wksta_name, 
365                                                lm_interactive_pwd ? &local_lm_blob : NULL,
366                                                nt_interactive_pwd ? &local_nt_blob : NULL,
367                                                lm_interactive_pwd ? &lm_interactive_blob : NULL,
368                                                nt_interactive_pwd ? &nt_interactive_blob : NULL,
369                                                NULL,
370                                                True);
371
372                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
373                 data_blob_free(&local_lm_blob);
374                 data_blob_free(&local_nt_blob);
375                 data_blob_free(&lm_interactive_blob);
376                 data_blob_free(&nt_interactive_blob);
377                 return ret;
378         }
379 }
380
381
382 /****************************************************************************
383  Create an auth_usersupplied_data structure
384 ****************************************************************************/
385
386 BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, 
387                               const char *smb_name, 
388                               const char *client_domain,
389                               const uint8 chal[8],
390                               DATA_BLOB plaintext_password)
391 {
392
393         DATA_BLOB local_lm_blob;
394         DATA_BLOB local_nt_blob;
395         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
396                         
397         /*
398          * Not encrypted - do so.
399          */
400         
401         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n"));
402         
403         if (plaintext_password.data) {
404                 unsigned char local_lm_response[24];
405                 
406 #ifdef DEBUG_PASSWORD
407                 DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length));
408                 dump_data(100, plaintext_password.data, plaintext_password.length);
409 #endif
410
411                 SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response);
412                 local_lm_blob = data_blob(local_lm_response, 24);
413                 
414                 /* We can't do an NT hash here, as the password needs to be
415                    case insensitive */
416                 local_nt_blob = data_blob(NULL, 0); 
417                 
418         } else {
419                 local_lm_blob = data_blob(NULL, 0); 
420                 local_nt_blob = data_blob(NULL, 0); 
421         }
422         
423         ret = make_user_info_map(user_info, smb_name,
424                                  client_domain, 
425                                  get_remote_machine_name(),
426                                  local_lm_blob.data ? &local_lm_blob : NULL,
427                                  local_nt_blob.data ? &local_nt_blob : NULL,
428                                  NULL, NULL,
429                                  plaintext_password.data ? &plaintext_password : NULL, 
430                                  False);
431         
432         data_blob_free(&local_lm_blob);
433         return NT_STATUS_IS_OK(ret) ? True : False;
434 }
435
436 /****************************************************************************
437  Create an auth_usersupplied_data structure
438 ****************************************************************************/
439
440 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
441                                       const char *smb_name,
442                                       const char *client_domain, 
443                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
444 {
445         return make_user_info_map(user_info, smb_name, 
446                                   client_domain, 
447                                   get_remote_machine_name(), 
448                                   lm_resp.data ? &lm_resp : NULL, 
449                                   nt_resp.data ? &nt_resp : NULL, 
450                                   NULL, NULL, NULL,
451                                   True);
452 }
453
454 /****************************************************************************
455  Create a guest user_info blob, for anonymous authenticaion.
456 ****************************************************************************/
457
458 BOOL make_user_info_guest(auth_usersupplied_info **user_info) 
459 {
460         NTSTATUS nt_status;
461
462         nt_status = make_user_info(user_info, 
463                                    "","", 
464                                    "","", 
465                                    "", 
466                                    NULL, NULL, 
467                                    NULL, NULL, 
468                                    NULL,
469                                    True);
470                               
471         return NT_STATUS_IS_OK(nt_status) ? True : False;
472 }
473
474 /****************************************************************************
475  prints a NT_USER_TOKEN to debug output.
476 ****************************************************************************/
477
478 void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
479 {
480         fstring sid_str;
481         size_t     i;
482         
483         if (!token) {
484                 DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
485                 return;
486         }
487         
488         DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
489                                     sid_to_string(sid_str, &token->user_sids[0]) ));
490         DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));
491         for (i = 0; i < token->num_sids; i++)
492                 DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, 
493                                                sid_to_string(sid_str, &token->user_sids[i])));
494
495         dump_se_priv( dbg_class, dbg_lev, &token->privileges );
496 }
497
498 /****************************************************************************
499  prints a UNIX 'token' to debug output.
500 ****************************************************************************/
501
502 void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups)
503 {
504         int     i;
505         DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));
506
507         DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));
508         for (i = 0; i < n_groups; i++)
509                 DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i, 
510                         (long int)groups[i]));
511 }
512
513 /****************************************************************************
514  Create the SID list for this user.
515 ****************************************************************************/
516
517 static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid, 
518                                      int n_groupSIDs, DOM_SID *groupSIDs, 
519                                      BOOL is_guest, NT_USER_TOKEN **token)
520 {
521         NTSTATUS       nt_status = NT_STATUS_OK;
522         NT_USER_TOKEN *ptoken;
523         int i;
524         int sid_ndx;
525         
526         if ((ptoken = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL) {
527                 DEBUG(0, ("create_nt_token: Out of memory allocating token\n"));
528                 nt_status = NT_STATUS_NO_MEMORY;
529                 return nt_status;
530         }
531
532         ZERO_STRUCTP(ptoken);
533
534         ptoken->num_sids = n_groupSIDs + 5;
535
536         if ((ptoken->user_sids = SMB_MALLOC_ARRAY( DOM_SID, ptoken->num_sids )) == NULL) {
537                 DEBUG(0, ("create_nt_token: Out of memory allocating SIDs\n"));
538                 nt_status = NT_STATUS_NO_MEMORY;
539                 return nt_status;
540         }
541         
542         memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);
543         
544         /*
545          * Note - user SID *MUST* be first in token !
546          * se_access_check depends on this.
547          *
548          * Primary group SID is second in token. Convention.
549          */
550
551         sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);
552         if (group_sid)
553                 sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);
554
555         /*
556          * Finally add the "standard" SIDs.
557          * The only difference between guest and "anonymous" (which we
558          * don't really support) is the addition of Authenticated_Users.
559          */
560
561         sid_copy(&ptoken->user_sids[2], &global_sid_World);
562         sid_copy(&ptoken->user_sids[3], &global_sid_Network);
563
564         if (is_guest)
565                 sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);
566         else
567                 sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);
568         
569         sid_ndx = 5; /* next available spot */
570
571         for (i = 0; i < n_groupSIDs; i++) {
572                 size_t check_sid_idx;
573                 for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
574                         if (sid_equal(&ptoken->user_sids[check_sid_idx], 
575                                       &groupSIDs[i])) {
576                                 break;
577                         }
578                 }
579                 
580                 if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
581                         sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);
582                 } else {
583                         ptoken->num_sids--;
584                 }
585         }
586
587         /* add privileges assigned to this user */
588
589         get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );
590         
591         debug_nt_user_token(DBGC_AUTH, 10, ptoken);
592         
593         if ((lp_log_nt_token_command() != NULL) &&
594             (strlen(lp_log_nt_token_command()) > 0)) {
595                 TALLOC_CTX *mem_ctx;
596                 char *command;
597                 fstring sidstr;
598                 char *user_sidstr, *group_sidstr;
599
600                 mem_ctx = talloc_init("setnttoken");
601                 if (mem_ctx == NULL)
602                         return NT_STATUS_NO_MEMORY;
603
604                 sid_to_string(sidstr, &ptoken->user_sids[0]);
605                 user_sidstr = talloc_strdup(mem_ctx, sidstr);
606
607                 group_sidstr = talloc_strdup(mem_ctx, "");
608                 for (i=1; i<ptoken->num_sids; i++) {
609                         sid_to_string(sidstr, &ptoken->user_sids[i]);
610                         group_sidstr = talloc_asprintf(mem_ctx, "%s %s",
611                                                        group_sidstr, sidstr);
612                 }
613
614                 command = strdup(lp_log_nt_token_command());
615                 command = realloc_string_sub(command, "%s", user_sidstr);
616                 command = realloc_string_sub(command, "%t", group_sidstr);
617                 DEBUG(8, ("running command: [%s]\n", command));
618                 if (smbrun(command, NULL) != 0) {
619                         DEBUG(0, ("Could not log NT token\n"));
620                         nt_status = NT_STATUS_ACCESS_DENIED;
621                 }
622                 talloc_destroy(mem_ctx);
623                 SAFE_FREE(command);
624         }
625
626         *token = ptoken;
627
628         return nt_status;
629 }
630
631 /****************************************************************************
632  Create the SID list for this user.
633 ****************************************************************************/
634
635 NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
636 {
637         DOM_SID user_sid;
638         DOM_SID group_sid;
639         DOM_SID *group_sids;
640         NT_USER_TOKEN *token;
641         int i;
642
643         if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) {
644                 return NULL;
645         }
646         if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) {
647                 return NULL;
648         }
649
650         group_sids = SMB_MALLOC_ARRAY(DOM_SID, ngroups);
651         if (!group_sids) {
652                 DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
653                 return NULL;
654         }
655
656         for (i = 0; i < ngroups; i++) {
657                 if (!NT_STATUS_IS_OK(gid_to_sid(&(group_sids)[i], (groups)[i]))) {
658                         DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));
659                         SAFE_FREE(group_sids);
660                         return NULL;
661                 }
662         }
663
664         if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid, 
665                                                   ngroups, group_sids, is_guest, &token))) {
666                 SAFE_FREE(group_sids);
667                 return NULL;
668         }
669
670         SAFE_FREE(group_sids);
671
672         return token;
673 }
674
675 /******************************************************************************
676  * this function returns the groups (SIDs) of the local SAM the user is in.
677  * If this samba server is a DC of the domain the user belongs to, it returns 
678  * both domain groups and local / builtin groups. If the user is in a trusted
679  * domain, or samba is a member server of a domain, then this function returns
680  * local and builtin groups the user is a member of.
681  *
682  * currently this is a hack, as there is no sam implementation that is capable
683  * of groups.
684  *
685  * NOTE!! This function will fail if you pass in a winbind user without 
686  * the domain   --jerry
687  ******************************************************************************/
688
689 static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,
690                                 int *n_groups, DOM_SID **groups, gid_t **unix_groups)
691 {
692         int             n_unix_groups;
693         int             i;
694
695         *n_groups = 0;
696         *groups   = NULL;
697
698         if (strchr(username, *lp_winbind_separator()) == NULL) {
699                 NTSTATUS result;
700
701                 become_root();
702                 result = pdb_enum_group_memberships(username, gid, groups,
703                                                     unix_groups, n_groups);
704                 unbecome_root();
705                 return result;
706         }
707
708         /* We have the separator, this must be winbind */
709         
710         n_unix_groups = winbind_getgroups( username, unix_groups );
711
712         DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",
713                   username,  n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
714                           
715         if ( n_unix_groups == -1 )
716                 return NT_STATUS_NO_SUCH_USER; /* what should this return
717                                                 * value be? */  
718
719         debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
720         
721         /* now setup the space for storing the SIDS */
722         
723         if (n_unix_groups > 0) {
724         
725                 *groups   = SMB_MALLOC_ARRAY(DOM_SID, n_unix_groups);
726                 
727                 if (!*groups) {
728                         DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n"));
729                         SAFE_FREE(*unix_groups);
730                         return NT_STATUS_NO_MEMORY;
731                 }
732         }
733
734         *n_groups = n_unix_groups;
735
736         for (i = 0; i < *n_groups; i++) {
737                 if (!NT_STATUS_IS_OK(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) {
738                         DEBUG(1, ("get_user_groups: failed to convert gid %ld to a sid!\n", 
739                                 (long int)(*unix_groups)[i+1]));
740                         SAFE_FREE(*groups);
741                         SAFE_FREE(*unix_groups);
742                         return NT_STATUS_NO_SUCH_USER;
743                 }
744         }
745                      
746         return NT_STATUS_OK;
747 }
748
749 /***************************************************************************
750  Make a user_info struct
751 ***************************************************************************/
752
753 static NTSTATUS make_server_info(auth_serversupplied_info **server_info)
754 {
755         *server_info = SMB_MALLOC_P(auth_serversupplied_info);
756         if (!*server_info) {
757                 DEBUG(0,("make_server_info: malloc failed!\n"));
758                 return NT_STATUS_NO_MEMORY;
759         }
760         ZERO_STRUCTP(*server_info);
761
762         /* Initialise the uid and gid values to something non-zero
763            which may save us from giving away root access if there
764            is a bug in allocating these fields. */
765
766         (*server_info)->uid = -1;
767         (*server_info)->gid = -1;
768
769         return NT_STATUS_OK;
770 }
771
772 /***************************************************************************
773 Fill a server_info struct from a SAM_ACCOUNT with their groups
774 ***************************************************************************/
775
776 static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, 
777                                 const char * unix_username,
778                                 SAM_ACCOUNT *sampass,
779                                 uid_t uid, gid_t gid)
780 {
781         NTSTATUS nt_status;
782         const DOM_SID *user_sid = pdb_get_user_sid(sampass);
783         const DOM_SID *group_sid = pdb_get_group_sid(sampass);
784         int       n_groupSIDs = 0;
785         DOM_SID  *groupSIDs   = NULL;
786         gid_t    *unix_groups = NULL;
787         NT_USER_TOKEN *token;
788         BOOL is_guest;
789         uint32 rid;
790
791         nt_status = get_user_groups(unix_username, uid, gid, 
792                 &n_groupSIDs, &groupSIDs, &unix_groups);
793                 
794         if (!NT_STATUS_IS_OK(nt_status)) {
795                 DEBUG(4,("get_user_groups_from_local_sam failed\n"));
796                 free_server_info(server_info);
797                 return nt_status;
798         }
799         
800         is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);
801
802         if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,
803                                                               n_groupSIDs, groupSIDs, is_guest, 
804                                                               &token)))
805         {
806                 DEBUG(4,("create_nt_user_token failed\n"));
807                 SAFE_FREE(groupSIDs);
808                 SAFE_FREE(unix_groups);
809                 free_server_info(server_info);
810                 return nt_status;
811         }
812         
813         SAFE_FREE(groupSIDs);
814
815         (*server_info)->n_groups = n_groupSIDs;
816         (*server_info)->groups = unix_groups;
817         (*server_info)->ptok = token;
818
819         return nt_status;
820 }
821
822 /***************************************************************************
823  Make (and fill) a user_info struct from a SAM_ACCOUNT
824 ***************************************************************************/
825
826 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, 
827                               SAM_ACCOUNT *sampass)
828 {
829         NTSTATUS nt_status;
830         struct passwd *pwd;
831
832         if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info)))
833                 return nt_status;
834
835         (*server_info)->sam_account    = sampass;
836
837         if ( !(pwd = getpwnam_alloc(pdb_get_username(sampass))) )  {
838                 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
839                           pdb_get_username(sampass)));
840                 free_server_info(server_info);
841                 return NT_STATUS_NO_SUCH_USER;
842         }
843         (*server_info)->unix_name = smb_xstrdup(pwd->pw_name);
844         (*server_info)->gid = pwd->pw_gid;
845         (*server_info)->uid = pwd->pw_uid;
846         
847         passwd_free(&pwd);
848
849         if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, pdb_get_username(sampass), 
850                                                          sampass,
851                                                          (*server_info)->uid, 
852                                                          (*server_info)->gid))) 
853         {
854                 free_server_info(server_info);
855                 return nt_status;
856         }
857
858         (*server_info)->sam_fill_level = SAM_FILL_ALL;
859         DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
860                  pdb_get_username(sampass),
861                  (*server_info)->unix_name));
862
863         return nt_status;
864 }
865
866 /***************************************************************************
867  Make (and fill) a user_info struct from a 'struct passwd' by conversion 
868  to a SAM_ACCOUNT
869 ***************************************************************************/
870
871 NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, 
872                              char *unix_username,
873                              struct passwd *pwd)
874 {
875         NTSTATUS nt_status;
876         SAM_ACCOUNT *sampass = NULL;
877         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {             
878                 return nt_status;
879         }
880         if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
881                 return nt_status;
882         }
883
884         (*server_info)->sam_account    = sampass;
885
886         if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
887                 sampass, pwd->pw_uid, pwd->pw_gid))) 
888         {
889                 return nt_status;
890         }
891
892         (*server_info)->unix_name = smb_xstrdup(unix_username);
893
894         (*server_info)->sam_fill_level = SAM_FILL_ALL;
895         (*server_info)->uid = pwd->pw_uid;
896         (*server_info)->gid = pwd->pw_gid;
897         return nt_status;
898 }
899
900 /***************************************************************************
901  Make (and fill) a user_info struct for a guest login.
902 ***************************************************************************/
903
904 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
905 {
906         NTSTATUS nt_status;
907         SAM_ACCOUNT *sampass = NULL;
908         DOM_SID guest_sid;
909
910         if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
911                 return nt_status;
912         }
913
914         sid_copy(&guest_sid, get_global_sam_sid());
915         sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
916
917         become_root();
918         if (!pdb_getsampwsid(sampass, &guest_sid)) {
919                 unbecome_root();
920                 return NT_STATUS_NO_SUCH_USER;
921         }
922         unbecome_root();
923
924         nt_status = make_server_info_sam(server_info, sampass);
925
926         if (NT_STATUS_IS_OK(nt_status)) {
927                 static const char zeros[16];
928                 (*server_info)->guest = True;
929                 
930                 /* annoying, but the Guest really does have a session key, 
931                    and it is all zeros! */
932                 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
933                 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
934         }
935
936         return nt_status;
937 }
938
939 static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
940 {
941         auth_serversupplied_info *dst;
942
943         if (!NT_STATUS_IS_OK(make_server_info(&dst)))
944                 return NULL;
945
946         dst->guest = src->guest;
947         dst->uid = src->uid;
948         dst->gid = src->gid;
949         dst->n_groups = src->n_groups;
950         if (src->n_groups != 0)
951                 dst->groups = memdup(src->groups, sizeof(gid_t)*dst->n_groups);
952         else
953                 dst->groups = NULL;
954         dst->ptok = dup_nt_token(src->ptok);
955         dst->user_session_key = data_blob(src->user_session_key.data,
956                                           src->user_session_key.length);
957         dst->lm_session_key = data_blob(src->lm_session_key.data,
958                                           src->lm_session_key.length);
959         pdb_copy_sam_account(src->sam_account, &dst->sam_account);
960         dst->pam_handle = NULL;
961         dst->unix_name = smb_xstrdup(src->unix_name);
962
963         return dst;
964 }
965
966 static auth_serversupplied_info *guest_info = NULL;
967
968 BOOL init_guest_info(void)
969 {
970         if (guest_info != NULL)
971                 return True;
972
973         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
974 }
975
976 NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
977 {
978         *server_info = copy_serverinfo(guest_info);
979         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
980 }
981
982 /***************************************************************************
983  Purely internal function for make_server_info_info3
984  Fill the sam account from getpwnam
985 ***************************************************************************/
986 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, 
987                                  const char *domain,
988                                  const char *username,
989                                  char **found_username,
990                                  uid_t *uid, gid_t *gid,
991                                  SAM_ACCOUNT **sam_account)
992 {
993         fstring dom_user, lower_username;
994         fstring real_username;
995         struct passwd *passwd;
996
997         fstrcpy( lower_username, username );
998         strlower_m( lower_username );
999
1000         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
1001                 lower_username);
1002
1003         /* get the passwd struct but don't create the user if he/she 
1004            does not exist.  We were explicitly called from a following
1005            a winbindd authentication request so we should assume that 
1006            nss_winbindd is working */
1007
1008         map_username( dom_user );
1009
1010         if ( !(passwd = smb_getpwnam( dom_user, real_username, True )) )
1011                 return NT_STATUS_NO_SUCH_USER;
1012
1013         *uid = passwd->pw_uid;
1014         *gid = passwd->pw_gid;
1015
1016         /* This is pointless -- there is no suport for differing 
1017            unix and windows names.  Make sure to always store the 
1018            one we actually looked up and succeeded. Have I mentioned
1019            why I hate the 'winbind use default domain' parameter?   
1020                                          --jerry              */
1021            
1022         *found_username = talloc_strdup( mem_ctx, real_username );
1023         
1024         DEBUG(5,("fill_sam_account: located username was [%s]\n",
1025                 *found_username));
1026
1027         return pdb_init_sam_pw(sam_account, passwd);
1028 }
1029
1030 /****************************************************************************
1031  Wrapper to allow the getpwnam() call to strip the domain name and 
1032  try again in case a local UNIX user is already there.  Also run through 
1033  the username if we fallback to the username only.
1034  ****************************************************************************/
1035  
1036 struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
1037 {
1038         struct passwd *pw = NULL;
1039         char *p;
1040         fstring username;
1041         
1042         /* we only save a copy of the username it has been mangled 
1043            by winbindd use default domain */
1044            
1045         save_username[0] = '\0';
1046            
1047         /* don't call map_username() here since it has to be done higher 
1048            up the stack so we don't call it mutliple times */
1049
1050         fstrcpy( username, domuser );
1051         
1052         p = strchr_m( username, *lp_winbind_separator() );
1053         
1054         /* code for a DOMAIN\user string */
1055         
1056         if ( p ) {
1057                 fstring strip_username;
1058
1059                 pw = Get_Pwnam( domuser );
1060                 if ( pw ) {     
1061                         /* make sure we get the case of the username correct */
1062                         /* work around 'winbind use default domain = yes' */
1063
1064                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1065                                 char *domain;
1066                                 
1067                                 /* split the domain and username into 2 strings */
1068                                 *p = '\0';
1069                                 domain = username;
1070
1071                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1072                         }
1073                         else
1074                                 fstrcpy( save_username, pw->pw_name );
1075
1076                         /* whew -- done! */             
1077                         return pw;
1078                 }
1079
1080                 /* setup for lookup of just the username */
1081                 /* remember that p and username are overlapping memory */
1082
1083                 p++;
1084                 fstrcpy( strip_username, p );
1085                 fstrcpy( username, strip_username );
1086         }
1087         
1088         /* just lookup a plain username */
1089         
1090         pw = Get_Pwnam(username);
1091                 
1092         /* Create local user if requested. */
1093         
1094         if ( !pw && create ) {
1095                 /* Don't add a machine account. */
1096                 if (username[strlen(username)-1] == '$')
1097                         return NULL;
1098
1099                 auth_add_user_script(NULL, username);
1100                 pw = Get_Pwnam(username);
1101         }
1102         
1103         /* one last check for a valid passwd struct */
1104         
1105         if ( pw )
1106                 fstrcpy( save_username, pw->pw_name );
1107
1108         return pw;
1109 }
1110
1111 /***************************************************************************
1112  Make a server_info struct from the info3 returned by a domain logon 
1113 ***************************************************************************/
1114
1115 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1116                                 const char *internal_username,
1117                                 const char *sent_nt_username,
1118                                 const char *domain,
1119                                 auth_serversupplied_info **server_info, 
1120                                 NET_USER_INFO_3 *info3) 
1121 {
1122         static const char zeros[16];
1123
1124         NTSTATUS nt_status = NT_STATUS_OK;
1125         char *found_username;
1126         const char *nt_domain;
1127         const char *nt_username;
1128
1129         SAM_ACCOUNT *sam_account = NULL;
1130         DOM_SID user_sid;
1131         DOM_SID group_sid;
1132
1133         uid_t uid;
1134         gid_t gid;
1135
1136         int n_lgroupSIDs;
1137         DOM_SID *lgroupSIDs   = NULL;
1138
1139         gid_t *unix_groups = NULL;
1140         NT_USER_TOKEN *token;
1141
1142         DOM_SID *all_group_SIDs;
1143         size_t i;
1144
1145         /* 
1146            Here is where we should check the list of
1147            trusted domains, and verify that the SID 
1148            matches.
1149         */
1150
1151         sid_copy(&user_sid, &info3->dom_sid.sid);
1152         if (!sid_append_rid(&user_sid, info3->user_rid)) {
1153                 return NT_STATUS_INVALID_PARAMETER;
1154         }
1155         
1156         sid_copy(&group_sid, &info3->dom_sid.sid);
1157         if (!sid_append_rid(&group_sid, info3->group_rid)) {
1158                 return NT_STATUS_INVALID_PARAMETER;
1159         }
1160
1161         if (!(nt_username = unistr2_tdup(mem_ctx, &(info3->uni_user_name)))) {
1162                 /* If the server didn't give us one, just use the one we sent them */
1163                 nt_username = sent_nt_username;
1164         }
1165
1166         if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3->uni_logon_dom)))) {
1167                 /* If the server didn't give us one, just use the one we sent them */
1168                 nt_domain = domain;
1169         }
1170         
1171         /* try to fill the SAM account..  If getpwnam() fails, then try the 
1172            add user script (2.2.x behavior).
1173
1174            We use the _unmapped_ username here in an attempt to provide
1175            consistent username mapping behavior between kerberos and NTLM[SSP]
1176            authentication in domain mode security.  I.E. Username mapping should
1177            be applied to the fully qualified username (e.g. DOMAIN\user) and
1178            no just the login name.  Yes this mean swe called map_username()
1179            unnecessarily in make_user_info_map() but that is how the current
1180            code is designed.  Making the change here is the least disruptive 
1181            place.    -- jerry */
1182            
1183         nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1184                 &found_username, &uid, &gid, &sam_account);
1185
1186         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
1187                 DEBUG(3,("User %s does not exist, trying to add it\n", internal_username));
1188                 auth_add_user_script( nt_domain, sent_nt_username );
1189                 nt_status = fill_sam_account( mem_ctx, nt_domain, sent_nt_username, 
1190                         &found_username, &uid, &gid, &sam_account );
1191         }
1192         
1193         if (!NT_STATUS_IS_OK(nt_status)) {
1194                 DEBUG(0, ("make_server_info_info3: pdb_init_sam failed!\n"));
1195                 return nt_status;
1196         }
1197                 
1198         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1199                 pdb_free_sam(&sam_account);
1200                 return NT_STATUS_NO_MEMORY;
1201         }
1202
1203         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1204                 pdb_free_sam(&sam_account);
1205                 return NT_STATUS_NO_MEMORY;
1206         }
1207
1208         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1209                 pdb_free_sam(&sam_account);
1210                 return NT_STATUS_NO_MEMORY;
1211         }
1212
1213         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1214                 pdb_free_sam(&sam_account);
1215                 return NT_STATUS_UNSUCCESSFUL;
1216         }
1217
1218         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1219                 pdb_free_sam(&sam_account);
1220                 return NT_STATUS_UNSUCCESSFUL;
1221         }
1222                 
1223         if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), 
1224                               PDB_CHANGED)) {
1225                 pdb_free_sam(&sam_account);
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         if (!pdb_set_logon_script(sam_account, unistr2_static(&(info3->uni_logon_script)), PDB_CHANGED)) {
1230                 pdb_free_sam(&sam_account);
1231                 return NT_STATUS_NO_MEMORY;
1232         }
1233
1234         if (!pdb_set_profile_path(sam_account, unistr2_static(&(info3->uni_profile_path)), PDB_CHANGED)) {
1235                 pdb_free_sam(&sam_account);
1236                 return NT_STATUS_NO_MEMORY;
1237         }
1238
1239         if (!pdb_set_homedir(sam_account, unistr2_static(&(info3->uni_home_dir)), PDB_CHANGED)) {
1240                 pdb_free_sam(&sam_account);
1241                 return NT_STATUS_NO_MEMORY;
1242         }
1243
1244         if (!pdb_set_dir_drive(sam_account, unistr2_static(&(info3->uni_dir_drive)), PDB_CHANGED)) {
1245                 pdb_free_sam(&sam_account);
1246                 return NT_STATUS_NO_MEMORY;
1247         }
1248
1249         if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
1250                 DEBUG(4, ("make_server_info failed!\n"));
1251                 pdb_free_sam(&sam_account);
1252                 return nt_status;
1253         }
1254
1255         /* save this here to _net_sam_logon() doesn't fail (it assumes a 
1256            valid SAM_ACCOUNT) */
1257                    
1258         (*server_info)->sam_account = sam_account;
1259
1260         (*server_info)->unix_name = smb_xstrdup(found_username);
1261
1262         /* Fill in the unix info we found on the way */
1263
1264         (*server_info)->sam_fill_level = SAM_FILL_ALL;
1265         (*server_info)->uid = uid;
1266         (*server_info)->gid = gid;
1267
1268         /* Store the user group information in the server_info 
1269            returned to the caller. */
1270         
1271         nt_status = get_user_groups((*server_info)->unix_name,
1272                 uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups);
1273                 
1274         if ( !NT_STATUS_IS_OK(nt_status) ) {
1275                 DEBUG(4,("get_user_groups failed\n"));
1276                 return nt_status;
1277         }
1278
1279         (*server_info)->groups = unix_groups;
1280         (*server_info)->n_groups = n_lgroupSIDs;
1281         
1282         /* Create a 'combined' list of all SIDs we might want in the SD */
1283         
1284         all_group_SIDs = SMB_MALLOC_ARRAY(DOM_SID,info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs);
1285         
1286         if (!all_group_SIDs) {
1287                 DEBUG(0, ("malloc() failed for DOM_SID list!\n"));
1288                 SAFE_FREE(lgroupSIDs);
1289                 free_server_info(server_info);
1290                 return NT_STATUS_NO_MEMORY;
1291         }
1292
1293         /* and create (by appending rids) the 'domain' sids */
1294         
1295         for (i = 0; i < info3->num_groups2; i++) {
1296         
1297                 sid_copy(&all_group_SIDs[i], &(info3->dom_sid.sid));
1298                 
1299                 if (!sid_append_rid(&all_group_SIDs[i], info3->gids[i].g_rid)) {
1300                 
1301                         nt_status = NT_STATUS_INVALID_PARAMETER;
1302                         
1303                         DEBUG(3,("could not append additional group rid 0x%x\n",
1304                                 info3->gids[i].g_rid));                 
1305                                 
1306                         SAFE_FREE(lgroupSIDs);
1307                         SAFE_FREE(all_group_SIDs);
1308                         free_server_info(server_info);
1309                         
1310                         return nt_status;
1311                         
1312                 }
1313         }
1314
1315         /* Copy 'other' sids.  We need to do sid filtering here to
1316            prevent possible elevation of privileges.  See:
1317
1318            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
1319          */
1320
1321         for (i = 0; i < info3->num_other_sids; i++) {
1322                 sid_copy(&all_group_SIDs[info3->num_groups2 + i],
1323                          &info3->other_sids[i].sid);
1324         }
1325
1326
1327         /* add local alias sids */ 
1328
1329         for (i = 0; i < n_lgroupSIDs; i++) {
1330                 sid_copy(&all_group_SIDs[info3->num_groups2 +
1331                                          info3->num_other_sids + i],
1332                          &lgroupSIDs[i]);
1333         }
1334         
1335         /* Where are the 'global' sids... */
1336
1337         /* can the user be guest? if yes, where is it stored? */
1338         
1339         nt_status = create_nt_user_token(&user_sid, &group_sid,
1340                 info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs,
1341                 all_group_SIDs, False, &token);
1342                 
1343         if ( !NT_STATUS_IS_OK(nt_status) ) {
1344                 DEBUG(4,("create_nt_user_token failed\n"));
1345                 SAFE_FREE(lgroupSIDs);
1346                 SAFE_FREE(all_group_SIDs);
1347                 free_server_info(server_info);
1348                 return nt_status;
1349         }
1350
1351         (*server_info)->ptok = token; 
1352
1353         SAFE_FREE(lgroupSIDs);
1354         SAFE_FREE(all_group_SIDs);
1355
1356         /* ensure we are never given NULL session keys */
1357         
1358         if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
1359                 (*server_info)->user_session_key = data_blob(NULL, 0);
1360         } else {
1361                 (*server_info)->user_session_key = data_blob(info3->user_sess_key, sizeof(info3->user_sess_key));
1362         }
1363
1364         if (memcmp(info3->lm_sess_key, zeros, 8) == 0) {
1365                 (*server_info)->lm_session_key = data_blob(NULL, 0);
1366         } else {
1367                 (*server_info)->lm_session_key = data_blob(info3->lm_sess_key, sizeof(info3->lm_sess_key));
1368         } 
1369
1370         return NT_STATUS_OK;
1371 }
1372
1373 /***************************************************************************
1374  Free a user_info struct
1375 ***************************************************************************/
1376
1377 void free_user_info(auth_usersupplied_info **user_info)
1378 {
1379         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
1380         if (*user_info != NULL) {
1381                 if ((*user_info)->smb_name.str) {
1382                         DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
1383                 }
1384                 SAFE_FREE((*user_info)->smb_name.str);
1385                 SAFE_FREE((*user_info)->internal_username.str);
1386                 SAFE_FREE((*user_info)->client_domain.str);
1387                 SAFE_FREE((*user_info)->domain.str);
1388                 SAFE_FREE((*user_info)->wksta_name.str);
1389                 data_blob_free(&(*user_info)->lm_resp);
1390                 data_blob_free(&(*user_info)->nt_resp);
1391                 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
1392                 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
1393                 data_blob_clear_free(&(*user_info)->plaintext_password);
1394                 ZERO_STRUCT(**user_info);
1395         }
1396         SAFE_FREE(*user_info);
1397 }
1398
1399 /***************************************************************************
1400  Clear out a server_info struct that has been allocated
1401 ***************************************************************************/
1402
1403 void free_server_info(auth_serversupplied_info **server_info)
1404 {
1405         DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
1406         if (*server_info != NULL) {
1407                 pdb_free_sam(&(*server_info)->sam_account);
1408
1409                 /* call pam_end here, unless we know we are keeping it */
1410                 delete_nt_token( &(*server_info)->ptok );
1411                 SAFE_FREE((*server_info)->groups);
1412                 SAFE_FREE((*server_info)->unix_name);
1413                 data_blob_free(&(*server_info)->lm_session_key);
1414                 data_blob_free(&(*server_info)->user_session_key);
1415                 ZERO_STRUCT(**server_info);
1416         }
1417         SAFE_FREE(*server_info);
1418 }
1419
1420 /***************************************************************************
1421  Make an auth_methods struct
1422 ***************************************************************************/
1423
1424 BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
1425 {
1426         if (!auth_context) {
1427                 smb_panic("no auth_context supplied to make_auth_methods()!\n");
1428         }
1429
1430         if (!auth_method) {
1431                 smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
1432         }
1433
1434         *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
1435         if (!*auth_method) {
1436                 DEBUG(0,("make_auth_method: malloc failed!\n"));
1437                 return False;
1438         }
1439         ZERO_STRUCTP(*auth_method);
1440         
1441         return True;
1442 }
1443
1444 /****************************************************************************
1445  Delete a SID token.
1446 ****************************************************************************/
1447
1448 void delete_nt_token(NT_USER_TOKEN **pptoken)
1449 {
1450         if (*pptoken) {
1451                 NT_USER_TOKEN *ptoken = *pptoken;
1452
1453                 SAFE_FREE( ptoken->user_sids );
1454                 ZERO_STRUCTP(ptoken);
1455         }
1456         SAFE_FREE(*pptoken);
1457 }
1458
1459 /****************************************************************************
1460  Duplicate a SID token.
1461 ****************************************************************************/
1462
1463 NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
1464 {
1465         NT_USER_TOKEN *token;
1466
1467         if (!ptoken)
1468                 return NULL;
1469
1470         if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
1471                 return NULL;
1472
1473         ZERO_STRUCTP(token);
1474         
1475         token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
1476         
1477         if ( !token ) {
1478                 SAFE_FREE(token);
1479                 return NULL;
1480         }
1481
1482         token->num_sids = ptoken->num_sids;
1483         
1484         /* copy the privileges; don't consider failure to be critical here */
1485         
1486         if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) {
1487                 DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!.  Continuing with 0 privileges assigned.\n"));
1488         }
1489
1490         return token;
1491 }
1492
1493 /****************************************************************************
1494  Check for a SID in an NT_USER_TOKEN
1495 ****************************************************************************/
1496
1497 BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token )
1498 {
1499         int i;
1500         
1501         if ( !sid || !token )
1502                 return False;
1503         
1504         for ( i=0; i<token->num_sids; i++ ) {
1505                 if ( sid_equal( sid, &token->user_sids[i] ) )
1506                         return True;
1507         }
1508
1509         return False;
1510 }
1511
1512 BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid ) 
1513 {
1514         DOM_SID domain_sid;
1515
1516         /* if we are a domain member, the get the domain SID, else for 
1517            a DC or standalone server, use our own SID */
1518
1519         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1520                 if ( !secrets_fetch_domain_sid( lp_workgroup(), &domain_sid ) ) {
1521                         DEBUG(1,("nt_token_check_domain_rid: Cannot lookup SID for domain [%s]\n",
1522                                 lp_workgroup()));
1523                         return False;
1524                 }
1525         } 
1526         else
1527                 sid_copy( &domain_sid, get_global_sam_sid() );
1528
1529         sid_append_rid( &domain_sid, rid );
1530         
1531         return nt_token_check_sid( &domain_sid, token );\
1532 }
1533
1534 /**
1535  * Verify whether or not given domain is trusted.
1536  *
1537  * @param domain_name name of the domain to be verified
1538  * @return true if domain is one of the trusted once or
1539  *         false if otherwise
1540  **/
1541
1542 BOOL is_trusted_domain(const char* dom_name)
1543 {
1544         DOM_SID trustdom_sid;
1545         char *pass = NULL;
1546         time_t lct;
1547         BOOL ret;
1548
1549         /* no trusted domains for a standalone server */
1550
1551         if ( lp_server_role() == ROLE_STANDALONE )
1552                 return False;
1553
1554         /* if we are a DC, then check for a direct trust relationships */
1555
1556         if ( IS_DC ) {
1557                 become_root();
1558                 DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n",
1559                         dom_name ));
1560                 ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
1561                 unbecome_root();
1562                 SAFE_FREE(pass);
1563                 if (ret)
1564                         return True;
1565         }
1566         else {
1567                 /* if winbindd is not up and we are a domain member) then we need to update the
1568                    trustdom_cache ourselves */
1569
1570                 if ( !winbind_ping() )
1571                         update_trustdom_cache();
1572         }
1573
1574         /* now the trustdom cache should be available a DC could still
1575          * have a transitive trust so fall back to the cache of trusted
1576          * domains (like a domain member would use  */
1577
1578         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1579                 return True;
1580         }
1581
1582         return False;
1583 }
1584