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