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