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