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