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