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