s4/script/rodcdns: str type doesn't need decoding
[Samba.git] / source3 / auth / auth_util.c
blobd0be7e6c576ed49937b9a93615bbee4326768fc1
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
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.
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.
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/>.
24 #include "includes.h"
25 #include "auth.h"
26 #include "lib/util_unixsids.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/util_pw.h"
31 #include "lib/winbind_util.h"
32 #include "passdb.h"
33 #include "../librpc/gen_ndr/ndr_auth.h"
34 #include "../auth/auth_sam_reply.h"
35 #include "../librpc/gen_ndr/idmap.h"
36 #include "lib/param/loadparm.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "rpc_client/util_netlogon.h"
39 #include "source4/auth/auth.h"
40 #include "auth/auth_util.h"
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_AUTH
45 /****************************************************************************
46 Create a UNIX user on demand.
47 ****************************************************************************/
49 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
51 TALLOC_CTX *ctx = talloc_tos();
52 char *add_script;
53 int ret;
55 add_script = lp_add_user_script(ctx);
56 if (!add_script || !*add_script) {
57 return -1;
59 add_script = talloc_all_string_sub(ctx,
60 add_script,
61 "%u",
62 unix_username);
63 if (!add_script) {
64 return -1;
66 if (domain) {
67 add_script = talloc_all_string_sub(ctx,
68 add_script,
69 "%D",
70 domain);
71 if (!add_script) {
72 return -1;
75 if (homedir) {
76 add_script = talloc_all_string_sub(ctx,
77 add_script,
78 "%H",
79 homedir);
80 if (!add_script) {
81 return -1;
84 ret = smbrun(add_script, NULL, NULL);
85 flush_pwnam_cache();
86 DEBUG(ret ? 0 : 3,
87 ("smb_create_user: Running the command `%s' gave %d\n",
88 add_script,ret));
89 return ret;
92 /****************************************************************************
93 Create an auth_usersupplied_data structure after appropriate mapping.
94 ****************************************************************************/
96 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
97 struct auth_usersupplied_info **user_info,
98 const char *smb_name,
99 const char *client_domain,
100 const char *workstation_name,
101 const struct tsocket_address *remote_address,
102 const struct tsocket_address *local_address,
103 const char *service_description,
104 const DATA_BLOB *lm_pwd,
105 const DATA_BLOB *nt_pwd,
106 const struct samr_Password *lm_interactive_pwd,
107 const struct samr_Password *nt_interactive_pwd,
108 const char *plaintext,
109 enum auth_password_state password_state)
111 const char *domain;
112 NTSTATUS result;
113 bool was_mapped;
114 char *internal_username = NULL;
116 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
117 if (!internal_username) {
118 return NT_STATUS_NO_MEMORY;
121 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
122 client_domain, smb_name, workstation_name));
125 * We let the auth stack canonicalize, username
126 * and domain.
128 domain = client_domain;
130 result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
131 client_domain, domain, workstation_name,
132 remote_address, local_address,
133 service_description, lm_pwd, nt_pwd,
134 lm_interactive_pwd, nt_interactive_pwd,
135 plaintext, password_state);
136 if (NT_STATUS_IS_OK(result)) {
137 /* We have tried mapping */
138 (*user_info)->mapped_state = true;
139 /* did we actually map the user to a different name? */
140 (*user_info)->was_mapped = was_mapped;
142 return result;
145 /****************************************************************************
146 Create an auth_usersupplied_data, making the DATA_BLOBs here.
147 Decrypt and encrypt the passwords.
148 ****************************************************************************/
150 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
151 struct auth_usersupplied_info **user_info,
152 const char *smb_name,
153 const char *client_domain,
154 const char *workstation_name,
155 const struct tsocket_address *remote_address,
156 const struct tsocket_address *local_address,
157 uint32_t logon_parameters,
158 const uchar *lm_network_pwd,
159 int lm_pwd_len,
160 const uchar *nt_network_pwd,
161 int nt_pwd_len)
163 bool ret;
164 NTSTATUS status;
165 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
166 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
168 status = make_user_info_map(mem_ctx, user_info,
169 smb_name, client_domain,
170 workstation_name,
171 remote_address,
172 local_address,
173 "SamLogon",
174 lm_pwd_len ? &lm_blob : NULL,
175 nt_pwd_len ? &nt_blob : NULL,
176 NULL, NULL, NULL,
177 AUTH_PASSWORD_RESPONSE);
179 if (NT_STATUS_IS_OK(status)) {
180 (*user_info)->logon_parameters = logon_parameters;
182 ret = NT_STATUS_IS_OK(status) ? true : false;
184 data_blob_free(&lm_blob);
185 data_blob_free(&nt_blob);
186 return ret;
189 /****************************************************************************
190 Create an auth_usersupplied_data, making the DATA_BLOBs here.
191 Decrypt and encrypt the passwords.
192 ****************************************************************************/
194 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
195 struct auth_usersupplied_info **user_info,
196 const char *smb_name,
197 const char *client_domain,
198 const char *workstation_name,
199 const struct tsocket_address *remote_address,
200 const struct tsocket_address *local_address,
201 uint32_t logon_parameters,
202 const uchar chal[8],
203 const uchar lm_interactive_pwd[16],
204 const uchar nt_interactive_pwd[16])
206 struct samr_Password lm_pwd;
207 struct samr_Password nt_pwd;
208 unsigned char local_lm_response[24];
209 unsigned char local_nt_response[24];
211 if (lm_interactive_pwd)
212 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
214 if (nt_interactive_pwd)
215 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
217 if (lm_interactive_pwd)
218 SMBOWFencrypt(lm_pwd.hash, chal,
219 local_lm_response);
221 if (nt_interactive_pwd)
222 SMBOWFencrypt(nt_pwd.hash, chal,
223 local_nt_response);
226 bool ret;
227 NTSTATUS nt_status;
228 DATA_BLOB local_lm_blob = data_blob_null;
229 DATA_BLOB local_nt_blob = data_blob_null;
231 if (lm_interactive_pwd) {
232 local_lm_blob = data_blob(local_lm_response,
233 sizeof(local_lm_response));
236 if (nt_interactive_pwd) {
237 local_nt_blob = data_blob(local_nt_response,
238 sizeof(local_nt_response));
241 nt_status = make_user_info_map(
242 mem_ctx,
243 user_info,
244 smb_name, client_domain, workstation_name,
245 remote_address,
246 local_address,
247 "SamLogon",
248 lm_interactive_pwd ? &local_lm_blob : NULL,
249 nt_interactive_pwd ? &local_nt_blob : NULL,
250 lm_interactive_pwd ? &lm_pwd : NULL,
251 nt_interactive_pwd ? &nt_pwd : NULL,
252 NULL, AUTH_PASSWORD_HASH);
254 if (NT_STATUS_IS_OK(nt_status)) {
255 (*user_info)->logon_parameters = logon_parameters;
258 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
259 data_blob_free(&local_lm_blob);
260 data_blob_free(&local_nt_blob);
261 return ret;
266 /****************************************************************************
267 Create an auth_usersupplied_data structure
268 ****************************************************************************/
270 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
271 struct auth_usersupplied_info **user_info,
272 const char *smb_name,
273 const char *client_domain,
274 const struct tsocket_address *remote_address,
275 const struct tsocket_address *local_address,
276 const char *service_description,
277 const uint8_t chal[8],
278 DATA_BLOB plaintext_password)
281 DATA_BLOB local_lm_blob;
282 DATA_BLOB local_nt_blob;
283 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
284 char *plaintext_password_string;
286 * Not encrypted - do so.
289 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
290 "format.\n"));
291 if (plaintext_password.data && plaintext_password.length) {
292 unsigned char local_lm_response[24];
294 #ifdef DEBUG_PASSWORD
295 DEBUG(10,("Unencrypted password (len %d):\n",
296 (int)plaintext_password.length));
297 dump_data(100, plaintext_password.data,
298 plaintext_password.length);
299 #endif
301 SMBencrypt( (const char *)plaintext_password.data,
302 (const uchar*)chal, local_lm_response);
303 local_lm_blob = data_blob(local_lm_response, 24);
305 /* We can't do an NT hash here, as the password needs to be
306 case insensitive */
307 local_nt_blob = data_blob_null;
308 } else {
309 local_lm_blob = data_blob_null;
310 local_nt_blob = data_blob_null;
313 plaintext_password_string = talloc_strndup(talloc_tos(),
314 (const char *)plaintext_password.data,
315 plaintext_password.length);
316 if (!plaintext_password_string) {
317 return false;
320 ret = make_user_info(mem_ctx,
321 user_info, smb_name, smb_name, client_domain, client_domain,
322 get_remote_machine_name(),
323 remote_address,
324 local_address,
325 service_description,
326 local_lm_blob.data ? &local_lm_blob : NULL,
327 local_nt_blob.data ? &local_nt_blob : NULL,
328 NULL, NULL,
329 plaintext_password_string,
330 AUTH_PASSWORD_PLAIN);
332 if (plaintext_password_string) {
333 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
334 talloc_free(plaintext_password_string);
337 data_blob_free(&local_lm_blob);
338 return NT_STATUS_IS_OK(ret) ? true : false;
341 /****************************************************************************
342 Create an auth_usersupplied_data structure
343 ****************************************************************************/
345 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
346 struct auth_usersupplied_info **user_info,
347 const char *smb_name,
348 const char *client_domain,
349 const struct tsocket_address *remote_address,
350 const struct tsocket_address *local_address,
351 const char *service_description,
352 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
354 bool allow_raw = lp_raw_ntlmv2_auth();
356 if (!allow_raw && nt_resp.length >= 48) {
358 * NTLMv2_RESPONSE has at least 48 bytes
359 * and should only be supported via NTLMSSP.
361 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
362 "user [%s\\%s] from[%s]\n",
363 client_domain, smb_name,
364 tsocket_address_string(remote_address, mem_ctx)));
365 return NT_STATUS_INVALID_PARAMETER;
368 return make_user_info(mem_ctx,
369 user_info, smb_name, smb_name,
370 client_domain, client_domain,
371 get_remote_machine_name(),
372 remote_address,
373 local_address,
374 service_description,
375 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
376 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
377 NULL, NULL, NULL,
378 AUTH_PASSWORD_RESPONSE);
381 /****************************************************************************
382 Create a guest user_info blob, for anonymous authentication.
383 ****************************************************************************/
385 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
386 const struct tsocket_address *remote_address,
387 const struct tsocket_address *local_address,
388 const char *service_description,
389 struct auth_usersupplied_info **user_info)
391 NTSTATUS nt_status;
393 nt_status = make_user_info(mem_ctx,
394 user_info,
395 "","",
396 "","",
397 "",
398 remote_address,
399 local_address,
400 service_description,
401 NULL, NULL,
402 NULL, NULL,
403 NULL,
404 AUTH_PASSWORD_RESPONSE);
406 return NT_STATUS_IS_OK(nt_status) ? true : false;
409 static NTSTATUS log_nt_token(struct security_token *token)
411 TALLOC_CTX *frame = talloc_stackframe();
412 char *command;
413 char *group_sidstr;
414 struct dom_sid_buf buf;
415 size_t i;
417 if ((lp_log_nt_token_command(frame) == NULL) ||
418 (strlen(lp_log_nt_token_command(frame)) == 0)) {
419 TALLOC_FREE(frame);
420 return NT_STATUS_OK;
423 group_sidstr = talloc_strdup(frame, "");
424 for (i=1; i<token->num_sids; i++) {
425 group_sidstr = talloc_asprintf(
426 frame, "%s %s", group_sidstr,
427 dom_sid_str_buf(&token->sids[i], &buf));
430 command = talloc_string_sub(
431 frame, lp_log_nt_token_command(frame),
432 "%s", dom_sid_str_buf(&token->sids[0], &buf));
433 command = talloc_string_sub(frame, command, "%t", group_sidstr);
435 if (command == NULL) {
436 TALLOC_FREE(frame);
437 return NT_STATUS_NO_MEMORY;
440 DEBUG(8, ("running command: [%s]\n", command));
441 if (smbrun(command, NULL, NULL) != 0) {
442 DEBUG(0, ("Could not log NT token\n"));
443 TALLOC_FREE(frame);
444 return NT_STATUS_ACCESS_DENIED;
447 TALLOC_FREE(frame);
448 return NT_STATUS_OK;
452 * Create the token to use from server_info->info3 and
453 * server_info->sids (the info3/sam groups). Find the unix gids.
456 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
457 const struct auth_serversupplied_info *server_info,
458 DATA_BLOB *session_key,
459 const char *smb_username, /* for ->sanitized_username, for %U subs */
460 struct auth_session_info **session_info_out)
462 struct security_token *t;
463 NTSTATUS status;
464 size_t i;
465 struct dom_sid tmp_sid;
466 struct auth_session_info *session_info;
467 struct unixid *ids;
468 fstring tmp;
470 /* Ensure we can't possible take a code path leading to a
471 * null defref. */
472 if (!server_info) {
473 return NT_STATUS_LOGON_FAILURE;
476 if (server_info->cached_session_info != NULL) {
477 session_info = copy_session_info(mem_ctx,
478 server_info->cached_session_info);
479 if (session_info == NULL) {
480 return NT_STATUS_NO_MEMORY;
483 /* This is a potentially untrusted username for use in %U */
484 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
485 session_info->unix_info->sanitized_username =
486 talloc_strdup(session_info->unix_info, tmp);
487 if (session_info->unix_info->sanitized_username == NULL) {
488 TALLOC_FREE(session_info);
489 return NT_STATUS_NO_MEMORY;
492 session_info->unique_session_token = GUID_random();
494 *session_info_out = session_info;
495 return NT_STATUS_OK;
498 session_info = talloc_zero(mem_ctx, struct auth_session_info);
499 if (!session_info) {
500 return NT_STATUS_NO_MEMORY;
503 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
504 if (!session_info->unix_token) {
505 TALLOC_FREE(session_info);
506 return NT_STATUS_NO_MEMORY;
509 session_info->unix_token->uid = server_info->utok.uid;
510 session_info->unix_token->gid = server_info->utok.gid;
512 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
513 if (!session_info->unix_info) {
514 TALLOC_FREE(session_info);
515 return NT_STATUS_NO_MEMORY;
518 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
519 if (!session_info->unix_info->unix_name) {
520 TALLOC_FREE(session_info);
521 return NT_STATUS_NO_MEMORY;
524 /* This is a potentially untrusted username for use in %U */
525 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
526 session_info->unix_info->sanitized_username =
527 talloc_strdup(session_info->unix_info, tmp);
529 if (session_key) {
530 data_blob_free(&session_info->session_key);
531 session_info->session_key = data_blob_talloc(session_info,
532 session_key->data,
533 session_key->length);
534 if (!session_info->session_key.data && session_key->length) {
535 return NT_STATUS_NO_MEMORY;
537 } else {
538 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
539 server_info->session_key.length);
542 /* We need to populate session_info->info with the information found in server_info->info3 */
543 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
544 server_info->guest == false,
545 &session_info->info);
546 if (!NT_STATUS_IS_OK(status)) {
547 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
548 TALLOC_FREE(session_info);
549 return status;
553 * If winbind is not around, we can not make much use of the SIDs the
554 * domain controller provided us with. Likewise if the user name was
555 * mapped to some local unix user.
558 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
559 (server_info->nss_token)) {
560 char *found_username = NULL;
561 status = create_token_from_username(session_info,
562 server_info->unix_name,
563 server_info->guest,
564 &session_info->unix_token->uid,
565 &session_info->unix_token->gid,
566 &found_username,
567 &session_info->security_token);
568 if (NT_STATUS_IS_OK(status)) {
569 session_info->unix_info->unix_name = found_username;
571 } else {
572 status = create_local_nt_token_from_info3(session_info,
573 server_info->guest,
574 server_info->info3,
575 &server_info->extra,
576 &session_info->security_token);
579 if (!NT_STATUS_IS_OK(status)) {
580 return status;
583 /* Convert the SIDs to gids. */
585 session_info->unix_token->ngroups = 0;
586 session_info->unix_token->groups = NULL;
588 t = session_info->security_token;
590 ids = talloc_array(talloc_tos(), struct unixid,
591 t->num_sids);
592 if (ids == NULL) {
593 return NT_STATUS_NO_MEMORY;
596 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
597 TALLOC_FREE(ids);
598 return NT_STATUS_NO_MEMORY;
601 for (i=0; i<t->num_sids; i++) {
603 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
604 continue;
607 if (ids[i].type != ID_TYPE_GID &&
608 ids[i].type != ID_TYPE_BOTH) {
609 struct dom_sid_buf buf;
610 DEBUG(10, ("Could not convert SID %s to gid, "
611 "ignoring it\n",
612 dom_sid_str_buf(&t->sids[i], &buf)));
613 continue;
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;
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
631 * For consistency we also add the "Unix User" SID,
632 * so that the complete unix token is represented within
633 * the nt token.
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);
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);
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);
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);
660 status = log_nt_token(session_info->security_token);
661 if (!NT_STATUS_IS_OK(status)) {
662 return status;
665 session_info->unique_session_token = GUID_random();
667 *session_info_out = session_info;
668 return NT_STATUS_OK;
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)
676 uint32_t orig_num_sids = user_info_dc->num_sids;
677 struct dom_sid tmp_sid = { 0, };
678 NTSTATUS status;
681 * We add S-5-88-1-X in order to pass the uid
682 * for the unix token.
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;
698 * We add S-5-88-2-X in order to pass the gid
699 * for the unix token.
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;
715 * We add S-5-88-3-X in order to pass some flags
716 * (AUTH3_UNIX_HINT_*) to auth3_create_session_info().
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;
731 return NT_STATUS_OK;
733 fail:
734 user_info_dc->num_sids = orig_num_sids;
735 return status;
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)
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;
762 *session_info_out = NULL;
764 if (user_info_dc->num_sids == 0) {
765 TALLOC_FREE(frame);
766 return NT_STATUS_INVALID_TOKEN;
769 if (user_info_dc->info == NULL) {
770 TALLOC_FREE(frame);
771 return NT_STATUS_INVALID_TOKEN;
774 if (user_info_dc->info->account_name == NULL) {
775 TALLOC_FREE(frame);
776 return NT_STATUS_INVALID_TOKEN;
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;
784 /* keep this under frame for easier cleanup */
785 talloc_reparent(mem_ctx, frame, session_info);
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;
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;
802 * Avoid a lot of reallocations and allocate what we'll
803 * use in most cases.
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;
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;
819 * S-1-5-88-X-Y sids are only used to give hints
820 * to the unix token construction.
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_*
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;
832 match = sid_peek_rid(&user_info_dc->sids[i], &hint);
833 if (!match) {
834 continue;
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;
844 found_hint_uid = true;
845 hint_uid = (uid_t)hint;
846 continue;
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;
856 found_hint_gid = true;
857 hint_gid = (gid_t)hint;
858 continue;
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;
868 found_hint_flags = true;
869 hint_flags = hint;
870 continue;
873 continue;
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;
887 * We need at least one usable SID
889 if (session_info->security_token->num_sids == 0) {
890 TALLOC_FREE(frame);
891 return NT_STATUS_INVALID_TOKEN;
895 * We need all tree hints: uid, gid, flags
896 * or none of them.
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;
904 if (!found_hint_gid) {
905 TALLOC_FREE(frame);
906 return NT_STATUS_INVALID_TOKEN;
909 if (!found_hint_flags) {
910 TALLOC_FREE(frame);
911 return NT_STATUS_INVALID_TOKEN;
915 if (session_info->info->authenticated) {
916 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
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;
927 * unless set otherwise, the session key is the user session
928 * key from the auth subsystem
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;
939 if (!(session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)) {
940 goto done;
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;
948 session_info->unix_token->uid = -1;
949 session_info->unix_token->gid = -1;
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;
957 /* Convert the SIDs to uid/gids. */
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;
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;
976 if (found_hint_uid) {
977 session_info->unix_token->uid = hint_uid;
978 } else if (ids[0].type == ID_TYPE_UID) {
980 * The primary SID resolves to a UID only.
982 session_info->unix_token->uid = ids[0].id;
983 } else if (ids[0].type == ID_TYPE_BOTH) {
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.
989 session_info->unix_token->uid = ids[0].id;
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;
999 } else {
1001 * It we can't get a uid, we can't imporsonate
1002 * the user.
1004 TALLOC_FREE(frame);
1005 return NT_STATUS_INVALID_TOKEN;
1008 if (found_hint_gid) {
1009 session_info->unix_token->gid = hint_gid;
1010 } else {
1011 need_getpwuid = true;
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;
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;
1033 } else {
1034 need_getpwuid = true;
1037 if (need_getpwuid) {
1038 struct passwd *pwd = NULL;
1041 * Ask the system for the primary gid
1042 * and the real unix name.
1044 pwd = getpwuid_alloc(frame, session_info->unix_token->uid);
1045 if (pwd == NULL) {
1046 TALLOC_FREE(frame);
1047 return NT_STATUS_INVALID_TOKEN;
1049 if (!found_hint_gid) {
1050 session_info->unix_token->gid = pwd->pw_gid;
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;
1060 TALLOC_FREE(pwd);
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;
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;
1081 for (i=0; i < session_info->security_token->num_sids; i++) {
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 struct dom_sid_buf buf;
1089 DEBUG(10, ("Could not convert SID %s to gid, "
1090 "ignoring it\n",
1091 dom_sid_str_buf(&nt_token->sids[i], &buf)));
1092 continue;
1095 ok = add_gid_to_array_unique(session_info->unix_token,
1096 ids[i].id,
1097 &session_info->unix_token->groups,
1098 &session_info->unix_token->ngroups);
1099 if (!ok) {
1100 TALLOC_FREE(frame);
1101 return NT_STATUS_NO_MEMORY;
1104 TALLOC_FREE(ids);
1107 * Now we must get any groups this user has been
1108 * added to in /etc/group and merge them in.
1109 * This has to be done in every code path
1110 * that creates an NT token, as remote users
1111 * may have been added to the local /etc/group
1112 * database. Tokens created merely from the
1113 * info3 structs (via the DC or via the krb5 PAC)
1114 * won't have these local groups. Note the
1115 * groups added here will only be UNIX groups
1116 * (S-1-22-2-XXXX groups) as getgroups_unix_user()
1117 * turns off winbindd before calling getgroups().
1119 * NB. This is duplicating work already
1120 * done in the 'unix_user:' case of
1121 * create_token_from_sid() but won't
1122 * do anything other than be inefficient
1123 * in that case.
1125 if (!(hint_flags & AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS)) {
1126 ok = getgroups_unix_user(frame,
1127 session_info->unix_info->unix_name,
1128 session_info->unix_token->gid,
1129 &gids, &num_gids);
1130 if (!ok) {
1131 TALLOC_FREE(frame);
1132 return NT_STATUS_INVALID_TOKEN;
1136 for (i=0; i < num_gids; i++) {
1138 ok = add_gid_to_array_unique(session_info->unix_token,
1139 gids[i],
1140 &session_info->unix_token->groups,
1141 &session_info->unix_token->ngroups);
1142 if (!ok) {
1143 TALLOC_FREE(frame);
1144 return NT_STATUS_NO_MEMORY;
1147 TALLOC_FREE(gids);
1149 if (hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS) {
1151 * We should not translate the unix token uid/gids
1152 * to S-1-22-X-Y SIDs.
1154 goto done;
1158 * Add the "Unix Group" SID for each gid to catch mapped groups
1159 * and their Unix equivalent. This is to solve the backwards
1160 * compatibility problem of 'valid users = +ntadmin' where
1161 * ntadmin has been paired with "Domain Admins" in the group
1162 * mapping table. Otherwise smb.conf would need to be changed
1163 * to 'valid user = "Domain Admins"'. --jerry
1165 * For consistency we also add the "Unix User" SID,
1166 * so that the complete unix token is represented within
1167 * the nt token.
1170 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
1171 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1172 &session_info->security_token->sids,
1173 &session_info->security_token->num_sids);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 TALLOC_FREE(frame);
1176 return status;
1179 gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
1180 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1181 &session_info->security_token->sids,
1182 &session_info->security_token->num_sids);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 TALLOC_FREE(frame);
1185 return status;
1188 for (i=0; i < session_info->unix_token->ngroups; i++ ) {
1189 struct security_token *nt_token = session_info->security_token;
1191 gid_to_unix_groups_sid(session_info->unix_token->groups[i],
1192 &tmp_sid);
1193 status = add_sid_to_array_unique(nt_token->sids,
1194 &tmp_sid,
1195 &nt_token->sids,
1196 &nt_token->num_sids);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 TALLOC_FREE(frame);
1199 return status;
1203 done:
1204 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
1205 if (session_info->unix_token != NULL) {
1206 debug_unix_user_token(DBGC_AUTH, 10,
1207 session_info->unix_token->uid,
1208 session_info->unix_token->gid,
1209 session_info->unix_token->ngroups,
1210 session_info->unix_token->groups);
1213 status = log_nt_token(session_info->security_token);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 TALLOC_FREE(frame);
1216 return status;
1219 session_info->unique_session_token = GUID_random();
1221 *session_info_out = talloc_move(mem_ctx, &session_info);
1222 TALLOC_FREE(frame);
1223 return NT_STATUS_OK;
1226 /***************************************************************************
1227 Make (and fill) a server_info struct from a 'struct passwd' by conversion
1228 to a struct samu
1229 ***************************************************************************/
1231 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
1232 const char *unix_username,
1233 const struct passwd *pwd,
1234 struct auth_serversupplied_info **server_info)
1236 NTSTATUS status;
1237 TALLOC_CTX *tmp_ctx = NULL;
1238 struct auth_serversupplied_info *result;
1240 tmp_ctx = talloc_stackframe();
1241 if (tmp_ctx == NULL) {
1242 return NT_STATUS_NO_MEMORY;
1245 result = make_server_info(tmp_ctx);
1246 if (result == NULL) {
1247 status = NT_STATUS_NO_MEMORY;
1248 goto done;
1251 status = passwd_to_SamInfo3(result,
1252 unix_username,
1253 pwd,
1254 &result->info3,
1255 &result->extra);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 goto done;
1260 result->unix_name = talloc_strdup(result, unix_username);
1261 if (result->unix_name == NULL) {
1262 status = NT_STATUS_NO_MEMORY;
1263 goto done;
1266 result->utok.uid = pwd->pw_uid;
1267 result->utok.gid = pwd->pw_gid;
1269 *server_info = talloc_steal(mem_ctx, result);
1270 status = NT_STATUS_OK;
1271 done:
1272 talloc_free(tmp_ctx);
1274 return status;
1277 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
1278 struct netr_SamInfo3 *info3)
1280 const char *guest_account = lp_guest_account();
1281 struct dom_sid domain_sid;
1282 struct passwd *pwd;
1283 const char *tmp;
1285 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
1286 if (pwd == NULL) {
1287 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
1288 "account [%s]!\n", guest_account));
1289 return NT_STATUS_NO_SUCH_USER;
1292 /* Set account name */
1293 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
1294 if (tmp == NULL) {
1295 return NT_STATUS_NO_MEMORY;
1297 init_lsa_String(&info3->base.account_name, tmp);
1299 /* Set domain name */
1300 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
1301 if (tmp == NULL) {
1302 return NT_STATUS_NO_MEMORY;
1304 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
1306 /* Domain sid */
1307 sid_copy(&domain_sid, get_global_sam_sid());
1309 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
1310 if (info3->base.domain_sid == NULL) {
1311 return NT_STATUS_NO_MEMORY;
1314 /* Guest rid */
1315 info3->base.rid = DOMAIN_RID_GUEST;
1317 /* Primary gid */
1318 info3->base.primary_gid = DOMAIN_RID_GUESTS;
1320 /* Set as guest */
1321 info3->base.user_flags = NETLOGON_GUEST;
1323 TALLOC_FREE(pwd);
1324 return NT_STATUS_OK;
1327 /***************************************************************************
1328 Make (and fill) a user_info struct for a guest login.
1329 This *must* succeed for smbd to start. If there is no mapping entry for
1330 the guest gid, then create one.
1332 The resulting structure is a 'session_info' because
1333 create_local_token() has already been called on it. This is quite
1334 nasty, as the auth subsystem isn't expect this, but the behavior is
1335 left as-is for now.
1336 ***************************************************************************/
1338 static NTSTATUS make_new_session_info_guest(TALLOC_CTX *mem_ctx,
1339 struct auth_session_info **_session_info,
1340 struct auth_serversupplied_info **_server_info)
1342 struct auth_session_info *session_info = NULL;
1343 struct auth_serversupplied_info *server_info = NULL;
1344 const char *guest_account = lp_guest_account();
1345 const char *domain = lp_netbios_name();
1346 struct netr_SamInfo3 info3;
1347 TALLOC_CTX *tmp_ctx;
1348 NTSTATUS status;
1350 tmp_ctx = talloc_stackframe();
1351 if (tmp_ctx == NULL) {
1352 return NT_STATUS_NO_MEMORY;
1355 ZERO_STRUCT(info3);
1357 status = get_guest_info3(tmp_ctx, &info3);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 DEBUG(0, ("get_guest_info3 failed with %s\n",
1360 nt_errstr(status)));
1361 goto done;
1364 status = make_server_info_info3(tmp_ctx,
1365 guest_account,
1366 domain,
1367 &server_info,
1368 &info3);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 DEBUG(0, ("make_server_info_info3 failed with %s\n",
1371 nt_errstr(status)));
1372 goto done;
1375 server_info->guest = true;
1377 /* This should not be done here (we should produce a server
1378 * info, and later construct a session info from it), but for
1379 * now this does not change the previous behavior */
1380 status = create_local_token(tmp_ctx, server_info, NULL,
1381 server_info->info3->base.account_name.string,
1382 &session_info);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 DEBUG(0, ("create_local_token failed: %s\n",
1385 nt_errstr(status)));
1386 goto done;
1390 * It's ugly, but for now it's
1391 * needed to force Builtin_Guests
1392 * here, because memberships of
1393 * Builtin_Guests might be incomplete.
1395 status = add_sid_to_array_unique(session_info->security_token,
1396 &global_sid_Builtin_Guests,
1397 &session_info->security_token->sids,
1398 &session_info->security_token->num_sids);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 DBG_ERR("Failed to force Builtin_Guests to nt token\n");
1401 goto done;
1404 /* annoying, but the Guest really does have a session key, and it is
1405 all zeros! */
1406 session_info->session_key = data_blob_talloc_zero(session_info, 16);
1408 *_session_info = talloc_move(mem_ctx, &session_info);
1409 *_server_info = talloc_move(mem_ctx, &server_info);
1411 status = NT_STATUS_OK;
1412 done:
1413 TALLOC_FREE(tmp_ctx);
1414 return status;
1417 /***************************************************************************
1418 Make (and fill) a auth_session_info struct for a system user login.
1419 This *must* succeed for smbd to start.
1420 ***************************************************************************/
1422 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
1423 struct auth_session_info **session_info)
1425 TALLOC_CTX *frame = talloc_stackframe();
1426 struct auth_user_info_dc *user_info_dc = NULL;
1427 uid_t uid = -1;
1428 gid_t gid = -1;
1429 uint32_t hint_flags = 0;
1430 uint32_t session_info_flags = 0;
1431 NTSTATUS status;
1433 status = auth_system_user_info_dc(frame, lp_netbios_name(),
1434 &user_info_dc);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 DEBUG(0, ("auth_system_user_info_dc failed: %s\n",
1437 nt_errstr(status)));
1438 goto done;
1442 * Just get the initial uid/gid
1443 * and don't expand the unix groups.
1445 uid = sec_initial_uid();
1446 gid = sec_initial_gid();
1447 hint_flags |= AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS;
1450 * Also avoid sid mapping to gids,
1451 * as well as adding the unix_token uid/gids as
1452 * S-1-22-X-Y SIDs to the nt token.
1454 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS;
1455 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS;
1458 * The unix name will be "NT AUTHORITY+SYSTEM",
1459 * where '+' is the "winbind separator" character.
1461 hint_flags |= AUTH3_UNIX_HINT_QUALIFIED_NAME;
1462 status = auth3_user_info_dc_add_hints(user_info_dc,
1463 uid,
1464 gid,
1465 hint_flags);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1468 nt_errstr(status)));
1469 goto done;
1472 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1473 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1474 status = auth3_session_info_create(mem_ctx, user_info_dc,
1475 user_info_dc->info->account_name,
1476 session_info_flags,
1477 session_info);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1480 nt_errstr(status)));
1481 goto done;
1484 done:
1485 TALLOC_FREE(frame);
1486 return status;
1489 static NTSTATUS make_new_session_info_anonymous(TALLOC_CTX *mem_ctx,
1490 struct auth_session_info **session_info)
1492 TALLOC_CTX *frame = talloc_stackframe();
1493 const char *guest_account = lp_guest_account();
1494 struct auth_user_info_dc *user_info_dc = NULL;
1495 struct passwd *pwd = NULL;
1496 uint32_t hint_flags = 0;
1497 uint32_t session_info_flags = 0;
1498 NTSTATUS status;
1501 * We use the guest account for the unix token
1502 * while we use a true anonymous nt token.
1504 * It's very important to have a separate
1505 * nt token for anonymous.
1508 pwd = Get_Pwnam_alloc(frame, guest_account);
1509 if (pwd == NULL) {
1510 DBG_ERR("Unable to locate guest account [%s]!\n",
1511 guest_account);
1512 status = NT_STATUS_NO_SUCH_USER;
1513 goto done;
1516 status = auth_anonymous_user_info_dc(frame, lp_netbios_name(),
1517 &user_info_dc);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 DEBUG(0, ("auth_anonymous_user_info_dc failed: %s\n",
1520 nt_errstr(status)));
1521 goto done;
1525 * Note we don't pass AUTH3_UNIX_HINT_QUALIFIED_NAME
1526 * nor AUTH3_UNIX_HINT_ISOLATED_NAME here
1527 * as we want the unix name be found by getpwuid_alloc().
1530 status = auth3_user_info_dc_add_hints(user_info_dc,
1531 pwd->pw_uid,
1532 pwd->pw_gid,
1533 hint_flags);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1536 nt_errstr(status)));
1537 goto done;
1541 * In future we may want to remove
1542 * AUTH_SESSION_INFO_DEFAULT_GROUPS.
1544 * Similar to Windows with EveryoneIncludesAnonymous
1545 * and RestrictAnonymous.
1547 * We may introduce AUTH_SESSION_INFO_ANON_WORLD...
1549 * But for this is required to keep the existing tests
1550 * working.
1552 session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
1553 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1554 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1555 status = auth3_session_info_create(mem_ctx, user_info_dc,
1557 session_info_flags,
1558 session_info);
1559 if (!NT_STATUS_IS_OK(status)) {
1560 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1561 nt_errstr(status)));
1562 goto done;
1565 done:
1566 TALLOC_FREE(frame);
1567 return status;
1570 /****************************************************************************
1571 Fake a auth_session_info just from a username (as a
1572 session_info structure, with create_local_token() already called on
1574 ****************************************************************************/
1576 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
1577 const char *username,
1578 bool is_guest,
1579 struct auth_session_info **session_info)
1581 struct passwd *pwd;
1582 NTSTATUS status;
1583 struct auth_serversupplied_info *result;
1584 TALLOC_CTX *tmp_ctx;
1586 tmp_ctx = talloc_stackframe();
1587 if (tmp_ctx == NULL) {
1588 return NT_STATUS_NO_MEMORY;
1591 pwd = Get_Pwnam_alloc(tmp_ctx, username);
1592 if (pwd == NULL) {
1593 status = NT_STATUS_NO_SUCH_USER;
1594 goto done;
1597 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 goto done;
1602 result->nss_token = true;
1603 result->guest = is_guest;
1605 /* Now turn the server_info into a session_info with the full token etc */
1606 status = create_local_token(mem_ctx,
1607 result,
1608 NULL,
1609 pwd->pw_name,
1610 session_info);
1612 done:
1613 talloc_free(tmp_ctx);
1615 return status;
1618 /* This function MUST only used to create the cached server_info for
1619 * guest.
1621 * This is a lossy conversion. Variables known to be lost so far
1622 * include:
1624 * - nss_token (not needed because the only read doesn't happen
1625 * for the GUEST user, as this routine populates ->security_token
1627 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1629 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1631 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1632 const struct auth_session_info *src,
1633 struct auth_serversupplied_info *server_info)
1635 struct auth_serversupplied_info *dst;
1636 NTSTATUS status;
1638 dst = make_server_info(mem_ctx);
1639 if (dst == NULL) {
1640 return NULL;
1643 /* This element must be provided to convert back to an auth_serversupplied_info */
1644 SMB_ASSERT(src->unix_info);
1646 dst->guest = true;
1648 /* This element must be provided to convert back to an
1649 * auth_serversupplied_info. This needs to be from the
1650 * auth_session_info because the group values in particular
1651 * may change during create_local_token() processing */
1652 SMB_ASSERT(src->unix_token);
1653 dst->utok.uid = src->unix_token->uid;
1654 dst->utok.gid = src->unix_token->gid;
1655 dst->utok.ngroups = src->unix_token->ngroups;
1656 if (src->unix_token->ngroups != 0) {
1657 dst->utok.groups = (gid_t *)talloc_memdup(
1658 dst, src->unix_token->groups,
1659 sizeof(gid_t)*dst->utok.ngroups);
1660 } else {
1661 dst->utok.groups = NULL;
1664 /* We must have a security_token as otherwise the lossy
1665 * conversion without nss_token would cause create_local_token
1666 * to take the wrong path */
1667 SMB_ASSERT(src->security_token);
1669 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1670 src->session_key.length);
1672 /* This is OK because this functions is only used for the
1673 * GUEST account, which has all-zero keys for both values */
1674 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1675 src->session_key.length);
1677 status = copy_netr_SamInfo3(dst,
1678 server_info->info3,
1679 &dst->info3);
1680 if (!NT_STATUS_IS_OK(status)) {
1681 TALLOC_FREE(dst);
1682 return NULL;
1685 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1686 if (!dst->unix_name) {
1687 TALLOC_FREE(dst);
1688 return NULL;
1691 dst->cached_session_info = src;
1692 return dst;
1696 * Set a new session key. Used in the rpc server where we have to override the
1697 * SMB level session key with SystemLibraryDTC
1700 bool session_info_set_session_key(struct auth_session_info *info,
1701 DATA_BLOB session_key)
1703 TALLOC_FREE(info->session_key.data);
1705 info->session_key = data_blob_talloc(
1706 info, session_key.data, session_key.length);
1708 return (info->session_key.data != NULL);
1711 static struct auth_session_info *guest_info = NULL;
1712 static struct auth_session_info *anonymous_info = NULL;
1714 static struct auth_serversupplied_info *guest_server_info = NULL;
1716 bool init_guest_session_info(TALLOC_CTX *mem_ctx)
1718 NTSTATUS status;
1720 if (guest_info != NULL)
1721 return true;
1723 status = make_new_session_info_guest(mem_ctx,
1724 &guest_info,
1725 &guest_server_info);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 return false;
1730 status = make_new_session_info_anonymous(mem_ctx,
1731 &anonymous_info);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 return false;
1736 return true;
1739 bool reinit_guest_session_info(TALLOC_CTX *mem_ctx)
1741 TALLOC_FREE(guest_info);
1742 TALLOC_FREE(guest_server_info);
1743 TALLOC_FREE(anonymous_info);
1745 DBG_DEBUG("Reinitialing guest info\n");
1747 return init_guest_session_info(mem_ctx);
1750 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1751 struct auth_serversupplied_info **server_info)
1753 /* This is trickier than it would appear to need to be because
1754 * we are trying to avoid certain costly operations when the
1755 * structure is converted to a 'auth_session_info' again in
1756 * create_local_token() */
1757 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1758 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1761 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1762 struct auth_session_info **session_info)
1764 *session_info = copy_session_info(mem_ctx, guest_info);
1765 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1768 NTSTATUS make_server_info_anonymous(TALLOC_CTX *mem_ctx,
1769 struct auth_serversupplied_info **server_info)
1771 if (anonymous_info == NULL) {
1772 return NT_STATUS_UNSUCCESSFUL;
1776 * This is trickier than it would appear to need to be because
1777 * we are trying to avoid certain costly operations when the
1778 * structure is converted to a 'auth_session_info' again in
1779 * create_local_token()
1781 * We use a guest server_info, but with the anonymous session info,
1782 * which means create_local_token() will return a copy
1783 * of the anonymous token.
1785 * The server info is just used as legacy in order to
1786 * keep existing code working. Maybe some debug messages
1787 * will still refer to guest instead of anonymous.
1789 *server_info = copy_session_info_serverinfo_guest(mem_ctx, anonymous_info,
1790 guest_server_info);
1791 if (*server_info == NULL) {
1792 return NT_STATUS_NO_MEMORY;
1795 return NT_STATUS_OK;
1798 NTSTATUS make_session_info_anonymous(TALLOC_CTX *mem_ctx,
1799 struct auth_session_info **session_info)
1801 if (anonymous_info == NULL) {
1802 return NT_STATUS_UNSUCCESSFUL;
1805 *session_info = copy_session_info(mem_ctx, anonymous_info);
1806 if (*session_info == NULL) {
1807 return NT_STATUS_NO_MEMORY;
1810 return NT_STATUS_OK;
1813 static struct auth_session_info *system_info = NULL;
1815 NTSTATUS init_system_session_info(TALLOC_CTX *mem_ctx)
1817 if (system_info != NULL)
1818 return NT_STATUS_OK;
1820 return make_new_session_info_system(mem_ctx, &system_info);
1823 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1824 struct auth_session_info **session_info)
1826 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1827 *session_info = copy_session_info(mem_ctx, system_info);
1828 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1831 const struct auth_session_info *get_session_info_system(void)
1833 return system_info;
1836 /***************************************************************************
1837 Purely internal function for make_server_info_info3
1838 ***************************************************************************/
1840 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1841 const char *username, char **found_username,
1842 struct passwd **pwd,
1843 bool *username_was_mapped)
1845 char *orig_dom_user = NULL;
1846 char *dom_user = NULL;
1847 char *lower_username = NULL;
1848 char *real_username = NULL;
1849 struct passwd *passwd;
1851 lower_username = talloc_strdup(mem_ctx, username);
1852 if (!lower_username) {
1853 return NT_STATUS_NO_MEMORY;
1855 if (!strlower_m( lower_username )) {
1856 return NT_STATUS_INVALID_PARAMETER;
1859 orig_dom_user = talloc_asprintf(mem_ctx,
1860 "%s%c%s",
1861 domain,
1862 *lp_winbind_separator(),
1863 lower_username);
1864 if (!orig_dom_user) {
1865 return NT_STATUS_NO_MEMORY;
1868 /* Get the passwd struct. Try to create the account if necessary. */
1870 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1871 if (!dom_user) {
1872 return NT_STATUS_NO_MEMORY;
1875 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1876 if (!passwd) {
1877 DEBUG(3, ("Failed to find authenticated user %s via "
1878 "getpwnam(), denying access.\n", dom_user));
1879 return NT_STATUS_NO_SUCH_USER;
1882 if (!real_username) {
1883 return NT_STATUS_NO_MEMORY;
1886 *pwd = passwd;
1888 /* This is pointless -- there is no support for differing
1889 unix and windows names. Make sure to always store the
1890 one we actually looked up and succeeded. Have I mentioned
1891 why I hate the 'winbind use default domain' parameter?
1892 --jerry */
1894 *found_username = talloc_strdup( mem_ctx, real_username );
1896 return NT_STATUS_OK;
1899 /****************************************************************************
1900 Wrapper to allow the getpwnam() call to strip the domain name and
1901 try again in case a local UNIX user is already there. Also run through
1902 the username if we fallback to the username only.
1903 ****************************************************************************/
1905 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1906 char **p_save_username, bool create )
1908 struct passwd *pw = NULL;
1909 char *p = NULL;
1910 char *username = NULL;
1912 /* we only save a copy of the username it has been mangled
1913 by winbindd use default domain */
1914 *p_save_username = NULL;
1916 /* don't call map_username() here since it has to be done higher
1917 up the stack so we don't call it multiple times */
1919 username = talloc_strdup(mem_ctx, domuser);
1920 if (!username) {
1921 return NULL;
1924 p = strchr_m( username, *lp_winbind_separator() );
1926 /* code for a DOMAIN\user string */
1928 if ( p ) {
1929 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1930 if ( pw ) {
1931 /* make sure we get the case of the username correct */
1932 /* work around 'winbind use default domain = yes' */
1934 if ( lp_winbind_use_default_domain() &&
1935 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1936 char *domain;
1938 /* split the domain and username into 2 strings */
1939 *p = '\0';
1940 domain = username;
1942 *p_save_username = talloc_asprintf(mem_ctx,
1943 "%s%c%s",
1944 domain,
1945 *lp_winbind_separator(),
1946 pw->pw_name);
1947 if (!*p_save_username) {
1948 TALLOC_FREE(pw);
1949 return NULL;
1951 } else {
1952 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1955 /* whew -- done! */
1956 return pw;
1959 /* setup for lookup of just the username */
1960 /* remember that p and username are overlapping memory */
1962 p++;
1963 username = talloc_strdup(mem_ctx, p);
1964 if (!username) {
1965 return NULL;
1969 /* just lookup a plain username */
1971 pw = Get_Pwnam_alloc(mem_ctx, username);
1973 /* Create local user if requested but only if winbindd
1974 is not running. We need to protect against cases
1975 where winbindd is failing and then prematurely
1976 creating users in /etc/passwd */
1978 if ( !pw && create && !winbind_ping() ) {
1979 /* Don't add a machine account. */
1980 if (username[strlen(username)-1] == '$')
1981 return NULL;
1983 _smb_create_user(NULL, username, NULL);
1984 pw = Get_Pwnam_alloc(mem_ctx, username);
1987 /* one last check for a valid passwd struct */
1989 if (pw) {
1990 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1992 return pw;
1995 /***************************************************************************
1996 Make a server_info struct from the info3 returned by a domain logon
1997 ***************************************************************************/
1999 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
2000 const char *sent_nt_username,
2001 const char *domain,
2002 struct auth_serversupplied_info **server_info,
2003 const struct netr_SamInfo3 *info3)
2005 NTSTATUS nt_status = NT_STATUS_OK;
2006 char *found_username = NULL;
2007 const char *nt_domain;
2008 const char *nt_username;
2009 struct dom_sid user_sid;
2010 struct dom_sid group_sid;
2011 bool username_was_mapped;
2012 struct passwd *pwd;
2013 struct auth_serversupplied_info *result;
2014 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2017 Here is where we should check the list of
2018 trusted domains, and verify that the SID
2019 matches.
2022 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
2023 nt_status = NT_STATUS_INVALID_PARAMETER;
2024 goto out;
2027 if (!sid_compose(&group_sid, info3->base.domain_sid,
2028 info3->base.primary_gid)) {
2029 nt_status = NT_STATUS_INVALID_PARAMETER;
2030 goto out;
2033 nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
2034 if (!nt_username) {
2035 /* If the server didn't give us one, just use the one we sent
2036 * them */
2037 nt_username = sent_nt_username;
2040 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
2041 if (!nt_domain) {
2042 /* If the server didn't give us one, just use the one we sent
2043 * them */
2044 nt_domain = domain;
2047 /* If getpwnam() fails try the add user script (2.2.x behavior).
2049 We use the _unmapped_ username here in an attempt to provide
2050 consistent username mapping behavior between kerberos and NTLM[SSP]
2051 authentication in domain mode security. I.E. Username mapping
2052 should be applied to the fully qualified username
2053 (e.g. DOMAIN\user) and not just the login name. Yes this means we
2054 called map_username() unnecessarily in make_user_info_map() but
2055 that is how the current code is designed. Making the change here
2056 is the least disruptive place. -- jerry */
2058 /* this call will try to create the user if necessary */
2060 nt_status = check_account(tmp_ctx,
2061 nt_domain,
2062 nt_username,
2063 &found_username,
2064 &pwd,
2065 &username_was_mapped);
2067 if (!NT_STATUS_IS_OK(nt_status)) {
2068 /* Handle 'map to guest = Bad Uid */
2069 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
2070 (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
2071 lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
2072 DBG_NOTICE("Try to map %s to guest account",
2073 nt_username);
2074 nt_status = make_server_info_guest(tmp_ctx, &result);
2075 if (NT_STATUS_IS_OK(nt_status)) {
2076 *server_info = talloc_move(mem_ctx, &result);
2079 goto out;
2082 result = make_server_info(tmp_ctx);
2083 if (result == NULL) {
2084 DEBUG(4, ("make_server_info failed!\n"));
2085 nt_status = NT_STATUS_NO_MEMORY;
2086 goto out;
2089 result->unix_name = talloc_strdup(result, found_username);
2091 /* copy in the info3 */
2092 nt_status = copy_netr_SamInfo3(result,
2093 info3,
2094 &result->info3);
2095 if (!NT_STATUS_IS_OK(nt_status)) {
2096 goto out;
2099 /* Fill in the unix info we found on the way */
2101 result->utok.uid = pwd->pw_uid;
2102 result->utok.gid = pwd->pw_gid;
2104 /* ensure we are never given NULL session keys */
2106 if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
2107 result->session_key = data_blob_null;
2108 } else {
2109 result->session_key = data_blob_talloc(
2110 result, info3->base.key.key,
2111 sizeof(info3->base.key.key));
2114 if (all_zero(info3->base.LMSessKey.key,
2115 sizeof(info3->base.LMSessKey.key))) {
2116 result->lm_session_key = data_blob_null;
2117 } else {
2118 result->lm_session_key = data_blob_talloc(
2119 result, info3->base.LMSessKey.key,
2120 sizeof(info3->base.LMSessKey.key));
2123 result->nss_token |= username_was_mapped;
2125 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
2127 *server_info = talloc_move(mem_ctx, &result);
2129 nt_status = NT_STATUS_OK;
2130 out:
2131 talloc_free(tmp_ctx);
2133 return nt_status;
2136 /*****************************************************************************
2137 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
2138 ******************************************************************************/
2140 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
2141 const char *sent_nt_username,
2142 const char *domain,
2143 const struct wbcAuthUserInfo *info,
2144 struct auth_serversupplied_info **server_info)
2146 struct netr_SamInfo3 info3;
2147 struct netr_SamInfo6 *info6;
2149 info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
2150 if (!info6) {
2151 return NT_STATUS_NO_MEMORY;
2154 info3.base = info6->base;
2155 info3.sidcount = info6->sidcount;
2156 info3.sids = info6->sids;
2158 return make_server_info_info3(mem_ctx,
2159 sent_nt_username, domain,
2160 server_info, &info3);
2164 * Verify whether or not given domain is trusted.
2166 * This should only be used on a DC.
2168 * @param domain_name name of the domain to be verified
2169 * @return true if domain is one of the trusted ones or
2170 * false if otherwise
2173 bool is_trusted_domain(const char* dom_name)
2175 bool ret;
2177 if (!IS_DC) {
2178 return false;
2181 if (dom_name == NULL || dom_name[0] == '\0') {
2182 return false;
2185 if (strequal(dom_name, get_global_sam_name())) {
2186 return false;
2189 become_root();
2190 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2191 "[%s]\n", dom_name ));
2192 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2193 unbecome_root();
2195 return ret;
2201 on a logon error possibly map the error to success if "map to guest"
2202 is set approriately
2204 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
2205 NTSTATUS status,
2206 const char *user,
2207 const char *domain,
2208 struct auth_serversupplied_info **server_info)
2210 user = user ? user : "";
2211 domain = domain ? domain : "";
2213 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2214 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
2215 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
2216 DEBUG(3,("No such user %s [%s] - using guest account\n",
2217 user, domain));
2218 return make_server_info_guest(mem_ctx, server_info);
2220 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2221 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
2222 DEBUG(3,("Registered username %s for guest access\n",
2223 user));
2224 return make_server_info_guest(mem_ctx, server_info);
2228 return status;
2232 Extract session key from a session info and return it in a blob
2233 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
2235 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
2236 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
2238 Note that returned session_key is referencing the original key, it is supposed to be
2239 short-lived. If original session_info->session_key is gone, the reference will be broken.
2241 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
2244 if (session_key == NULL || session_info == NULL) {
2245 return NT_STATUS_INVALID_PARAMETER;
2248 if (session_info->session_key.length == 0) {
2249 return NT_STATUS_NO_USER_SESSION_KEY;
2252 *session_key = session_info->session_key;
2253 if (intent == KEY_USE_16BYTES) {
2254 session_key->length = MIN(session_info->session_key.length, 16);
2256 return NT_STATUS_OK;