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