3b951e7fa0a6a2d1c9e3610801a887f899a5f5da
[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-2011
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Volker Lendecke 2006-2008
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 "auth.h"
26 #include "lib/util_unixsids.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../lib/crypto/arcfour.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "lib/winbind_util.h"
33 #include "passdb.h"
34 #include "../librpc/gen_ndr/ndr_auth.h"
35 #include "../auth/auth_sam_reply.h"
36 #include "../librpc/gen_ndr/idmap.h"
37 #include "lib/param/loadparm.h"
38 #include "../lib/tsocket/tsocket.h"
39 #include "rpc_client/util_netlogon.h"
40 #include "source4/auth/auth.h"
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_AUTH
44
45 /****************************************************************************
46  Create a UNIX user on demand.
47 ****************************************************************************/
48
49 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
50 {
51         TALLOC_CTX *ctx = talloc_tos();
52         char *add_script;
53         int ret;
54
55         add_script = lp_add_user_script(ctx);
56         if (!add_script || !*add_script) {
57                 return -1;
58         }
59         add_script = talloc_all_string_sub(ctx,
60                                 add_script,
61                                 "%u",
62                                 unix_username);
63         if (!add_script) {
64                 return -1;
65         }
66         if (domain) {
67                 add_script = talloc_all_string_sub(ctx,
68                                         add_script,
69                                         "%D",
70                                         domain);
71                 if (!add_script) {
72                         return -1;
73                 }
74         }
75         if (homedir) {
76                 add_script = talloc_all_string_sub(ctx,
77                                 add_script,
78                                 "%H",
79                                 homedir);
80                 if (!add_script) {
81                         return -1;
82                 }
83         }
84         ret = smbrun(add_script, NULL, NULL);
85         flush_pwnam_cache();
86         DEBUG(ret ? 0 : 3,
87                 ("smb_create_user: Running the command `%s' gave %d\n",
88                  add_script,ret));
89         return ret;
90 }
91
92 /****************************************************************************
93  Create an auth_usersupplied_data structure after appropriate mapping.
94 ****************************************************************************/
95
96 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
97                             struct auth_usersupplied_info **user_info,
98                             const char *smb_name,
99                             const char *client_domain,
100                             const char *workstation_name,
101                             const struct tsocket_address *remote_address,
102                             const struct tsocket_address *local_address,
103                             const char *service_description,
104                             const DATA_BLOB *lm_pwd,
105                             const DATA_BLOB *nt_pwd,
106                             const struct samr_Password *lm_interactive_pwd,
107                             const struct samr_Password *nt_interactive_pwd,
108                             const char *plaintext,
109                             enum auth_password_state password_state)
110 {
111         const char *domain;
112         NTSTATUS result;
113         bool was_mapped;
114         char *internal_username = NULL;
115
116         was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
117         if (!internal_username) {
118                 return NT_STATUS_NO_MEMORY;
119         }
120
121         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
122                  client_domain, smb_name, workstation_name));
123
124         /*
125          * We let the auth stack canonicalize, username
126          * and domain.
127          */
128         domain = client_domain;
129
130         result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
131                                 client_domain, domain, workstation_name,
132                                 remote_address, local_address,
133                                 service_description, lm_pwd, nt_pwd,
134                                 lm_interactive_pwd, nt_interactive_pwd,
135                                 plaintext, password_state);
136         if (NT_STATUS_IS_OK(result)) {
137                 /* We have tried mapping */
138                 (*user_info)->mapped_state = true;
139                 /* did we actually map the user to a different name? */
140                 (*user_info)->was_mapped = was_mapped;
141         }
142         return result;
143 }
144
145 /****************************************************************************
146  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
147  Decrypt and encrypt the passwords.
148 ****************************************************************************/
149
150 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
151                                      struct auth_usersupplied_info **user_info,
152                                      const char *smb_name, 
153                                      const char *client_domain, 
154                                      const char *workstation_name,
155                                      const struct tsocket_address *remote_address,
156                                      const struct tsocket_address *local_address,
157                                      uint32_t logon_parameters,
158                                      const uchar *lm_network_pwd,
159                                      int lm_pwd_len,
160                                      const uchar *nt_network_pwd,
161                                      int nt_pwd_len)
162 {
163         bool ret;
164         NTSTATUS status;
165         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
166         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
167
168         status = make_user_info_map(mem_ctx, user_info,
169                                     smb_name, client_domain, 
170                                     workstation_name,
171                                     remote_address,
172                                     local_address,
173                                     "SamLogon",
174                                     lm_pwd_len ? &lm_blob : NULL, 
175                                     nt_pwd_len ? &nt_blob : NULL,
176                                     NULL, NULL, NULL,
177                                     AUTH_PASSWORD_RESPONSE);
178
179         if (NT_STATUS_IS_OK(status)) {
180                 (*user_info)->logon_parameters = logon_parameters;
181         }
182         ret = NT_STATUS_IS_OK(status) ? true : false;
183
184         data_blob_free(&lm_blob);
185         data_blob_free(&nt_blob);
186         return ret;
187 }
188
189 /****************************************************************************
190  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
191  Decrypt and encrypt the passwords.
192 ****************************************************************************/
193
194 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
195                                          struct auth_usersupplied_info **user_info,
196                                          const char *smb_name, 
197                                          const char *client_domain, 
198                                          const char *workstation_name,
199                                          const struct tsocket_address *remote_address,
200                                          const struct tsocket_address *local_address,
201                                          uint32_t logon_parameters,
202                                          const uchar chal[8], 
203                                          const uchar lm_interactive_pwd[16], 
204                                          const uchar nt_interactive_pwd[16])
205 {
206         struct samr_Password lm_pwd;
207         struct samr_Password nt_pwd;
208         unsigned char local_lm_response[24];
209         unsigned char local_nt_response[24];
210
211         if (lm_interactive_pwd)
212                 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
213
214         if (nt_interactive_pwd)
215                 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
216
217         if (lm_interactive_pwd)
218                 SMBOWFencrypt(lm_pwd.hash, chal,
219                               local_lm_response);
220
221         if (nt_interactive_pwd)
222                 SMBOWFencrypt(nt_pwd.hash, chal,
223                               local_nt_response);
224
225         {
226                 bool ret;
227                 NTSTATUS nt_status;
228                 DATA_BLOB local_lm_blob = data_blob_null;
229                 DATA_BLOB local_nt_blob = data_blob_null;
230
231                 if (lm_interactive_pwd) {
232                         local_lm_blob = data_blob(local_lm_response,
233                                                   sizeof(local_lm_response));
234                 }
235
236                 if (nt_interactive_pwd) {
237                         local_nt_blob = data_blob(local_nt_response,
238                                                   sizeof(local_nt_response));
239                 }
240
241                 nt_status = make_user_info_map(
242                         mem_ctx,
243                         user_info, 
244                         smb_name, client_domain, workstation_name,
245                         remote_address,
246                         local_address,
247                         "SamLogon",
248                         lm_interactive_pwd ? &local_lm_blob : NULL,
249                         nt_interactive_pwd ? &local_nt_blob : NULL,
250                         lm_interactive_pwd ? &lm_pwd : NULL,
251                         nt_interactive_pwd ? &nt_pwd : NULL,
252                         NULL, AUTH_PASSWORD_HASH);
253
254                 if (NT_STATUS_IS_OK(nt_status)) {
255                         (*user_info)->logon_parameters = logon_parameters;
256                 }
257
258                 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
259                 data_blob_free(&local_lm_blob);
260                 data_blob_free(&local_nt_blob);
261                 return ret;
262         }
263 }
264
265
266 /****************************************************************************
267  Create an auth_usersupplied_data structure
268 ****************************************************************************/
269
270 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
271                               struct auth_usersupplied_info **user_info,
272                               const char *smb_name, 
273                               const char *client_domain,
274                               const struct tsocket_address *remote_address,
275                               const struct tsocket_address *local_address,
276                               const char *service_description,
277                               const uint8_t chal[8],
278                               DATA_BLOB plaintext_password)
279 {
280
281         DATA_BLOB local_lm_blob;
282         DATA_BLOB local_nt_blob;
283         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
284         char *plaintext_password_string;
285         /*
286          * Not encrypted - do so.
287          */
288
289         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
290                  "format.\n"));
291         if (plaintext_password.data && plaintext_password.length) {
292                 unsigned char local_lm_response[24];
293
294 #ifdef DEBUG_PASSWORD
295                 DEBUG(10,("Unencrypted password (len %d):\n",
296                           (int)plaintext_password.length));
297                 dump_data(100, plaintext_password.data,
298                           plaintext_password.length);
299 #endif
300
301                 SMBencrypt( (const char *)plaintext_password.data,
302                             (const uchar*)chal, local_lm_response);
303                 local_lm_blob = data_blob(local_lm_response, 24);
304
305                 /* We can't do an NT hash here, as the password needs to be
306                    case insensitive */
307                 local_nt_blob = data_blob_null; 
308         } else {
309                 local_lm_blob = data_blob_null; 
310                 local_nt_blob = data_blob_null; 
311         }
312
313         plaintext_password_string = talloc_strndup(talloc_tos(),
314                                                    (const char *)plaintext_password.data,
315                                                    plaintext_password.length);
316         if (!plaintext_password_string) {
317                 return false;
318         }
319
320         ret = make_user_info(mem_ctx,
321                 user_info, smb_name, smb_name, client_domain, client_domain, 
322                 get_remote_machine_name(),
323                 remote_address,
324                 local_address,
325                 service_description,
326                 local_lm_blob.data ? &local_lm_blob : NULL,
327                 local_nt_blob.data ? &local_nt_blob : NULL,
328                 NULL, NULL,
329                 plaintext_password_string,
330                 AUTH_PASSWORD_PLAIN);
331
332         if (plaintext_password_string) {
333                 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
334                 talloc_free(plaintext_password_string);
335         }
336
337         data_blob_free(&local_lm_blob);
338         return NT_STATUS_IS_OK(ret) ? true : false;
339 }
340
341 /****************************************************************************
342  Create an auth_usersupplied_data structure
343 ****************************************************************************/
344
345 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
346                                       struct auth_usersupplied_info **user_info,
347                                       const char *smb_name,
348                                       const char *client_domain,
349                                       const struct tsocket_address *remote_address,
350                                       const struct tsocket_address *local_address,
351                                       const char *service_description,
352                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
353 {
354         bool allow_raw = lp_raw_ntlmv2_auth();
355
356         if (!allow_raw && nt_resp.length >= 48) {
357                 /*
358                  * NTLMv2_RESPONSE has at least 48 bytes
359                  * and should only be supported via NTLMSSP.
360                  */
361                 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
362                          "user [%s\\%s] from[%s]\n",
363                          client_domain, smb_name,
364                          tsocket_address_string(remote_address, mem_ctx)));
365                 return NT_STATUS_INVALID_PARAMETER;
366         }
367
368         return make_user_info(mem_ctx,
369                               user_info, smb_name, smb_name,
370                               client_domain, client_domain,
371                               get_remote_machine_name(),
372                               remote_address,
373                               local_address,
374                               service_description,
375                               lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
376                               nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
377                               NULL, NULL, NULL,
378                               AUTH_PASSWORD_RESPONSE);
379 }
380
381 /****************************************************************************
382  Create a guest user_info blob, for anonymous authentication.
383 ****************************************************************************/
384
385 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
386                           const struct tsocket_address *remote_address,
387                           const struct tsocket_address *local_address,
388                           const char *service_description,
389                           struct auth_usersupplied_info **user_info)
390 {
391         NTSTATUS nt_status;
392
393         nt_status = make_user_info(mem_ctx,
394                                    user_info,
395                                    "","", 
396                                    "","", 
397                                    "", 
398                                    remote_address,
399                                    local_address,
400                                    service_description,
401                                    NULL, NULL, 
402                                    NULL, NULL, 
403                                    NULL,
404                                    AUTH_PASSWORD_RESPONSE);
405
406         return NT_STATUS_IS_OK(nt_status) ? true : false;
407 }
408
409 static NTSTATUS log_nt_token(struct security_token *token)
410 {
411         TALLOC_CTX *frame = talloc_stackframe();
412         char *command;
413         char *group_sidstr;
414         size_t i;
415
416         if ((lp_log_nt_token_command(frame) == NULL) ||
417             (strlen(lp_log_nt_token_command(frame)) == 0)) {
418                 TALLOC_FREE(frame);
419                 return NT_STATUS_OK;
420         }
421
422         group_sidstr = talloc_strdup(frame, "");
423         for (i=1; i<token->num_sids; i++) {
424                 group_sidstr = talloc_asprintf(
425                         frame, "%s %s", group_sidstr,
426                         sid_string_talloc(frame, &token->sids[i]));
427         }
428
429         command = talloc_string_sub(
430                 frame, lp_log_nt_token_command(frame),
431                 "%s", sid_string_talloc(frame, &token->sids[0]));
432         command = talloc_string_sub(frame, command, "%t", group_sidstr);
433
434         if (command == NULL) {
435                 TALLOC_FREE(frame);
436                 return NT_STATUS_NO_MEMORY;
437         }
438
439         DEBUG(8, ("running command: [%s]\n", command));
440         if (smbrun(command, NULL, NULL) != 0) {
441                 DEBUG(0, ("Could not log NT token\n"));
442                 TALLOC_FREE(frame);
443                 return NT_STATUS_ACCESS_DENIED;
444         }
445
446         TALLOC_FREE(frame);
447         return NT_STATUS_OK;
448 }
449
450 /*
451  * Create the token to use from server_info->info3 and
452  * server_info->sids (the info3/sam groups). Find the unix gids.
453  */
454
455 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
456                             const struct auth_serversupplied_info *server_info,
457                             DATA_BLOB *session_key,
458                             const char *smb_username, /* for ->sanitized_username, for %U subs */
459                             struct auth_session_info **session_info_out)
460 {
461         struct security_token *t;
462         NTSTATUS status;
463         size_t i;
464         struct dom_sid tmp_sid;
465         struct auth_session_info *session_info;
466         struct unixid *ids;
467         fstring tmp;
468
469         /* Ensure we can't possible take a code path leading to a
470          * null defref. */
471         if (!server_info) {
472                 return NT_STATUS_LOGON_FAILURE;
473         }
474
475         if (server_info->cached_session_info != NULL) {
476                 session_info = copy_session_info(mem_ctx,
477                                 server_info->cached_session_info);
478                 if (session_info == NULL) {
479                         return NT_STATUS_NO_MEMORY;
480                 }
481
482                 /* This is a potentially untrusted username for use in %U */
483                 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
484                 session_info->unix_info->sanitized_username =
485                                 talloc_strdup(session_info->unix_info, tmp);
486                 if (session_info->unix_info->sanitized_username == NULL) {
487                         TALLOC_FREE(session_info);
488                         return NT_STATUS_NO_MEMORY;
489                 }
490
491                 *session_info_out = session_info;
492                 return NT_STATUS_OK;
493         }
494
495         session_info = talloc_zero(mem_ctx, struct auth_session_info);
496         if (!session_info) {
497                 return NT_STATUS_NO_MEMORY;
498         }
499
500         session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
501         if (!session_info->unix_token) {
502                 TALLOC_FREE(session_info);
503                 return NT_STATUS_NO_MEMORY;
504         }
505
506         session_info->unix_token->uid = server_info->utok.uid;
507         session_info->unix_token->gid = server_info->utok.gid;
508
509         session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
510         if (!session_info->unix_info) {
511                 TALLOC_FREE(session_info);
512                 return NT_STATUS_NO_MEMORY;
513         }
514
515         session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
516         if (!session_info->unix_info->unix_name) {
517                 TALLOC_FREE(session_info);
518                 return NT_STATUS_NO_MEMORY;
519         }
520
521         /* This is a potentially untrusted username for use in %U */
522         alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
523         session_info->unix_info->sanitized_username =
524                                 talloc_strdup(session_info->unix_info, tmp);
525
526         if (session_key) {
527                 data_blob_free(&session_info->session_key);
528                 session_info->session_key = data_blob_talloc(session_info,
529                                                                   session_key->data,
530                                                                   session_key->length);
531                 if (!session_info->session_key.data && session_key->length) {
532                         return NT_STATUS_NO_MEMORY;
533                 }
534         } else {
535                 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
536                                                               server_info->session_key.length);
537         }
538
539         /* We need to populate session_info->info with the information found in server_info->info3 */
540         status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
541                                             server_info->guest == false,
542                                             &session_info->info);
543         if (!NT_STATUS_IS_OK(status)) {
544                 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
545                 TALLOC_FREE(session_info);
546                 return status;
547         }
548
549         /*
550          * If winbind is not around, we can not make much use of the SIDs the
551          * domain controller provided us with. Likewise if the user name was
552          * mapped to some local unix user.
553          */
554
555         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
556             (server_info->nss_token)) {
557                 char *found_username = NULL;
558                 status = create_token_from_username(session_info,
559                                                     server_info->unix_name,
560                                                     server_info->guest,
561                                                     &session_info->unix_token->uid,
562                                                     &session_info->unix_token->gid,
563                                                     &found_username,
564                                                     &session_info->security_token);
565                 if (NT_STATUS_IS_OK(status)) {
566                         session_info->unix_info->unix_name = found_username;
567                 }
568         } else {
569                 status = create_local_nt_token_from_info3(session_info,
570                                                           server_info->guest,
571                                                           server_info->info3,
572                                                           &server_info->extra,
573                                                           &session_info->security_token);
574         }
575
576         if (!NT_STATUS_IS_OK(status)) {
577                 return status;
578         }
579
580         /* Convert the SIDs to gids. */
581
582         session_info->unix_token->ngroups = 0;
583         session_info->unix_token->groups = NULL;
584
585         t = session_info->security_token;
586
587         ids = talloc_array(talloc_tos(), struct unixid,
588                            t->num_sids);
589         if (ids == NULL) {
590                 return NT_STATUS_NO_MEMORY;
591         }
592
593         if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
594                 TALLOC_FREE(ids);
595                 return NT_STATUS_NO_MEMORY;
596         }
597
598         for (i=0; i<t->num_sids; i++) {
599
600                 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
601                         continue;
602                 }
603
604                 if (ids[i].type != ID_TYPE_GID &&
605                     ids[i].type != ID_TYPE_BOTH) {
606                         DEBUG(10, ("Could not convert SID %s to gid, "
607                                    "ignoring it\n",
608                                    sid_string_dbg(&t->sids[i])));
609                         continue;
610                 }
611                 if (!add_gid_to_array_unique(session_info->unix_token,
612                                              ids[i].id,
613                                              &session_info->unix_token->groups,
614                                              &session_info->unix_token->ngroups)) {
615                         return NT_STATUS_NO_MEMORY;
616                 }
617         }
618
619         /*
620          * Add the "Unix Group" SID for each gid to catch mapped groups
621          * and their Unix equivalent.  This is to solve the backwards
622          * compatibility problem of 'valid users = +ntadmin' where
623          * ntadmin has been paired with "Domain Admins" in the group
624          * mapping table.  Otherwise smb.conf would need to be changed
625          * to 'valid user = "Domain Admins"'.  --jerry
626          *
627          * For consistency we also add the "Unix User" SID,
628          * so that the complete unix token is represented within
629          * the nt token.
630          */
631
632         uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
633         add_sid_to_array_unique(session_info->security_token, &tmp_sid,
634                                 &session_info->security_token->sids,
635                                 &session_info->security_token->num_sids);
636
637         gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
638         add_sid_to_array_unique(session_info->security_token, &tmp_sid,
639                                 &session_info->security_token->sids,
640                                 &session_info->security_token->num_sids);
641
642         for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
643                 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
644                 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
645                                         &session_info->security_token->sids,
646                                         &session_info->security_token->num_sids);
647         }
648
649         security_token_debug(DBGC_AUTH, 10, session_info->security_token);
650         debug_unix_user_token(DBGC_AUTH, 10,
651                               session_info->unix_token->uid,
652                               session_info->unix_token->gid,
653                               session_info->unix_token->ngroups,
654                               session_info->unix_token->groups);
655
656         status = log_nt_token(session_info->security_token);
657         if (!NT_STATUS_IS_OK(status)) {
658                 return status;
659         }
660
661         *session_info_out = session_info;
662         return NT_STATUS_OK;
663 }
664
665 NTSTATUS auth3_user_info_dc_add_hints(struct auth_user_info_dc *user_info_dc,
666                                       uid_t uid,
667                                       gid_t gid,
668                                       uint32_t flags)
669 {
670         uint32_t orig_num_sids = user_info_dc->num_sids;
671         struct dom_sid tmp_sid = { 0, };
672         NTSTATUS status;
673
674         /*
675          * We add S-5-88-1-X in order to pass the uid
676          * for the unix token.
677          */
678         sid_compose(&tmp_sid,
679                     &global_sid_Unix_NFS_Users,
680                     (uint32_t)uid);
681         status = add_sid_to_array_unique(user_info_dc->sids,
682                                          &tmp_sid,
683                                          &user_info_dc->sids,
684                                          &user_info_dc->num_sids);
685         if (!NT_STATUS_IS_OK(status)) {
686                 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
687                           nt_errstr(status)));
688                 goto fail;
689         }
690
691         /*
692          * We add S-5-88-2-X in order to pass the gid
693          * for the unix token.
694          */
695         sid_compose(&tmp_sid,
696                     &global_sid_Unix_NFS_Groups,
697                     (uint32_t)gid);
698         status = add_sid_to_array_unique(user_info_dc->sids,
699                                          &tmp_sid,
700                                          &user_info_dc->sids,
701                                          &user_info_dc->num_sids);
702         if (!NT_STATUS_IS_OK(status)) {
703                 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
704                           nt_errstr(status)));
705                 goto fail;
706         }
707
708         /*
709          * We add S-5-88-3-X in order to pass some flags
710          * (AUTH3_UNIX_HINT_*) to auth3_create_session_info().
711          */
712         sid_compose(&tmp_sid,
713                     &global_sid_Unix_NFS_Mode,
714                     flags);
715         status = add_sid_to_array_unique(user_info_dc->sids,
716                                          &tmp_sid,
717                                          &user_info_dc->sids,
718                                          &user_info_dc->num_sids);
719         if (!NT_STATUS_IS_OK(status)) {
720                 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
721                           nt_errstr(status)));
722                 goto fail;
723         }
724
725         return NT_STATUS_OK;
726
727 fail:
728         user_info_dc->num_sids = orig_num_sids;
729         return status;
730 }
731
732 NTSTATUS auth3_session_info_create(TALLOC_CTX *mem_ctx,
733                                    const struct auth_user_info_dc *user_info_dc,
734                                    const char *original_user_name,
735                                    uint32_t session_info_flags,
736                                    struct auth_session_info **session_info_out)
737 {
738         TALLOC_CTX *frame = talloc_stackframe();
739         struct auth_session_info *session_info = NULL;
740         uid_t hint_uid = -1;
741         bool found_hint_uid = false;
742         uid_t hint_gid = -1;
743         bool found_hint_gid = false;
744         uint32_t hint_flags = 0;
745         bool found_hint_flags = false;
746         bool need_getpwuid = false;
747         struct unixid *ids = NULL;
748         uint32_t num_gids = 0;
749         gid_t *gids = NULL;
750         struct dom_sid tmp_sid = { 0, };
751         fstring tmp = { 0, };
752         NTSTATUS status;
753         size_t i;
754         bool ok;
755
756         *session_info_out = NULL;
757
758         if (user_info_dc->num_sids == 0) {
759                 TALLOC_FREE(frame);
760                 return NT_STATUS_INVALID_TOKEN;
761         }
762
763         if (user_info_dc->info == NULL) {
764                 TALLOC_FREE(frame);
765                 return NT_STATUS_INVALID_TOKEN;
766         }
767
768         if (user_info_dc->info->account_name == NULL) {
769                 TALLOC_FREE(frame);
770                 return NT_STATUS_INVALID_TOKEN;
771         }
772
773         session_info = talloc_zero(mem_ctx, struct auth_session_info);
774         if (session_info == NULL) {
775                 TALLOC_FREE(frame);
776                 return NT_STATUS_NO_MEMORY;
777         }
778         /* keep this under frame for easier cleanup */
779         talloc_reparent(mem_ctx, frame, session_info);
780
781         session_info->info = auth_user_info_copy(session_info,
782                                                  user_info_dc->info);
783         if (session_info->info == NULL) {
784                 TALLOC_FREE(frame);
785                 return NT_STATUS_NO_MEMORY;
786         }
787
788         session_info->security_token = talloc_zero(session_info,
789                                                    struct security_token);
790         if (session_info->security_token == NULL) {
791                 TALLOC_FREE(frame);
792                 return NT_STATUS_NO_MEMORY;
793         }
794
795         /*
796          * Avoid a lot of reallocations and allocate what we'll
797          * use in most cases.
798          */
799         session_info->security_token->sids = talloc_zero_array(
800                                                 session_info->security_token,
801                                                 struct dom_sid,
802                                                 user_info_dc->num_sids);
803         if (session_info->security_token->sids == NULL) {
804                 TALLOC_FREE(frame);
805                 return NT_STATUS_NO_MEMORY;
806         }
807
808         for (i = PRIMARY_USER_SID_INDEX; i < user_info_dc->num_sids; i++) {
809                 struct security_token *nt_token = session_info->security_token;
810                 int cmp;
811
812                 /*
813                  * S-1-5-88-X-Y sids are only used to give hints
814                  * to the unix token construction.
815                  *
816                  * S-1-5-88-1-Y gives the uid=Y
817                  * S-1-5-88-2-Y gives the gid=Y
818                  * S-1-5-88-3-Y gives flags=Y: AUTH3_UNIX_HINT_*
819                  */
820                 cmp = dom_sid_compare_domain(&global_sid_Unix_NFS,
821                                              &user_info_dc->sids[i]);
822                 if (cmp == 0) {
823                         bool match;
824                         uint32_t hint = 0;
825
826                         match = sid_peek_rid(&user_info_dc->sids[i], &hint);
827                         if (!match) {
828                                 continue;
829                         }
830
831                         match = dom_sid_in_domain(&global_sid_Unix_NFS_Users,
832                                                   &user_info_dc->sids[i]);
833                         if (match) {
834                                 if (found_hint_uid) {
835                                         TALLOC_FREE(frame);
836                                         return NT_STATUS_INVALID_TOKEN;
837                                 }
838                                 found_hint_uid = true;
839                                 hint_uid = (uid_t)hint;
840                                 continue;
841                         }
842
843                         match = dom_sid_in_domain(&global_sid_Unix_NFS_Groups,
844                                                   &user_info_dc->sids[i]);
845                         if (match) {
846                                 if (found_hint_gid) {
847                                         TALLOC_FREE(frame);
848                                         return NT_STATUS_INVALID_TOKEN;
849                                 }
850                                 found_hint_gid = true;
851                                 hint_gid = (gid_t)hint;
852                                 continue;
853                         }
854
855                         match = dom_sid_in_domain(&global_sid_Unix_NFS_Mode,
856                                                   &user_info_dc->sids[i]);
857                         if (match) {
858                                 if (found_hint_flags) {
859                                         TALLOC_FREE(frame);
860                                         return NT_STATUS_INVALID_TOKEN;
861                                 }
862                                 found_hint_flags = true;
863                                 hint_flags = hint;
864                                 continue;
865                         }
866
867                         continue;
868                 }
869
870                 status = add_sid_to_array_unique(nt_token->sids,
871                                                  &user_info_dc->sids[i],
872                                                  &nt_token->sids,
873                                                  &nt_token->num_sids);
874                 if (!NT_STATUS_IS_OK(status)) {
875                         TALLOC_FREE(frame);
876                         return status;
877                 }
878         }
879
880         /*
881          * We need at least one usable SID
882          */
883         if (session_info->security_token->num_sids == 0) {
884                 TALLOC_FREE(frame);
885                 return NT_STATUS_INVALID_TOKEN;
886         }
887
888         /*
889          * We need all tree hints: uid, gid, flags
890          * or none of them.
891          */
892         if (found_hint_uid || found_hint_gid || found_hint_flags) {
893                 if (!found_hint_uid) {
894                         TALLOC_FREE(frame);
895                         return NT_STATUS_INVALID_TOKEN;
896                 }
897
898                 if (!found_hint_gid) {
899                         TALLOC_FREE(frame);
900                         return NT_STATUS_INVALID_TOKEN;
901                 }
902
903                 if (!found_hint_flags) {
904                         TALLOC_FREE(frame);
905                         return NT_STATUS_INVALID_TOKEN;
906                 }
907         }
908
909         if (session_info->info->authenticated) {
910                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
911         }
912
913         status = finalize_local_nt_token(session_info->security_token,
914                                          session_info_flags);
915         if (!NT_STATUS_IS_OK(status)) {
916                 TALLOC_FREE(frame);
917                 return status;
918         }
919
920         /*
921          * unless set otherwise, the session key is the user session
922          * key from the auth subsystem
923          */
924         if (user_info_dc->user_session_key.length != 0) {
925                 session_info->session_key = data_blob_dup_talloc(session_info,
926                                                 user_info_dc->user_session_key);
927                 if (session_info->session_key.data == NULL) {
928                         TALLOC_FREE(frame);
929                         return NT_STATUS_NO_MEMORY;
930                 }
931         }
932
933         if (!(session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)) {
934                 goto done;
935         }
936
937         session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
938         if (session_info->unix_token == NULL) {
939                 TALLOC_FREE(frame);
940                 return NT_STATUS_NO_MEMORY;
941         }
942         session_info->unix_token->uid = -1;
943         session_info->unix_token->gid = -1;
944
945         session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
946         if (session_info->unix_info == NULL) {
947                 TALLOC_FREE(frame);
948                 return NT_STATUS_NO_MEMORY;
949         }
950
951         /* Convert the SIDs to uid/gids. */
952
953         ids = talloc_zero_array(frame, struct unixid,
954                                 session_info->security_token->num_sids);
955         if (ids == NULL) {
956                 TALLOC_FREE(frame);
957                 return NT_STATUS_NO_MEMORY;
958         }
959
960         if (!(hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS)) {
961                 ok = sids_to_unixids(session_info->security_token->sids,
962                                      session_info->security_token->num_sids,
963                                      ids);
964                 if (!ok) {
965                         TALLOC_FREE(frame);
966                         return NT_STATUS_NO_MEMORY;
967                 }
968         }
969
970         if (found_hint_uid) {
971                 session_info->unix_token->uid = hint_uid;
972         } else if (ids[0].type == ID_TYPE_UID) {
973                 /*
974                  * The primary SID resolves to a UID only.
975                  */
976                 session_info->unix_token->uid = ids[0].id;
977         } else if (ids[0].type == ID_TYPE_BOTH) {
978                 /*
979                  * The primary SID resolves to a UID and GID,
980                  * use it as uid and add it as first element
981                  * to the groups array.
982                  */
983                 session_info->unix_token->uid = ids[0].id;
984
985                 ok = add_gid_to_array_unique(session_info->unix_token,
986                                              session_info->unix_token->uid,
987                                              &session_info->unix_token->groups,
988                                              &session_info->unix_token->ngroups);
989                 if (!ok) {
990                         TALLOC_FREE(frame);
991                         return NT_STATUS_NO_MEMORY;
992                 }
993         } else {
994                 /*
995                  * It we can't get a uid, we can't imporsonate
996                  * the user.
997                  */
998                 TALLOC_FREE(frame);
999                 return NT_STATUS_INVALID_TOKEN;
1000         }
1001
1002         if (found_hint_gid) {
1003                 session_info->unix_token->gid = hint_gid;
1004         } else {
1005                 need_getpwuid = true;
1006         }
1007
1008         if (hint_flags & AUTH3_UNIX_HINT_QUALIFIED_NAME) {
1009                 session_info->unix_info->unix_name =
1010                         talloc_asprintf(session_info->unix_info,
1011                                         "%s%c%s",
1012                                         session_info->info->domain_name,
1013                                         *lp_winbind_separator(),
1014                                         session_info->info->account_name);
1015                 if (session_info->unix_info->unix_name == NULL) {
1016                         TALLOC_FREE(frame);
1017                         return NT_STATUS_NO_MEMORY;
1018                 }
1019         } else if (hint_flags & AUTH3_UNIX_HINT_ISLOLATED_NAME) {
1020                 session_info->unix_info->unix_name =
1021                         talloc_strdup(session_info->unix_info,
1022                                       session_info->info->account_name);
1023                 if (session_info->unix_info->unix_name == NULL) {
1024                         TALLOC_FREE(frame);
1025                         return NT_STATUS_NO_MEMORY;
1026                 }
1027         } else {
1028                 need_getpwuid = true;
1029         }
1030
1031         if (need_getpwuid) {
1032                 struct passwd *pwd = NULL;
1033
1034                 /*
1035                  * Ask the system for the primary gid
1036                  * and the real unix name.
1037                  */
1038                 pwd = getpwuid_alloc(frame, session_info->unix_token->uid);
1039                 if (pwd == NULL) {
1040                         TALLOC_FREE(frame);
1041                         return NT_STATUS_INVALID_TOKEN;
1042                 }
1043                 if (!found_hint_gid) {
1044                         session_info->unix_token->gid = pwd->pw_gid;
1045                 }
1046
1047                 session_info->unix_info->unix_name =
1048                         talloc_strdup(session_info->unix_info, pwd->pw_name);
1049                 if (session_info->unix_info->unix_name == NULL) {
1050                         TALLOC_FREE(frame);
1051                         return NT_STATUS_NO_MEMORY;
1052                 }
1053
1054                 TALLOC_FREE(pwd);
1055         }
1056
1057         ok = add_gid_to_array_unique(session_info->unix_token,
1058                                      session_info->unix_token->gid,
1059                                      &session_info->unix_token->groups,
1060                                      &session_info->unix_token->ngroups);
1061         if (!ok) {
1062                 TALLOC_FREE(frame);
1063                 return NT_STATUS_NO_MEMORY;
1064         }
1065
1066         /* This is a potentially untrusted username for use in %U */
1067         alpha_strcpy(tmp, original_user_name, ". _-$", sizeof(tmp));
1068         session_info->unix_info->sanitized_username =
1069                                 talloc_strdup(session_info->unix_info, tmp);
1070         if (session_info->unix_info->sanitized_username == NULL) {
1071                 TALLOC_FREE(frame);
1072                 return NT_STATUS_NO_MEMORY;
1073         }
1074
1075         for (i=0; i < session_info->security_token->num_sids; i++) {
1076
1077                 if (ids[i].type != ID_TYPE_GID &&
1078                     ids[i].type != ID_TYPE_BOTH) {
1079                         struct security_token *nt_token =
1080                                 session_info->security_token;
1081
1082                         DEBUG(10, ("Could not convert SID %s to gid, "
1083                                    "ignoring it\n",
1084                                    sid_string_dbg(&nt_token->sids[i])));
1085                         continue;
1086                 }
1087
1088                 ok = add_gid_to_array_unique(session_info->unix_token,
1089                                              ids[i].id,
1090                                              &session_info->unix_token->groups,
1091                                              &session_info->unix_token->ngroups);
1092                 if (!ok) {
1093                         TALLOC_FREE(frame);
1094                         return NT_STATUS_NO_MEMORY;
1095                 }
1096         }
1097         TALLOC_FREE(ids);
1098
1099         /*
1100          * Now we must get any groups this user has been
1101          * added to in /etc/group and merge them in.
1102          * This has to be done in every code path
1103          * that creates an NT token, as remote users
1104          * may have been added to the local /etc/group
1105          * database. Tokens created merely from the
1106          * info3 structs (via the DC or via the krb5 PAC)
1107          * won't have these local groups. Note the
1108          * groups added here will only be UNIX groups
1109          * (S-1-22-2-XXXX groups) as getgroups_unix_user()
1110          * turns off winbindd before calling getgroups().
1111          *
1112          * NB. This is duplicating work already
1113          * done in the 'unix_user:' case of
1114          * create_token_from_sid() but won't
1115          * do anything other than be inefficient
1116          * in that case.
1117          */
1118         if (!(hint_flags & AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS)) {
1119                 ok = getgroups_unix_user(frame,
1120                                          session_info->unix_info->unix_name,
1121                                          session_info->unix_token->gid,
1122                                          &gids, &num_gids);
1123                 if (!ok) {
1124                         TALLOC_FREE(frame);
1125                         return NT_STATUS_INVALID_TOKEN;
1126                 }
1127         }
1128
1129         for (i=0; i < num_gids; i++) {
1130
1131                 ok = add_gid_to_array_unique(session_info->unix_token,
1132                                              gids[i],
1133                                              &session_info->unix_token->groups,
1134                                              &session_info->unix_token->ngroups);
1135                 if (!ok) {
1136                         TALLOC_FREE(frame);
1137                         return NT_STATUS_NO_MEMORY;
1138                 }
1139         }
1140         TALLOC_FREE(gids);
1141
1142         if (hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS) {
1143                 /*
1144                  * We should not translate the unix token uid/gids
1145                  * to S-1-22-X-Y SIDs.
1146                  */
1147                 goto done;
1148         }
1149
1150         /*
1151          * Add the "Unix Group" SID for each gid to catch mapped groups
1152          * and their Unix equivalent.  This is to solve the backwards
1153          * compatibility problem of 'valid users = +ntadmin' where
1154          * ntadmin has been paired with "Domain Admins" in the group
1155          * mapping table.  Otherwise smb.conf would need to be changed
1156          * to 'valid user = "Domain Admins"'.  --jerry
1157          *
1158          * For consistency we also add the "Unix User" SID,
1159          * so that the complete unix token is represented within
1160          * the nt token.
1161          */
1162
1163         uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
1164         status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1165                                          &session_info->security_token->sids,
1166                                          &session_info->security_token->num_sids);
1167         if (!NT_STATUS_IS_OK(status)) {
1168                 TALLOC_FREE(frame);
1169                 return status;
1170         }
1171
1172         gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
1173         status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1174                                          &session_info->security_token->sids,
1175                                          &session_info->security_token->num_sids);
1176         if (!NT_STATUS_IS_OK(status)) {
1177                 TALLOC_FREE(frame);
1178                 return status;
1179         }
1180
1181         for (i=0; i < session_info->unix_token->ngroups; i++ ) {
1182                 struct security_token *nt_token = session_info->security_token;
1183
1184                 gid_to_unix_groups_sid(session_info->unix_token->groups[i],
1185                                        &tmp_sid);
1186                 status = add_sid_to_array_unique(nt_token->sids,
1187                                                  &tmp_sid,
1188                                                  &nt_token->sids,
1189                                                  &nt_token->num_sids);
1190                 if (!NT_STATUS_IS_OK(status)) {
1191                         TALLOC_FREE(frame);
1192                         return status;
1193                 }
1194         }
1195
1196 done:
1197         security_token_debug(DBGC_AUTH, 10, session_info->security_token);
1198         if (session_info->unix_token != NULL) {
1199                 debug_unix_user_token(DBGC_AUTH, 10,
1200                                       session_info->unix_token->uid,
1201                                       session_info->unix_token->gid,
1202                                       session_info->unix_token->ngroups,
1203                                       session_info->unix_token->groups);
1204         }
1205
1206         status = log_nt_token(session_info->security_token);
1207         if (!NT_STATUS_IS_OK(status)) {
1208                 TALLOC_FREE(frame);
1209                 return status;
1210         }
1211
1212         *session_info_out = talloc_move(mem_ctx, &session_info);
1213         TALLOC_FREE(frame);
1214         return NT_STATUS_OK;
1215 }
1216
1217 /***************************************************************************
1218  Make (and fill) a server_info struct from a 'struct passwd' by conversion
1219  to a struct samu
1220 ***************************************************************************/
1221
1222 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
1223                              const char *unix_username,
1224                              const struct passwd *pwd,
1225                              struct auth_serversupplied_info **server_info)
1226 {
1227         NTSTATUS status;
1228         TALLOC_CTX *tmp_ctx = NULL;
1229         struct auth_serversupplied_info *result;
1230
1231         tmp_ctx = talloc_stackframe();
1232         if (tmp_ctx == NULL) {
1233                 return NT_STATUS_NO_MEMORY;
1234         }
1235
1236         result = make_server_info(tmp_ctx);
1237         if (result == NULL) {
1238                 status = NT_STATUS_NO_MEMORY;
1239                 goto done;
1240         }
1241
1242         status = passwd_to_SamInfo3(result,
1243                                     unix_username,
1244                                     pwd,
1245                                     &result->info3,
1246                                     &result->extra);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 goto done;
1249         }
1250
1251         result->unix_name = talloc_strdup(result, unix_username);
1252         if (result->unix_name == NULL) {
1253                 status = NT_STATUS_NO_MEMORY;
1254                 goto done;
1255         }
1256
1257         result->utok.uid = pwd->pw_uid;
1258         result->utok.gid = pwd->pw_gid;
1259
1260         *server_info = talloc_steal(mem_ctx, result);
1261         status = NT_STATUS_OK;
1262 done:
1263         talloc_free(tmp_ctx);
1264
1265         return status;
1266 }
1267
1268 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
1269                                 struct netr_SamInfo3 *info3)
1270 {
1271         const char *guest_account = lp_guest_account();
1272         struct dom_sid domain_sid;
1273         struct passwd *pwd;
1274         const char *tmp;
1275
1276         pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
1277         if (pwd == NULL) {
1278                 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
1279                          "account [%s]!\n", guest_account));
1280                 return NT_STATUS_NO_SUCH_USER;
1281         }
1282
1283         /* Set account name */
1284         tmp = talloc_strdup(mem_ctx, pwd->pw_name);
1285         if (tmp == NULL) {
1286                 return NT_STATUS_NO_MEMORY;
1287         }
1288         init_lsa_String(&info3->base.account_name, tmp);
1289
1290         /* Set domain name */
1291         tmp = talloc_strdup(mem_ctx, get_global_sam_name());
1292         if (tmp == NULL) {
1293                 return NT_STATUS_NO_MEMORY;
1294         }
1295         init_lsa_StringLarge(&info3->base.logon_domain, tmp);
1296
1297         /* Domain sid */
1298         sid_copy(&domain_sid, get_global_sam_sid());
1299
1300         info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
1301         if (info3->base.domain_sid == NULL) {
1302                 return NT_STATUS_NO_MEMORY;
1303         }
1304
1305         /* Guest rid */
1306         info3->base.rid = DOMAIN_RID_GUEST;
1307
1308         /* Primary gid */
1309         info3->base.primary_gid = DOMAIN_RID_GUESTS;
1310
1311         /* Set as guest */
1312         info3->base.user_flags = NETLOGON_GUEST;
1313
1314         TALLOC_FREE(pwd);
1315         return NT_STATUS_OK;
1316 }
1317
1318 /***************************************************************************
1319  Make (and fill) a user_info struct for a guest login.
1320  This *must* succeed for smbd to start. If there is no mapping entry for
1321  the guest gid, then create one.
1322
1323  The resulting structure is a 'session_info' because
1324  create_local_token() has already been called on it.  This is quite
1325  nasty, as the auth subsystem isn't expect this, but the behavior is
1326  left as-is for now.
1327 ***************************************************************************/
1328
1329 static NTSTATUS make_new_session_info_guest(TALLOC_CTX *mem_ctx,
1330                 struct auth_session_info **_session_info,
1331                 struct auth_serversupplied_info **_server_info)
1332 {
1333         struct auth_session_info *session_info = NULL;
1334         struct auth_serversupplied_info *server_info = NULL;
1335         const char *guest_account = lp_guest_account();
1336         const char *domain = lp_netbios_name();
1337         struct netr_SamInfo3 info3;
1338         TALLOC_CTX *tmp_ctx;
1339         NTSTATUS status;
1340
1341         tmp_ctx = talloc_stackframe();
1342         if (tmp_ctx == NULL) {
1343                 return NT_STATUS_NO_MEMORY;
1344         }
1345
1346         ZERO_STRUCT(info3);
1347
1348         status = get_guest_info3(tmp_ctx, &info3);
1349         if (!NT_STATUS_IS_OK(status)) {
1350                 DEBUG(0, ("get_guest_info3 failed with %s\n",
1351                           nt_errstr(status)));
1352                 goto done;
1353         }
1354
1355         status = make_server_info_info3(tmp_ctx,
1356                                         guest_account,
1357                                         domain,
1358                                         &server_info,
1359                                         &info3);
1360         if (!NT_STATUS_IS_OK(status)) {
1361                 DEBUG(0, ("make_server_info_info3 failed with %s\n",
1362                           nt_errstr(status)));
1363                 goto done;
1364         }
1365
1366         server_info->guest = true;
1367
1368         /* This should not be done here (we should produce a server
1369          * info, and later construct a session info from it), but for
1370          * now this does not change the previous behavior */
1371         status = create_local_token(tmp_ctx, server_info, NULL,
1372                                     server_info->info3->base.account_name.string,
1373                                     &session_info);
1374         if (!NT_STATUS_IS_OK(status)) {
1375                 DEBUG(0, ("create_local_token failed: %s\n",
1376                           nt_errstr(status)));
1377                 goto done;
1378         }
1379
1380         /* annoying, but the Guest really does have a session key, and it is
1381            all zeros! */
1382         session_info->session_key = data_blob_talloc_zero(session_info, 16);
1383
1384         *_session_info = talloc_move(mem_ctx, &session_info);
1385         *_server_info = talloc_move(mem_ctx, &server_info);
1386
1387         status = NT_STATUS_OK;
1388 done:
1389         TALLOC_FREE(tmp_ctx);
1390         return status;
1391 }
1392
1393 /***************************************************************************
1394  Make (and fill) a auth_session_info struct for a system user login.
1395  This *must* succeed for smbd to start.
1396 ***************************************************************************/
1397
1398 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
1399                                             struct auth_session_info **session_info)
1400 {
1401         TALLOC_CTX *frame = talloc_stackframe();
1402         struct auth_user_info_dc *user_info_dc = NULL;
1403         uid_t uid = -1;
1404         gid_t gid = -1;
1405         uint32_t hint_flags = 0;
1406         uint32_t session_info_flags = 0;
1407         NTSTATUS status;
1408
1409         status = auth_system_user_info_dc(frame, lp_netbios_name(),
1410                                           &user_info_dc);
1411         if (!NT_STATUS_IS_OK(status)) {
1412                 DEBUG(0, ("auth_system_user_info_dc failed: %s\n",
1413                           nt_errstr(status)));
1414                 goto done;
1415         }
1416
1417         /*
1418          * Just get the initial uid/gid
1419          * and don't expand the unix groups.
1420          */
1421         uid = sec_initial_uid();
1422         gid = sec_initial_gid();
1423         hint_flags |= AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS;
1424
1425         /*
1426          * Also avoid sid mapping to gids,
1427          * as well as adding the unix_token uid/gids as
1428          * S-1-22-X-Y SIDs to the nt token.
1429          */
1430         hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS;
1431         hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS;
1432
1433         /*
1434          * The unix name will be "NT AUTHORITY+SYSTEM",
1435          * where '+' is the "winbind separator" character.
1436          */
1437         hint_flags |= AUTH3_UNIX_HINT_QUALIFIED_NAME;
1438         status = auth3_user_info_dc_add_hints(user_info_dc,
1439                                               uid,
1440                                               gid,
1441                                               hint_flags);
1442         if (!NT_STATUS_IS_OK(status)) {
1443                 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1444                           nt_errstr(status)));
1445                 goto done;
1446         }
1447
1448         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1449         session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1450         status = auth3_session_info_create(mem_ctx, user_info_dc,
1451                                            user_info_dc->info->account_name,
1452                                            session_info_flags,
1453                                            session_info);
1454         if (!NT_STATUS_IS_OK(status)) {
1455                 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1456                           nt_errstr(status)));
1457                 goto done;
1458         }
1459
1460 done:
1461         TALLOC_FREE(frame);
1462         return status;
1463 }
1464
1465 static NTSTATUS make_new_session_info_anonymous(TALLOC_CTX *mem_ctx,
1466                                         struct auth_session_info **session_info)
1467 {
1468         TALLOC_CTX *frame = talloc_stackframe();
1469         const char *guest_account = lp_guest_account();
1470         struct auth_user_info_dc *user_info_dc = NULL;
1471         struct passwd *pwd = NULL;
1472         uint32_t hint_flags = 0;
1473         uint32_t session_info_flags = 0;
1474         NTSTATUS status;
1475
1476         /*
1477          * We use the guest account for the unix token
1478          * while we use a true anonymous nt token.
1479          *
1480          * It's very important to have a separate
1481          * nt token for anonymous.
1482          */
1483
1484         pwd = Get_Pwnam_alloc(frame, guest_account);
1485         if (pwd == NULL) {
1486                 DBG_ERR("Unable to locate guest account [%s]!\n",
1487                         guest_account);
1488                 status = NT_STATUS_NO_SUCH_USER;
1489                 goto done;
1490         }
1491
1492         status = auth_anonymous_user_info_dc(frame, lp_netbios_name(),
1493                                              &user_info_dc);
1494         if (!NT_STATUS_IS_OK(status)) {
1495                 DEBUG(0, ("auth_anonymous_user_info_dc failed: %s\n",
1496                           nt_errstr(status)));
1497                 goto done;
1498         }
1499
1500         /*
1501          * Note we don't pass AUTH3_UNIX_HINT_QUALIFIED_NAME
1502          * nor AUTH3_UNIX_HINT_ISOLATED_NAME here
1503          * as we want the unix name be found by getpwuid_alloc().
1504          */
1505
1506         status = auth3_user_info_dc_add_hints(user_info_dc,
1507                                               pwd->pw_uid,
1508                                               pwd->pw_gid,
1509                                               hint_flags);
1510         if (!NT_STATUS_IS_OK(status)) {
1511                 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1512                           nt_errstr(status)));
1513                 goto done;
1514         }
1515
1516         /*
1517          * In future we may want to remove
1518          * AUTH_SESSION_INFO_DEFAULT_GROUPS.
1519          *
1520          * Similar to Windows with EveryoneIncludesAnonymous
1521          * and RestrictAnonymous.
1522          *
1523          * We may introduce AUTH_SESSION_INFO_ANON_WORLD...
1524          *
1525          * But for this is required to keep the existing tests
1526          * working.
1527          */
1528         session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
1529         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1530         session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1531         status = auth3_session_info_create(mem_ctx, user_info_dc,
1532                                            "",
1533                                            session_info_flags,
1534                                            session_info);
1535         if (!NT_STATUS_IS_OK(status)) {
1536                 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1537                           nt_errstr(status)));
1538                 goto done;
1539         }
1540
1541 done:
1542         TALLOC_FREE(frame);
1543         return status;
1544 }
1545
1546 /****************************************************************************
1547   Fake a auth_session_info just from a username (as a
1548   session_info structure, with create_local_token() already called on
1549   it.
1550 ****************************************************************************/
1551
1552 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
1553                                          const char *username,
1554                                          bool is_guest,
1555                                          struct auth_session_info **session_info)
1556 {
1557         struct passwd *pwd;
1558         NTSTATUS status;
1559         struct auth_serversupplied_info *result;
1560         TALLOC_CTX *tmp_ctx;
1561
1562         tmp_ctx = talloc_stackframe();
1563         if (tmp_ctx == NULL) {
1564                 return NT_STATUS_NO_MEMORY;
1565         }
1566
1567         pwd = Get_Pwnam_alloc(tmp_ctx, username);
1568         if (pwd == NULL) {
1569                 status = NT_STATUS_NO_SUCH_USER;
1570                 goto done;
1571         }
1572
1573         status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
1574         if (!NT_STATUS_IS_OK(status)) {
1575                 goto done;
1576         }
1577
1578         result->nss_token = true;
1579         result->guest = is_guest;
1580
1581         /* Now turn the server_info into a session_info with the full token etc */
1582         status = create_local_token(mem_ctx,
1583                                     result,
1584                                     NULL,
1585                                     pwd->pw_name,
1586                                     session_info);
1587
1588 done:
1589         talloc_free(tmp_ctx);
1590
1591         return status;
1592 }
1593
1594 /* This function MUST only used to create the cached server_info for
1595  * guest.
1596  *
1597  * This is a lossy conversion.  Variables known to be lost so far
1598  * include:
1599  *
1600  * - nss_token (not needed because the only read doesn't happen
1601  * for the GUEST user, as this routine populates ->security_token
1602  *
1603  * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1604  *
1605  * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1606  */
1607 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1608                                                                            const struct auth_session_info *src,
1609                                                                            struct auth_serversupplied_info *server_info)
1610 {
1611         struct auth_serversupplied_info *dst;
1612         NTSTATUS status;
1613
1614         dst = make_server_info(mem_ctx);
1615         if (dst == NULL) {
1616                 return NULL;
1617         }
1618
1619         /* This element must be provided to convert back to an auth_serversupplied_info */
1620         SMB_ASSERT(src->unix_info);
1621
1622         dst->guest = true;
1623
1624         /* This element must be provided to convert back to an
1625          * auth_serversupplied_info.  This needs to be from the
1626          * auth_session_info because the group values in particular
1627          * may change during create_local_token() processing */
1628         SMB_ASSERT(src->unix_token);
1629         dst->utok.uid = src->unix_token->uid;
1630         dst->utok.gid = src->unix_token->gid;
1631         dst->utok.ngroups = src->unix_token->ngroups;
1632         if (src->unix_token->ngroups != 0) {
1633                 dst->utok.groups = (gid_t *)talloc_memdup(
1634                         dst, src->unix_token->groups,
1635                         sizeof(gid_t)*dst->utok.ngroups);
1636         } else {
1637                 dst->utok.groups = NULL;
1638         }
1639
1640         /* We must have a security_token as otherwise the lossy
1641          * conversion without nss_token would cause create_local_token
1642          * to take the wrong path */
1643         SMB_ASSERT(src->security_token);
1644
1645         dst->session_key = data_blob_talloc( dst, src->session_key.data,
1646                                                 src->session_key.length);
1647
1648         /* This is OK because this functions is only used for the
1649          * GUEST account, which has all-zero keys for both values */
1650         dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1651                                                 src->session_key.length);
1652
1653         status = copy_netr_SamInfo3(dst,
1654                                     server_info->info3,
1655                                     &dst->info3);
1656         if (!NT_STATUS_IS_OK(status)) {
1657                 TALLOC_FREE(dst);
1658                 return NULL;
1659         }
1660
1661         dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1662         if (!dst->unix_name) {
1663                 TALLOC_FREE(dst);
1664                 return NULL;
1665         }
1666
1667         dst->cached_session_info = src;
1668         return dst;
1669 }
1670
1671 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1672                                              const struct auth_session_info *src)
1673 {
1674         struct auth_session_info *dst;
1675         DATA_BLOB blob;
1676         enum ndr_err_code ndr_err;
1677
1678         ndr_err = ndr_push_struct_blob(
1679                 &blob, talloc_tos(), src,
1680                 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1681         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1682                 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1683                            "%s\n", ndr_errstr(ndr_err)));
1684                 return NULL;
1685         }
1686
1687         dst = talloc(mem_ctx, struct auth_session_info);
1688         if (dst == NULL) {
1689                 DEBUG(0, ("talloc failed\n"));
1690                 TALLOC_FREE(blob.data);
1691                 return NULL;
1692         }
1693
1694         ndr_err = ndr_pull_struct_blob(
1695                 &blob, dst, dst,
1696                 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1697         TALLOC_FREE(blob.data);
1698
1699         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1700                 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1701                            "%s\n", ndr_errstr(ndr_err)));
1702                 TALLOC_FREE(dst);
1703                 return NULL;
1704         }
1705
1706         return dst;
1707 }
1708
1709 /*
1710  * Set a new session key. Used in the rpc server where we have to override the
1711  * SMB level session key with SystemLibraryDTC
1712  */
1713
1714 bool session_info_set_session_key(struct auth_session_info *info,
1715                                  DATA_BLOB session_key)
1716 {
1717         TALLOC_FREE(info->session_key.data);
1718
1719         info->session_key = data_blob_talloc(
1720                 info, session_key.data, session_key.length);
1721
1722         return (info->session_key.data != NULL);
1723 }
1724
1725 static struct auth_session_info *guest_info = NULL;
1726 static struct auth_session_info *anonymous_info = NULL;
1727
1728 static struct auth_serversupplied_info *guest_server_info = NULL;
1729
1730 bool init_guest_session_info(TALLOC_CTX *mem_ctx)
1731 {
1732         NTSTATUS status;
1733
1734         if (guest_info != NULL)
1735                 return true;
1736
1737         status = make_new_session_info_guest(mem_ctx,
1738                                              &guest_info,
1739                                              &guest_server_info);
1740         if (!NT_STATUS_IS_OK(status)) {
1741                 return false;
1742         }
1743
1744         status = make_new_session_info_anonymous(mem_ctx,
1745                                                  &anonymous_info);
1746         if (!NT_STATUS_IS_OK(status)) {
1747                 return false;
1748         }
1749
1750         return true;
1751 }
1752
1753 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1754                                 struct auth_serversupplied_info **server_info)
1755 {
1756         /* This is trickier than it would appear to need to be because
1757          * we are trying to avoid certain costly operations when the
1758          * structure is converted to a 'auth_session_info' again in
1759          * create_local_token() */
1760         *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1761         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1762 }
1763
1764 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1765                                 struct auth_session_info **session_info)
1766 {
1767         *session_info = copy_session_info(mem_ctx, guest_info);
1768         return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1769 }
1770
1771 NTSTATUS make_server_info_anonymous(TALLOC_CTX *mem_ctx,
1772                                     struct auth_serversupplied_info **server_info)
1773 {
1774         if (anonymous_info == NULL) {
1775                 return NT_STATUS_UNSUCCESSFUL;
1776         }
1777
1778         /*
1779          * This is trickier than it would appear to need to be because
1780          * we are trying to avoid certain costly operations when the
1781          * structure is converted to a 'auth_session_info' again in
1782          * create_local_token()
1783          *
1784          * We use a guest server_info, but with the anonymous session info,
1785          * which means create_local_token() will return a copy
1786          * of the anonymous token.
1787          *
1788          * The server info is just used as legacy in order to
1789          * keep existing code working. Maybe some debug messages
1790          * will still refer to guest instead of anonymous.
1791          */
1792         *server_info = copy_session_info_serverinfo_guest(mem_ctx, anonymous_info,
1793                                                           guest_server_info);
1794         if (*server_info == NULL) {
1795                 return NT_STATUS_NO_MEMORY;
1796         }
1797
1798         return NT_STATUS_OK;
1799 }
1800
1801 NTSTATUS make_session_info_anonymous(TALLOC_CTX *mem_ctx,
1802                                      struct auth_session_info **session_info)
1803 {
1804         if (anonymous_info == NULL) {
1805                 return NT_STATUS_UNSUCCESSFUL;
1806         }
1807
1808         *session_info = copy_session_info(mem_ctx, anonymous_info);
1809         if (*session_info == NULL) {
1810                 return NT_STATUS_NO_MEMORY;
1811         }
1812
1813         return NT_STATUS_OK;
1814 }
1815
1816 static struct auth_session_info *system_info = NULL;
1817
1818 NTSTATUS init_system_session_info(TALLOC_CTX *mem_ctx)
1819 {
1820         if (system_info != NULL)
1821                 return NT_STATUS_OK;
1822
1823         return make_new_session_info_system(mem_ctx, &system_info);
1824 }
1825
1826 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1827                                 struct auth_session_info **session_info)
1828 {
1829         if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1830         *session_info = copy_session_info(mem_ctx, system_info);
1831         return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1832 }
1833
1834 const struct auth_session_info *get_session_info_system(void)
1835 {
1836     return system_info;
1837 }
1838
1839 /***************************************************************************
1840  Purely internal function for make_server_info_info3
1841 ***************************************************************************/
1842
1843 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1844                               const char *username, char **found_username,
1845                               struct passwd **pwd,
1846                               bool *username_was_mapped)
1847 {
1848         char *orig_dom_user = NULL;
1849         char *dom_user = NULL;
1850         char *lower_username = NULL;
1851         char *real_username = NULL;
1852         struct passwd *passwd;
1853
1854         lower_username = talloc_strdup(mem_ctx, username);
1855         if (!lower_username) {
1856                 return NT_STATUS_NO_MEMORY;
1857         }
1858         if (!strlower_m( lower_username )) {
1859                 return NT_STATUS_INVALID_PARAMETER;
1860         }
1861
1862         orig_dom_user = talloc_asprintf(mem_ctx,
1863                                 "%s%c%s",
1864                                 domain,
1865                                 *lp_winbind_separator(),
1866                                 lower_username);
1867         if (!orig_dom_user) {
1868                 return NT_STATUS_NO_MEMORY;
1869         }
1870
1871         /* Get the passwd struct.  Try to create the account if necessary. */
1872
1873         *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1874         if (!dom_user) {
1875                 return NT_STATUS_NO_MEMORY;
1876         }
1877
1878         passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1879         if (!passwd) {
1880                 DEBUG(3, ("Failed to find authenticated user %s via "
1881                           "getpwnam(), denying access.\n", dom_user));
1882                 return NT_STATUS_NO_SUCH_USER;
1883         }
1884
1885         if (!real_username) {
1886                 return NT_STATUS_NO_MEMORY;
1887         }
1888
1889         *pwd = passwd;
1890
1891         /* This is pointless -- there is no support for differing
1892            unix and windows names.  Make sure to always store the 
1893            one we actually looked up and succeeded. Have I mentioned
1894            why I hate the 'winbind use default domain' parameter?   
1895                                          --jerry              */
1896
1897         *found_username = talloc_strdup( mem_ctx, real_username );
1898
1899         return NT_STATUS_OK;
1900 }
1901
1902 /****************************************************************************
1903  Wrapper to allow the getpwnam() call to strip the domain name and 
1904  try again in case a local UNIX user is already there.  Also run through 
1905  the username if we fallback to the username only.
1906  ****************************************************************************/
1907
1908 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1909                              char **p_save_username, bool create )
1910 {
1911         struct passwd *pw = NULL;
1912         char *p = NULL;
1913         char *username = NULL;
1914
1915         /* we only save a copy of the username it has been mangled 
1916            by winbindd use default domain */
1917         *p_save_username = NULL;
1918
1919         /* don't call map_username() here since it has to be done higher 
1920            up the stack so we don't call it multiple times */
1921
1922         username = talloc_strdup(mem_ctx, domuser);
1923         if (!username) {
1924                 return NULL;
1925         }
1926
1927         p = strchr_m( username, *lp_winbind_separator() );
1928
1929         /* code for a DOMAIN\user string */
1930
1931         if ( p ) {
1932                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1933                 if ( pw ) {
1934                         /* make sure we get the case of the username correct */
1935                         /* work around 'winbind use default domain = yes' */
1936
1937                         if ( lp_winbind_use_default_domain() &&
1938                              !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1939                                 char *domain;
1940
1941                                 /* split the domain and username into 2 strings */
1942                                 *p = '\0';
1943                                 domain = username;
1944
1945                                 *p_save_username = talloc_asprintf(mem_ctx,
1946                                                                 "%s%c%s",
1947                                                                 domain,
1948                                                                 *lp_winbind_separator(),
1949                                                                 pw->pw_name);
1950                                 if (!*p_save_username) {
1951                                         TALLOC_FREE(pw);
1952                                         return NULL;
1953                                 }
1954                         } else {
1955                                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1956                         }
1957
1958                         /* whew -- done! */
1959                         return pw;
1960                 }
1961
1962                 /* setup for lookup of just the username */
1963                 /* remember that p and username are overlapping memory */
1964
1965                 p++;
1966                 username = talloc_strdup(mem_ctx, p);
1967                 if (!username) {
1968                         return NULL;
1969                 }
1970         }
1971
1972         /* just lookup a plain username */
1973
1974         pw = Get_Pwnam_alloc(mem_ctx, username);
1975
1976         /* Create local user if requested but only if winbindd
1977            is not running.  We need to protect against cases
1978            where winbindd is failing and then prematurely
1979            creating users in /etc/passwd */
1980
1981         if ( !pw && create && !winbind_ping() ) {
1982                 /* Don't add a machine account. */
1983                 if (username[strlen(username)-1] == '$')
1984                         return NULL;
1985
1986                 _smb_create_user(NULL, username, NULL);
1987                 pw = Get_Pwnam_alloc(mem_ctx, username);
1988         }
1989
1990         /* one last check for a valid passwd struct */
1991
1992         if (pw) {
1993                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1994         }
1995         return pw;
1996 }
1997
1998 /***************************************************************************
1999  Make a server_info struct from the info3 returned by a domain logon 
2000 ***************************************************************************/
2001
2002 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
2003                                 const char *sent_nt_username,
2004                                 const char *domain,
2005                                 struct auth_serversupplied_info **server_info,
2006                                 const struct netr_SamInfo3 *info3)
2007 {
2008         NTSTATUS nt_status = NT_STATUS_OK;
2009         char *found_username = NULL;
2010         const char *nt_domain;
2011         const char *nt_username;
2012         struct dom_sid user_sid;
2013         struct dom_sid group_sid;
2014         bool username_was_mapped;
2015         struct passwd *pwd;
2016         struct auth_serversupplied_info *result;
2017         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2018
2019         /* 
2020            Here is where we should check the list of
2021            trusted domains, and verify that the SID 
2022            matches.
2023         */
2024
2025         if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
2026                 nt_status = NT_STATUS_INVALID_PARAMETER;
2027                 goto out;
2028         }
2029
2030         if (!sid_compose(&group_sid, info3->base.domain_sid,
2031                          info3->base.primary_gid)) {
2032                 nt_status = NT_STATUS_INVALID_PARAMETER;
2033                 goto out;
2034         }
2035
2036         nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
2037         if (!nt_username) {
2038                 /* If the server didn't give us one, just use the one we sent
2039                  * them */
2040                 nt_username = sent_nt_username;
2041         }
2042
2043         nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
2044         if (!nt_domain) {
2045                 /* If the server didn't give us one, just use the one we sent
2046                  * them */
2047                 nt_domain = domain;
2048         }
2049
2050         /* If getpwnam() fails try the add user script (2.2.x behavior).
2051
2052            We use the _unmapped_ username here in an attempt to provide
2053            consistent username mapping behavior between kerberos and NTLM[SSP]
2054            authentication in domain mode security.  I.E. Username mapping
2055            should be applied to the fully qualified username
2056            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
2057            called map_username() unnecessarily in make_user_info_map() but
2058            that is how the current code is designed.  Making the change here
2059            is the least disruptive place.  -- jerry */
2060
2061         /* this call will try to create the user if necessary */
2062
2063         nt_status = check_account(tmp_ctx,
2064                                   nt_domain,
2065                                   nt_username,
2066                                   &found_username,
2067                                   &pwd,
2068                                   &username_was_mapped);
2069
2070         if (!NT_STATUS_IS_OK(nt_status)) {
2071                 /* Handle 'map to guest = Bad Uid */
2072                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
2073                     (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
2074                     lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
2075                         DBG_NOTICE("Try to map %s to guest account",
2076                                    nt_username);
2077                         nt_status = make_server_info_guest(tmp_ctx, &result);
2078                         if (NT_STATUS_IS_OK(nt_status)) {
2079                                 *server_info = talloc_move(mem_ctx, &result);
2080                         }
2081                 }
2082                 goto out;
2083         }
2084
2085         result = make_server_info(tmp_ctx);
2086         if (result == NULL) {
2087                 DEBUG(4, ("make_server_info failed!\n"));
2088                 nt_status = NT_STATUS_NO_MEMORY;
2089                 goto out;
2090         }
2091
2092         result->unix_name = talloc_strdup(result, found_username);
2093
2094         /* copy in the info3 */
2095         nt_status = copy_netr_SamInfo3(result,
2096                                        info3,
2097                                        &result->info3);
2098         if (!NT_STATUS_IS_OK(nt_status)) {
2099                 goto out;
2100         }
2101
2102         /* Fill in the unix info we found on the way */
2103
2104         result->utok.uid = pwd->pw_uid;
2105         result->utok.gid = pwd->pw_gid;
2106
2107         /* ensure we are never given NULL session keys */
2108
2109         if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
2110                 result->session_key = data_blob_null;
2111         } else {
2112                 result->session_key = data_blob_talloc(
2113                         result, info3->base.key.key,
2114                         sizeof(info3->base.key.key));
2115         }
2116
2117         if (all_zero(info3->base.LMSessKey.key,
2118                      sizeof(info3->base.LMSessKey.key))) {
2119                 result->lm_session_key = data_blob_null;
2120         } else {
2121                 result->lm_session_key = data_blob_talloc(
2122                         result, info3->base.LMSessKey.key,
2123                         sizeof(info3->base.LMSessKey.key));
2124         }
2125
2126         result->nss_token |= username_was_mapped;
2127
2128         result->guest = (info3->base.user_flags & NETLOGON_GUEST);
2129
2130         *server_info = talloc_move(mem_ctx, &result);
2131
2132         nt_status = NT_STATUS_OK;
2133 out:
2134         talloc_free(tmp_ctx);
2135
2136         return nt_status;
2137 }
2138
2139 /*****************************************************************************
2140  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
2141 ******************************************************************************/
2142
2143 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
2144                                           const char *sent_nt_username,
2145                                           const char *domain,
2146                                           const struct wbcAuthUserInfo *info,
2147                                           struct auth_serversupplied_info **server_info)
2148 {
2149         struct netr_SamInfo3 info3;
2150         struct netr_SamInfo6 *info6;
2151
2152         info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
2153         if (!info6) {
2154                 return NT_STATUS_NO_MEMORY;
2155         }
2156
2157         info3.base = info6->base;
2158         info3.sidcount = info6->sidcount;
2159         info3.sids = info6->sids;
2160
2161         return make_server_info_info3(mem_ctx,
2162                                       sent_nt_username, domain,
2163                                       server_info, &info3);
2164 }
2165
2166 /**
2167  * Verify whether or not given domain is trusted.
2168  *
2169  * This should only be used on a DC.
2170  *
2171  * @param domain_name name of the domain to be verified
2172  * @return true if domain is one of the trusted ones or
2173  *         false if otherwise
2174  **/
2175
2176 bool is_trusted_domain(const char* dom_name)
2177 {
2178         bool ret;
2179
2180         if (!IS_DC) {
2181                 return false;
2182         }
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         become_root();
2193         DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2194                   "[%s]\n", dom_name ));
2195         ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2196         unbecome_root();
2197
2198         return ret;
2199 }
2200
2201
2202
2203 /*
2204   on a logon error possibly map the error to success if "map to guest"
2205   is set approriately
2206 */
2207 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
2208                                      NTSTATUS status,
2209                                      const char *user,
2210                                      const char *domain,
2211                                      struct auth_serversupplied_info **server_info)
2212 {
2213         user = user ? user : "";
2214         domain = domain ? domain : "";
2215
2216         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2217                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
2218                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
2219                         DEBUG(3,("No such user %s [%s] - using guest account\n",
2220                                  user, domain));
2221                         return make_server_info_guest(mem_ctx, server_info);
2222                 }
2223         } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2224                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
2225                         DEBUG(3,("Registered username %s for guest access\n",
2226                                 user));
2227                         return make_server_info_guest(mem_ctx, server_info);
2228                 }
2229         }
2230
2231         return status;
2232 }
2233
2234 /*
2235   Extract session key from a session info and return it in a blob
2236   if intent is KEY_USE_16BYTES, truncate it to 16 bytes
2237
2238   See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
2239   Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
2240
2241   Note that returned session_key is referencing the original key, it is supposed to be
2242   short-lived. If original session_info->session_key is gone, the reference will be broken.
2243 */
2244 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
2245 {
2246
2247         if (session_key == NULL || session_info == NULL) {
2248                 return NT_STATUS_INVALID_PARAMETER;
2249         }
2250
2251         if (session_info->session_key.length == 0) {
2252                 return NT_STATUS_NO_USER_SESSION_KEY;
2253         }
2254
2255         *session_key = session_info->session_key;
2256         if (intent == KEY_USE_16BYTES) {
2257                 session_key->length = MIN(session_info->session_key.length, 16);
2258         }
2259         return NT_STATUS_OK;
2260 }