7509b5ad1ce22f08ae7e50d06a435fef69416cb5
[jra/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; 
376                 
377         } else {
378                 local_lm_blob = data_blob_null; 
379                 local_nt_blob = data_blob_null; 
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         char *qualified_name = NULL;
970         TALLOC_CTX *mem_ctx = NULL;
971         DOM_SID u_sid;
972         enum lsa_SidType type;
973         auth_serversupplied_info *result;
974         
975         if ( !(sampass = samu_new( NULL )) ) {
976                 return NT_STATUS_NO_MEMORY;
977         }
978         
979         status = samu_set_unix( sampass, pwd );
980         if (!NT_STATUS_IS_OK(status)) {
981                 return status;
982         }
983
984         result = make_server_info(NULL);
985         if (result == NULL) {
986                 TALLOC_FREE(sampass);
987                 return NT_STATUS_NO_MEMORY;
988         }
989
990         result->sam_account = sampass;
991         result->unix_name = talloc_strdup(result, unix_username);
992         result->uid = pwd->pw_uid;
993         result->gid = pwd->pw_gid;
994
995         status = pdb_enum_group_memberships(result, sampass,
996                                             &result->sids, &gids,
997                                             &result->num_sids);
998
999         if (!NT_STATUS_IS_OK(status)) {
1000                 DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
1001                            nt_errstr(status)));
1002                 TALLOC_FREE(result);
1003                 return status;
1004         }
1005
1006         /*
1007          * The SID returned in server_info->sam_account is based
1008          * on our SAM sid even though for a pure UNIX account this should
1009          * not be the case as it doesn't really exist in the SAM db.
1010          * This causes lookups on "[in]valid users" to fail as they
1011          * will lookup this name as a "Unix User" SID to check against
1012          * the user token. Fix this by adding the "Unix User"\unix_username
1013          * SID to the sid array. The correct fix should probably be
1014          * changing the server_info->sam_account user SID to be a
1015          * S-1-22 Unix SID, but this might break old configs where
1016          * plaintext passwords were used with no SAM backend.
1017          */
1018
1019         mem_ctx = talloc_init("make_server_info_pw_tmp");
1020         if (!mem_ctx) {
1021                 TALLOC_FREE(result);
1022                 return NT_STATUS_NO_MEMORY;
1023         }
1024
1025         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
1026                                         unix_users_domain_name(),
1027                                         unix_username );
1028         if (!qualified_name) {
1029                 TALLOC_FREE(result);
1030                 TALLOC_FREE(mem_ctx);
1031                 return NT_STATUS_NO_MEMORY;
1032         }
1033
1034         if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
1035                                                 NULL, NULL,
1036                                                 &u_sid, &type)) {
1037                 TALLOC_FREE(result);
1038                 TALLOC_FREE(mem_ctx);
1039                 return NT_STATUS_NO_SUCH_USER;
1040         }
1041
1042         TALLOC_FREE(mem_ctx);
1043
1044         if (type != SID_NAME_USER) {
1045                 TALLOC_FREE(result);
1046                 return NT_STATUS_NO_SUCH_USER;
1047         }
1048
1049         if (!add_sid_to_array_unique(result, &u_sid,
1050                                         &result->sids,
1051                                         &result->num_sids)) {
1052                 TALLOC_FREE(result);
1053                 return NT_STATUS_NO_MEMORY;
1054         }
1055
1056         /* For now we throw away the gids and convert via sid_to_gid
1057          * later. This needs fixing, but I'd like to get the code straight and
1058          * simple first. */
1059         TALLOC_FREE(gids);
1060
1061         *server_info = result;
1062
1063         return NT_STATUS_OK;
1064 }
1065
1066 /***************************************************************************
1067  Make (and fill) a user_info struct for a guest login.
1068  This *must* succeed for smbd to start. If there is no mapping entry for
1069  the guest gid, then create one.
1070 ***************************************************************************/
1071
1072 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
1073 {
1074         NTSTATUS status;
1075         struct samu *sampass = NULL;
1076         DOM_SID guest_sid;
1077         BOOL ret;
1078         static const char zeros[16] = { 0, };
1079
1080         if ( !(sampass = samu_new( NULL )) ) {
1081                 return NT_STATUS_NO_MEMORY;
1082         }
1083
1084         sid_copy(&guest_sid, get_global_sam_sid());
1085         sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
1086
1087         become_root();
1088         ret = pdb_getsampwsid(sampass, &guest_sid);
1089         unbecome_root();
1090
1091         if (!ret) {
1092                 TALLOC_FREE(sampass);
1093                 return NT_STATUS_NO_SUCH_USER;
1094         }
1095
1096         status = make_server_info_sam(server_info, sampass);
1097         if (!NT_STATUS_IS_OK(status)) {
1098                 TALLOC_FREE(sampass);
1099                 return status;
1100         }
1101         
1102         (*server_info)->guest = True;
1103
1104         status = create_local_token(*server_info);
1105         if (!NT_STATUS_IS_OK(status)) {
1106                 DEBUG(10, ("create_local_token failed: %s\n",
1107                            nt_errstr(status)));
1108                 return status;
1109         }
1110
1111         /* annoying, but the Guest really does have a session key, and it is
1112            all zeros! */
1113         (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
1114         (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
1115
1116         return NT_STATUS_OK;
1117 }
1118
1119 static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
1120 {
1121         auth_serversupplied_info *dst;
1122
1123         dst = make_server_info(NULL);
1124         if (dst == NULL) {
1125                 return NULL;
1126         }
1127
1128         dst->guest = src->guest;
1129         dst->uid = src->uid;
1130         dst->gid = src->gid;
1131         dst->n_groups = src->n_groups;
1132         if (src->n_groups != 0) {
1133                 dst->groups = (gid_t *)TALLOC_MEMDUP(
1134                         dst, src->groups, sizeof(gid_t)*dst->n_groups);
1135         } else {
1136                 dst->groups = NULL;
1137         }
1138
1139         if (src->ptok) {
1140                 dst->ptok = dup_nt_token(dst, src->ptok);
1141                 if (!dst->ptok) {
1142                         TALLOC_FREE(dst);
1143                         return NULL;
1144                 }
1145         }
1146         
1147         dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
1148                                                 src->user_session_key.length);
1149
1150         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
1151                                                 src->lm_session_key.length);
1152
1153         dst->sam_account = samu_new(NULL);
1154         if (!dst->sam_account) {
1155                 TALLOC_FREE(dst);
1156                 return NULL;
1157         }
1158
1159         if (!pdb_copy_sam_account(dst->sam_account, src->sam_account)) {
1160                 TALLOC_FREE(dst);
1161                 return NULL;
1162         }
1163         
1164         dst->pam_handle = NULL;
1165         dst->unix_name = talloc_strdup(dst, src->unix_name);
1166         if (!dst->unix_name) {
1167                 TALLOC_FREE(dst);
1168                 return NULL;
1169         }
1170
1171         return dst;
1172 }
1173
1174 static auth_serversupplied_info *guest_info = NULL;
1175
1176 BOOL init_guest_info(void)
1177 {
1178         if (guest_info != NULL)
1179                 return True;
1180
1181         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1182 }
1183
1184 NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
1185 {
1186         *server_info = copy_serverinfo(guest_info);
1187         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1188 }
1189
1190 BOOL copy_current_user(struct current_user *dst, struct current_user *src)
1191 {
1192         gid_t *groups;
1193         NT_USER_TOKEN *nt_token;
1194
1195         groups = (gid_t *)memdup(src->ut.groups,
1196                                  sizeof(gid_t) * src->ut.ngroups);
1197         if ((src->ut.ngroups != 0) && (groups == NULL)) {
1198                 return False;
1199         }
1200
1201         nt_token = dup_nt_token(NULL, src->nt_user_token);
1202         if (nt_token == NULL) {
1203                 SAFE_FREE(groups);
1204                 return False;
1205         }
1206
1207         dst->conn = src->conn;
1208         dst->vuid = src->vuid;
1209         dst->ut.uid = src->ut.uid;
1210         dst->ut.gid = src->ut.gid;
1211         dst->ut.ngroups = src->ut.ngroups;
1212         dst->ut.groups = groups;
1213         dst->nt_user_token = nt_token;
1214         return True;
1215 }
1216
1217 BOOL set_current_user_guest(struct current_user *dst)
1218 {
1219         gid_t *groups;
1220         NT_USER_TOKEN *nt_token;
1221
1222         groups = (gid_t *)memdup(guest_info->groups,
1223                                  sizeof(gid_t) * guest_info->n_groups);
1224         if (groups == NULL) {
1225                 return False;
1226         }
1227
1228         nt_token = dup_nt_token(NULL, guest_info->ptok);
1229         if (nt_token == NULL) {
1230                 SAFE_FREE(groups);
1231                 return False;
1232         }
1233
1234         TALLOC_FREE(dst->nt_user_token);
1235         SAFE_FREE(dst->ut.groups);
1236
1237         /* dst->conn is never really dereferenced, it's only tested for
1238          * equality in uid.c */
1239         dst->conn = NULL;
1240
1241         dst->vuid = UID_FIELD_INVALID;
1242         dst->ut.uid = guest_info->uid;
1243         dst->ut.gid = guest_info->gid;
1244         dst->ut.ngroups = guest_info->n_groups;
1245         dst->ut.groups = groups;
1246         dst->nt_user_token = nt_token;
1247         return True;
1248 }
1249
1250 /***************************************************************************
1251  Purely internal function for make_server_info_info3
1252  Fill the sam account from getpwnam
1253 ***************************************************************************/
1254 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, 
1255                                  const char *domain,
1256                                  const char *username,
1257                                  char **found_username,
1258                                  uid_t *uid, gid_t *gid,
1259                                  struct samu *account,
1260                                  BOOL *username_was_mapped)
1261 {
1262         NTSTATUS nt_status;
1263         fstring dom_user, lower_username;
1264         fstring real_username;
1265         struct passwd *passwd;
1266
1267         fstrcpy( lower_username, username );
1268         strlower_m( lower_username );
1269
1270         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
1271                 lower_username);
1272
1273         /* Get the passwd struct.  Try to create the account is necessary. */
1274
1275         *username_was_mapped = map_username( dom_user );
1276
1277         if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
1278                 return NT_STATUS_NO_SUCH_USER;
1279
1280         *uid = passwd->pw_uid;
1281         *gid = passwd->pw_gid;
1282
1283         /* This is pointless -- there is no suport for differing 
1284            unix and windows names.  Make sure to always store the 
1285            one we actually looked up and succeeded. Have I mentioned
1286            why I hate the 'winbind use default domain' parameter?   
1287                                          --jerry              */
1288            
1289         *found_username = talloc_strdup( mem_ctx, real_username );
1290         
1291         DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
1292
1293         nt_status = samu_set_unix( account, passwd );
1294         
1295         TALLOC_FREE(passwd);
1296         
1297         return nt_status;
1298 }
1299
1300 /****************************************************************************
1301  Wrapper to allow the getpwnam() call to strip the domain name and 
1302  try again in case a local UNIX user is already there.  Also run through 
1303  the username if we fallback to the username only.
1304  ****************************************************************************/
1305  
1306 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
1307                              fstring save_username, BOOL create )
1308 {
1309         struct passwd *pw = NULL;
1310         char *p;
1311         fstring username;
1312         
1313         /* we only save a copy of the username it has been mangled 
1314            by winbindd use default domain */
1315            
1316         save_username[0] = '\0';
1317            
1318         /* don't call map_username() here since it has to be done higher 
1319            up the stack so we don't call it mutliple times */
1320
1321         fstrcpy( username, domuser );
1322         
1323         p = strchr_m( username, *lp_winbind_separator() );
1324         
1325         /* code for a DOMAIN\user string */
1326         
1327         if ( p ) {
1328                 fstring strip_username;
1329
1330                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1331                 if ( pw ) {     
1332                         /* make sure we get the case of the username correct */
1333                         /* work around 'winbind use default domain = yes' */
1334
1335                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1336                                 char *domain;
1337                                 
1338                                 /* split the domain and username into 2 strings */
1339                                 *p = '\0';
1340                                 domain = username;
1341
1342                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1343                         }
1344                         else
1345                                 fstrcpy( save_username, pw->pw_name );
1346
1347                         /* whew -- done! */             
1348                         return pw;
1349                 }
1350
1351                 /* setup for lookup of just the username */
1352                 /* remember that p and username are overlapping memory */
1353
1354                 p++;
1355                 fstrcpy( strip_username, p );
1356                 fstrcpy( username, strip_username );
1357         }
1358         
1359         /* just lookup a plain username */
1360         
1361         pw = Get_Pwnam_alloc(mem_ctx, username);
1362                 
1363         /* Create local user if requested but only if winbindd
1364            is not running.  We need to protect against cases
1365            where winbindd is failing and then prematurely
1366            creating users in /etc/passwd */
1367         
1368         if ( !pw && create && !winbind_ping() ) {
1369                 /* Don't add a machine account. */
1370                 if (username[strlen(username)-1] == '$')
1371                         return NULL;
1372
1373                 smb_create_user(NULL, username, NULL);
1374                 pw = Get_Pwnam_alloc(mem_ctx, username);
1375         }
1376         
1377         /* one last check for a valid passwd struct */
1378         
1379         if ( pw )
1380                 fstrcpy( save_username, pw->pw_name );
1381
1382         return pw;
1383 }
1384
1385 /***************************************************************************
1386  Make a server_info struct from the info3 returned by a domain logon 
1387 ***************************************************************************/
1388
1389 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1390                                 const char *sent_nt_username,
1391                                 const char *domain,
1392                                 auth_serversupplied_info **server_info, 
1393                                 NET_USER_INFO_3 *info3) 
1394 {
1395         static const char zeros[16] = { 0, };
1396
1397         NTSTATUS nt_status = NT_STATUS_OK;
1398         char *found_username;
1399         const char *nt_domain;
1400         const char *nt_username;
1401         struct samu *sam_account = NULL;
1402         DOM_SID user_sid;
1403         DOM_SID group_sid;
1404         BOOL username_was_mapped;
1405
1406         uid_t uid;
1407         gid_t gid;
1408
1409         size_t i;
1410
1411         auth_serversupplied_info *result;
1412
1413         /* 
1414            Here is where we should check the list of
1415            trusted domains, and verify that the SID 
1416            matches.
1417         */
1418
1419         sid_copy(&user_sid, &info3->dom_sid.sid);
1420         if (!sid_append_rid(&user_sid, info3->user_rid)) {
1421                 return NT_STATUS_INVALID_PARAMETER;
1422         }
1423         
1424         sid_copy(&group_sid, &info3->dom_sid.sid);
1425         if (!sid_append_rid(&group_sid, info3->group_rid)) {
1426                 return NT_STATUS_INVALID_PARAMETER;
1427         }
1428
1429         if (!(nt_username = unistr2_tdup(mem_ctx, &(info3->uni_user_name)))) {
1430                 /* If the server didn't give us one, just use the one we sent
1431                  * them */
1432                 nt_username = sent_nt_username;
1433         }
1434
1435         if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3->uni_logon_dom)))) {
1436                 /* If the server didn't give us one, just use the one we sent
1437                  * them */
1438                 nt_domain = domain;
1439         }
1440         
1441         /* try to fill the SAM account..  If getpwnam() fails, then try the 
1442            add user script (2.2.x behavior).
1443
1444            We use the _unmapped_ username here in an attempt to provide
1445            consistent username mapping behavior between kerberos and NTLM[SSP]
1446            authentication in domain mode security.  I.E. Username mapping
1447            should be applied to the fully qualified username
1448            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1449            called map_username() unnecessarily in make_user_info_map() but
1450            that is how the current code is designed.  Making the change here
1451            is the least disruptive place.  -- jerry */
1452            
1453         if ( !(sam_account = samu_new( NULL )) ) {
1454                 return NT_STATUS_NO_MEMORY;
1455         }
1456
1457         /* this call will try to create the user if necessary */
1458
1459         nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1460                                      &found_username, &uid, &gid, sam_account,
1461                                      &username_was_mapped);
1462
1463         
1464         /* if we still don't have a valid unix account check for 
1465           'map to guest = bad uid' */
1466           
1467         if (!NT_STATUS_IS_OK(nt_status)) {
1468                 TALLOC_FREE( sam_account );
1469                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1470                         make_server_info_guest(server_info); 
1471                         return NT_STATUS_OK;
1472                 }
1473                 return nt_status;
1474         }
1475                 
1476         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1477                 TALLOC_FREE(sam_account);
1478                 return NT_STATUS_NO_MEMORY;
1479         }
1480
1481         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1482                 TALLOC_FREE(sam_account);
1483                 return NT_STATUS_NO_MEMORY;
1484         }
1485
1486         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1487                 TALLOC_FREE(sam_account);
1488                 return NT_STATUS_NO_MEMORY;
1489         }
1490
1491         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1492                 TALLOC_FREE(sam_account);
1493                 return NT_STATUS_UNSUCCESSFUL;
1494         }
1495
1496         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1497                 TALLOC_FREE(sam_account);
1498                 return NT_STATUS_UNSUCCESSFUL;
1499         }
1500                 
1501         if (!pdb_set_fullname(sam_account,
1502                               unistr2_static(&(info3->uni_full_name)), 
1503                               PDB_CHANGED)) {
1504                 TALLOC_FREE(sam_account);
1505                 return NT_STATUS_NO_MEMORY;
1506         }
1507
1508         if (!pdb_set_logon_script(sam_account,
1509                                   unistr2_static(&(info3->uni_logon_script)),
1510                                   PDB_CHANGED)) {
1511                 TALLOC_FREE(sam_account);
1512                 return NT_STATUS_NO_MEMORY;
1513         }
1514
1515         if (!pdb_set_profile_path(sam_account,
1516                                   unistr2_static(&(info3->uni_profile_path)),
1517                                   PDB_CHANGED)) {
1518                 TALLOC_FREE(sam_account);
1519                 return NT_STATUS_NO_MEMORY;
1520         }
1521
1522         if (!pdb_set_homedir(sam_account,
1523                              unistr2_static(&(info3->uni_home_dir)),
1524                              PDB_CHANGED)) {
1525                 TALLOC_FREE(sam_account);
1526                 return NT_STATUS_NO_MEMORY;
1527         }
1528
1529         if (!pdb_set_dir_drive(sam_account,
1530                                unistr2_static(&(info3->uni_dir_drive)),
1531                                PDB_CHANGED)) {
1532                 TALLOC_FREE(sam_account);
1533                 return NT_STATUS_NO_MEMORY;
1534         }
1535
1536         if (!pdb_set_acct_ctrl(sam_account, info3->acct_flags, PDB_CHANGED)) {
1537                 TALLOC_FREE(sam_account);
1538                 return NT_STATUS_NO_MEMORY;
1539         }
1540
1541         if (!pdb_set_pass_last_set_time(
1542                     sam_account,
1543                     nt_time_to_unix(info3->pass_last_set_time),
1544                     PDB_CHANGED)) {
1545                 TALLOC_FREE(sam_account);
1546                 return NT_STATUS_NO_MEMORY;
1547         }
1548
1549         if (!pdb_set_pass_can_change_time(
1550                     sam_account,
1551                     nt_time_to_unix(info3->pass_can_change_time),
1552                     PDB_CHANGED)) {
1553                 TALLOC_FREE(sam_account);
1554                 return NT_STATUS_NO_MEMORY;
1555         }
1556
1557         if (!pdb_set_pass_must_change_time(
1558                     sam_account,
1559                     nt_time_to_unix(info3->pass_must_change_time),
1560                     PDB_CHANGED)) {
1561                 TALLOC_FREE(sam_account);
1562                 return NT_STATUS_NO_MEMORY;
1563         }
1564
1565         result = make_server_info(NULL);
1566         if (result == NULL) {
1567                 DEBUG(4, ("make_server_info failed!\n"));
1568                 TALLOC_FREE(sam_account);
1569                 return NT_STATUS_NO_MEMORY;
1570         }
1571
1572         /* save this here to _net_sam_logon() doesn't fail (it assumes a 
1573            valid struct samu) */
1574                    
1575         result->sam_account = sam_account;
1576         result->unix_name = talloc_strdup(result, found_username);
1577
1578         /* Fill in the unix info we found on the way */
1579
1580         result->uid = uid;
1581         result->gid = gid;
1582
1583         /* Create a 'combined' list of all SIDs we might want in the SD */
1584
1585         result->num_sids = 0;
1586         result->sids = NULL;
1587
1588         /* and create (by appending rids) the 'domain' sids */
1589         
1590         for (i = 0; i < info3->num_groups2; i++) {
1591                 DOM_SID sid;
1592                 if (!sid_compose(&sid, &info3->dom_sid.sid,
1593                                  info3->gids[i].g_rid)) {
1594                         DEBUG(3,("could not append additional group rid "
1595                                  "0x%x\n", info3->gids[i].g_rid));
1596                         TALLOC_FREE(result);
1597                         return NT_STATUS_INVALID_PARAMETER;
1598                 }
1599                 if (!add_sid_to_array(result, &sid, &result->sids,
1600                                  &result->num_sids)) {
1601                         TALLOC_FREE(result);
1602                         return NT_STATUS_NO_MEMORY;
1603                 }
1604         }
1605
1606         /* Copy 'other' sids.  We need to do sid filtering here to
1607            prevent possible elevation of privileges.  See:
1608
1609            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
1610          */
1611
1612         for (i = 0; i < info3->num_other_sids; i++) {
1613                 if (!add_sid_to_array(result, &info3->other_sids[i].sid,
1614                                          &result->sids,
1615                                          &result->num_sids)) {
1616                         TALLOC_FREE(result);
1617                         return NT_STATUS_NO_MEMORY;
1618                 }
1619         }
1620
1621         result->login_server = unistr2_tdup(result, 
1622                                             &(info3->uni_logon_srv));
1623
1624         /* ensure we are never given NULL session keys */
1625         
1626         if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
1627                 result->user_session_key = data_blob_null;
1628         } else {
1629                 result->user_session_key = data_blob_talloc(
1630                         result, info3->user_sess_key,
1631                         sizeof(info3->user_sess_key));
1632         }
1633
1634         if (memcmp(info3->lm_sess_key, zeros, 8) == 0) {
1635                 result->lm_session_key = data_blob_null;
1636         } else {
1637                 result->lm_session_key = data_blob_talloc(
1638                         result, info3->lm_sess_key,
1639                         sizeof(info3->lm_sess_key));
1640         }
1641
1642         result->was_mapped = username_was_mapped;
1643
1644         *server_info = result;
1645
1646         return NT_STATUS_OK;
1647 }
1648
1649 /***************************************************************************
1650  Free a user_info struct
1651 ***************************************************************************/
1652
1653 void free_user_info(auth_usersupplied_info **user_info)
1654 {
1655         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
1656         if (*user_info != NULL) {
1657                 if ((*user_info)->smb_name) {
1658                         DEBUG(10,("structure was created for %s\n",
1659                                   (*user_info)->smb_name));
1660                 }
1661                 SAFE_FREE((*user_info)->smb_name);
1662                 SAFE_FREE((*user_info)->internal_username);
1663                 SAFE_FREE((*user_info)->client_domain);
1664                 SAFE_FREE((*user_info)->domain);
1665                 SAFE_FREE((*user_info)->wksta_name);
1666                 data_blob_free(&(*user_info)->lm_resp);
1667                 data_blob_free(&(*user_info)->nt_resp);
1668                 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
1669                 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
1670                 data_blob_clear_free(&(*user_info)->plaintext_password);
1671                 ZERO_STRUCT(**user_info);
1672         }
1673         SAFE_FREE(*user_info);
1674 }
1675
1676 /***************************************************************************
1677  Make an auth_methods struct
1678 ***************************************************************************/
1679
1680 BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
1681 {
1682         if (!auth_context) {
1683                 smb_panic("no auth_context supplied to "
1684                           "make_auth_methods()!\n");
1685         }
1686
1687         if (!auth_method) {
1688                 smb_panic("make_auth_methods: pointer to auth_method pointer "
1689                           "is NULL!\n");
1690         }
1691
1692         *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
1693         if (!*auth_method) {
1694                 DEBUG(0,("make_auth_method: malloc failed!\n"));
1695                 return False;
1696         }
1697         ZERO_STRUCTP(*auth_method);
1698         
1699         return True;
1700 }
1701
1702 /**
1703  * Verify whether or not given domain is trusted.
1704  *
1705  * @param domain_name name of the domain to be verified
1706  * @return true if domain is one of the trusted once or
1707  *         false if otherwise
1708  **/
1709
1710 BOOL is_trusted_domain(const char* dom_name)
1711 {
1712         DOM_SID trustdom_sid;
1713         BOOL ret;
1714
1715         /* no trusted domains for a standalone server */
1716
1717         if ( lp_server_role() == ROLE_STANDALONE )
1718                 return False;
1719
1720         /* if we are a DC, then check for a direct trust relationships */
1721
1722         if ( IS_DC ) {
1723                 become_root();
1724                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1725                           "[%s]\n", dom_name ));
1726                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1727                 unbecome_root();
1728                 if (ret)
1729                         return True;
1730         }
1731         else {
1732                 NSS_STATUS result;
1733
1734                 /* If winbind is around, ask it */
1735
1736                 result = wb_is_trusted_domain(dom_name);
1737
1738                 if (result == NSS_STATUS_SUCCESS) {
1739                         return True;
1740                 }
1741
1742                 if (result == NSS_STATUS_NOTFOUND) {
1743                         /* winbind could not find the domain */
1744                         return False;
1745                 }
1746
1747                 /* The only other possible result is that winbind is not up
1748                    and running. We need to update the trustdom_cache
1749                    ourselves */
1750                 
1751                 update_trustdom_cache();
1752         }
1753
1754         /* now the trustdom cache should be available a DC could still
1755          * have a transitive trust so fall back to the cache of trusted
1756          * domains (like a domain member would use  */
1757
1758         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1759                 return True;
1760         }
1761
1762         return False;
1763 }
1764