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