s3: Replace most calls to sid_append_rid() by sid_compose()
[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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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 struct 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, struct 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(struct auth_serversupplied_info **server_info,
566                               struct samu *sampass)
567 {
568         struct passwd *pwd;
569         gid_t *gids;
570         struct 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(struct 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(struct 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         struct 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(struct 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_compose(&guest_sid, get_global_sam_sid(), DOMAIN_USER_RID_GUEST);
1278
1279         become_root();
1280         ret = pdb_getsampwsid(sampass, &guest_sid);
1281         unbecome_root();
1282
1283         if (!ret) {
1284                 TALLOC_FREE(sampass);
1285                 return NT_STATUS_NO_SUCH_USER;
1286         }
1287
1288         status = make_server_info_sam(server_info, sampass);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 TALLOC_FREE(sampass);
1291                 return status;
1292         }
1293         
1294         (*server_info)->guest = True;
1295
1296         status = create_local_token(*server_info);
1297         if (!NT_STATUS_IS_OK(status)) {
1298                 DEBUG(10, ("create_local_token failed: %s\n",
1299                            nt_errstr(status)));
1300                 return status;
1301         }
1302
1303         /* annoying, but the Guest really does have a session key, and it is
1304            all zeros! */
1305         ZERO_STRUCT(zeros);
1306         (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
1307         (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
1308
1309         alpha_strcpy(tmp, pdb_get_username(sampass), ". _-$", sizeof(tmp));
1310         (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
1311
1312         return NT_STATUS_OK;
1313 }
1314
1315 /****************************************************************************
1316   Fake a auth_serversupplied_info just from a username
1317 ****************************************************************************/
1318
1319 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
1320                                        const char *username,
1321                                        bool is_guest,
1322                                        struct auth_serversupplied_info **presult)
1323 {
1324         struct auth_serversupplied_info *result;
1325         struct passwd *pwd;
1326         NTSTATUS status;
1327
1328         pwd = getpwnam_alloc(talloc_tos(), username);
1329         if (pwd == NULL) {
1330                 return NT_STATUS_NO_SUCH_USER;
1331         }
1332
1333         status = make_server_info_pw(&result, pwd->pw_name, pwd);
1334
1335         TALLOC_FREE(pwd);
1336
1337         if (!NT_STATUS_IS_OK(status)) {
1338                 return status;
1339         }
1340
1341         result->nss_token = true;
1342         result->guest = is_guest;
1343
1344         status = create_local_token(result);
1345
1346         if (!NT_STATUS_IS_OK(status)) {
1347                 TALLOC_FREE(result);
1348                 return status;
1349         }
1350
1351         *presult = result;
1352         return NT_STATUS_OK;
1353 }
1354
1355
1356 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
1357                                                  const struct auth_serversupplied_info *src)
1358 {
1359         struct auth_serversupplied_info *dst;
1360
1361         dst = make_server_info(mem_ctx);
1362         if (dst == NULL) {
1363                 return NULL;
1364         }
1365
1366         dst->guest = src->guest;
1367         dst->utok.uid = src->utok.uid;
1368         dst->utok.gid = src->utok.gid;
1369         dst->utok.ngroups = src->utok.ngroups;
1370         if (src->utok.ngroups != 0) {
1371                 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
1372                         dst, src->utok.groups,
1373                         sizeof(gid_t)*dst->utok.ngroups);
1374         } else {
1375                 dst->utok.groups = NULL;
1376         }
1377
1378         if (src->ptok) {
1379                 dst->ptok = dup_nt_token(dst, src->ptok);
1380                 if (!dst->ptok) {
1381                         TALLOC_FREE(dst);
1382                         return NULL;
1383                 }
1384         }
1385         
1386         dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
1387                                                 src->user_session_key.length);
1388
1389         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
1390                                                 src->lm_session_key.length);
1391
1392         dst->sam_account = samu_new(NULL);
1393         if (!dst->sam_account) {
1394                 TALLOC_FREE(dst);
1395                 return NULL;
1396         }
1397
1398         if (!pdb_copy_sam_account(dst->sam_account, src->sam_account)) {
1399                 TALLOC_FREE(dst);
1400                 return NULL;
1401         }
1402         
1403         dst->pam_handle = NULL;
1404         dst->unix_name = talloc_strdup(dst, src->unix_name);
1405         if (!dst->unix_name) {
1406                 TALLOC_FREE(dst);
1407                 return NULL;
1408         }
1409
1410         dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
1411         if (!dst->sanitized_username) {
1412                 TALLOC_FREE(dst);
1413                 return NULL;
1414         }
1415
1416         return dst;
1417 }
1418
1419 /*
1420  * Set a new session key. Used in the rpc server where we have to override the
1421  * SMB level session key with SystemLibraryDTC
1422  */
1423
1424 bool server_info_set_session_key(struct auth_serversupplied_info *info,
1425                                  DATA_BLOB session_key)
1426 {
1427         TALLOC_FREE(info->user_session_key.data);
1428
1429         info->user_session_key = data_blob_talloc(
1430                 info, session_key.data, session_key.length);
1431
1432         return (info->user_session_key.data != NULL);
1433 }
1434
1435 static struct auth_serversupplied_info *guest_info = NULL;
1436
1437 bool init_guest_info(void)
1438 {
1439         if (guest_info != NULL)
1440                 return True;
1441
1442         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1443 }
1444
1445 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1446                                 struct auth_serversupplied_info **server_info)
1447 {
1448         *server_info = copy_serverinfo(mem_ctx, guest_info);
1449         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1450 }
1451
1452 bool copy_current_user(struct current_user *dst, struct current_user *src)
1453 {
1454         gid_t *groups;
1455         NT_USER_TOKEN *nt_token;
1456
1457         groups = (gid_t *)memdup(src->ut.groups,
1458                                  sizeof(gid_t) * src->ut.ngroups);
1459         if ((src->ut.ngroups != 0) && (groups == NULL)) {
1460                 return False;
1461         }
1462
1463         nt_token = dup_nt_token(NULL, src->nt_user_token);
1464         if (nt_token == NULL) {
1465                 SAFE_FREE(groups);
1466                 return False;
1467         }
1468
1469         dst->conn = src->conn;
1470         dst->vuid = src->vuid;
1471         dst->ut.uid = src->ut.uid;
1472         dst->ut.gid = src->ut.gid;
1473         dst->ut.ngroups = src->ut.ngroups;
1474         dst->ut.groups = groups;
1475         dst->nt_user_token = nt_token;
1476         return True;
1477 }
1478
1479 /***************************************************************************
1480  Purely internal function for make_server_info_info3
1481  Fill the sam account from getpwnam
1482 ***************************************************************************/
1483 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, 
1484                                  const char *domain,
1485                                  const char *username,
1486                                  char **found_username,
1487                                  uid_t *uid, gid_t *gid,
1488                                  struct samu *account,
1489                                  bool *username_was_mapped)
1490 {
1491         struct smbd_server_connection *sconn = smbd_server_conn;
1492         NTSTATUS nt_status;
1493         fstring dom_user, lower_username;
1494         fstring real_username;
1495         struct passwd *passwd;
1496
1497         fstrcpy( lower_username, username );
1498         strlower_m( lower_username );
1499
1500         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
1501                 lower_username);
1502
1503         /* Get the passwd struct.  Try to create the account is necessary. */
1504
1505         *username_was_mapped = map_username(sconn, dom_user);
1506
1507         if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
1508                 return NT_STATUS_NO_SUCH_USER;
1509
1510         *uid = passwd->pw_uid;
1511         *gid = passwd->pw_gid;
1512
1513         /* This is pointless -- there is no suport for differing 
1514            unix and windows names.  Make sure to always store the 
1515            one we actually looked up and succeeded. Have I mentioned
1516            why I hate the 'winbind use default domain' parameter?   
1517                                          --jerry              */
1518            
1519         *found_username = talloc_strdup( mem_ctx, real_username );
1520         
1521         DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
1522
1523         nt_status = samu_set_unix( account, passwd );
1524         
1525         TALLOC_FREE(passwd);
1526         
1527         return nt_status;
1528 }
1529
1530 /****************************************************************************
1531  Wrapper to allow the getpwnam() call to strip the domain name and 
1532  try again in case a local UNIX user is already there.  Also run through 
1533  the username if we fallback to the username only.
1534  ****************************************************************************/
1535  
1536 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
1537                              fstring save_username, bool create )
1538 {
1539         struct passwd *pw = NULL;
1540         char *p;
1541         fstring username;
1542         
1543         /* we only save a copy of the username it has been mangled 
1544            by winbindd use default domain */
1545            
1546         save_username[0] = '\0';
1547            
1548         /* don't call map_username() here since it has to be done higher 
1549            up the stack so we don't call it mutliple times */
1550
1551         fstrcpy( username, domuser );
1552         
1553         p = strchr_m( username, *lp_winbind_separator() );
1554         
1555         /* code for a DOMAIN\user string */
1556         
1557         if ( p ) {
1558                 fstring strip_username;
1559
1560                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1561                 if ( pw ) {     
1562                         /* make sure we get the case of the username correct */
1563                         /* work around 'winbind use default domain = yes' */
1564
1565                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1566                                 char *domain;
1567                                 
1568                                 /* split the domain and username into 2 strings */
1569                                 *p = '\0';
1570                                 domain = username;
1571
1572                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1573                         }
1574                         else
1575                                 fstrcpy( save_username, pw->pw_name );
1576
1577                         /* whew -- done! */             
1578                         return pw;
1579                 }
1580
1581                 /* setup for lookup of just the username */
1582                 /* remember that p and username are overlapping memory */
1583
1584                 p++;
1585                 fstrcpy( strip_username, p );
1586                 fstrcpy( username, strip_username );
1587         }
1588         
1589         /* just lookup a plain username */
1590         
1591         pw = Get_Pwnam_alloc(mem_ctx, username);
1592                 
1593         /* Create local user if requested but only if winbindd
1594            is not running.  We need to protect against cases
1595            where winbindd is failing and then prematurely
1596            creating users in /etc/passwd */
1597         
1598         if ( !pw && create && !winbind_ping() ) {
1599                 /* Don't add a machine account. */
1600                 if (username[strlen(username)-1] == '$')
1601                         return NULL;
1602
1603                 _smb_create_user(NULL, username, NULL);
1604                 pw = Get_Pwnam_alloc(mem_ctx, username);
1605         }
1606         
1607         /* one last check for a valid passwd struct */
1608         
1609         if ( pw )
1610                 fstrcpy( save_username, pw->pw_name );
1611
1612         return pw;
1613 }
1614
1615 /***************************************************************************
1616  Make a server_info struct from the info3 returned by a domain logon 
1617 ***************************************************************************/
1618
1619 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1620                                 const char *sent_nt_username,
1621                                 const char *domain,
1622                                 struct auth_serversupplied_info **server_info,
1623                                 struct netr_SamInfo3 *info3)
1624 {
1625         char zeros[16];
1626
1627         NTSTATUS nt_status = NT_STATUS_OK;
1628         char *found_username = NULL;
1629         const char *nt_domain;
1630         const char *nt_username;
1631         struct samu *sam_account = NULL;
1632         DOM_SID user_sid;
1633         DOM_SID group_sid;
1634         bool username_was_mapped;
1635
1636         uid_t uid = (uid_t)-1;
1637         gid_t gid = (gid_t)-1;
1638
1639         struct auth_serversupplied_info *result;
1640
1641         /* 
1642            Here is where we should check the list of
1643            trusted domains, and verify that the SID 
1644            matches.
1645         */
1646
1647         if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1648                 return NT_STATUS_INVALID_PARAMETER;
1649         }
1650         
1651         if (!sid_compose(&group_sid, info3->base.domain_sid,
1652                          info3->base.primary_gid)) {
1653                 return NT_STATUS_INVALID_PARAMETER;
1654         }
1655
1656         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1657         if (!nt_username) {
1658                 /* If the server didn't give us one, just use the one we sent
1659                  * them */
1660                 nt_username = sent_nt_username;
1661         }
1662
1663         nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1664         if (!nt_domain) {
1665                 /* If the server didn't give us one, just use the one we sent
1666                  * them */
1667                 nt_domain = domain;
1668         }
1669         
1670         /* try to fill the SAM account..  If getpwnam() fails, then try the 
1671            add user script (2.2.x behavior).
1672
1673            We use the _unmapped_ username here in an attempt to provide
1674            consistent username mapping behavior between kerberos and NTLM[SSP]
1675            authentication in domain mode security.  I.E. Username mapping
1676            should be applied to the fully qualified username
1677            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1678            called map_username() unnecessarily in make_user_info_map() but
1679            that is how the current code is designed.  Making the change here
1680            is the least disruptive place.  -- jerry */
1681            
1682         if ( !(sam_account = samu_new( NULL )) ) {
1683                 return NT_STATUS_NO_MEMORY;
1684         }
1685
1686         /* this call will try to create the user if necessary */
1687
1688         nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1689                                      &found_username, &uid, &gid, sam_account,
1690                                      &username_was_mapped);
1691
1692         
1693         /* if we still don't have a valid unix account check for 
1694           'map to guest = bad uid' */
1695           
1696         if (!NT_STATUS_IS_OK(nt_status)) {
1697                 TALLOC_FREE( sam_account );
1698                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1699                         make_server_info_guest(NULL, server_info);
1700                         return NT_STATUS_OK;
1701                 }
1702                 return nt_status;
1703         }
1704                 
1705         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1706                 TALLOC_FREE(sam_account);
1707                 return NT_STATUS_NO_MEMORY;
1708         }
1709
1710         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1711                 TALLOC_FREE(sam_account);
1712                 return NT_STATUS_NO_MEMORY;
1713         }
1714
1715         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1716                 TALLOC_FREE(sam_account);
1717                 return NT_STATUS_NO_MEMORY;
1718         }
1719
1720         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1721                 TALLOC_FREE(sam_account);
1722                 return NT_STATUS_UNSUCCESSFUL;
1723         }
1724
1725         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1726                 TALLOC_FREE(sam_account);
1727                 return NT_STATUS_UNSUCCESSFUL;
1728         }
1729
1730         if (!pdb_set_fullname(sam_account,
1731                               info3->base.full_name.string,
1732                               PDB_CHANGED)) {
1733                 TALLOC_FREE(sam_account);
1734                 return NT_STATUS_NO_MEMORY;
1735         }
1736
1737         if (!pdb_set_logon_script(sam_account,
1738                                   info3->base.logon_script.string,
1739                                   PDB_CHANGED)) {
1740                 TALLOC_FREE(sam_account);
1741                 return NT_STATUS_NO_MEMORY;
1742         }
1743
1744         if (!pdb_set_profile_path(sam_account,
1745                                   info3->base.profile_path.string,
1746                                   PDB_CHANGED)) {
1747                 TALLOC_FREE(sam_account);
1748                 return NT_STATUS_NO_MEMORY;
1749         }
1750
1751         if (!pdb_set_homedir(sam_account,
1752                              info3->base.home_directory.string,
1753                              PDB_CHANGED)) {
1754                 TALLOC_FREE(sam_account);
1755                 return NT_STATUS_NO_MEMORY;
1756         }
1757
1758         if (!pdb_set_dir_drive(sam_account,
1759                                info3->base.home_drive.string,
1760                                PDB_CHANGED)) {
1761                 TALLOC_FREE(sam_account);
1762                 return NT_STATUS_NO_MEMORY;
1763         }
1764
1765         if (!pdb_set_acct_ctrl(sam_account, info3->base.acct_flags, PDB_CHANGED)) {
1766                 TALLOC_FREE(sam_account);
1767                 return NT_STATUS_NO_MEMORY;
1768         }
1769
1770         if (!pdb_set_pass_last_set_time(
1771                     sam_account,
1772                     nt_time_to_unix(info3->base.last_password_change),
1773                     PDB_CHANGED)) {
1774                 TALLOC_FREE(sam_account);
1775                 return NT_STATUS_NO_MEMORY;
1776         }
1777
1778         if (!pdb_set_pass_can_change_time(
1779                     sam_account,
1780                     nt_time_to_unix(info3->base.allow_password_change),
1781                     PDB_CHANGED)) {
1782                 TALLOC_FREE(sam_account);
1783                 return NT_STATUS_NO_MEMORY;
1784         }
1785
1786         if (!pdb_set_pass_must_change_time(
1787                     sam_account,
1788                     nt_time_to_unix(info3->base.force_password_change),
1789                     PDB_CHANGED)) {
1790                 TALLOC_FREE(sam_account);
1791                 return NT_STATUS_NO_MEMORY;
1792         }
1793
1794         result = make_server_info(NULL);
1795         if (result == NULL) {
1796                 DEBUG(4, ("make_server_info failed!\n"));
1797                 TALLOC_FREE(sam_account);
1798                 return NT_STATUS_NO_MEMORY;
1799         }
1800
1801         /* save this here to _net_sam_logon() doesn't fail (it assumes a 
1802            valid struct samu) */
1803                    
1804         result->sam_account = sam_account;
1805         result->unix_name = talloc_strdup(result, found_username);
1806
1807         result->sanitized_username = sanitize_username(result,
1808                                                        result->unix_name);
1809         if (result->sanitized_username == NULL) {
1810                 TALLOC_FREE(result);
1811                 return NT_STATUS_NO_MEMORY;
1812         }
1813
1814         /* Fill in the unix info we found on the way */
1815
1816         result->utok.uid = uid;
1817         result->utok.gid = gid;
1818
1819         /* Create a 'combined' list of all SIDs we might want in the SD */
1820
1821         result->num_sids = 0;
1822         result->sids = NULL;
1823
1824         nt_status = sid_array_from_info3(result, info3,
1825                                          &result->sids,
1826                                          &result->num_sids,
1827                                          false, false);
1828         if (!NT_STATUS_IS_OK(nt_status)) {
1829                 TALLOC_FREE(result);
1830                 return nt_status;
1831         }
1832
1833         /* Ensure the primary group sid is at position 0. */
1834         sort_sid_array_for_smbd(result, &group_sid);
1835
1836         result->login_server = talloc_strdup(result,
1837                                              info3->base.logon_server.string);
1838
1839         /* ensure we are never given NULL session keys */
1840
1841         ZERO_STRUCT(zeros);
1842
1843         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1844                 result->user_session_key = data_blob_null;
1845         } else {
1846                 result->user_session_key = data_blob_talloc(
1847                         result, info3->base.key.key,
1848                         sizeof(info3->base.key.key));
1849         }
1850
1851         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1852                 result->lm_session_key = data_blob_null;
1853         } else {
1854                 result->lm_session_key = data_blob_talloc(
1855                         result, info3->base.LMSessKey.key,
1856                         sizeof(info3->base.LMSessKey.key));
1857         }
1858
1859         result->nss_token |= username_was_mapped;
1860
1861         *server_info = result;
1862
1863         return NT_STATUS_OK;
1864 }
1865
1866 /*****************************************************************************
1867  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1868 ******************************************************************************/
1869
1870 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1871                                           const char *sent_nt_username,
1872                                           const char *domain,
1873                                           const struct wbcAuthUserInfo *info,
1874                                           struct auth_serversupplied_info **server_info)
1875 {
1876         char zeros[16];
1877
1878         NTSTATUS nt_status = NT_STATUS_OK;
1879         char *found_username = NULL;
1880         const char *nt_domain;
1881         const char *nt_username;
1882         struct samu *sam_account = NULL;
1883         DOM_SID user_sid;
1884         DOM_SID group_sid;
1885         bool username_was_mapped;
1886         uint32_t i;
1887
1888         uid_t uid = (uid_t)-1;
1889         gid_t gid = (gid_t)-1;
1890
1891         struct auth_serversupplied_info *result;
1892
1893         result = make_server_info(NULL);
1894         if (result == NULL) {
1895                 DEBUG(4, ("make_server_info failed!\n"));
1896                 return NT_STATUS_NO_MEMORY;
1897         }
1898
1899         /*
1900            Here is where we should check the list of
1901            trusted domains, and verify that the SID
1902            matches.
1903         */
1904
1905         memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
1906         memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
1907
1908         if (info->account_name) {
1909                 nt_username = talloc_strdup(result, info->account_name);
1910         } else {
1911                 /* If the server didn't give us one, just use the one we sent
1912                  * them */
1913                 nt_username = talloc_strdup(result, sent_nt_username);
1914         }
1915         if (!nt_username) {
1916                 TALLOC_FREE(result);
1917                 return NT_STATUS_NO_MEMORY;
1918         }
1919
1920         if (info->domain_name) {
1921                 nt_domain = talloc_strdup(result, info->domain_name);
1922         } else {
1923                 /* If the server didn't give us one, just use the one we sent
1924                  * them */
1925                 nt_domain = talloc_strdup(result, domain);
1926         }
1927         if (!nt_domain) {
1928                 TALLOC_FREE(result);
1929                 return NT_STATUS_NO_MEMORY;
1930         }
1931
1932         /* try to fill the SAM account..  If getpwnam() fails, then try the
1933            add user script (2.2.x behavior).
1934
1935            We use the _unmapped_ username here in an attempt to provide
1936            consistent username mapping behavior between kerberos and NTLM[SSP]
1937            authentication in domain mode security.  I.E. Username mapping
1938            should be applied to the fully qualified username
1939            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1940            called map_username() unnecessarily in make_user_info_map() but
1941            that is how the current code is designed.  Making the change here
1942            is the least disruptive place.  -- jerry */
1943
1944         if ( !(sam_account = samu_new( result )) ) {
1945                 TALLOC_FREE(result);
1946                 return NT_STATUS_NO_MEMORY;
1947         }
1948
1949         /* this call will try to create the user if necessary */
1950
1951         nt_status = fill_sam_account(result, nt_domain, sent_nt_username,
1952                                      &found_username, &uid, &gid, sam_account,
1953                                      &username_was_mapped);
1954
1955         /* if we still don't have a valid unix account check for
1956           'map to guest = bad uid' */
1957
1958         if (!NT_STATUS_IS_OK(nt_status)) {
1959                 TALLOC_FREE( result );
1960                 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1961                         make_server_info_guest(NULL, server_info);
1962                         return NT_STATUS_OK;
1963                 }
1964                 return nt_status;
1965         }
1966
1967         if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1968                 TALLOC_FREE(result);
1969                 return NT_STATUS_NO_MEMORY;
1970         }
1971
1972         if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1973                 TALLOC_FREE(result);
1974                 return NT_STATUS_NO_MEMORY;
1975         }
1976
1977         if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1978                 TALLOC_FREE(result);
1979                 return NT_STATUS_NO_MEMORY;
1980         }
1981
1982         if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1983                 TALLOC_FREE(result);
1984                 return NT_STATUS_UNSUCCESSFUL;
1985         }
1986
1987         if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1988                 TALLOC_FREE(result);
1989                 return NT_STATUS_UNSUCCESSFUL;
1990         }
1991
1992         if (!pdb_set_fullname(sam_account, info->full_name, PDB_CHANGED)) {
1993                 TALLOC_FREE(result);
1994                 return NT_STATUS_NO_MEMORY;
1995         }
1996
1997         if (!pdb_set_logon_script(sam_account, info->logon_script, PDB_CHANGED)) {
1998                 TALLOC_FREE(result);
1999                 return NT_STATUS_NO_MEMORY;
2000         }
2001
2002         if (!pdb_set_profile_path(sam_account, info->profile_path, PDB_CHANGED)) {
2003                 TALLOC_FREE(result);
2004                 return NT_STATUS_NO_MEMORY;
2005         }
2006
2007         if (!pdb_set_homedir(sam_account, info->home_directory, PDB_CHANGED)) {
2008                 TALLOC_FREE(result);
2009                 return NT_STATUS_NO_MEMORY;
2010         }
2011
2012         if (!pdb_set_dir_drive(sam_account, info->home_drive, PDB_CHANGED)) {
2013                 TALLOC_FREE(result);
2014                 return NT_STATUS_NO_MEMORY;
2015         }
2016
2017         if (!pdb_set_acct_ctrl(sam_account, info->acct_flags, PDB_CHANGED)) {
2018                 TALLOC_FREE(result);
2019                 return NT_STATUS_NO_MEMORY;
2020         }
2021
2022         if (!pdb_set_pass_last_set_time(
2023                     sam_account,
2024                     nt_time_to_unix(info->pass_last_set_time),
2025                     PDB_CHANGED)) {
2026                 TALLOC_FREE(result);
2027                 return NT_STATUS_NO_MEMORY;
2028         }
2029
2030         if (!pdb_set_pass_can_change_time(
2031                     sam_account,
2032                     nt_time_to_unix(info->pass_can_change_time),
2033                     PDB_CHANGED)) {
2034                 TALLOC_FREE(result);
2035                 return NT_STATUS_NO_MEMORY;
2036         }
2037
2038         if (!pdb_set_pass_must_change_time(
2039                     sam_account,
2040                     nt_time_to_unix(info->pass_must_change_time),
2041                     PDB_CHANGED)) {
2042                 TALLOC_FREE(result);
2043                 return NT_STATUS_NO_MEMORY;
2044         }
2045
2046         /* save this here to _net_sam_logon() doesn't fail (it assumes a
2047            valid struct samu) */
2048
2049         result->sam_account = sam_account;
2050         result->unix_name = talloc_strdup(result, found_username);
2051
2052         result->sanitized_username = sanitize_username(result,
2053                                                        result->unix_name);
2054         result->login_server = talloc_strdup(result, info->logon_server);
2055
2056         if ((result->unix_name == NULL)
2057             || (result->sanitized_username == NULL)
2058             || (result->login_server == NULL)) {
2059                 TALLOC_FREE(result);
2060                 return NT_STATUS_NO_MEMORY;
2061         }
2062
2063         /* Fill in the unix info we found on the way */
2064
2065         result->utok.uid = uid;
2066         result->utok.gid = gid;
2067
2068         /* Create a 'combined' list of all SIDs we might want in the SD */
2069
2070         result->num_sids = info->num_sids - 2;
2071         result->sids = talloc_array(result, DOM_SID, result->num_sids);
2072         if (result->sids == NULL) {
2073                 TALLOC_FREE(result);
2074                 return NT_STATUS_NO_MEMORY;
2075         }
2076
2077         for (i=0; i < result->num_sids; i++) {
2078                 memcpy(&result->sids[i], &info->sids[i+2].sid, sizeof(result->sids[i]));
2079         }
2080
2081         /* Ensure the primary group sid is at position 0. */
2082         sort_sid_array_for_smbd(result, &group_sid);
2083
2084         /* ensure we are never given NULL session keys */
2085
2086         ZERO_STRUCT(zeros);
2087
2088         if (memcmp(info->user_session_key, zeros, sizeof(zeros)) == 0) {
2089                 result->user_session_key = data_blob_null;
2090         } else {
2091                 result->user_session_key = data_blob_talloc(
2092                         result, info->user_session_key,
2093                         sizeof(info->user_session_key));
2094         }
2095
2096         if (memcmp(info->lm_session_key, zeros, 8) == 0) {
2097                 result->lm_session_key = data_blob_null;
2098         } else {
2099                 result->lm_session_key = data_blob_talloc(
2100                         result, info->lm_session_key,
2101                         sizeof(info->lm_session_key));
2102         }
2103
2104         result->nss_token |= username_was_mapped;
2105
2106         *server_info = result;
2107
2108         return NT_STATUS_OK;
2109 }
2110
2111 /***************************************************************************
2112  Free a user_info struct
2113 ***************************************************************************/
2114
2115 void free_user_info(struct auth_usersupplied_info **user_info)
2116 {
2117         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
2118         if (*user_info != NULL) {
2119                 if ((*user_info)->smb_name) {
2120                         DEBUG(10,("structure was created for %s\n",
2121                                   (*user_info)->smb_name));
2122                 }
2123                 SAFE_FREE((*user_info)->smb_name);
2124                 SAFE_FREE((*user_info)->internal_username);
2125                 SAFE_FREE((*user_info)->client_domain);
2126                 SAFE_FREE((*user_info)->domain);
2127                 SAFE_FREE((*user_info)->wksta_name);
2128                 data_blob_free(&(*user_info)->lm_resp);
2129                 data_blob_free(&(*user_info)->nt_resp);
2130                 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
2131                 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
2132                 data_blob_clear_free(&(*user_info)->plaintext_password);
2133                 ZERO_STRUCT(**user_info);
2134         }
2135         SAFE_FREE(*user_info);
2136 }
2137
2138 /***************************************************************************
2139  Make an auth_methods struct
2140 ***************************************************************************/
2141
2142 bool make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
2143 {
2144         if (!auth_context) {
2145                 smb_panic("no auth_context supplied to "
2146                           "make_auth_methods()!\n");
2147         }
2148
2149         if (!auth_method) {
2150                 smb_panic("make_auth_methods: pointer to auth_method pointer "
2151                           "is NULL!\n");
2152         }
2153
2154         *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
2155         if (!*auth_method) {
2156                 DEBUG(0,("make_auth_method: malloc failed!\n"));
2157                 return False;
2158         }
2159         ZERO_STRUCTP(*auth_method);
2160         
2161         return True;
2162 }
2163
2164 /**
2165  * Verify whether or not given domain is trusted.
2166  *
2167  * @param domain_name name of the domain to be verified
2168  * @return true if domain is one of the trusted ones or
2169  *         false if otherwise
2170  **/
2171
2172 bool is_trusted_domain(const char* dom_name)
2173 {
2174         DOM_SID trustdom_sid;
2175         bool ret;
2176
2177         /* no trusted domains for a standalone server */
2178
2179         if ( lp_server_role() == ROLE_STANDALONE )
2180                 return False;
2181
2182         if (dom_name == NULL || dom_name[0] == '\0') {
2183                 return false;
2184         }
2185
2186         if (strequal(dom_name, get_global_sam_name())) {
2187                 return false;
2188         }
2189
2190         /* if we are a DC, then check for a direct trust relationships */
2191
2192         if ( IS_DC ) {
2193                 become_root();
2194                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2195                           "[%s]\n", dom_name ));
2196                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2197                 unbecome_root();
2198                 if (ret)
2199                         return True;
2200         }
2201         else {
2202                 wbcErr result;
2203
2204                 /* If winbind is around, ask it */
2205
2206                 result = wb_is_trusted_domain(dom_name);
2207
2208                 if (result == WBC_ERR_SUCCESS) {
2209                         return True;
2210                 }
2211
2212                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
2213                         /* winbind could not find the domain */
2214                         return False;
2215                 }
2216
2217                 /* The only other possible result is that winbind is not up
2218                    and running. We need to update the trustdom_cache
2219                    ourselves */
2220                 
2221                 update_trustdom_cache();
2222         }
2223
2224         /* now the trustdom cache should be available a DC could still
2225          * have a transitive trust so fall back to the cache of trusted
2226          * domains (like a domain member would use  */
2227
2228         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
2229                 return True;
2230         }
2231
2232         return False;
2233 }
2234