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