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