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