s3 auth: Make debug message louder and more useful
[nivanova/samba-autobuild/.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 #include "../libcli/auth/libcli_auth.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_AUTH
29
30 /****************************************************************************
31  Ensure primary group SID is always at position 0 in a 
32  auth_serversupplied_info struct.
33 ****************************************************************************/
34
35 static void sort_sid_array_for_smbd(auth_serversupplied_info *result,
36                                 const DOM_SID *pgroup_sid)
37 {
38         unsigned int i;
39
40         if (!result->sids) {
41                 return;
42         }
43
44         if (sid_compare(&result->sids[0], pgroup_sid)==0) {
45                 return;
46         }
47
48         for (i = 1; i < result->num_sids; i++) {
49                 if (sid_compare(pgroup_sid,
50                                 &result->sids[i]) == 0) {
51                         sid_copy(&result->sids[i], &result->sids[0]);
52                         sid_copy(&result->sids[0], pgroup_sid);
53                         return;
54                 }
55         }
56 }
57
58 /****************************************************************************
59  Create a UNIX user on demand.
60 ****************************************************************************/
61
62 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
63 {
64         TALLOC_CTX *ctx = talloc_tos();
65         char *add_script;
66         int ret;
67
68         add_script = talloc_strdup(ctx, lp_adduser_script());
69         if (!add_script || !*add_script) {
70                 return -1;
71         }
72         add_script = talloc_all_string_sub(ctx,
73                                 add_script,
74                                 "%u",
75                                 unix_username);
76         if (!add_script) {
77                 return -1;
78         }
79         if (domain) {
80                 add_script = talloc_all_string_sub(ctx,
81                                         add_script,
82                                         "%D",
83                                         domain);
84                 if (!add_script) {
85                         return -1;
86                 }
87         }
88         if (homedir) {
89                 add_script = talloc_all_string_sub(ctx,
90                                 add_script,
91                                 "%H",
92                                 homedir);
93                 if (!add_script) {
94                         return -1;
95                 }
96         }
97         ret = smbrun(add_script,NULL);
98         flush_pwnam_cache();
99         DEBUG(ret ? 0 : 3,
100                 ("smb_create_user: Running the command `%s' gave %d\n",
101                  add_script,ret));
102         return ret;
103 }
104
105 /****************************************************************************
106  Create an auth_usersupplied_data structure
107 ****************************************************************************/
108
109 static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
110                                const char *smb_name,
111                                const char *internal_username,
112                                const char *client_domain,
113                                const char *domain,
114                                const char *wksta_name,
115                                DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
116                                DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
117                                DATA_BLOB *plaintext,
118                                bool encrypted)
119 {
120
121         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
122
123         *user_info = SMB_MALLOC_P(auth_usersupplied_info);
124         if (*user_info == NULL) {
125                 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
126                 return NT_STATUS_NO_MEMORY;
127         }
128
129         ZERO_STRUCTP(*user_info);
130
131         DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
132
133         (*user_info)->smb_name = SMB_STRDUP(smb_name);
134         if ((*user_info)->smb_name == NULL) { 
135                 free_user_info(user_info);
136                 return NT_STATUS_NO_MEMORY;
137         }
138         
139         (*user_info)->internal_username = SMB_STRDUP(internal_username);
140         if ((*user_info)->internal_username == NULL) { 
141                 free_user_info(user_info);
142                 return NT_STATUS_NO_MEMORY;
143         }
144
145         (*user_info)->domain = SMB_STRDUP(domain);
146         if ((*user_info)->domain == NULL) { 
147                 free_user_info(user_info);
148                 return NT_STATUS_NO_MEMORY;
149         }
150
151         (*user_info)->client_domain = SMB_STRDUP(client_domain);
152         if ((*user_info)->client_domain == NULL) { 
153                 free_user_info(user_info);
154                 return NT_STATUS_NO_MEMORY;
155         }
156
157         (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
158         if ((*user_info)->wksta_name == NULL) { 
159                 free_user_info(user_info);
160                 return NT_STATUS_NO_MEMORY;
161         }
162
163         DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
164
165         if (lm_pwd)
166                 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
167         if (nt_pwd)
168                 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
169         if (lm_interactive_pwd)
170                 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
171         if (nt_interactive_pwd)
172                 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
173
174         if (plaintext)
175                 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
176
177         (*user_info)->encrypted = encrypted;
178
179         (*user_info)->logon_parameters = 0;
180
181         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
182
183         return NT_STATUS_OK;
184 }
185
186 /****************************************************************************
187  Create an auth_usersupplied_data structure after appropriate mapping.
188 ****************************************************************************/
189
190 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
191                             const char *smb_name,
192                             const char *client_domain,
193                             const char *wksta_name,
194                             DATA_BLOB *lm_pwd,
195                             DATA_BLOB *nt_pwd,
196                             DATA_BLOB *lm_interactive_pwd,
197                             DATA_BLOB *nt_interactive_pwd,
198                             DATA_BLOB *plaintext,
199                             bool encrypted)
200 {
201         const char *domain;
202         NTSTATUS result;
203         bool was_mapped;
204         fstring internal_username;
205         fstrcpy(internal_username, smb_name);
206         was_mapped = map_username(internal_username);
207
208         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
209                  client_domain, smb_name, wksta_name));
210
211         /* don't allow "" as a domain, fixes a Win9X bug
212            where it doens't supply a domain for logon script
213            'net use' commands.                                 */
214
215         if ( *client_domain )
216                 domain = client_domain;
217         else
218                 domain = lp_workgroup();
219
220         /* If you connect to a Windows domain member using a bogus domain name,
221          * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
222          * the Windows box is a DC the name will become DOMAIN\user and be
223          * authenticated against AD, if the Windows box is a member server but
224          * not a DC the name will become WORKSTATION\user.  A standalone
225          * non-domain member box will also map to WORKSTATION\user. */
226
227         if (!is_trusted_domain(domain) &&
228             !strequal(domain, get_global_sam_name()) )
229         {
230                 if (lp_map_untrusted_to_domain())
231                         domain = my_sam_name();
232                 else
233                         domain = get_global_sam_name();
234                 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
235                           "workstation [%s]\n",
236                           client_domain, domain, smb_name, wksta_name));
237         }
238
239         /* We know that the given domain is trusted (and we are allowing them),
240          * it is our global SAM name, or for legacy behavior it is our
241          * primary domain name */
242
243         result = make_user_info(user_info, smb_name, internal_username,
244                               client_domain, domain, wksta_name,
245                               lm_pwd, nt_pwd,
246                               lm_interactive_pwd, nt_interactive_pwd,
247                               plaintext, encrypted);
248         if (NT_STATUS_IS_OK(result)) {
249                 (*user_info)->was_mapped = was_mapped;
250         }
251         return result;
252 }
253
254 /****************************************************************************
255  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
256  Decrypt and encrypt the passwords.
257 ****************************************************************************/
258
259 bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
260                                      const char *smb_name, 
261                                      const char *client_domain, 
262                                      const char *wksta_name, 
263                                      uint32 logon_parameters,
264                                      const uchar *lm_network_pwd,
265                                      int lm_pwd_len,
266                                      const uchar *nt_network_pwd,
267                                      int nt_pwd_len)
268 {
269         bool ret;
270         NTSTATUS status;
271         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
272         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
273
274         status = make_user_info_map(user_info,
275                                     smb_name, client_domain, 
276                                     wksta_name, 
277                                     lm_pwd_len ? &lm_blob : NULL, 
278                                     nt_pwd_len ? &nt_blob : NULL,
279                                     NULL, NULL, NULL,
280                                     True);
281
282         if (NT_STATUS_IS_OK(status)) {
283                 (*user_info)->logon_parameters = logon_parameters;
284         }
285         ret = NT_STATUS_IS_OK(status) ? True : False;
286
287         data_blob_free(&lm_blob);
288         data_blob_free(&nt_blob);
289         return ret;
290 }
291
292 /****************************************************************************
293  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
294  Decrypt and encrypt the passwords.
295 ****************************************************************************/
296
297 bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
298                                          const char *smb_name, 
299                                          const char *client_domain, 
300                                          const char *wksta_name, 
301                                          uint32 logon_parameters,
302                                          const uchar chal[8], 
303                                          const uchar lm_interactive_pwd[16], 
304                                          const uchar nt_interactive_pwd[16], 
305                                          const uchar *dc_sess_key)
306 {
307         unsigned char lm_pwd[16];
308         unsigned char nt_pwd[16];
309         unsigned char local_lm_response[24];
310         unsigned char local_nt_response[24];
311         unsigned char key[16];
312         
313         memcpy(key, dc_sess_key, 16);
314         
315         if (lm_interactive_pwd)
316                 memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
317
318         if (nt_interactive_pwd)
319                 memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
320         
321 #ifdef DEBUG_PASSWORD
322         DEBUG(100,("key:"));
323         dump_data(100, key, sizeof(key));
324         
325         DEBUG(100,("lm owf password:"));
326         dump_data(100, lm_pwd, sizeof(lm_pwd));
327         
328         DEBUG(100,("nt owf password:"));
329         dump_data(100, nt_pwd, sizeof(nt_pwd));
330 #endif
331         
332         if (lm_interactive_pwd)
333                 arcfour_crypt(lm_pwd, key, sizeof(lm_pwd));
334         
335         if (nt_interactive_pwd)
336                 arcfour_crypt(nt_pwd, key, sizeof(nt_pwd));
337         
338 #ifdef DEBUG_PASSWORD
339         DEBUG(100,("decrypt of lm owf password:"));
340         dump_data(100, lm_pwd, sizeof(lm_pwd));
341         
342         DEBUG(100,("decrypt of nt owf password:"));
343         dump_data(100, nt_pwd, sizeof(nt_pwd));
344 #endif
345         
346         if (lm_interactive_pwd)
347                 SMBOWFencrypt(lm_pwd, chal,
348                               local_lm_response);
349
350         if (nt_interactive_pwd)
351                 SMBOWFencrypt(nt_pwd, chal,
352                               local_nt_response);
353         
354         /* Password info paranoia */
355         ZERO_STRUCT(key);
356
357         {
358                 bool ret;
359                 NTSTATUS nt_status;
360                 DATA_BLOB local_lm_blob;
361                 DATA_BLOB local_nt_blob;
362
363                 DATA_BLOB lm_interactive_blob;
364                 DATA_BLOB nt_interactive_blob;
365                 
366                 if (lm_interactive_pwd) {
367                         local_lm_blob = data_blob(local_lm_response,
368                                                   sizeof(local_lm_response));
369                         lm_interactive_blob = data_blob(lm_pwd,
370                                                         sizeof(lm_pwd));
371                         ZERO_STRUCT(lm_pwd);
372                 }
373                 
374                 if (nt_interactive_pwd) {
375                         local_nt_blob = data_blob(local_nt_response,
376                                                   sizeof(local_nt_response));
377                         nt_interactive_blob = data_blob(nt_pwd,
378                                                         sizeof(nt_pwd));
379                         ZERO_STRUCT(nt_pwd);
380                 }
381
382                 nt_status = make_user_info_map(
383                         user_info, 
384                         smb_name, client_domain, wksta_name, 
385                         lm_interactive_pwd ? &local_lm_blob : NULL,
386                         nt_interactive_pwd ? &local_nt_blob : NULL,
387                         lm_interactive_pwd ? &lm_interactive_blob : NULL,
388                         nt_interactive_pwd ? &nt_interactive_blob : NULL,
389                         NULL, True);
390
391                 if (NT_STATUS_IS_OK(nt_status)) {
392                         (*user_info)->logon_parameters = logon_parameters;
393                 }
394
395                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
396                 data_blob_free(&local_lm_blob);
397                 data_blob_free(&local_nt_blob);
398                 data_blob_free(&lm_interactive_blob);
399                 data_blob_free(&nt_interactive_blob);
400                 return ret;
401         }
402 }
403
404
405 /****************************************************************************
406  Create an auth_usersupplied_data structure
407 ****************************************************************************/
408
409 bool make_user_info_for_reply(auth_usersupplied_info **user_info, 
410                               const char *smb_name, 
411                               const char *client_domain,
412                               const uint8 chal[8],
413                               DATA_BLOB plaintext_password)
414 {
415
416         DATA_BLOB local_lm_blob;
417         DATA_BLOB local_nt_blob;
418         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
419                         
420         /*
421          * Not encrypted - do so.
422          */
423         
424         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
425                  "format.\n"));
426         
427         if (plaintext_password.data) {
428                 unsigned char local_lm_response[24];
429                 
430 #ifdef DEBUG_PASSWORD
431                 DEBUG(10,("Unencrypted password (len %d):\n",
432                           (int)plaintext_password.length));
433                 dump_data(100, plaintext_password.data,
434                           plaintext_password.length);
435 #endif
436
437                 SMBencrypt( (const char *)plaintext_password.data,
438                             (const uchar*)chal, local_lm_response);
439                 local_lm_blob = data_blob(local_lm_response, 24);
440                 
441                 /* We can't do an NT hash here, as the password needs to be
442                    case insensitive */
443                 local_nt_blob = data_blob_null; 
444                 
445         } else {
446                 local_lm_blob = data_blob_null; 
447                 local_nt_blob = data_blob_null; 
448         }
449         
450         ret = make_user_info_map(
451                 user_info, smb_name, client_domain, 
452                 get_remote_machine_name(),
453                 local_lm_blob.data ? &local_lm_blob : NULL,
454                 local_nt_blob.data ? &local_nt_blob : NULL,
455                 NULL, NULL,
456                 plaintext_password.data ? &plaintext_password : NULL, 
457                 False);
458         
459         data_blob_free(&local_lm_blob);
460         return NT_STATUS_IS_OK(ret) ? True : False;
461 }
462
463 /****************************************************************************
464  Create an auth_usersupplied_data structure
465 ****************************************************************************/
466
467 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
468                                       const char *smb_name,
469                                       const char *client_domain, 
470                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
471 {
472         return make_user_info_map(user_info, smb_name, 
473                                   client_domain, 
474                                   get_remote_machine_name(), 
475                                   lm_resp.data ? &lm_resp : NULL, 
476                                   nt_resp.data ? &nt_resp : NULL, 
477                                   NULL, NULL, NULL,
478                                   True);
479 }
480
481 /****************************************************************************
482  Create a guest user_info blob, for anonymous authenticaion.
483 ****************************************************************************/
484
485 bool make_user_info_guest(auth_usersupplied_info **user_info) 
486 {
487         NTSTATUS nt_status;
488
489         nt_status = make_user_info(user_info, 
490                                    "","", 
491                                    "","", 
492                                    "", 
493                                    NULL, NULL, 
494                                    NULL, NULL, 
495                                    NULL,
496                                    True);
497                               
498         return NT_STATUS_IS_OK(nt_status) ? True : False;
499 }
500
501 static int server_info_dtor(auth_serversupplied_info *server_info)
502 {
503         TALLOC_FREE(server_info->sam_account);
504         ZERO_STRUCTP(server_info);
505         return 0;
506 }
507
508 /***************************************************************************
509  Make a server_info struct. Free with TALLOC_FREE().
510 ***************************************************************************/
511
512 static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
513 {
514         struct auth_serversupplied_info *result;
515
516         result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
517         if (result == NULL) {
518                 DEBUG(0, ("talloc failed\n"));
519                 return NULL;
520         }
521
522         talloc_set_destructor(result, server_info_dtor);
523
524         /* Initialise the uid and gid values to something non-zero
525            which may save us from giving away root access if there
526            is a bug in allocating these fields. */
527
528         result->utok.uid = -1;
529         result->utok.gid = -1;
530         return result;
531 }
532
533 static char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
534 {
535         fstring tmp;
536
537         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
538         return talloc_strdup(mem_ctx, tmp);
539 }
540
541 /***************************************************************************
542  Is the incoming username our own machine account ?
543  If so, the connection is almost certainly from winbindd.
544 ***************************************************************************/
545
546 static bool is_our_machine_account(const char *username)
547 {
548         bool ret;
549         char *truncname = NULL;
550         size_t ulen = strlen(username);
551
552         if (ulen == 0 || username[ulen-1] != '$') {
553                 return false;
554         }
555         truncname = SMB_STRDUP(username);
556         if (!truncname) {
557                 return false;
558         }
559         truncname[ulen-1] = '\0';
560         ret = strequal(truncname, global_myname());
561         SAFE_FREE(truncname);
562         return ret;
563 }
564
565 /***************************************************************************
566  Make (and fill) a user_info struct from a struct samu
567 ***************************************************************************/
568
569 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
570                               struct samu *sampass)
571 {
572         struct passwd *pwd;
573         gid_t *gids;
574         auth_serversupplied_info *result;
575         const char *username = pdb_get_username(sampass);
576         NTSTATUS status;
577
578         if ( !(result = make_server_info(NULL)) ) {
579                 return NT_STATUS_NO_MEMORY;
580         }
581
582         if ( !(pwd = getpwnam_alloc(result, username)) ) {
583                 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
584                           pdb_get_username(sampass)));
585                 TALLOC_FREE(result);
586                 return NT_STATUS_NO_SUCH_USER;
587         }
588
589         result->sam_account = sampass;
590         result->unix_name = pwd->pw_name;
591         /* Ensure that we keep pwd->pw_name, because we will free pwd below */
592         talloc_steal(result, pwd->pw_name);
593         result->utok.gid = pwd->pw_gid;
594         result->utok.uid = pwd->pw_uid;
595
596         TALLOC_FREE(pwd);
597
598         result->sanitized_username = sanitize_username(result,
599                                                        result->unix_name);
600         if (result->sanitized_username == NULL) {
601                 TALLOC_FREE(result);
602                 return NT_STATUS_NO_MEMORY;
603         }
604
605         if (IS_DC && is_our_machine_account(username)) {
606                 /*
607                  * Ensure for a connection from our own
608                  * machine account (from winbindd on a DC)
609                  * there are no supplementary groups.
610                  * Prevents loops in calling gid_to_sid().
611                  */
612                 result->sids = NULL;
613                 gids = NULL;
614                 result->num_sids = 0;
615
616                 /*
617                  * This is a hack of monstrous proportions.
618                  * If we know it's winbindd talking to us,
619                  * we know we must never recurse into it,
620                  * so turn off contacting winbindd for this
621                  * entire process. This will get fixed when
622                  * winbindd doesn't need to talk to smbd on
623                  * a PDC. JRA.
624                  */
625
626                 (void)winbind_off();
627
628                 DEBUG(10, ("make_server_info_sam: our machine account %s "
629                         "setting supplementary group list empty and "
630                         "turning off winbindd requests.\n",
631                         username));
632         } else {
633                 status = pdb_enum_group_memberships(result, sampass,
634                                             &result->sids, &gids,
635                                             &result->num_sids);
636
637                 if (!NT_STATUS_IS_OK(status)) {
638                         DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
639                                    nt_errstr(status)));
640                         result->sam_account = NULL; /* Don't free on error exit. */
641                         TALLOC_FREE(result);
642                         return status;
643                 }
644         }
645
646         /* For now we throw away the gids and convert via sid_to_gid
647          * later. This needs fixing, but I'd like to get the code straight and
648          * simple first. */
649          
650         TALLOC_FREE(gids);
651
652         DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
653                  pdb_get_username(sampass), result->unix_name));
654
655         *server_info = result;
656         /* Ensure that the sampass will be freed with the result */
657         talloc_steal(result, sampass);
658
659         return NT_STATUS_OK;
660 }
661
662 static NTSTATUS log_nt_token(NT_USER_TOKEN *token)
663 {
664         TALLOC_CTX *frame = talloc_stackframe();
665         char *command;
666         char *group_sidstr;
667         size_t i;
668
669         if ((lp_log_nt_token_command() == NULL) ||
670             (strlen(lp_log_nt_token_command()) == 0)) {
671                 TALLOC_FREE(frame);
672                 return NT_STATUS_OK;
673         }
674
675         group_sidstr = talloc_strdup(frame, "");
676         for (i=1; i<token->num_sids; i++) {
677                 group_sidstr = talloc_asprintf(
678                         frame, "%s %s", group_sidstr,
679                         sid_string_talloc(frame, &token->user_sids[i]));
680         }
681
682         command = talloc_string_sub(
683                 frame, lp_log_nt_token_command(),
684                 "%s", sid_string_talloc(frame, &token->user_sids[0]));
685         command = talloc_string_sub(frame, command, "%t", group_sidstr);
686
687         if (command == NULL) {
688                 TALLOC_FREE(frame);
689                 return NT_STATUS_NO_MEMORY;
690         }
691
692         DEBUG(8, ("running command: [%s]\n", command));
693         if (smbrun(command, NULL) != 0) {
694                 DEBUG(0, ("Could not log NT token\n"));
695                 TALLOC_FREE(frame);
696                 return NT_STATUS_ACCESS_DENIED;
697         }
698
699         TALLOC_FREE(frame);
700         return NT_STATUS_OK;
701 }
702
703 /*
704  * Create the token to use from server_info->sam_account and
705  * server_info->sids (the info3/sam groups). Find the unix gids.
706  */
707
708 NTSTATUS create_local_token(auth_serversupplied_info *server_info)
709 {
710         NTSTATUS status;
711         size_t i;
712         struct dom_sid tmp_sid;
713
714         /*
715          * If winbind is not around, we can not make much use of the SIDs the
716          * domain controller provided us with. Likewise if the user name was
717          * mapped to some local unix user.
718          */
719
720         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
721             (server_info->nss_token)) {
722                 status = create_token_from_username(server_info,
723                                                     server_info->unix_name,
724                                                     server_info->guest,
725                                                     &server_info->utok.uid,
726                                                     &server_info->utok.gid,
727                                                     &server_info->unix_name,
728                                                     &server_info->ptok);
729
730         } else {
731                 server_info->ptok = create_local_nt_token(
732                         server_info,
733                         pdb_get_user_sid(server_info->sam_account),
734                         server_info->guest,
735                         server_info->num_sids, server_info->sids);
736                 status = server_info->ptok ?
737                         NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
738         }
739
740         if (!NT_STATUS_IS_OK(status)) {
741                 return status;
742         }
743
744         /* Convert the SIDs to gids. */
745
746         server_info->utok.ngroups = 0;
747         server_info->utok.groups = NULL;
748
749         /* Start at index 1, where the groups start. */
750
751         for (i=1; i<server_info->ptok->num_sids; i++) {
752                 gid_t gid;
753                 DOM_SID *sid = &server_info->ptok->user_sids[i];
754
755                 if (!sid_to_gid(sid, &gid)) {
756                         DEBUG(10, ("Could not convert SID %s to gid, "
757                                    "ignoring it\n", sid_string_dbg(sid)));
758                         continue;
759                 }
760                 add_gid_to_array_unique(server_info, gid,
761                                         &server_info->utok.groups,
762                                         &server_info->utok.ngroups);
763         }
764
765         /*
766          * Add the "Unix Group" SID for each gid to catch mapped groups
767          * and their Unix equivalent.  This is to solve the backwards
768          * compatibility problem of 'valid users = +ntadmin' where
769          * ntadmin has been paired with "Domain Admins" in the group
770          * mapping table.  Otherwise smb.conf would need to be changed
771          * to 'valid user = "Domain Admins"'.  --jerry
772          *
773          * For consistency we also add the "Unix User" SID,
774          * so that the complete unix token is represented within
775          * the nt token.
776          */
777
778         if (!uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid)) {
779                 DEBUG(1,("create_local_token: Failed to create SID "
780                         "for uid %u!\n", (unsigned int)server_info->utok.uid));
781         }
782         add_sid_to_array_unique(server_info->ptok, &tmp_sid,
783                                 &server_info->ptok->user_sids,
784                                 &server_info->ptok->num_sids);
785
786         for ( i=0; i<server_info->utok.ngroups; i++ ) {
787                 if (!gid_to_unix_groups_sid( server_info->utok.groups[i], &tmp_sid ) ) {
788                         DEBUG(1,("create_local_token: Failed to create SID "
789                                 "for gid %u!\n", (unsigned int)server_info->utok.groups[i]));
790                         continue;
791                 }
792                 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
793                                         &server_info->ptok->user_sids,
794                                         &server_info->ptok->num_sids);
795         }
796
797         debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
798         debug_unix_user_token(DBGC_AUTH, 10,
799                               server_info->utok.uid,
800                               server_info->utok.gid,
801                               server_info->utok.ngroups,
802                               server_info->utok.groups);
803
804         status = log_nt_token(server_info->ptok);
805         return status;
806 }
807
808 /*
809  * Create an artificial NT token given just a username. (Initially intended
810  * for force user)
811  *
812  * We go through lookup_name() to avoid problems we had with 'winbind use
813  * default domain'.
814  *
815  * We have 3 cases:
816  *
817  * unmapped unix users: Go directly to nss to find the user's group.
818  *
819  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
820  *
821  * If the user is provided by winbind, the primary gid is set to "domain
822  * users" of the user's domain. For an explanation why this is necessary, see
823  * the thread starting at
824  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
825  */
826
827 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
828                                     bool is_guest,
829                                     uid_t *uid, gid_t *gid,
830                                     char **found_username,
831                                     struct nt_user_token **token)
832 {
833         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
834         TALLOC_CTX *tmp_ctx;
835         DOM_SID user_sid;
836         enum lsa_SidType type;
837         gid_t *gids;
838         DOM_SID *group_sids;
839         DOM_SID unix_group_sid;
840         size_t num_group_sids;
841         size_t num_gids;
842         size_t i;
843
844         tmp_ctx = talloc_new(NULL);
845         if (tmp_ctx == NULL) {
846                 DEBUG(0, ("talloc_new failed\n"));
847                 return NT_STATUS_NO_MEMORY;
848         }
849
850         if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
851                          NULL, NULL, &user_sid, &type)) {
852                 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
853                 goto done;
854         }
855
856         if (type != SID_NAME_USER) {
857                 DEBUG(1, ("%s is a %s, not a user\n", username,
858                           sid_type_lookup(type)));
859                 goto done;
860         }
861
862         if (sid_check_is_in_our_domain(&user_sid)) {
863                 bool ret;
864
865                 /* This is a passdb user, so ask passdb */
866
867                 struct samu *sam_acct = NULL;
868
869                 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
870                         result = NT_STATUS_NO_MEMORY;
871                         goto done;
872                 }
873
874                 become_root();
875                 ret = pdb_getsampwsid(sam_acct, &user_sid);
876                 unbecome_root();
877
878                 if (!ret) {
879                         DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
880                                   sid_string_dbg(&user_sid), username));
881                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
882                         goto unix_user;
883                 }
884
885                 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
886                                                     &group_sids, &gids,
887                                                     &num_group_sids);
888                 if (!NT_STATUS_IS_OK(result)) {
889                         DEBUG(1, ("enum_group_memberships failed for %s (%s): "
890                                   "%s\n", username, sid_string_dbg(&user_sid),
891                                   nt_errstr(result)));
892                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
893                         goto unix_user;
894                 }
895
896                 /* see the smb_panic() in pdb_default_enum_group_memberships */
897                 SMB_ASSERT(num_group_sids > 0); 
898
899                 *gid = gids[0];
900
901                 /* Ensure we're returning the found_username on the right context. */
902                 *found_username = talloc_strdup(mem_ctx,
903                                                 pdb_get_username(sam_acct));
904
905                 /*
906                  * If the SID from lookup_name() was the guest sid, passdb knows
907                  * about the mapping of guest sid to lp_guestaccount()
908                  * username and will return the unix_pw info for a guest
909                  * user. Use it if it's there, else lookup the *uid details
910                  * using getpwnam_alloc(). See bug #6291 for details. JRA.
911                  */
912
913                 /* We must always assign the *uid. */
914                 if (sam_acct->unix_pw == NULL) {
915                         struct passwd *pwd = getpwnam_alloc(sam_acct, *found_username );
916                         if (!pwd) {
917                                 DEBUG(10, ("getpwnam_alloc failed for %s\n",
918                                         *found_username));
919                                 result = NT_STATUS_NO_SUCH_USER;
920                                 goto done;
921                         }
922                         result = samu_set_unix(sam_acct, pwd );
923                         if (!NT_STATUS_IS_OK(result)) {
924                                 DEBUG(10, ("samu_set_unix failed for %s\n",
925                                         *found_username));
926                                 result = NT_STATUS_NO_SUCH_USER;
927                                 goto done;
928                         }
929                 }
930                 *uid = sam_acct->unix_pw->pw_uid;
931
932         } else  if (sid_check_is_in_unix_users(&user_sid)) {
933
934                 /* This is a unix user not in passdb. We need to ask nss
935                  * directly, without consulting passdb */
936
937                 struct passwd *pass;
938
939                 /*
940                  * This goto target is used as a fallback for the passdb
941                  * case. The concrete bug report is when passdb gave us an
942                  * unmapped gid.
943                  */
944
945         unix_user:
946
947                 if (!sid_to_uid(&user_sid, uid)) {
948                         DEBUG(1, ("unix_user case, sid_to_uid for %s (%s) failed\n",
949                                   username, sid_string_dbg(&user_sid)));
950                         result = NT_STATUS_NO_SUCH_USER;
951                         goto done;
952                 }
953
954                 uid_to_unix_users_sid(*uid, &user_sid);
955
956                 pass = getpwuid_alloc(tmp_ctx, *uid);
957                 if (pass == NULL) {
958                         DEBUG(1, ("getpwuid(%u) for user %s failed\n",
959                                   (unsigned int)*uid, username));
960                         goto done;
961                 }
962
963                 if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
964                                          &gids, &num_group_sids)) {
965                         DEBUG(1, ("getgroups_unix_user for user %s failed\n",
966                                   username));
967                         goto done;
968                 }
969
970                 if (num_group_sids) {
971                         group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
972                         if (group_sids == NULL) {
973                                 DEBUG(1, ("TALLOC_ARRAY failed\n"));
974                                 result = NT_STATUS_NO_MEMORY;
975                                 goto done;
976                         }
977                 } else {
978                         group_sids = NULL;
979                 }
980
981                 for (i=0; i<num_group_sids; i++) {
982                         gid_to_sid(&group_sids[i], gids[i]);
983                 }
984
985                 /* In getgroups_unix_user we always set the primary gid */
986                 SMB_ASSERT(num_group_sids > 0); 
987
988                 *gid = gids[0];
989
990                 /* Ensure we're returning the found_username on the right context. */
991                 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
992         } else {
993
994                 /* This user is from winbind, force the primary gid to the
995                  * user's "domain users" group. Under certain circumstances
996                  * (user comes from NT4), this might be a loss of
997                  * information. But we can not rely on winbind getting the
998                  * correct info. AD might prohibit winbind looking up that
999                  * information. */
1000
1001                 uint32 dummy;
1002
1003                 /* We must always assign the *uid. */
1004                 if (!sid_to_uid(&user_sid, uid)) {
1005                         DEBUG(1, ("winbindd case, sid_to_uid for %s (%s) failed\n",
1006                                   username, sid_string_dbg(&user_sid)));
1007                         result = NT_STATUS_NO_SUCH_USER;
1008                         goto done;
1009                 }
1010
1011                 num_group_sids = 1;
1012                 group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
1013                 if (group_sids == NULL) {
1014                         DEBUG(1, ("TALLOC_ARRAY failed\n"));
1015                         result = NT_STATUS_NO_MEMORY;
1016                         goto done;
1017                 }
1018
1019                 sid_copy(&group_sids[0], &user_sid);
1020                 sid_split_rid(&group_sids[0], &dummy);
1021                 sid_append_rid(&group_sids[0], DOMAIN_GROUP_RID_USERS);
1022
1023                 if (!sid_to_gid(&group_sids[0], gid)) {
1024                         DEBUG(1, ("sid_to_gid(%s) failed\n",
1025                                   sid_string_dbg(&group_sids[0])));
1026                         goto done;
1027                 }
1028
1029                 gids = gid;
1030
1031                 /* Ensure we're returning the found_username on the right context. */
1032                 *found_username = talloc_strdup(mem_ctx, username);
1033         }
1034
1035         /* Add the "Unix Group" SID for each gid to catch mapped groups
1036            and their Unix equivalent.  This is to solve the backwards
1037            compatibility problem of 'valid users = +ntadmin' where
1038            ntadmin has been paired with "Domain Admins" in the group
1039            mapping table.  Otherwise smb.conf would need to be changed
1040            to 'valid user = "Domain Admins"'.  --jerry */
1041
1042         num_gids = num_group_sids;
1043         for ( i=0; i<num_gids; i++ ) {
1044                 gid_t high, low;
1045
1046                 /* don't pickup anything managed by Winbind */
1047
1048                 if ( lp_idmap_gid(&low, &high) && (gids[i] >= low) && (gids[i] <= high) )
1049                         continue;
1050
1051                 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
1052                         DEBUG(1,("create_token_from_username: Failed to create SID "
1053                                 "for gid %u!\n", (unsigned int)gids[i]));
1054                         continue;
1055                 }
1056                 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
1057                                                  &group_sids, &num_group_sids);
1058                 if (!NT_STATUS_IS_OK(result)) {
1059                         goto done;
1060                 }
1061         }
1062
1063         /* Ensure we're creating the nt_token on the right context. */
1064         *token = create_local_nt_token(mem_ctx, &user_sid,
1065                                        is_guest, num_group_sids, group_sids);
1066
1067         if ((*token == NULL) || (*found_username == NULL)) {
1068                 result = NT_STATUS_NO_MEMORY;
1069                 goto done;
1070         }
1071
1072         result = NT_STATUS_OK;
1073  done:
1074         TALLOC_FREE(tmp_ctx);
1075         return result;
1076 }
1077
1078 /***************************************************************************
1079  Build upon create_token_from_username:
1080
1081  Expensive helper function to figure out whether a user given its name is
1082  member of a particular group.
1083 ***************************************************************************/
1084
1085 bool user_in_group_sid(const char *username, const DOM_SID *group_sid)
1086 {
1087         NTSTATUS status;
1088         uid_t uid;
1089         gid_t gid;
1090         char *found_username;
1091         struct nt_user_token *token;
1092         bool result;
1093
1094         TALLOC_CTX *mem_ctx;
1095
1096         mem_ctx = talloc_new(NULL);
1097         if (mem_ctx == NULL) {
1098                 DEBUG(0, ("talloc_new failed\n"));
1099                 return False;
1100         }
1101
1102         status = create_token_from_username(mem_ctx, username, False,
1103                                             &uid, &gid, &found_username,
1104                                             &token);
1105
1106         if (!NT_STATUS_IS_OK(status)) {
1107                 DEBUG(10, ("could not create token for %s\n", username));
1108                 return False;
1109         }
1110
1111         result = nt_token_check_sid(group_sid, token);
1112
1113         TALLOC_FREE(mem_ctx);
1114         return result;
1115         
1116 }
1117
1118 bool user_in_group(const char *username, const char *groupname)
1119 {
1120         TALLOC_CTX *mem_ctx;
1121         DOM_SID group_sid;
1122         bool ret;
1123
1124         mem_ctx = talloc_new(NULL);
1125         if (mem_ctx == NULL) {
1126                 DEBUG(0, ("talloc_new failed\n"));
1127                 return False;
1128         }
1129
1130         ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
1131                           NULL, NULL, &group_sid, NULL);
1132         TALLOC_FREE(mem_ctx);
1133
1134         if (!ret) {
1135                 DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
1136                 return False;
1137         }
1138
1139         return user_in_group_sid(username, &group_sid);
1140 }
1141
1142 /***************************************************************************
1143  Make (and fill) a server_info struct from a 'struct passwd' by conversion
1144  to a struct samu
1145 ***************************************************************************/
1146
1147 NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, 
1148                              char *unix_username,
1149                              struct passwd *pwd)
1150 {
1151         NTSTATUS status;
1152         struct samu *sampass = NULL;
1153         gid_t *gids;
1154         char *qualified_name = NULL;
1155         TALLOC_CTX *mem_ctx = NULL;
1156         DOM_SID u_sid;
1157         enum lsa_SidType type;
1158         auth_serversupplied_info *result;
1159         
1160         if ( !(sampass = samu_new( NULL )) ) {
1161                 return NT_STATUS_NO_MEMORY;
1162         }
1163         
1164         status = samu_set_unix( sampass, pwd );
1165         if (!NT_STATUS_IS_OK(status)) {
1166                 return status;
1167         }
1168
1169         result = make_server_info(NULL);
1170         if (result == NULL) {
1171                 TALLOC_FREE(sampass);
1172                 return NT_STATUS_NO_MEMORY;
1173         }
1174
1175         result->sam_account = sampass;
1176
1177         result->unix_name = talloc_strdup(result, unix_username);
1178         result->sanitized_username = sanitize_username(result, unix_username);
1179
1180         if ((result->unix_name == NULL)
1181             || (result->sanitized_username == NULL)) {
1182                 TALLOC_FREE(sampass);
1183                 TALLOC_FREE(result);
1184                 return NT_STATUS_NO_MEMORY;
1185         }
1186
1187         result->utok.uid = pwd->pw_uid;
1188         result->utok.gid = pwd->pw_gid;
1189
1190         status = pdb_enum_group_memberships(result, sampass,
1191                                             &result->sids, &gids,
1192                                             &result->num_sids);
1193
1194         if (!NT_STATUS_IS_OK(status)) {
1195                 DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
1196                            nt_errstr(status)));
1197                 TALLOC_FREE(result);
1198                 return status;
1199         }
1200
1201         /*
1202          * The SID returned in server_info->sam_account is based
1203          * on our SAM sid even though for a pure UNIX account this should
1204          * not be the case as it doesn't really exist in the SAM db.
1205          * This causes lookups on "[in]valid users" to fail as they
1206          * will lookup this name as a "Unix User" SID to check against
1207          * the user token. Fix this by adding the "Unix User"\unix_username
1208          * SID to the sid array. The correct fix should probably be
1209          * changing the server_info->sam_account user SID to be a
1210          * S-1-22 Unix SID, but this might break old configs where
1211          * plaintext passwords were used with no SAM backend.
1212          */
1213
1214         mem_ctx = talloc_init("make_server_info_pw_tmp");
1215         if (!mem_ctx) {
1216                 TALLOC_FREE(result);
1217                 return NT_STATUS_NO_MEMORY;
1218         }
1219
1220         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
1221                                         unix_users_domain_name(),
1222                                         unix_username );
1223         if (!qualified_name) {
1224                 TALLOC_FREE(result);
1225                 TALLOC_FREE(mem_ctx);
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
1230                                                 NULL, NULL,
1231                                                 &u_sid, &type)) {
1232                 TALLOC_FREE(result);
1233                 TALLOC_FREE(mem_ctx);
1234                 return NT_STATUS_NO_SUCH_USER;
1235         }
1236
1237         TALLOC_FREE(mem_ctx);
1238
1239         if (type != SID_NAME_USER) {
1240                 TALLOC_FREE(result);
1241                 return NT_STATUS_NO_SUCH_USER;
1242         }
1243
1244         status = add_sid_to_array_unique(result, &u_sid,
1245                                          &result->sids,
1246                                          &result->num_sids);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 TALLOC_FREE(result);
1249                 return status;
1250         }
1251
1252         /* For now we throw away the gids and convert via sid_to_gid
1253          * later. This needs fixing, but I'd like to get the code straight and
1254          * simple first. */
1255         TALLOC_FREE(gids);
1256
1257         *server_info = result;
1258
1259         return NT_STATUS_OK;
1260 }
1261
1262 /***************************************************************************
1263  Make (and fill) a user_info struct for a guest login.
1264  This *must* succeed for smbd to start. If there is no mapping entry for
1265  the guest gid, then create one.
1266 ***************************************************************************/
1267
1268 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
1269 {
1270         NTSTATUS status;
1271         struct samu *sampass = NULL;
1272         DOM_SID guest_sid;
1273         bool ret;
1274         char zeros[16];
1275         fstring tmp;
1276
1277         if ( !(sampass = samu_new( NULL )) ) {
1278                 return NT_STATUS_NO_MEMORY;
1279         }
1280
1281         sid_copy(&guest_sid, get_global_sam_sid());
1282         sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
1283
1284         become_root();
1285         ret = pdb_getsampwsid(sampass, &guest_sid);
1286         unbecome_root();
1287
1288         if (!ret) {
1289                 TALLOC_FREE(sampass);
1290                 return NT_STATUS_NO_SUCH_USER;
1291         }
1292
1293         status = make_server_info_sam(server_info, sampass);
1294         if (!NT_STATUS_IS_OK(status)) {
1295                 TALLOC_FREE(sampass);
1296                 return status;
1297         }
1298         
1299         (*server_info)->guest = True;
1300
1301         status = create_local_token(*server_info);
1302         if (!NT_STATUS_IS_OK(status)) {
1303                 DEBUG(10, ("create_local_token failed: %s\n",
1304                            nt_errstr(status)));
1305                 return status;
1306         }
1307
1308         /* annoying, but the Guest really does have a session key, and it is
1309            all zeros! */
1310         ZERO_STRUCT(zeros);
1311         (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
1312         (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
1313
1314         alpha_strcpy(tmp, pdb_get_username(sampass), ". _-$", sizeof(tmp));
1315         (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
1316
1317         return NT_STATUS_OK;
1318 }
1319
1320 /****************************************************************************
1321   Fake a auth_serversupplied_info just from a username
1322 ****************************************************************************/
1323
1324 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
1325                                        const char *username,
1326                                        bool is_guest,
1327                                        struct auth_serversupplied_info **presult)
1328 {
1329         struct auth_serversupplied_info *result;
1330         struct passwd *pwd;
1331         NTSTATUS status;
1332
1333         pwd = getpwnam_alloc(talloc_tos(), username);
1334         if (pwd == NULL) {
1335                 return NT_STATUS_NO_SUCH_USER;
1336         }
1337
1338         status = make_server_info_pw(&result, pwd->pw_name, pwd);
1339
1340         TALLOC_FREE(pwd);
1341
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 return status;
1344         }
1345
1346         result->nss_token = true;
1347         result->guest = is_guest;
1348
1349         status = create_local_token(result);
1350
1351         if (!NT_STATUS_IS_OK(status)) {
1352                 TALLOC_FREE(result);
1353                 return status;
1354         }
1355
1356         *presult = result;
1357         return NT_STATUS_OK;
1358 }
1359
1360
1361 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
1362                                                  const auth_serversupplied_info *src)
1363 {
1364         auth_serversupplied_info *dst;
1365
1366         dst = make_server_info(mem_ctx);
1367         if (dst == NULL) {
1368                 return NULL;
1369         }
1370
1371         dst->guest = src->guest;
1372         dst->utok.uid = src->utok.uid;
1373         dst->utok.gid = src->utok.gid;
1374         dst->utok.ngroups = src->utok.ngroups;
1375         if (src->utok.ngroups != 0) {
1376                 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
1377                         dst, src->utok.groups,
1378                         sizeof(gid_t)*dst->utok.ngroups);
1379         } else {
1380                 dst->utok.groups = NULL;
1381         }
1382
1383         if (src->ptok) {
1384                 dst->ptok = dup_nt_token(dst, src->ptok);
1385                 if (!dst->ptok) {
1386                         TALLOC_FREE(dst);
1387                         return NULL;
1388                 }
1389         }
1390         
1391         dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
1392                                                 src->user_session_key.length);
1393
1394         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
1395                                                 src->lm_session_key.length);
1396
1397         dst->sam_account = samu_new(NULL);
1398         if (!dst->sam_account) {
1399                 TALLOC_FREE(dst);
1400                 return NULL;
1401         }
1402
1403         if (!pdb_copy_sam_account(dst->sam_account, src->sam_account)) {
1404                 TALLOC_FREE(dst);
1405                 return NULL;
1406         }
1407         
1408         dst->pam_handle = NULL;
1409         dst->unix_name = talloc_strdup(dst, src->unix_name);
1410         if (!dst->unix_name) {
1411                 TALLOC_FREE(dst);
1412                 return NULL;
1413         }
1414
1415         dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
1416         if (!dst->sanitized_username) {
1417                 TALLOC_FREE(dst);
1418                 return NULL;
1419         }
1420
1421         return dst;
1422 }
1423
1424 /*
1425  * Set a new session key. Used in the rpc server where we have to override the
1426  * SMB level session key with SystemLibraryDTC
1427  */
1428
1429 bool server_info_set_session_key(struct auth_serversupplied_info *info,
1430                                  DATA_BLOB session_key)
1431 {
1432         TALLOC_FREE(info->user_session_key.data);
1433
1434         info->user_session_key = data_blob_talloc(
1435                 info, session_key.data, session_key.length);
1436
1437         return (info->user_session_key.data != NULL);
1438 }
1439
1440 static auth_serversupplied_info *guest_info = NULL;
1441
1442 bool init_guest_info(void)
1443 {
1444         if (guest_info != NULL)
1445                 return True;
1446
1447         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1448 }
1449
1450 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1451                                 auth_serversupplied_info **server_info)
1452 {
1453         *server_info = copy_serverinfo(mem_ctx, guest_info);
1454         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1455 }
1456
1457 bool copy_current_user(struct current_user *dst, struct current_user *src)
1458 {
1459         gid_t *groups;
1460         NT_USER_TOKEN *nt_token;
1461
1462         groups = (gid_t *)memdup(src->ut.groups,
1463                                  sizeof(gid_t) * src->ut.ngroups);
1464         if ((src->ut.ngroups != 0) && (groups == NULL)) {
1465                 return False;
1466         }
1467
1468         nt_token = dup_nt_token(NULL, src->nt_user_token);
1469         if (nt_token == NULL) {
1470                 SAFE_FREE(groups);
1471                 return False;
1472         }
1473
1474         dst->conn = src->conn;
1475         dst->vuid = src->vuid;
1476         dst->ut.uid = src->ut.uid;
1477         dst->ut.gid = src->ut.gid;
1478         dst->ut.ngroups = src->ut.ngroups;
1479         dst->ut.groups = groups;
1480         dst->nt_user_token = nt_token;
1481         return True;
1482 }
1483
1484 /***************************************************************************
1485  Purely internal function for make_server_info_info3
1486  Fill the sam account from getpwnam
1487 ***************************************************************************/
1488 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, 
1489                                  const char *domain,
1490                                  const char *username,
1491                                  char **found_username,
1492                                  uid_t *uid, gid_t *gid,
1493                                  struct samu *account,
1494                                  bool *username_was_mapped)
1495 {
1496         NTSTATUS nt_status;
1497         fstring dom_user, lower_username;
1498         fstring real_username;
1499         struct passwd *passwd;
1500
1501         fstrcpy( lower_username, username );
1502         strlower_m( lower_username );
1503
1504         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
1505                 lower_username);
1506
1507         /* Get the passwd struct.  Try to create the account is necessary. */
1508
1509         *username_was_mapped = map_username( dom_user );
1510
1511         if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
1512                 return NT_STATUS_NO_SUCH_USER;
1513
1514         *uid = passwd->pw_uid;
1515         *gid = passwd->pw_gid;
1516
1517         /* This is pointless -- there is no suport for differing 
1518            unix and windows names.  Make sure to always store the 
1519            one we actually looked up and succeeded. Have I mentioned
1520            why I hate the 'winbind use default domain' parameter?   
1521                                          --jerry              */
1522            
1523         *found_username = talloc_strdup( mem_ctx, real_username );
1524         
1525         DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
1526
1527         nt_status = samu_set_unix( account, passwd );
1528         
1529         TALLOC_FREE(passwd);
1530         
1531         return nt_status;
1532 }
1533
1534 /****************************************************************************
1535  Wrapper to allow the getpwnam() call to strip the domain name and 
1536  try again in case a local UNIX user is already there.  Also run through 
1537  the username if we fallback to the username only.
1538  ****************************************************************************/
1539  
1540 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
1541                              fstring save_username, bool create )
1542 {
1543         struct passwd *pw = NULL;
1544         char *p;
1545         fstring username;
1546         
1547         /* we only save a copy of the username it has been mangled 
1548            by winbindd use default domain */
1549            
1550         save_username[0] = '\0';
1551            
1552         /* don't call map_username() here since it has to be done higher 
1553            up the stack so we don't call it mutliple times */
1554
1555         fstrcpy( username, domuser );
1556         
1557         p = strchr_m( username, *lp_winbind_separator() );
1558         
1559         /* code for a DOMAIN\user string */
1560         
1561         if ( p ) {
1562                 fstring strip_username;
1563
1564                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1565                 if ( pw ) {     
1566                         /* make sure we get the case of the username correct */
1567                         /* work around 'winbind use default domain = yes' */
1568
1569                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1570                                 char *domain;
1571                                 
1572                                 /* split the domain and username into 2 strings */
1573                                 *p = '\0';
1574                                 domain = username;
1575
1576                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1577                         }
1578                         else
1579                                 fstrcpy( save_username, pw->pw_name );
1580
1581                         /* whew -- done! */             
1582                         return pw;
1583                 }
1584
1585                 /* setup for lookup of just the username */
1586                 /* remember that p and username are overlapping memory */
1587
1588                 p++;
1589                 fstrcpy( strip_username, p );
1590                 fstrcpy( username, strip_username );
1591         }
1592         
1593         /* just lookup a plain username */
1594         
1595         pw = Get_Pwnam_alloc(mem_ctx, username);
1596                 
1597         /* Create local user if requested but only if winbindd
1598            is not running.  We need to protect against cases
1599            where winbindd is failing and then prematurely
1600            creating users in /etc/passwd */
1601         
1602         if ( !pw && create && !winbind_ping() ) {
1603                 /* Don't add a machine account. */
1604                 if (username[strlen(username)-1] == '$')
1605                         return NULL;
1606
1607                 _smb_create_user(NULL, username, NULL);
1608                 pw = Get_Pwnam_alloc(mem_ctx, username);
1609         }
1610         
1611         /* one last check for a valid passwd struct */
1612         
1613         if ( pw )
1614                 fstrcpy( save_username, pw->pw_name );
1615
1616         return pw;
1617 }
1618
1619 /***************************************************************************
1620  Make a server_info struct from the info3 returned by a domain logon 
1621 ***************************************************************************/
1622
1623 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1624                                 const char *sent_nt_username,
1625                                 const char *domain,
1626                                 auth_serversupplied_info **server_info, 
1627                                 struct netr_SamInfo3 *info3)
1628 {
1629         char zeros[16];
1630
1631         NTSTATUS nt_status = NT_STATUS_OK;
1632         char *found_username = NULL;
1633         const char *nt_domain;
1634         const char *nt_username;
1635         struct samu *sam_account = NULL;
1636         DOM_SID user_sid;
1637         DOM_SID group_sid;
1638         bool username_was_mapped;
1639
1640         uid_t uid = (uid_t)-1;
1641         gid_t gid = (gid_t)-1;
1642
1643         auth_serversupplied_info *result;
1644
1645         /* 
1646            Here is where we should check the list of
1647            trusted domains, and verify that the SID 
1648            matches.
1649         */
1650
1651         sid_copy(&user_sid, info3->base.domain_sid);
1652         if (!sid_append_rid(&user_sid, info3->base.rid)) {
1653                 return NT_STATUS_INVALID_PARAMETER;
1654         }
1655         
1656         sid_copy(&group_sid, info3->base.domain_sid);
1657         if (!sid_append_rid(&group_sid, info3->base.primary_gid)) {
1658                 return NT_STATUS_INVALID_PARAMETER;
1659         }
1660
1661         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1662         if (!nt_username) {
1663                 /* If the server didn't give us one, just use the one we sent
1664                  * them */
1665                 nt_username = sent_nt_username;
1666         }
1667
1668         nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1669         if (!nt_domain) {
1670                 /* If the server didn't give us one, just use the one we sent
1671                  * them */
1672                 nt_domain = domain;
1673         }
1674         
1675         /* try to fill the SAM account..  If getpwnam() fails, then try the 
1676            add user script (2.2.x behavior).
1677
1678            We use the _unmapped_ username here in an attempt to provide
1679            consistent username mapping behavior between kerberos and NTLM[SSP]
1680            authentication in domain mode security.  I.E. Username mapping
1681            should be applied to the fully qualified username
1682            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1683            called map_username() unnecessarily in make_user_info_map() but
1684            that is how the current code is designed.  Making the change here
1685            is the least disruptive place.  -- jerry */
1686            
1687         if ( !(sam_account = samu_new( NULL )) ) {
1688                 return NT_STATUS_NO_MEMORY;
1689         }
1690
1691         /* this call will try to create the user if necessary */
1692
1693         nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1694                                      &found_username, &uid, &gid, sam_account,
1695                                      &username_was_mapped);
1696
1697         
1698         /* if we still don't have a valid unix account check for 
1699           'map to guest = bad uid' */
1700           
1701         if (!NT_STATUS_IS_OK(nt_status)) {
1702                 TALLOC_FREE( sam_account );
1703                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1704                         make_server_info_guest(NULL, server_info);
1705                         return NT_STATUS_OK;
1706                 }
1707                 return nt_status;
1708         }
1709                 
1710         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1711                 TALLOC_FREE(sam_account);
1712                 return NT_STATUS_NO_MEMORY;
1713         }
1714
1715         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1716                 TALLOC_FREE(sam_account);
1717                 return NT_STATUS_NO_MEMORY;
1718         }
1719
1720         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1721                 TALLOC_FREE(sam_account);
1722                 return NT_STATUS_NO_MEMORY;
1723         }
1724
1725         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1726                 TALLOC_FREE(sam_account);
1727                 return NT_STATUS_UNSUCCESSFUL;
1728         }
1729
1730         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1731                 TALLOC_FREE(sam_account);
1732                 return NT_STATUS_UNSUCCESSFUL;
1733         }
1734
1735         if (!pdb_set_fullname(sam_account,
1736                               info3->base.full_name.string,
1737                               PDB_CHANGED)) {
1738                 TALLOC_FREE(sam_account);
1739                 return NT_STATUS_NO_MEMORY;
1740         }
1741
1742         if (!pdb_set_logon_script(sam_account,
1743                                   info3->base.logon_script.string,
1744                                   PDB_CHANGED)) {
1745                 TALLOC_FREE(sam_account);
1746                 return NT_STATUS_NO_MEMORY;
1747         }
1748
1749         if (!pdb_set_profile_path(sam_account,
1750                                   info3->base.profile_path.string,
1751                                   PDB_CHANGED)) {
1752                 TALLOC_FREE(sam_account);
1753                 return NT_STATUS_NO_MEMORY;
1754         }
1755
1756         if (!pdb_set_homedir(sam_account,
1757                              info3->base.home_directory.string,
1758                              PDB_CHANGED)) {
1759                 TALLOC_FREE(sam_account);
1760                 return NT_STATUS_NO_MEMORY;
1761         }
1762
1763         if (!pdb_set_dir_drive(sam_account,
1764                                info3->base.home_drive.string,
1765                                PDB_CHANGED)) {
1766                 TALLOC_FREE(sam_account);
1767                 return NT_STATUS_NO_MEMORY;
1768         }
1769
1770         if (!pdb_set_acct_ctrl(sam_account, info3->base.acct_flags, PDB_CHANGED)) {
1771                 TALLOC_FREE(sam_account);
1772                 return NT_STATUS_NO_MEMORY;
1773         }
1774
1775         if (!pdb_set_pass_last_set_time(
1776                     sam_account,
1777                     nt_time_to_unix(info3->base.last_password_change),
1778                     PDB_CHANGED)) {
1779                 TALLOC_FREE(sam_account);
1780                 return NT_STATUS_NO_MEMORY;
1781         }
1782
1783         if (!pdb_set_pass_can_change_time(
1784                     sam_account,
1785                     nt_time_to_unix(info3->base.allow_password_change),
1786                     PDB_CHANGED)) {
1787                 TALLOC_FREE(sam_account);
1788                 return NT_STATUS_NO_MEMORY;
1789         }
1790
1791         if (!pdb_set_pass_must_change_time(
1792                     sam_account,
1793                     nt_time_to_unix(info3->base.force_password_change),
1794                     PDB_CHANGED)) {
1795                 TALLOC_FREE(sam_account);
1796                 return NT_STATUS_NO_MEMORY;
1797         }
1798
1799         result = make_server_info(NULL);
1800         if (result == NULL) {
1801                 DEBUG(4, ("make_server_info failed!\n"));
1802                 TALLOC_FREE(sam_account);
1803                 return NT_STATUS_NO_MEMORY;
1804         }
1805
1806         /* save this here to _net_sam_logon() doesn't fail (it assumes a 
1807            valid struct samu) */
1808                    
1809         result->sam_account = sam_account;
1810         result->unix_name = talloc_strdup(result, found_username);
1811
1812         result->sanitized_username = sanitize_username(result,
1813                                                        result->unix_name);
1814         if (result->sanitized_username == NULL) {
1815                 TALLOC_FREE(result);
1816                 return NT_STATUS_NO_MEMORY;
1817         }
1818
1819         /* Fill in the unix info we found on the way */
1820
1821         result->utok.uid = uid;
1822         result->utok.gid = gid;
1823
1824         /* Create a 'combined' list of all SIDs we might want in the SD */
1825
1826         result->num_sids = 0;
1827         result->sids = NULL;
1828
1829         nt_status = sid_array_from_info3(result, info3,
1830                                          &result->sids,
1831                                          &result->num_sids,
1832                                          false, false);
1833         if (!NT_STATUS_IS_OK(nt_status)) {
1834                 TALLOC_FREE(result);
1835                 return nt_status;
1836         }
1837
1838         /* Ensure the primary group sid is at position 0. */
1839         sort_sid_array_for_smbd(result, &group_sid);
1840
1841         result->login_server = talloc_strdup(result,
1842                                              info3->base.logon_server.string);
1843
1844         /* ensure we are never given NULL session keys */
1845
1846         ZERO_STRUCT(zeros);
1847
1848         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1849                 result->user_session_key = data_blob_null;
1850         } else {
1851                 result->user_session_key = data_blob_talloc(
1852                         result, info3->base.key.key,
1853                         sizeof(info3->base.key.key));
1854         }
1855
1856         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1857                 result->lm_session_key = data_blob_null;
1858         } else {
1859                 result->lm_session_key = data_blob_talloc(
1860                         result, info3->base.LMSessKey.key,
1861                         sizeof(info3->base.LMSessKey.key));
1862         }
1863
1864         result->nss_token |= username_was_mapped;
1865
1866         *server_info = result;
1867
1868         return NT_STATUS_OK;
1869 }
1870
1871 /*****************************************************************************
1872  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1873 ******************************************************************************/
1874
1875 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1876                                           const char *sent_nt_username,
1877                                           const char *domain,
1878                                           const struct wbcAuthUserInfo *info,
1879                                           auth_serversupplied_info **server_info)
1880 {
1881         char zeros[16];
1882
1883         NTSTATUS nt_status = NT_STATUS_OK;
1884         char *found_username = NULL;
1885         const char *nt_domain;
1886         const char *nt_username;
1887         struct samu *sam_account = NULL;
1888         DOM_SID user_sid;
1889         DOM_SID group_sid;
1890         bool username_was_mapped;
1891         uint32_t i;
1892
1893         uid_t uid = (uid_t)-1;
1894         gid_t gid = (gid_t)-1;
1895
1896         auth_serversupplied_info *result;
1897
1898         result = make_server_info(NULL);
1899         if (result == NULL) {
1900                 DEBUG(4, ("make_server_info failed!\n"));
1901                 return NT_STATUS_NO_MEMORY;
1902         }
1903
1904         /*
1905            Here is where we should check the list of
1906            trusted domains, and verify that the SID
1907            matches.
1908         */
1909
1910         memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
1911         memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
1912
1913         if (info->account_name) {
1914                 nt_username = talloc_strdup(result, info->account_name);
1915         } else {
1916                 /* If the server didn't give us one, just use the one we sent
1917                  * them */
1918                 nt_username = talloc_strdup(result, sent_nt_username);
1919         }
1920         if (!nt_username) {
1921                 TALLOC_FREE(result);
1922                 return NT_STATUS_NO_MEMORY;
1923         }
1924
1925         if (info->domain_name) {
1926                 nt_domain = talloc_strdup(result, info->domain_name);
1927         } else {
1928                 /* If the server didn't give us one, just use the one we sent
1929                  * them */
1930                 nt_domain = talloc_strdup(result, domain);
1931         }
1932         if (!nt_domain) {
1933                 TALLOC_FREE(result);
1934                 return NT_STATUS_NO_MEMORY;
1935         }
1936
1937         /* try to fill the SAM account..  If getpwnam() fails, then try the
1938            add user script (2.2.x behavior).
1939
1940            We use the _unmapped_ username here in an attempt to provide
1941            consistent username mapping behavior between kerberos and NTLM[SSP]
1942            authentication in domain mode security.  I.E. Username mapping
1943            should be applied to the fully qualified username
1944            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1945            called map_username() unnecessarily in make_user_info_map() but
1946            that is how the current code is designed.  Making the change here
1947            is the least disruptive place.  -- jerry */
1948
1949         if ( !(sam_account = samu_new( result )) ) {
1950                 TALLOC_FREE(result);
1951                 return NT_STATUS_NO_MEMORY;
1952         }
1953
1954         /* this call will try to create the user if necessary */
1955
1956         nt_status = fill_sam_account(result, nt_domain, sent_nt_username,
1957                                      &found_username, &uid, &gid, sam_account,
1958                                      &username_was_mapped);
1959
1960         /* if we still don't have a valid unix account check for
1961           'map to guest = bad uid' */
1962
1963         if (!NT_STATUS_IS_OK(nt_status)) {
1964                 TALLOC_FREE( result );
1965                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1966                         make_server_info_guest(NULL, server_info);
1967                         return NT_STATUS_OK;
1968                 }
1969                 return nt_status;
1970         }
1971
1972         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1973                 TALLOC_FREE(result);
1974                 return NT_STATUS_NO_MEMORY;
1975         }
1976
1977         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1978                 TALLOC_FREE(result);
1979                 return NT_STATUS_NO_MEMORY;
1980         }
1981
1982         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1983                 TALLOC_FREE(result);
1984                 return NT_STATUS_NO_MEMORY;
1985         }
1986
1987         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1988                 TALLOC_FREE(result);
1989                 return NT_STATUS_UNSUCCESSFUL;
1990         }
1991
1992         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1993                 TALLOC_FREE(result);
1994                 return NT_STATUS_UNSUCCESSFUL;
1995         }
1996
1997         if (!pdb_set_fullname(sam_account, info->full_name, PDB_CHANGED)) {
1998                 TALLOC_FREE(result);
1999                 return NT_STATUS_NO_MEMORY;
2000         }
2001
2002         if (!pdb_set_logon_script(sam_account, info->logon_script, PDB_CHANGED)) {
2003                 TALLOC_FREE(result);
2004                 return NT_STATUS_NO_MEMORY;
2005         }
2006
2007         if (!pdb_set_profile_path(sam_account, info->profile_path, PDB_CHANGED)) {
2008                 TALLOC_FREE(result);
2009                 return NT_STATUS_NO_MEMORY;
2010         }
2011
2012         if (!pdb_set_homedir(sam_account, info->home_directory, PDB_CHANGED)) {
2013                 TALLOC_FREE(result);
2014                 return NT_STATUS_NO_MEMORY;
2015         }
2016
2017         if (!pdb_set_dir_drive(sam_account, info->home_drive, PDB_CHANGED)) {
2018                 TALLOC_FREE(result);
2019                 return NT_STATUS_NO_MEMORY;
2020         }
2021
2022         if (!pdb_set_acct_ctrl(sam_account, info->acct_flags, PDB_CHANGED)) {
2023                 TALLOC_FREE(result);
2024                 return NT_STATUS_NO_MEMORY;
2025         }
2026
2027         if (!pdb_set_pass_last_set_time(
2028                     sam_account,
2029                     nt_time_to_unix(info->pass_last_set_time),
2030                     PDB_CHANGED)) {
2031                 TALLOC_FREE(result);
2032                 return NT_STATUS_NO_MEMORY;
2033         }
2034
2035         if (!pdb_set_pass_can_change_time(
2036                     sam_account,
2037                     nt_time_to_unix(info->pass_can_change_time),
2038                     PDB_CHANGED)) {
2039                 TALLOC_FREE(result);
2040                 return NT_STATUS_NO_MEMORY;
2041         }
2042
2043         if (!pdb_set_pass_must_change_time(
2044                     sam_account,
2045                     nt_time_to_unix(info->pass_must_change_time),
2046                     PDB_CHANGED)) {
2047                 TALLOC_FREE(result);
2048                 return NT_STATUS_NO_MEMORY;
2049         }
2050
2051         /* save this here to _net_sam_logon() doesn't fail (it assumes a
2052            valid struct samu) */
2053
2054         result->sam_account = sam_account;
2055         result->unix_name = talloc_strdup(result, found_username);
2056
2057         result->sanitized_username = sanitize_username(result,
2058                                                        result->unix_name);
2059         result->login_server = talloc_strdup(result, info->logon_server);
2060
2061         if ((result->unix_name == NULL)
2062             || (result->sanitized_username == NULL)
2063             || (result->login_server == NULL)) {
2064                 TALLOC_FREE(result);
2065                 return NT_STATUS_NO_MEMORY;
2066         }
2067
2068         /* Fill in the unix info we found on the way */
2069
2070         result->utok.uid = uid;
2071         result->utok.gid = gid;
2072
2073         /* Create a 'combined' list of all SIDs we might want in the SD */
2074
2075         result->num_sids = info->num_sids - 2;
2076         result->sids = talloc_array(result, DOM_SID, result->num_sids);
2077         if (result->sids == NULL) {
2078                 TALLOC_FREE(result);
2079                 return NT_STATUS_NO_MEMORY;
2080         }
2081
2082         for (i=0; i < result->num_sids; i++) {
2083                 memcpy(&result->sids[i], &info->sids[i+2].sid, sizeof(result->sids[i]));
2084         }
2085
2086         /* Ensure the primary group sid is at position 0. */
2087         sort_sid_array_for_smbd(result, &group_sid);
2088
2089         /* ensure we are never given NULL session keys */
2090
2091         ZERO_STRUCT(zeros);
2092
2093         if (memcmp(info->user_session_key, zeros, sizeof(zeros)) == 0) {
2094                 result->user_session_key = data_blob_null;
2095         } else {
2096                 result->user_session_key = data_blob_talloc(
2097                         result, info->user_session_key,
2098                         sizeof(info->user_session_key));
2099         }
2100
2101         if (memcmp(info->lm_session_key, zeros, 8) == 0) {
2102                 result->lm_session_key = data_blob_null;
2103         } else {
2104                 result->lm_session_key = data_blob_talloc(
2105                         result, info->lm_session_key,
2106                         sizeof(info->lm_session_key));
2107         }
2108
2109         result->nss_token |= username_was_mapped;
2110
2111         *server_info = result;
2112
2113         return NT_STATUS_OK;
2114 }
2115
2116 /***************************************************************************
2117  Free a user_info struct
2118 ***************************************************************************/
2119
2120 void free_user_info(auth_usersupplied_info **user_info)
2121 {
2122         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
2123         if (*user_info != NULL) {
2124                 if ((*user_info)->smb_name) {
2125                         DEBUG(10,("structure was created for %s\n",
2126                                   (*user_info)->smb_name));
2127                 }
2128                 SAFE_FREE((*user_info)->smb_name);
2129                 SAFE_FREE((*user_info)->internal_username);
2130                 SAFE_FREE((*user_info)->client_domain);
2131                 SAFE_FREE((*user_info)->domain);
2132                 SAFE_FREE((*user_info)->wksta_name);
2133                 data_blob_free(&(*user_info)->lm_resp);
2134                 data_blob_free(&(*user_info)->nt_resp);
2135                 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
2136                 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
2137                 data_blob_clear_free(&(*user_info)->plaintext_password);
2138                 ZERO_STRUCT(**user_info);
2139         }
2140         SAFE_FREE(*user_info);
2141 }
2142
2143 /***************************************************************************
2144  Make an auth_methods struct
2145 ***************************************************************************/
2146
2147 bool make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
2148 {
2149         if (!auth_context) {
2150                 smb_panic("no auth_context supplied to "
2151                           "make_auth_methods()!\n");
2152         }
2153
2154         if (!auth_method) {
2155                 smb_panic("make_auth_methods: pointer to auth_method pointer "
2156                           "is NULL!\n");
2157         }
2158
2159         *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
2160         if (!*auth_method) {
2161                 DEBUG(0,("make_auth_method: malloc failed!\n"));
2162                 return False;
2163         }
2164         ZERO_STRUCTP(*auth_method);
2165         
2166         return True;
2167 }
2168
2169 /**
2170  * Verify whether or not given domain is trusted.
2171  *
2172  * @param domain_name name of the domain to be verified
2173  * @return true if domain is one of the trusted once or
2174  *         false if otherwise
2175  **/
2176
2177 bool is_trusted_domain(const char* dom_name)
2178 {
2179         DOM_SID trustdom_sid;
2180         bool ret;
2181
2182         /* no trusted domains for a standalone server */
2183
2184         if ( lp_server_role() == ROLE_STANDALONE )
2185                 return False;
2186
2187         /* if we are a DC, then check for a direct trust relationships */
2188
2189         if ( IS_DC ) {
2190                 become_root();
2191                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2192                           "[%s]\n", dom_name ));
2193                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2194                 unbecome_root();
2195                 if (ret)
2196                         return True;
2197         }
2198         else {
2199                 wbcErr result;
2200
2201                 /* If winbind is around, ask it */
2202
2203                 result = wb_is_trusted_domain(dom_name);
2204
2205                 if (result == WBC_ERR_SUCCESS) {
2206                         return True;
2207                 }
2208
2209                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
2210                         /* winbind could not find the domain */
2211                         return False;
2212                 }
2213
2214                 /* The only other possible result is that winbind is not up
2215                    and running. We need to update the trustdom_cache
2216                    ourselves */
2217                 
2218                 update_trustdom_cache();
2219         }
2220
2221         /* now the trustdom cache should be available a DC could still
2222          * have a transitive trust so fall back to the cache of trusted
2223          * domains (like a domain member would use  */
2224
2225         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
2226                 return True;
2227         }
2228
2229         return False;
2230 }
2231