auth3: Fix a few error path memleaks in create_local_token()
[Samba.git] / source3 / auth / auth_util.c
blob5a959bf1da8bfe08ee60930dd8a893619f4ee978
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 const struct loadparm_substitution *lp_sub =
53 loadparm_s3_global_substitution();
54 char *add_script;
55 int ret;
57 add_script = lp_add_user_script(ctx, lp_sub);
58 if (!add_script || !*add_script) {
59 return -1;
61 add_script = talloc_all_string_sub(ctx,
62 add_script,
63 "%u",
64 unix_username);
65 if (!add_script) {
66 return -1;
68 if (domain) {
69 add_script = talloc_all_string_sub(ctx,
70 add_script,
71 "%D",
72 domain);
73 if (!add_script) {
74 return -1;
77 if (homedir) {
78 add_script = talloc_all_string_sub(ctx,
79 add_script,
80 "%H",
81 homedir);
82 if (!add_script) {
83 return -1;
86 ret = smbrun(add_script, NULL, NULL);
87 flush_pwnam_cache();
88 DEBUG(ret ? 0 : 3,
89 ("smb_create_user: Running the command `%s' gave %d\n",
90 add_script,ret));
91 return ret;
94 /****************************************************************************
95 Create an auth_usersupplied_data structure after appropriate mapping.
96 ****************************************************************************/
98 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
99 struct auth_usersupplied_info **user_info,
100 const char *smb_name,
101 const char *client_domain,
102 const char *workstation_name,
103 const struct tsocket_address *remote_address,
104 const struct tsocket_address *local_address,
105 const char *service_description,
106 const DATA_BLOB *lm_pwd,
107 const DATA_BLOB *nt_pwd,
108 const struct samr_Password *lm_interactive_pwd,
109 const struct samr_Password *nt_interactive_pwd,
110 const char *plaintext,
111 enum auth_password_state password_state)
113 const char *domain;
114 NTSTATUS result;
115 bool was_mapped;
116 char *internal_username = NULL;
118 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
119 if (!internal_username) {
120 return NT_STATUS_NO_MEMORY;
123 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
124 client_domain, smb_name, workstation_name));
127 * We let the auth stack canonicalize, username
128 * and domain.
130 domain = client_domain;
132 result = make_user_info(mem_ctx, user_info, smb_name, internal_username,
133 client_domain, domain, workstation_name,
134 remote_address, local_address,
135 service_description, lm_pwd, nt_pwd,
136 lm_interactive_pwd, nt_interactive_pwd,
137 plaintext, password_state);
138 if (NT_STATUS_IS_OK(result)) {
139 /* We have tried mapping */
140 (*user_info)->mapped_state = true;
141 /* did we actually map the user to a different name? */
142 (*user_info)->was_mapped = was_mapped;
144 return result;
147 /****************************************************************************
148 Create an auth_usersupplied_data, making the DATA_BLOBs here.
149 Decrypt and encrypt the passwords.
150 ****************************************************************************/
152 bool make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
153 struct auth_usersupplied_info **user_info,
154 const char *smb_name,
155 const char *client_domain,
156 const char *workstation_name,
157 const struct tsocket_address *remote_address,
158 const struct tsocket_address *local_address,
159 uint32_t logon_parameters,
160 const uchar *lm_network_pwd,
161 int lm_pwd_len,
162 const uchar *nt_network_pwd,
163 int nt_pwd_len)
165 bool ret;
166 NTSTATUS status;
167 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
168 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
170 status = make_user_info_map(mem_ctx, user_info,
171 smb_name, client_domain,
172 workstation_name,
173 remote_address,
174 local_address,
175 "SamLogon",
176 lm_pwd_len ? &lm_blob : NULL,
177 nt_pwd_len ? &nt_blob : NULL,
178 NULL, NULL, NULL,
179 AUTH_PASSWORD_RESPONSE);
181 if (NT_STATUS_IS_OK(status)) {
182 (*user_info)->logon_parameters = logon_parameters;
184 ret = NT_STATUS_IS_OK(status) ? true : false;
186 data_blob_free(&lm_blob);
187 data_blob_free(&nt_blob);
188 return ret;
191 /****************************************************************************
192 Create an auth_usersupplied_data, making the DATA_BLOBs here.
193 Decrypt and encrypt the passwords.
194 ****************************************************************************/
196 bool make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
197 struct auth_usersupplied_info **user_info,
198 const char *smb_name,
199 const char *client_domain,
200 const char *workstation_name,
201 const struct tsocket_address *remote_address,
202 const struct tsocket_address *local_address,
203 uint32_t logon_parameters,
204 const uchar chal[8],
205 const uchar lm_interactive_pwd[16],
206 const uchar nt_interactive_pwd[16])
208 struct samr_Password lm_pwd;
209 struct samr_Password nt_pwd;
210 unsigned char local_lm_response[24];
211 unsigned char local_nt_response[24];
212 int rc;
214 if (lm_interactive_pwd)
215 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
217 if (nt_interactive_pwd)
218 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
220 if (lm_interactive_pwd) {
221 rc = SMBOWFencrypt(lm_pwd.hash, chal,
222 local_lm_response);
223 if (rc != 0) {
224 return false;
228 if (nt_interactive_pwd) {
229 rc = SMBOWFencrypt(nt_pwd.hash, chal,
230 local_nt_response);
231 if (rc != 0) {
232 return false;
237 bool ret;
238 NTSTATUS nt_status;
239 DATA_BLOB local_lm_blob = data_blob_null;
240 DATA_BLOB local_nt_blob = data_blob_null;
242 if (lm_interactive_pwd) {
243 local_lm_blob = data_blob(local_lm_response,
244 sizeof(local_lm_response));
247 if (nt_interactive_pwd) {
248 local_nt_blob = data_blob(local_nt_response,
249 sizeof(local_nt_response));
252 nt_status = make_user_info_map(
253 mem_ctx,
254 user_info,
255 smb_name, client_domain, workstation_name,
256 remote_address,
257 local_address,
258 "SamLogon",
259 lm_interactive_pwd ? &local_lm_blob : NULL,
260 nt_interactive_pwd ? &local_nt_blob : NULL,
261 lm_interactive_pwd ? &lm_pwd : NULL,
262 nt_interactive_pwd ? &nt_pwd : NULL,
263 NULL, AUTH_PASSWORD_HASH);
265 if (NT_STATUS_IS_OK(nt_status)) {
266 (*user_info)->logon_parameters = logon_parameters;
269 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
270 data_blob_free(&local_lm_blob);
271 data_blob_free(&local_nt_blob);
272 return ret;
277 /****************************************************************************
278 Create an auth_usersupplied_data structure
279 ****************************************************************************/
281 bool make_user_info_for_reply(TALLOC_CTX *mem_ctx,
282 struct auth_usersupplied_info **user_info,
283 const char *smb_name,
284 const char *client_domain,
285 const struct tsocket_address *remote_address,
286 const struct tsocket_address *local_address,
287 const char *service_description,
288 const uint8_t chal[8],
289 DATA_BLOB plaintext_password)
292 DATA_BLOB local_lm_blob;
293 DATA_BLOB local_nt_blob;
294 NTSTATUS ret;
295 char *plaintext_password_string;
297 * Not encrypted - do so.
300 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
301 "format.\n"));
302 if (plaintext_password.data && plaintext_password.length) {
303 unsigned char local_lm_response[24];
305 #ifdef DEBUG_PASSWORD
306 DEBUG(10,("Unencrypted password (len %d):\n",
307 (int)plaintext_password.length));
308 dump_data(100, plaintext_password.data,
309 plaintext_password.length);
310 #endif
312 SMBencrypt( (const char *)plaintext_password.data,
313 (const uchar*)chal, local_lm_response);
314 local_lm_blob = data_blob(local_lm_response, 24);
316 /* We can't do an NT hash here, as the password needs to be
317 case insensitive */
318 local_nt_blob = data_blob_null;
319 } else {
320 local_lm_blob = data_blob_null;
321 local_nt_blob = data_blob_null;
324 plaintext_password_string = talloc_strndup(talloc_tos(),
325 (const char *)plaintext_password.data,
326 plaintext_password.length);
327 if (!plaintext_password_string) {
328 return false;
331 ret = make_user_info(mem_ctx,
332 user_info, smb_name, smb_name, client_domain, client_domain,
333 get_remote_machine_name(),
334 remote_address,
335 local_address,
336 service_description,
337 local_lm_blob.data ? &local_lm_blob : NULL,
338 local_nt_blob.data ? &local_nt_blob : NULL,
339 NULL, NULL,
340 plaintext_password_string,
341 AUTH_PASSWORD_PLAIN);
343 if (plaintext_password_string) {
344 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
345 talloc_free(plaintext_password_string);
348 data_blob_free(&local_lm_blob);
349 return NT_STATUS_IS_OK(ret) ? true : false;
352 /****************************************************************************
353 Create an auth_usersupplied_data structure
354 ****************************************************************************/
356 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
357 struct auth_usersupplied_info **user_info,
358 const char *smb_name,
359 const char *client_domain,
360 const struct tsocket_address *remote_address,
361 const struct tsocket_address *local_address,
362 const char *service_description,
363 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
365 bool allow_raw = lp_raw_ntlmv2_auth();
367 if (!allow_raw && nt_resp.length >= 48) {
369 * NTLMv2_RESPONSE has at least 48 bytes
370 * and should only be supported via NTLMSSP.
372 DEBUG(2,("Rejecting raw NTLMv2 authentication with "
373 "user [%s\\%s] from[%s]\n",
374 client_domain, smb_name,
375 tsocket_address_string(remote_address, mem_ctx)));
376 return NT_STATUS_INVALID_PARAMETER;
379 return make_user_info(mem_ctx,
380 user_info, smb_name, smb_name,
381 client_domain, client_domain,
382 get_remote_machine_name(),
383 remote_address,
384 local_address,
385 service_description,
386 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
387 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
388 NULL, NULL, NULL,
389 AUTH_PASSWORD_RESPONSE);
392 /****************************************************************************
393 Create a guest user_info blob, for anonymous authentication.
394 ****************************************************************************/
396 bool make_user_info_guest(TALLOC_CTX *mem_ctx,
397 const struct tsocket_address *remote_address,
398 const struct tsocket_address *local_address,
399 const char *service_description,
400 struct auth_usersupplied_info **user_info)
402 NTSTATUS nt_status;
404 nt_status = make_user_info(mem_ctx,
405 user_info,
406 "","",
407 "","",
408 "",
409 remote_address,
410 local_address,
411 service_description,
412 NULL, NULL,
413 NULL, NULL,
414 NULL,
415 AUTH_PASSWORD_RESPONSE);
417 return NT_STATUS_IS_OK(nt_status) ? true : false;
420 static NTSTATUS log_nt_token(struct security_token *token)
422 TALLOC_CTX *frame = talloc_stackframe();
423 const struct loadparm_substitution *lp_sub =
424 loadparm_s3_global_substitution();
425 char *command;
426 char *group_sidstr;
427 struct dom_sid_buf buf;
428 size_t i;
430 if ((lp_log_nt_token_command(frame, lp_sub) == NULL) ||
431 (strlen(lp_log_nt_token_command(frame, lp_sub)) == 0)) {
432 TALLOC_FREE(frame);
433 return NT_STATUS_OK;
436 group_sidstr = talloc_strdup(frame, "");
437 for (i=1; i<token->num_sids; i++) {
438 group_sidstr = talloc_asprintf(
439 frame, "%s %s", group_sidstr,
440 dom_sid_str_buf(&token->sids[i], &buf));
443 command = talloc_string_sub(
444 frame, lp_log_nt_token_command(frame, lp_sub),
445 "%s", dom_sid_str_buf(&token->sids[0], &buf));
446 command = talloc_string_sub(frame, command, "%t", group_sidstr);
448 if (command == NULL) {
449 TALLOC_FREE(frame);
450 return NT_STATUS_NO_MEMORY;
453 DEBUG(8, ("running command: [%s]\n", command));
454 if (smbrun(command, NULL, NULL) != 0) {
455 DEBUG(0, ("Could not log NT token\n"));
456 TALLOC_FREE(frame);
457 return NT_STATUS_ACCESS_DENIED;
460 TALLOC_FREE(frame);
461 return NT_STATUS_OK;
465 * Create the token to use from server_info->info3 and
466 * server_info->sids (the info3/sam groups). Find the unix gids.
469 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
470 const struct auth_serversupplied_info *server_info,
471 DATA_BLOB *session_key,
472 const char *smb_username, /* for ->sanitized_username, for %U subs */
473 struct auth_session_info **session_info_out)
475 struct security_token *t;
476 NTSTATUS status;
477 size_t i;
478 struct dom_sid tmp_sid;
479 struct auth_session_info *session_info = NULL;
480 struct unixid *ids;
482 /* Ensure we can't possible take a code path leading to a
483 * null deref. */
484 if (!server_info) {
485 return NT_STATUS_LOGON_FAILURE;
488 if (!is_allowed_domain(server_info->info3->base.logon_domain.string)) {
489 DBG_NOTICE("Authentication failed for user [%s] "
490 "from firewalled domain [%s]\n",
491 server_info->info3->base.account_name.string,
492 server_info->info3->base.logon_domain.string);
493 return NT_STATUS_AUTHENTICATION_FIREWALL_FAILED;
496 if (server_info->cached_session_info != NULL) {
497 session_info = copy_session_info(mem_ctx,
498 server_info->cached_session_info);
499 if (session_info == NULL) {
500 goto nomem;
503 /* This is a potentially untrusted username for use in %U */
504 session_info->unix_info->sanitized_username =
505 talloc_alpha_strcpy(session_info->unix_info,
506 smb_username,
507 SAFE_NETBIOS_CHARS "$");
508 if (session_info->unix_info->sanitized_username == NULL) {
509 goto nomem;
512 session_info->unique_session_token = GUID_random();
514 *session_info_out = session_info;
515 return NT_STATUS_OK;
518 session_info = talloc_zero(mem_ctx, struct auth_session_info);
519 if (!session_info) {
520 goto nomem;
523 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
524 if (!session_info->unix_token) {
525 goto nomem;
528 session_info->unix_token->uid = server_info->utok.uid;
529 session_info->unix_token->gid = server_info->utok.gid;
531 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
532 if (!session_info->unix_info) {
533 goto nomem;
536 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
537 if (!session_info->unix_info->unix_name) {
538 goto nomem;
541 /* This is a potentially untrusted username for use in %U */
542 session_info->unix_info->sanitized_username =
543 talloc_alpha_strcpy(session_info->unix_info,
544 smb_username,
545 SAFE_NETBIOS_CHARS "$");
546 if (session_info->unix_info->sanitized_username == NULL) {
547 goto nomem;
550 if (session_key) {
551 data_blob_free(&session_info->session_key);
552 session_info->session_key = data_blob_talloc(session_info,
553 session_key->data,
554 session_key->length);
555 if (!session_info->session_key.data && session_key->length) {
556 goto nomem;
558 } else {
559 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
560 server_info->session_key.length);
563 /* We need to populate session_info->info with the information found in server_info->info3 */
564 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
565 server_info->guest == false,
566 &session_info->info);
567 if (!NT_STATUS_IS_OK(status)) {
568 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
569 goto fail;
573 * If winbind is not around, we can not make much use of the SIDs the
574 * domain controller provided us with. Likewise if the user name was
575 * mapped to some local unix user.
578 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
579 (server_info->nss_token)) {
580 char *found_username = NULL;
581 status = create_token_from_username(session_info,
582 server_info->unix_name,
583 server_info->guest,
584 &session_info->unix_token->uid,
585 &session_info->unix_token->gid,
586 &found_username,
587 &session_info->security_token);
588 if (NT_STATUS_IS_OK(status)) {
589 session_info->unix_info->unix_name = found_username;
591 } else {
592 status = create_local_nt_token_from_info3(session_info,
593 server_info->guest,
594 server_info->info3,
595 &server_info->extra,
596 &session_info->security_token);
599 if (!NT_STATUS_IS_OK(status)) {
600 goto fail;
603 /* Convert the SIDs to gids. */
605 session_info->unix_token->ngroups = 0;
606 session_info->unix_token->groups = NULL;
608 t = session_info->security_token;
610 ids = talloc_array(talloc_tos(), struct unixid,
611 t->num_sids);
612 if (ids == NULL) {
613 goto nomem;
616 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
617 goto nomem;
620 for (i=0; i<t->num_sids; i++) {
622 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
623 continue;
626 if (ids[i].type != ID_TYPE_GID &&
627 ids[i].type != ID_TYPE_BOTH) {
628 struct dom_sid_buf buf;
629 DEBUG(10, ("Could not convert SID %s to gid, "
630 "ignoring it\n",
631 dom_sid_str_buf(&t->sids[i], &buf)));
632 continue;
634 if (!add_gid_to_array_unique(session_info->unix_token,
635 ids[i].id,
636 &session_info->unix_token->groups,
637 &session_info->unix_token->ngroups)) {
638 goto nomem;
643 * Add the "Unix Group" SID for each gid to catch mapped groups
644 * and their Unix equivalent. This is to solve the backwards
645 * compatibility problem of 'valid users = +ntadmin' where
646 * ntadmin has been paired with "Domain Admins" in the group
647 * mapping table. Otherwise smb.conf would need to be changed
648 * to 'valid user = "Domain Admins"'. --jerry
650 * For consistency we also add the "Unix User" SID,
651 * so that the complete unix token is represented within
652 * the nt token.
655 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
656 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
657 &session_info->security_token->sids,
658 &session_info->security_token->num_sids);
660 gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
661 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
662 &session_info->security_token->sids,
663 &session_info->security_token->num_sids);
665 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
666 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
667 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
668 &session_info->security_token->sids,
669 &session_info->security_token->num_sids);
672 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
673 debug_unix_user_token(DBGC_AUTH, 10,
674 session_info->unix_token->uid,
675 session_info->unix_token->gid,
676 session_info->unix_token->ngroups,
677 session_info->unix_token->groups);
679 status = log_nt_token(session_info->security_token);
680 if (!NT_STATUS_IS_OK(status)) {
681 goto fail;
684 session_info->unique_session_token = GUID_random();
686 *session_info_out = session_info;
687 return NT_STATUS_OK;
688 nomem:
689 status = NT_STATUS_NO_MEMORY;
690 fail:
691 TALLOC_FREE(session_info);
692 return status;
695 NTSTATUS auth3_user_info_dc_add_hints(struct auth_user_info_dc *user_info_dc,
696 uid_t uid,
697 gid_t gid,
698 uint32_t flags)
700 uint32_t orig_num_sids = user_info_dc->num_sids;
701 struct dom_sid tmp_sid = { 0, };
702 NTSTATUS status;
705 * We add S-5-88-1-X in order to pass the uid
706 * for the unix token.
708 sid_compose(&tmp_sid,
709 &global_sid_Unix_NFS_Users,
710 (uint32_t)uid);
711 status = add_sid_to_array_unique(user_info_dc->sids,
712 &tmp_sid,
713 &user_info_dc->sids,
714 &user_info_dc->num_sids);
715 if (!NT_STATUS_IS_OK(status)) {
716 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
717 nt_errstr(status)));
718 goto fail;
722 * We add S-5-88-2-X in order to pass the gid
723 * for the unix token.
725 sid_compose(&tmp_sid,
726 &global_sid_Unix_NFS_Groups,
727 (uint32_t)gid);
728 status = add_sid_to_array_unique(user_info_dc->sids,
729 &tmp_sid,
730 &user_info_dc->sids,
731 &user_info_dc->num_sids);
732 if (!NT_STATUS_IS_OK(status)) {
733 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
734 nt_errstr(status)));
735 goto fail;
739 * We add S-5-88-3-X in order to pass some flags
740 * (AUTH3_UNIX_HINT_*) to auth3_create_session_info().
742 sid_compose(&tmp_sid,
743 &global_sid_Unix_NFS_Mode,
744 flags);
745 status = add_sid_to_array_unique(user_info_dc->sids,
746 &tmp_sid,
747 &user_info_dc->sids,
748 &user_info_dc->num_sids);
749 if (!NT_STATUS_IS_OK(status)) {
750 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
751 nt_errstr(status)));
752 goto fail;
755 return NT_STATUS_OK;
757 fail:
758 user_info_dc->num_sids = orig_num_sids;
759 return status;
762 NTSTATUS auth3_session_info_create(TALLOC_CTX *mem_ctx,
763 const struct auth_user_info_dc *user_info_dc,
764 const char *original_user_name,
765 uint32_t session_info_flags,
766 struct auth_session_info **session_info_out)
768 TALLOC_CTX *frame = talloc_stackframe();
769 struct auth_session_info *session_info = NULL;
770 uid_t hint_uid = -1;
771 bool found_hint_uid = false;
772 uid_t hint_gid = -1;
773 bool found_hint_gid = false;
774 uint32_t hint_flags = 0;
775 bool found_hint_flags = false;
776 bool need_getpwuid = false;
777 struct unixid *ids = NULL;
778 uint32_t num_gids = 0;
779 gid_t *gids = NULL;
780 struct dom_sid tmp_sid = { 0, };
781 NTSTATUS status;
782 size_t i;
783 bool ok;
785 *session_info_out = NULL;
787 if (user_info_dc->num_sids == 0) {
788 TALLOC_FREE(frame);
789 return NT_STATUS_INVALID_TOKEN;
792 if (user_info_dc->info == NULL) {
793 TALLOC_FREE(frame);
794 return NT_STATUS_INVALID_TOKEN;
797 if (user_info_dc->info->account_name == NULL) {
798 TALLOC_FREE(frame);
799 return NT_STATUS_INVALID_TOKEN;
802 session_info = talloc_zero(mem_ctx, struct auth_session_info);
803 if (session_info == NULL) {
804 TALLOC_FREE(frame);
805 return NT_STATUS_NO_MEMORY;
807 /* keep this under frame for easier cleanup */
808 talloc_reparent(mem_ctx, frame, session_info);
810 session_info->info = auth_user_info_copy(session_info,
811 user_info_dc->info);
812 if (session_info->info == NULL) {
813 TALLOC_FREE(frame);
814 return NT_STATUS_NO_MEMORY;
817 session_info->security_token = talloc_zero(session_info,
818 struct security_token);
819 if (session_info->security_token == NULL) {
820 TALLOC_FREE(frame);
821 return NT_STATUS_NO_MEMORY;
825 * Avoid a lot of reallocations and allocate what we'll
826 * use in most cases.
828 session_info->security_token->sids = talloc_zero_array(
829 session_info->security_token,
830 struct dom_sid,
831 user_info_dc->num_sids);
832 if (session_info->security_token->sids == NULL) {
833 TALLOC_FREE(frame);
834 return NT_STATUS_NO_MEMORY;
837 for (i = PRIMARY_USER_SID_INDEX; i < user_info_dc->num_sids; i++) {
838 struct security_token *nt_token = session_info->security_token;
839 int cmp;
842 * S-1-5-88-X-Y sids are only used to give hints
843 * to the unix token construction.
845 * S-1-5-88-1-Y gives the uid=Y
846 * S-1-5-88-2-Y gives the gid=Y
847 * S-1-5-88-3-Y gives flags=Y: AUTH3_UNIX_HINT_*
849 cmp = dom_sid_compare_domain(&global_sid_Unix_NFS,
850 &user_info_dc->sids[i]);
851 if (cmp == 0) {
852 bool match;
853 uint32_t hint = 0;
855 match = sid_peek_rid(&user_info_dc->sids[i], &hint);
856 if (!match) {
857 continue;
860 match = dom_sid_in_domain(&global_sid_Unix_NFS_Users,
861 &user_info_dc->sids[i]);
862 if (match) {
863 if (found_hint_uid) {
864 TALLOC_FREE(frame);
865 return NT_STATUS_INVALID_TOKEN;
867 found_hint_uid = true;
868 hint_uid = (uid_t)hint;
869 continue;
872 match = dom_sid_in_domain(&global_sid_Unix_NFS_Groups,
873 &user_info_dc->sids[i]);
874 if (match) {
875 if (found_hint_gid) {
876 TALLOC_FREE(frame);
877 return NT_STATUS_INVALID_TOKEN;
879 found_hint_gid = true;
880 hint_gid = (gid_t)hint;
881 continue;
884 match = dom_sid_in_domain(&global_sid_Unix_NFS_Mode,
885 &user_info_dc->sids[i]);
886 if (match) {
887 if (found_hint_flags) {
888 TALLOC_FREE(frame);
889 return NT_STATUS_INVALID_TOKEN;
891 found_hint_flags = true;
892 hint_flags = hint;
893 continue;
896 continue;
899 status = add_sid_to_array_unique(nt_token->sids,
900 &user_info_dc->sids[i],
901 &nt_token->sids,
902 &nt_token->num_sids);
903 if (!NT_STATUS_IS_OK(status)) {
904 TALLOC_FREE(frame);
905 return status;
910 * We need at least one usable SID
912 if (session_info->security_token->num_sids == 0) {
913 TALLOC_FREE(frame);
914 return NT_STATUS_INVALID_TOKEN;
918 * We need all tree hints: uid, gid, flags
919 * or none of them.
921 if (found_hint_uid || found_hint_gid || found_hint_flags) {
922 if (!found_hint_uid) {
923 TALLOC_FREE(frame);
924 return NT_STATUS_INVALID_TOKEN;
927 if (!found_hint_gid) {
928 TALLOC_FREE(frame);
929 return NT_STATUS_INVALID_TOKEN;
932 if (!found_hint_flags) {
933 TALLOC_FREE(frame);
934 return NT_STATUS_INVALID_TOKEN;
938 if (session_info->info->authenticated) {
939 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
942 status = finalize_local_nt_token(session_info->security_token,
943 session_info_flags);
944 if (!NT_STATUS_IS_OK(status)) {
945 TALLOC_FREE(frame);
946 return status;
950 * unless set otherwise, the session key is the user session
951 * key from the auth subsystem
953 if (user_info_dc->user_session_key.length != 0) {
954 session_info->session_key = data_blob_dup_talloc(session_info,
955 user_info_dc->user_session_key);
956 if (session_info->session_key.data == NULL) {
957 TALLOC_FREE(frame);
958 return NT_STATUS_NO_MEMORY;
962 if (!(session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)) {
963 goto done;
966 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
967 if (session_info->unix_token == NULL) {
968 TALLOC_FREE(frame);
969 return NT_STATUS_NO_MEMORY;
971 session_info->unix_token->uid = -1;
972 session_info->unix_token->gid = -1;
974 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
975 if (session_info->unix_info == NULL) {
976 TALLOC_FREE(frame);
977 return NT_STATUS_NO_MEMORY;
980 /* Convert the SIDs to uid/gids. */
982 ids = talloc_zero_array(frame, struct unixid,
983 session_info->security_token->num_sids);
984 if (ids == NULL) {
985 TALLOC_FREE(frame);
986 return NT_STATUS_NO_MEMORY;
989 if (!(hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS)) {
990 ok = sids_to_unixids(session_info->security_token->sids,
991 session_info->security_token->num_sids,
992 ids);
993 if (!ok) {
994 TALLOC_FREE(frame);
995 return NT_STATUS_NO_MEMORY;
999 if (found_hint_uid) {
1000 session_info->unix_token->uid = hint_uid;
1001 } else if (ids[0].type == ID_TYPE_UID) {
1003 * The primary SID resolves to a UID only.
1005 session_info->unix_token->uid = ids[0].id;
1006 } else if (ids[0].type == ID_TYPE_BOTH) {
1008 * The primary SID resolves to a UID and GID,
1009 * use it as uid and add it as first element
1010 * to the groups array.
1012 session_info->unix_token->uid = ids[0].id;
1014 ok = add_gid_to_array_unique(session_info->unix_token,
1015 session_info->unix_token->uid,
1016 &session_info->unix_token->groups,
1017 &session_info->unix_token->ngroups);
1018 if (!ok) {
1019 TALLOC_FREE(frame);
1020 return NT_STATUS_NO_MEMORY;
1022 } else {
1024 * It we can't get a uid, we can't imporsonate
1025 * the user.
1027 TALLOC_FREE(frame);
1028 return NT_STATUS_INVALID_TOKEN;
1031 if (found_hint_gid) {
1032 session_info->unix_token->gid = hint_gid;
1033 } else {
1034 need_getpwuid = true;
1037 if (hint_flags & AUTH3_UNIX_HINT_QUALIFIED_NAME) {
1038 session_info->unix_info->unix_name =
1039 talloc_asprintf(session_info->unix_info,
1040 "%s%c%s",
1041 session_info->info->domain_name,
1042 *lp_winbind_separator(),
1043 session_info->info->account_name);
1044 if (session_info->unix_info->unix_name == NULL) {
1045 TALLOC_FREE(frame);
1046 return NT_STATUS_NO_MEMORY;
1048 } else if (hint_flags & AUTH3_UNIX_HINT_ISLOLATED_NAME) {
1049 session_info->unix_info->unix_name =
1050 talloc_strdup(session_info->unix_info,
1051 session_info->info->account_name);
1052 if (session_info->unix_info->unix_name == NULL) {
1053 TALLOC_FREE(frame);
1054 return NT_STATUS_NO_MEMORY;
1056 } else {
1057 need_getpwuid = true;
1060 if (need_getpwuid) {
1061 struct passwd *pwd = NULL;
1064 * Ask the system for the primary gid
1065 * and the real unix name.
1067 pwd = getpwuid_alloc(frame, session_info->unix_token->uid);
1068 if (pwd == NULL) {
1069 TALLOC_FREE(frame);
1070 return NT_STATUS_INVALID_TOKEN;
1072 if (!found_hint_gid) {
1073 session_info->unix_token->gid = pwd->pw_gid;
1076 session_info->unix_info->unix_name =
1077 talloc_strdup(session_info->unix_info, pwd->pw_name);
1078 if (session_info->unix_info->unix_name == NULL) {
1079 TALLOC_FREE(frame);
1080 return NT_STATUS_NO_MEMORY;
1083 TALLOC_FREE(pwd);
1086 ok = add_gid_to_array_unique(session_info->unix_token,
1087 session_info->unix_token->gid,
1088 &session_info->unix_token->groups,
1089 &session_info->unix_token->ngroups);
1090 if (!ok) {
1091 TALLOC_FREE(frame);
1092 return NT_STATUS_NO_MEMORY;
1095 /* This is a potentially untrusted username for use in %U */
1096 session_info->unix_info->sanitized_username =
1097 talloc_alpha_strcpy(session_info->unix_info,
1098 original_user_name,
1099 SAFE_NETBIOS_CHARS "$");
1100 if (session_info->unix_info->sanitized_username == NULL) {
1101 TALLOC_FREE(frame);
1102 return NT_STATUS_NO_MEMORY;
1105 for (i=0; i < session_info->security_token->num_sids; i++) {
1107 if (ids[i].type != ID_TYPE_GID &&
1108 ids[i].type != ID_TYPE_BOTH) {
1109 struct security_token *nt_token =
1110 session_info->security_token;
1111 struct dom_sid_buf buf;
1113 DEBUG(10, ("Could not convert SID %s to gid, "
1114 "ignoring it\n",
1115 dom_sid_str_buf(&nt_token->sids[i], &buf)));
1116 continue;
1119 ok = add_gid_to_array_unique(session_info->unix_token,
1120 ids[i].id,
1121 &session_info->unix_token->groups,
1122 &session_info->unix_token->ngroups);
1123 if (!ok) {
1124 TALLOC_FREE(frame);
1125 return NT_STATUS_NO_MEMORY;
1128 TALLOC_FREE(ids);
1131 * Now we must get any groups this user has been
1132 * added to in /etc/group and merge them in.
1133 * This has to be done in every code path
1134 * that creates an NT token, as remote users
1135 * may have been added to the local /etc/group
1136 * database. Tokens created merely from the
1137 * info3 structs (via the DC or via the krb5 PAC)
1138 * won't have these local groups. Note the
1139 * groups added here will only be UNIX groups
1140 * (S-1-22-2-XXXX groups) as getgroups_unix_user()
1141 * turns off winbindd before calling getgroups().
1143 * NB. This is duplicating work already
1144 * done in the 'unix_user:' case of
1145 * create_token_from_sid() but won't
1146 * do anything other than be inefficient
1147 * in that case.
1149 if (!(hint_flags & AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS)) {
1150 ok = getgroups_unix_user(frame,
1151 session_info->unix_info->unix_name,
1152 session_info->unix_token->gid,
1153 &gids, &num_gids);
1154 if (!ok) {
1155 TALLOC_FREE(frame);
1156 return NT_STATUS_INVALID_TOKEN;
1160 for (i=0; i < num_gids; i++) {
1162 ok = add_gid_to_array_unique(session_info->unix_token,
1163 gids[i],
1164 &session_info->unix_token->groups,
1165 &session_info->unix_token->ngroups);
1166 if (!ok) {
1167 TALLOC_FREE(frame);
1168 return NT_STATUS_NO_MEMORY;
1171 TALLOC_FREE(gids);
1173 if (hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS) {
1175 * We should not translate the unix token uid/gids
1176 * to S-1-22-X-Y SIDs.
1178 goto done;
1182 * Add the "Unix Group" SID for each gid to catch mapped groups
1183 * and their Unix equivalent. This is to solve the backwards
1184 * compatibility problem of 'valid users = +ntadmin' where
1185 * ntadmin has been paired with "Domain Admins" in the group
1186 * mapping table. Otherwise smb.conf would need to be changed
1187 * to 'valid user = "Domain Admins"'. --jerry
1189 * For consistency we also add the "Unix User" SID,
1190 * so that the complete unix token is represented within
1191 * the nt token.
1194 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
1195 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1196 &session_info->security_token->sids,
1197 &session_info->security_token->num_sids);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 TALLOC_FREE(frame);
1200 return status;
1203 gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
1204 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1205 &session_info->security_token->sids,
1206 &session_info->security_token->num_sids);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 TALLOC_FREE(frame);
1209 return status;
1212 for (i=0; i < session_info->unix_token->ngroups; i++ ) {
1213 struct security_token *nt_token = session_info->security_token;
1215 gid_to_unix_groups_sid(session_info->unix_token->groups[i],
1216 &tmp_sid);
1217 status = add_sid_to_array_unique(nt_token->sids,
1218 &tmp_sid,
1219 &nt_token->sids,
1220 &nt_token->num_sids);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 TALLOC_FREE(frame);
1223 return status;
1227 done:
1228 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
1229 if (session_info->unix_token != NULL) {
1230 debug_unix_user_token(DBGC_AUTH, 10,
1231 session_info->unix_token->uid,
1232 session_info->unix_token->gid,
1233 session_info->unix_token->ngroups,
1234 session_info->unix_token->groups);
1237 status = log_nt_token(session_info->security_token);
1238 if (!NT_STATUS_IS_OK(status)) {
1239 TALLOC_FREE(frame);
1240 return status;
1243 session_info->unique_session_token = GUID_random();
1245 *session_info_out = talloc_move(mem_ctx, &session_info);
1246 TALLOC_FREE(frame);
1247 return NT_STATUS_OK;
1250 /***************************************************************************
1251 Make (and fill) a server_info struct from a 'struct passwd' by conversion
1252 to a struct samu
1253 ***************************************************************************/
1255 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
1256 const char *unix_username,
1257 const struct passwd *pwd,
1258 struct auth_serversupplied_info **server_info)
1260 NTSTATUS status;
1261 TALLOC_CTX *tmp_ctx = NULL;
1262 struct auth_serversupplied_info *result;
1264 tmp_ctx = talloc_stackframe();
1265 if (tmp_ctx == NULL) {
1266 return NT_STATUS_NO_MEMORY;
1269 result = make_server_info(tmp_ctx);
1270 if (result == NULL) {
1271 status = NT_STATUS_NO_MEMORY;
1272 goto done;
1275 status = passwd_to_SamInfo3(result,
1276 unix_username,
1277 pwd,
1278 &result->info3,
1279 &result->extra);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 goto done;
1284 result->unix_name = talloc_strdup(result, unix_username);
1285 if (result->unix_name == NULL) {
1286 status = NT_STATUS_NO_MEMORY;
1287 goto done;
1290 result->utok.uid = pwd->pw_uid;
1291 result->utok.gid = pwd->pw_gid;
1293 *server_info = talloc_move(mem_ctx, &result);
1294 status = NT_STATUS_OK;
1295 done:
1296 talloc_free(tmp_ctx);
1298 return status;
1301 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
1302 struct netr_SamInfo3 *info3)
1304 const char *guest_account = lp_guest_account();
1305 struct dom_sid domain_sid;
1306 struct passwd *pwd;
1307 const char *tmp;
1309 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
1310 if (pwd == NULL) {
1311 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
1312 "account [%s]!\n", guest_account));
1313 return NT_STATUS_NO_SUCH_USER;
1316 /* Set account name */
1317 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
1318 if (tmp == NULL) {
1319 return NT_STATUS_NO_MEMORY;
1321 init_lsa_String(&info3->base.account_name, tmp);
1323 /* Set domain name */
1324 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
1325 if (tmp == NULL) {
1326 return NT_STATUS_NO_MEMORY;
1328 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
1330 /* Domain sid */
1331 sid_copy(&domain_sid, get_global_sam_sid());
1333 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
1334 if (info3->base.domain_sid == NULL) {
1335 return NT_STATUS_NO_MEMORY;
1338 /* Guest rid */
1339 info3->base.rid = DOMAIN_RID_GUEST;
1341 /* Primary gid */
1342 info3->base.primary_gid = DOMAIN_RID_GUESTS;
1344 /* Set as guest */
1345 info3->base.user_flags = NETLOGON_GUEST;
1347 TALLOC_FREE(pwd);
1348 return NT_STATUS_OK;
1351 /***************************************************************************
1352 Make (and fill) a user_info struct for a guest login.
1353 This *must* succeed for smbd to start. If there is no mapping entry for
1354 the guest gid, then create one.
1356 The resulting structure is a 'session_info' because
1357 create_local_token() has already been called on it. This is quite
1358 nasty, as the auth subsystem isn't expect this, but the behavior is
1359 left as-is for now.
1360 ***************************************************************************/
1362 static NTSTATUS make_new_session_info_guest(TALLOC_CTX *mem_ctx,
1363 struct auth_session_info **_session_info,
1364 struct auth_serversupplied_info **_server_info)
1366 struct auth_session_info *session_info = NULL;
1367 struct auth_serversupplied_info *server_info = NULL;
1368 const char *guest_account = lp_guest_account();
1369 const char *domain = lp_netbios_name();
1370 struct netr_SamInfo3 info3;
1371 TALLOC_CTX *tmp_ctx;
1372 NTSTATUS status;
1374 tmp_ctx = talloc_stackframe();
1375 if (tmp_ctx == NULL) {
1376 return NT_STATUS_NO_MEMORY;
1379 ZERO_STRUCT(info3);
1381 status = get_guest_info3(tmp_ctx, &info3);
1382 if (!NT_STATUS_IS_OK(status)) {
1383 DEBUG(0, ("get_guest_info3 failed with %s\n",
1384 nt_errstr(status)));
1385 goto done;
1388 status = make_server_info_info3(tmp_ctx,
1389 guest_account,
1390 domain,
1391 &server_info,
1392 &info3);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DEBUG(0, ("make_server_info_info3 failed with %s\n",
1395 nt_errstr(status)));
1396 goto done;
1399 server_info->guest = true;
1401 /* This should not be done here (we should produce a server
1402 * info, and later construct a session info from it), but for
1403 * now this does not change the previous behavior */
1404 status = create_local_token(tmp_ctx, server_info, NULL,
1405 server_info->info3->base.account_name.string,
1406 &session_info);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 DEBUG(0, ("create_local_token failed: %s\n",
1409 nt_errstr(status)));
1410 goto done;
1414 * It's ugly, but for now it's
1415 * needed to force Builtin_Guests
1416 * here, because memberships of
1417 * Builtin_Guests might be incomplete.
1419 status = add_sid_to_array_unique(session_info->security_token,
1420 &global_sid_Builtin_Guests,
1421 &session_info->security_token->sids,
1422 &session_info->security_token->num_sids);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 DBG_ERR("Failed to force Builtin_Guests to nt token\n");
1425 goto done;
1428 /* annoying, but the Guest really does have a session key, and it is
1429 all zeros! */
1430 session_info->session_key = data_blob_talloc_zero(session_info, 16);
1432 *_session_info = talloc_move(mem_ctx, &session_info);
1433 *_server_info = talloc_move(mem_ctx, &server_info);
1435 status = NT_STATUS_OK;
1436 done:
1437 TALLOC_FREE(tmp_ctx);
1438 return status;
1441 /***************************************************************************
1442 Make (and fill) a auth_session_info struct for a system user login.
1443 This *must* succeed for smbd to start.
1444 ***************************************************************************/
1446 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
1447 struct auth_session_info **session_info)
1449 TALLOC_CTX *frame = talloc_stackframe();
1450 struct auth_user_info_dc *user_info_dc = NULL;
1451 uid_t uid = -1;
1452 gid_t gid = -1;
1453 uint32_t hint_flags = 0;
1454 uint32_t session_info_flags = 0;
1455 NTSTATUS status;
1457 status = auth_system_user_info_dc(frame, lp_netbios_name(),
1458 &user_info_dc);
1459 if (!NT_STATUS_IS_OK(status)) {
1460 DEBUG(0, ("auth_system_user_info_dc failed: %s\n",
1461 nt_errstr(status)));
1462 goto done;
1466 * Just get the initial uid/gid
1467 * and don't expand the unix groups.
1469 uid = sec_initial_uid();
1470 gid = sec_initial_gid();
1471 hint_flags |= AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS;
1474 * Also avoid sid mapping to gids,
1475 * as well as adding the unix_token uid/gids as
1476 * S-1-22-X-Y SIDs to the nt token.
1478 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS;
1479 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS;
1482 * The unix name will be "NT AUTHORITY+SYSTEM",
1483 * where '+' is the "winbind separator" character.
1485 hint_flags |= AUTH3_UNIX_HINT_QUALIFIED_NAME;
1486 status = auth3_user_info_dc_add_hints(user_info_dc,
1487 uid,
1488 gid,
1489 hint_flags);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1492 nt_errstr(status)));
1493 goto done;
1496 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1497 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1498 status = auth3_session_info_create(mem_ctx, user_info_dc,
1499 user_info_dc->info->account_name,
1500 session_info_flags,
1501 session_info);
1502 if (!NT_STATUS_IS_OK(status)) {
1503 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1504 nt_errstr(status)));
1505 goto done;
1508 done:
1509 TALLOC_FREE(frame);
1510 return status;
1513 static NTSTATUS make_new_session_info_anonymous(TALLOC_CTX *mem_ctx,
1514 struct auth_session_info **session_info)
1516 TALLOC_CTX *frame = talloc_stackframe();
1517 const char *guest_account = lp_guest_account();
1518 struct auth_user_info_dc *user_info_dc = NULL;
1519 struct passwd *pwd = NULL;
1520 uint32_t hint_flags = 0;
1521 uint32_t session_info_flags = 0;
1522 NTSTATUS status;
1525 * We use the guest account for the unix token
1526 * while we use a true anonymous nt token.
1528 * It's very important to have a separate
1529 * nt token for anonymous.
1532 pwd = Get_Pwnam_alloc(frame, guest_account);
1533 if (pwd == NULL) {
1534 DBG_ERR("Unable to locate guest account [%s]!\n",
1535 guest_account);
1536 status = NT_STATUS_NO_SUCH_USER;
1537 goto done;
1540 status = auth_anonymous_user_info_dc(frame, lp_netbios_name(),
1541 &user_info_dc);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 DEBUG(0, ("auth_anonymous_user_info_dc failed: %s\n",
1544 nt_errstr(status)));
1545 goto done;
1549 * Note we don't pass AUTH3_UNIX_HINT_QUALIFIED_NAME
1550 * nor AUTH3_UNIX_HINT_ISOLATED_NAME here
1551 * as we want the unix name be found by getpwuid_alloc().
1554 status = auth3_user_info_dc_add_hints(user_info_dc,
1555 pwd->pw_uid,
1556 pwd->pw_gid,
1557 hint_flags);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1560 nt_errstr(status)));
1561 goto done;
1565 * In future we may want to remove
1566 * AUTH_SESSION_INFO_DEFAULT_GROUPS.
1568 * Similar to Windows with EveryoneIncludesAnonymous
1569 * and RestrictAnonymous.
1571 * We may introduce AUTH_SESSION_INFO_ANON_WORLD...
1573 * But for this is required to keep the existing tests
1574 * working.
1576 session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
1577 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1578 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1579 status = auth3_session_info_create(mem_ctx, user_info_dc,
1581 session_info_flags,
1582 session_info);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1585 nt_errstr(status)));
1586 goto done;
1589 done:
1590 TALLOC_FREE(frame);
1591 return status;
1594 /****************************************************************************
1595 Fake a auth_session_info just from a username (as a
1596 session_info structure, with create_local_token() already called on
1598 ****************************************************************************/
1600 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
1601 const char *username,
1602 bool is_guest,
1603 struct auth_session_info **session_info)
1605 struct passwd *pwd;
1606 NTSTATUS status;
1607 struct auth_serversupplied_info *result;
1608 TALLOC_CTX *tmp_ctx;
1610 tmp_ctx = talloc_stackframe();
1611 if (tmp_ctx == NULL) {
1612 return NT_STATUS_NO_MEMORY;
1615 pwd = Get_Pwnam_alloc(tmp_ctx, username);
1616 if (pwd == NULL) {
1617 status = NT_STATUS_NO_SUCH_USER;
1618 goto done;
1621 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 goto done;
1626 result->nss_token = true;
1627 result->guest = is_guest;
1629 /* Now turn the server_info into a session_info with the full token etc */
1630 status = create_local_token(mem_ctx,
1631 result,
1632 NULL,
1633 pwd->pw_name,
1634 session_info);
1636 done:
1637 talloc_free(tmp_ctx);
1639 return status;
1642 /* This function MUST only used to create the cached server_info for
1643 * guest.
1645 * This is a lossy conversion. Variables known to be lost so far
1646 * include:
1648 * - nss_token (not needed because the only read doesn't happen
1649 * for the GUEST user, as this routine populates ->security_token
1651 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1653 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1655 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1656 const struct auth_session_info *src,
1657 struct auth_serversupplied_info *server_info)
1659 struct auth_serversupplied_info *dst;
1660 NTSTATUS status;
1662 dst = make_server_info(mem_ctx);
1663 if (dst == NULL) {
1664 return NULL;
1667 /* This element must be provided to convert back to an auth_serversupplied_info */
1668 SMB_ASSERT(src->unix_info);
1670 dst->guest = true;
1672 /* This element must be provided to convert back to an
1673 * auth_serversupplied_info. This needs to be from the
1674 * auth_session_info because the group values in particular
1675 * may change during create_local_token() processing */
1676 SMB_ASSERT(src->unix_token);
1677 dst->utok.uid = src->unix_token->uid;
1678 dst->utok.gid = src->unix_token->gid;
1679 dst->utok.ngroups = src->unix_token->ngroups;
1680 if (src->unix_token->ngroups != 0) {
1681 dst->utok.groups = (gid_t *)talloc_memdup(
1682 dst, src->unix_token->groups,
1683 sizeof(gid_t)*dst->utok.ngroups);
1684 } else {
1685 dst->utok.groups = NULL;
1688 /* We must have a security_token as otherwise the lossy
1689 * conversion without nss_token would cause create_local_token
1690 * to take the wrong path */
1691 SMB_ASSERT(src->security_token);
1693 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1694 src->session_key.length);
1696 /* This is OK because this functions is only used for the
1697 * GUEST account, which has all-zero keys for both values */
1698 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1699 src->session_key.length);
1701 status = copy_netr_SamInfo3(dst,
1702 server_info->info3,
1703 &dst->info3);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 TALLOC_FREE(dst);
1706 return NULL;
1709 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1710 if (!dst->unix_name) {
1711 TALLOC_FREE(dst);
1712 return NULL;
1715 dst->cached_session_info = src;
1716 return dst;
1720 * Set a new session key. Used in the rpc server where we have to override the
1721 * SMB level session key with SystemLibraryDTC
1724 bool session_info_set_session_key(struct auth_session_info *info,
1725 DATA_BLOB session_key)
1727 TALLOC_FREE(info->session_key.data);
1729 info->session_key = data_blob_talloc(
1730 info, session_key.data, session_key.length);
1732 return (info->session_key.data != NULL);
1735 static struct auth_session_info *guest_info = NULL;
1736 static struct auth_session_info *anonymous_info = NULL;
1738 static struct auth_serversupplied_info *guest_server_info = NULL;
1740 bool init_guest_session_info(TALLOC_CTX *mem_ctx)
1742 NTSTATUS status;
1744 if (guest_info != NULL)
1745 return true;
1747 status = make_new_session_info_guest(mem_ctx,
1748 &guest_info,
1749 &guest_server_info);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 return false;
1754 status = make_new_session_info_anonymous(mem_ctx,
1755 &anonymous_info);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return false;
1760 return true;
1763 bool reinit_guest_session_info(TALLOC_CTX *mem_ctx)
1765 TALLOC_FREE(guest_info);
1766 TALLOC_FREE(guest_server_info);
1767 TALLOC_FREE(anonymous_info);
1769 DBG_DEBUG("Reinitialing guest info\n");
1771 return init_guest_session_info(mem_ctx);
1774 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1775 struct auth_serversupplied_info **server_info)
1777 /* This is trickier than it would appear to need to be because
1778 * we are trying to avoid certain costly operations when the
1779 * structure is converted to a 'auth_session_info' again in
1780 * create_local_token() */
1781 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1782 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1785 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1786 struct auth_session_info **session_info)
1788 *session_info = copy_session_info(mem_ctx, guest_info);
1789 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1792 NTSTATUS make_server_info_anonymous(TALLOC_CTX *mem_ctx,
1793 struct auth_serversupplied_info **server_info)
1795 if (anonymous_info == NULL) {
1796 return NT_STATUS_UNSUCCESSFUL;
1800 * This is trickier than it would appear to need to be because
1801 * we are trying to avoid certain costly operations when the
1802 * structure is converted to a 'auth_session_info' again in
1803 * create_local_token()
1805 * We use a guest server_info, but with the anonymous session info,
1806 * which means create_local_token() will return a copy
1807 * of the anonymous token.
1809 * The server info is just used as legacy in order to
1810 * keep existing code working. Maybe some debug messages
1811 * will still refer to guest instead of anonymous.
1813 *server_info = copy_session_info_serverinfo_guest(mem_ctx, anonymous_info,
1814 guest_server_info);
1815 if (*server_info == NULL) {
1816 return NT_STATUS_NO_MEMORY;
1819 return NT_STATUS_OK;
1822 NTSTATUS make_session_info_anonymous(TALLOC_CTX *mem_ctx,
1823 struct auth_session_info **session_info)
1825 if (anonymous_info == NULL) {
1826 return NT_STATUS_UNSUCCESSFUL;
1829 *session_info = copy_session_info(mem_ctx, anonymous_info);
1830 if (*session_info == NULL) {
1831 return NT_STATUS_NO_MEMORY;
1834 return NT_STATUS_OK;
1837 static struct auth_session_info *system_info = NULL;
1839 NTSTATUS init_system_session_info(TALLOC_CTX *mem_ctx)
1841 if (system_info != NULL)
1842 return NT_STATUS_OK;
1844 return make_new_session_info_system(mem_ctx, &system_info);
1847 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1848 struct auth_session_info **session_info)
1850 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1851 *session_info = copy_session_info(mem_ctx, system_info);
1852 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1855 const struct auth_session_info *get_session_info_system(void)
1857 return system_info;
1860 /***************************************************************************
1861 Purely internal function for make_server_info_info3
1862 ***************************************************************************/
1864 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1865 const char *username, char **found_username,
1866 struct passwd **pwd,
1867 bool *username_was_mapped)
1869 char *orig_dom_user = NULL;
1870 char *dom_user = NULL;
1871 char *lower_username = NULL;
1872 char *real_username = NULL;
1873 struct passwd *passwd;
1875 lower_username = talloc_strdup(mem_ctx, username);
1876 if (!lower_username) {
1877 return NT_STATUS_NO_MEMORY;
1879 if (!strlower_m( lower_username )) {
1880 return NT_STATUS_INVALID_PARAMETER;
1883 orig_dom_user = talloc_asprintf(mem_ctx,
1884 "%s%c%s",
1885 domain,
1886 *lp_winbind_separator(),
1887 lower_username);
1888 if (!orig_dom_user) {
1889 return NT_STATUS_NO_MEMORY;
1892 /* Get the passwd struct. Try to create the account if necessary. */
1894 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1895 if (!dom_user) {
1896 return NT_STATUS_NO_MEMORY;
1899 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1900 if (!passwd) {
1901 DEBUG(3, ("Failed to find authenticated user %s via "
1902 "getpwnam(), denying access.\n", dom_user));
1903 return NT_STATUS_NO_SUCH_USER;
1906 if (!real_username) {
1907 return NT_STATUS_NO_MEMORY;
1910 *pwd = passwd;
1912 /* This is pointless -- there is no support for differing
1913 unix and windows names. Make sure to always store the
1914 one we actually looked up and succeeded. Have I mentioned
1915 why I hate the 'winbind use default domain' parameter?
1916 --jerry */
1918 *found_username = talloc_strdup( mem_ctx, real_username );
1920 return NT_STATUS_OK;
1923 /****************************************************************************
1924 Wrapper to allow the getpwnam() call to strip the domain name and
1925 try again in case a local UNIX user is already there. Also run through
1926 the username if we fallback to the username only.
1927 ****************************************************************************/
1929 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1930 char **p_save_username, bool create )
1932 struct passwd *pw = NULL;
1933 char *p = NULL;
1934 char *username = NULL;
1936 /* we only save a copy of the username it has been mangled
1937 by winbindd use default domain */
1938 *p_save_username = NULL;
1940 /* don't call map_username() here since it has to be done higher
1941 up the stack so we don't call it multiple times */
1943 username = talloc_strdup(mem_ctx, domuser);
1944 if (!username) {
1945 return NULL;
1948 p = strchr_m( username, *lp_winbind_separator() );
1950 /* code for a DOMAIN\user string */
1952 if ( p ) {
1953 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1954 if ( pw ) {
1955 /* make sure we get the case of the username correct */
1956 /* work around 'winbind use default domain = yes' */
1958 if ( lp_winbind_use_default_domain() &&
1959 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1960 char *domain;
1962 /* split the domain and username into 2 strings */
1963 *p = '\0';
1964 domain = username;
1966 *p_save_username = talloc_asprintf(mem_ctx,
1967 "%s%c%s",
1968 domain,
1969 *lp_winbind_separator(),
1970 pw->pw_name);
1971 if (!*p_save_username) {
1972 TALLOC_FREE(pw);
1973 return NULL;
1975 } else {
1976 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1979 /* whew -- done! */
1980 return pw;
1983 /* setup for lookup of just the username */
1984 /* remember that p and username are overlapping memory */
1986 p++;
1987 username = talloc_strdup(mem_ctx, p);
1988 if (!username) {
1989 return NULL;
1993 /* just lookup a plain username */
1995 pw = Get_Pwnam_alloc(mem_ctx, username);
1997 /* Create local user if requested but only if winbindd
1998 is not running. We need to protect against cases
1999 where winbindd is failing and then prematurely
2000 creating users in /etc/passwd */
2002 if ( !pw && create && !winbind_ping() ) {
2003 /* Don't add a machine account. */
2004 if (username[strlen(username)-1] == '$')
2005 return NULL;
2007 _smb_create_user(NULL, username, NULL);
2008 pw = Get_Pwnam_alloc(mem_ctx, username);
2011 /* one last check for a valid passwd struct */
2013 if (pw) {
2014 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
2016 return pw;
2019 /***************************************************************************
2020 Make a server_info struct from the info3 returned by a domain logon
2021 ***************************************************************************/
2023 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
2024 const char *sent_nt_username,
2025 const char *domain,
2026 struct auth_serversupplied_info **server_info,
2027 const struct netr_SamInfo3 *info3)
2029 NTSTATUS nt_status;
2030 char *found_username = NULL;
2031 const char *nt_domain;
2032 const char *nt_username;
2033 struct dom_sid user_sid;
2034 struct dom_sid group_sid;
2035 bool username_was_mapped;
2036 struct passwd *pwd;
2037 struct auth_serversupplied_info *result;
2038 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2041 Here is where we should check the list of
2042 trusted domains, and verify that the SID
2043 matches.
2046 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
2047 nt_status = NT_STATUS_INVALID_PARAMETER;
2048 goto out;
2051 if (!sid_compose(&group_sid, info3->base.domain_sid,
2052 info3->base.primary_gid)) {
2053 nt_status = NT_STATUS_INVALID_PARAMETER;
2054 goto out;
2057 nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
2058 if (!nt_username) {
2059 /* If the server didn't give us one, just use the one we sent
2060 * them */
2061 nt_username = sent_nt_username;
2064 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
2065 if (!nt_domain) {
2066 /* If the server didn't give us one, just use the one we sent
2067 * them */
2068 nt_domain = domain;
2071 /* If getpwnam() fails try the add user script (2.2.x behavior).
2073 We use the _unmapped_ username here in an attempt to provide
2074 consistent username mapping behavior between kerberos and NTLM[SSP]
2075 authentication in domain mode security. I.E. Username mapping
2076 should be applied to the fully qualified username
2077 (e.g. DOMAIN\user) and not just the login name. Yes this means we
2078 called map_username() unnecessarily in make_user_info_map() but
2079 that is how the current code is designed. Making the change here
2080 is the least disruptive place. -- jerry */
2082 /* this call will try to create the user if necessary */
2084 nt_status = check_account(tmp_ctx,
2085 nt_domain,
2086 nt_username,
2087 &found_username,
2088 &pwd,
2089 &username_was_mapped);
2091 if (!NT_STATUS_IS_OK(nt_status)) {
2092 /* Handle 'map to guest = Bad Uid */
2093 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
2094 (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
2095 lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
2096 DBG_NOTICE("Try to map %s to guest account",
2097 nt_username);
2098 nt_status = make_server_info_guest(tmp_ctx, &result);
2099 if (NT_STATUS_IS_OK(nt_status)) {
2100 *server_info = talloc_move(mem_ctx, &result);
2103 goto out;
2106 result = make_server_info(tmp_ctx);
2107 if (result == NULL) {
2108 DEBUG(4, ("make_server_info failed!\n"));
2109 nt_status = NT_STATUS_NO_MEMORY;
2110 goto out;
2113 result->unix_name = talloc_strdup(result, found_username);
2115 /* copy in the info3 */
2116 nt_status = copy_netr_SamInfo3(result,
2117 info3,
2118 &result->info3);
2119 if (!NT_STATUS_IS_OK(nt_status)) {
2120 goto out;
2123 /* Fill in the unix info we found on the way */
2125 result->utok.uid = pwd->pw_uid;
2126 result->utok.gid = pwd->pw_gid;
2128 /* ensure we are never given NULL session keys */
2130 if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
2131 result->session_key = data_blob_null;
2132 } else {
2133 result->session_key = data_blob_talloc(
2134 result, info3->base.key.key,
2135 sizeof(info3->base.key.key));
2138 if (all_zero(info3->base.LMSessKey.key,
2139 sizeof(info3->base.LMSessKey.key))) {
2140 result->lm_session_key = data_blob_null;
2141 } else {
2142 result->lm_session_key = data_blob_talloc(
2143 result, info3->base.LMSessKey.key,
2144 sizeof(info3->base.LMSessKey.key));
2147 result->nss_token |= username_was_mapped;
2149 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
2151 *server_info = talloc_move(mem_ctx, &result);
2153 nt_status = NT_STATUS_OK;
2154 out:
2155 talloc_free(tmp_ctx);
2157 return nt_status;
2160 /*****************************************************************************
2161 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
2162 ******************************************************************************/
2164 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
2165 const char *sent_nt_username,
2166 const char *domain,
2167 const struct wbcAuthUserInfo *info,
2168 struct auth_serversupplied_info **server_info)
2170 struct netr_SamInfo3 info3;
2171 struct netr_SamInfo6 *info6;
2173 info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
2174 if (!info6) {
2175 return NT_STATUS_NO_MEMORY;
2178 info3.base = info6->base;
2179 info3.sidcount = info6->sidcount;
2180 info3.sids = info6->sids;
2182 return make_server_info_info3(mem_ctx,
2183 sent_nt_username, domain,
2184 server_info, &info3);
2188 * Verify whether or not given domain is trusted.
2190 * This should only be used on a DC.
2192 * @param domain_name name of the domain to be verified
2193 * @return true if domain is one of the trusted ones or
2194 * false if otherwise
2197 bool is_trusted_domain(const char* dom_name)
2199 bool ret;
2201 if (!IS_DC) {
2202 return false;
2205 if (dom_name == NULL || dom_name[0] == '\0') {
2206 return false;
2209 if (strequal(dom_name, get_global_sam_name())) {
2210 return false;
2213 become_root();
2214 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2215 "[%s]\n", dom_name ));
2216 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2217 unbecome_root();
2219 return ret;
2225 on a logon error possibly map the error to success if "map to guest"
2226 is set approriately
2228 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
2229 NTSTATUS status,
2230 const char *user,
2231 const char *domain,
2232 struct auth_serversupplied_info **server_info)
2234 user = user ? user : "";
2235 domain = domain ? domain : "";
2237 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2238 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
2239 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
2240 DEBUG(3,("No such user %s [%s] - using guest account\n",
2241 user, domain));
2242 return make_server_info_guest(mem_ctx, server_info);
2244 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2245 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
2246 DEBUG(3,("Registered username %s for guest access\n",
2247 user));
2248 return make_server_info_guest(mem_ctx, server_info);
2252 return status;
2256 Extract session key from a session info and return it in a blob
2257 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
2259 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
2260 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
2262 Note that returned session_key is referencing the original key, it is supposed to be
2263 short-lived. If original session_info->session_key is gone, the reference will be broken.
2265 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
2268 if (session_key == NULL || session_info == NULL) {
2269 return NT_STATUS_INVALID_PARAMETER;
2272 if (session_info->session_key.length == 0) {
2273 return NT_STATUS_NO_USER_SESSION_KEY;
2276 *session_key = session_info->session_key;
2277 if (intent == KEY_USE_16BYTES) {
2278 session_key->length = MIN(session_info->session_key.length, 16);
2280 return NT_STATUS_OK;