winbindd: assert wb_parent_idmap_setup_send/recv() was called before idmap_child_handle()
[Samba.git] / source3 / auth / auth_util.c
blob9427c05f573d5c20073bec3f8b0b708886a7be71
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;
480 struct unixid *ids;
482 /* Ensure we can't possible take a code path leading to a
483 * null defref. */
484 if (!server_info) {
485 return NT_STATUS_LOGON_FAILURE;
488 if (server_info->cached_session_info != NULL) {
489 session_info = copy_session_info(mem_ctx,
490 server_info->cached_session_info);
491 if (session_info == NULL) {
492 return NT_STATUS_NO_MEMORY;
495 /* This is a potentially untrusted username for use in %U */
496 session_info->unix_info->sanitized_username =
497 talloc_alpha_strcpy(session_info->unix_info,
498 smb_username,
499 SAFE_NETBIOS_CHARS "$");
500 if (session_info->unix_info->sanitized_username == NULL) {
501 TALLOC_FREE(session_info);
502 return NT_STATUS_NO_MEMORY;
505 session_info->unique_session_token = GUID_random();
507 *session_info_out = session_info;
508 return NT_STATUS_OK;
511 session_info = talloc_zero(mem_ctx, struct auth_session_info);
512 if (!session_info) {
513 return NT_STATUS_NO_MEMORY;
516 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
517 if (!session_info->unix_token) {
518 TALLOC_FREE(session_info);
519 return NT_STATUS_NO_MEMORY;
522 session_info->unix_token->uid = server_info->utok.uid;
523 session_info->unix_token->gid = server_info->utok.gid;
525 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
526 if (!session_info->unix_info) {
527 TALLOC_FREE(session_info);
528 return NT_STATUS_NO_MEMORY;
531 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
532 if (!session_info->unix_info->unix_name) {
533 TALLOC_FREE(session_info);
534 return NT_STATUS_NO_MEMORY;
537 /* This is a potentially untrusted username for use in %U */
538 session_info->unix_info->sanitized_username =
539 talloc_alpha_strcpy(session_info->unix_info,
540 smb_username,
541 SAFE_NETBIOS_CHARS "$");
542 if (session_info->unix_info->sanitized_username == NULL) {
543 TALLOC_FREE(session_info);
544 return NT_STATUS_NO_MEMORY;
547 if (session_key) {
548 data_blob_free(&session_info->session_key);
549 session_info->session_key = data_blob_talloc(session_info,
550 session_key->data,
551 session_key->length);
552 if (!session_info->session_key.data && session_key->length) {
553 return NT_STATUS_NO_MEMORY;
555 } else {
556 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
557 server_info->session_key.length);
560 /* We need to populate session_info->info with the information found in server_info->info3 */
561 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
562 server_info->guest == false,
563 &session_info->info);
564 if (!NT_STATUS_IS_OK(status)) {
565 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
566 TALLOC_FREE(session_info);
567 return status;
571 * If winbind is not around, we can not make much use of the SIDs the
572 * domain controller provided us with. Likewise if the user name was
573 * mapped to some local unix user.
576 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
577 (server_info->nss_token)) {
578 char *found_username = NULL;
579 status = create_token_from_username(session_info,
580 server_info->unix_name,
581 server_info->guest,
582 &session_info->unix_token->uid,
583 &session_info->unix_token->gid,
584 &found_username,
585 &session_info->security_token);
586 if (NT_STATUS_IS_OK(status)) {
587 session_info->unix_info->unix_name = found_username;
589 } else {
590 status = create_local_nt_token_from_info3(session_info,
591 server_info->guest,
592 server_info->info3,
593 &server_info->extra,
594 &session_info->security_token);
597 if (!NT_STATUS_IS_OK(status)) {
598 return status;
601 /* Convert the SIDs to gids. */
603 session_info->unix_token->ngroups = 0;
604 session_info->unix_token->groups = NULL;
606 t = session_info->security_token;
608 ids = talloc_array(talloc_tos(), struct unixid,
609 t->num_sids);
610 if (ids == NULL) {
611 return NT_STATUS_NO_MEMORY;
614 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
615 TALLOC_FREE(ids);
616 return NT_STATUS_NO_MEMORY;
619 for (i=0; i<t->num_sids; i++) {
621 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
622 continue;
625 if (ids[i].type != ID_TYPE_GID &&
626 ids[i].type != ID_TYPE_BOTH) {
627 struct dom_sid_buf buf;
628 DEBUG(10, ("Could not convert SID %s to gid, "
629 "ignoring it\n",
630 dom_sid_str_buf(&t->sids[i], &buf)));
631 continue;
633 if (!add_gid_to_array_unique(session_info->unix_token,
634 ids[i].id,
635 &session_info->unix_token->groups,
636 &session_info->unix_token->ngroups)) {
637 return NT_STATUS_NO_MEMORY;
642 * Add the "Unix Group" SID for each gid to catch mapped groups
643 * and their Unix equivalent. This is to solve the backwards
644 * compatibility problem of 'valid users = +ntadmin' where
645 * ntadmin has been paired with "Domain Admins" in the group
646 * mapping table. Otherwise smb.conf would need to be changed
647 * to 'valid user = "Domain Admins"'. --jerry
649 * For consistency we also add the "Unix User" SID,
650 * so that the complete unix token is represented within
651 * the nt token.
654 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
655 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
656 &session_info->security_token->sids,
657 &session_info->security_token->num_sids);
659 gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
660 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
661 &session_info->security_token->sids,
662 &session_info->security_token->num_sids);
664 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
665 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
666 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
667 &session_info->security_token->sids,
668 &session_info->security_token->num_sids);
671 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
672 debug_unix_user_token(DBGC_AUTH, 10,
673 session_info->unix_token->uid,
674 session_info->unix_token->gid,
675 session_info->unix_token->ngroups,
676 session_info->unix_token->groups);
678 status = log_nt_token(session_info->security_token);
679 if (!NT_STATUS_IS_OK(status)) {
680 return status;
683 session_info->unique_session_token = GUID_random();
685 *session_info_out = session_info;
686 return NT_STATUS_OK;
689 NTSTATUS auth3_user_info_dc_add_hints(struct auth_user_info_dc *user_info_dc,
690 uid_t uid,
691 gid_t gid,
692 uint32_t flags)
694 uint32_t orig_num_sids = user_info_dc->num_sids;
695 struct dom_sid tmp_sid = { 0, };
696 NTSTATUS status;
699 * We add S-5-88-1-X in order to pass the uid
700 * for the unix token.
702 sid_compose(&tmp_sid,
703 &global_sid_Unix_NFS_Users,
704 (uint32_t)uid);
705 status = add_sid_to_array_unique(user_info_dc->sids,
706 &tmp_sid,
707 &user_info_dc->sids,
708 &user_info_dc->num_sids);
709 if (!NT_STATUS_IS_OK(status)) {
710 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
711 nt_errstr(status)));
712 goto fail;
716 * We add S-5-88-2-X in order to pass the gid
717 * for the unix token.
719 sid_compose(&tmp_sid,
720 &global_sid_Unix_NFS_Groups,
721 (uint32_t)gid);
722 status = add_sid_to_array_unique(user_info_dc->sids,
723 &tmp_sid,
724 &user_info_dc->sids,
725 &user_info_dc->num_sids);
726 if (!NT_STATUS_IS_OK(status)) {
727 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
728 nt_errstr(status)));
729 goto fail;
733 * We add S-5-88-3-X in order to pass some flags
734 * (AUTH3_UNIX_HINT_*) to auth3_create_session_info().
736 sid_compose(&tmp_sid,
737 &global_sid_Unix_NFS_Mode,
738 flags);
739 status = add_sid_to_array_unique(user_info_dc->sids,
740 &tmp_sid,
741 &user_info_dc->sids,
742 &user_info_dc->num_sids);
743 if (!NT_STATUS_IS_OK(status)) {
744 DEBUG(0, ("add_sid_to_array_unique failed: %s\n",
745 nt_errstr(status)));
746 goto fail;
749 return NT_STATUS_OK;
751 fail:
752 user_info_dc->num_sids = orig_num_sids;
753 return status;
756 NTSTATUS auth3_session_info_create(TALLOC_CTX *mem_ctx,
757 const struct auth_user_info_dc *user_info_dc,
758 const char *original_user_name,
759 uint32_t session_info_flags,
760 struct auth_session_info **session_info_out)
762 TALLOC_CTX *frame = talloc_stackframe();
763 struct auth_session_info *session_info = NULL;
764 uid_t hint_uid = -1;
765 bool found_hint_uid = false;
766 uid_t hint_gid = -1;
767 bool found_hint_gid = false;
768 uint32_t hint_flags = 0;
769 bool found_hint_flags = false;
770 bool need_getpwuid = false;
771 struct unixid *ids = NULL;
772 uint32_t num_gids = 0;
773 gid_t *gids = NULL;
774 struct dom_sid tmp_sid = { 0, };
775 NTSTATUS status;
776 size_t i;
777 bool ok;
779 *session_info_out = NULL;
781 if (user_info_dc->num_sids == 0) {
782 TALLOC_FREE(frame);
783 return NT_STATUS_INVALID_TOKEN;
786 if (user_info_dc->info == NULL) {
787 TALLOC_FREE(frame);
788 return NT_STATUS_INVALID_TOKEN;
791 if (user_info_dc->info->account_name == NULL) {
792 TALLOC_FREE(frame);
793 return NT_STATUS_INVALID_TOKEN;
796 session_info = talloc_zero(mem_ctx, struct auth_session_info);
797 if (session_info == NULL) {
798 TALLOC_FREE(frame);
799 return NT_STATUS_NO_MEMORY;
801 /* keep this under frame for easier cleanup */
802 talloc_reparent(mem_ctx, frame, session_info);
804 session_info->info = auth_user_info_copy(session_info,
805 user_info_dc->info);
806 if (session_info->info == NULL) {
807 TALLOC_FREE(frame);
808 return NT_STATUS_NO_MEMORY;
811 session_info->security_token = talloc_zero(session_info,
812 struct security_token);
813 if (session_info->security_token == NULL) {
814 TALLOC_FREE(frame);
815 return NT_STATUS_NO_MEMORY;
819 * Avoid a lot of reallocations and allocate what we'll
820 * use in most cases.
822 session_info->security_token->sids = talloc_zero_array(
823 session_info->security_token,
824 struct dom_sid,
825 user_info_dc->num_sids);
826 if (session_info->security_token->sids == NULL) {
827 TALLOC_FREE(frame);
828 return NT_STATUS_NO_MEMORY;
831 for (i = PRIMARY_USER_SID_INDEX; i < user_info_dc->num_sids; i++) {
832 struct security_token *nt_token = session_info->security_token;
833 int cmp;
836 * S-1-5-88-X-Y sids are only used to give hints
837 * to the unix token construction.
839 * S-1-5-88-1-Y gives the uid=Y
840 * S-1-5-88-2-Y gives the gid=Y
841 * S-1-5-88-3-Y gives flags=Y: AUTH3_UNIX_HINT_*
843 cmp = dom_sid_compare_domain(&global_sid_Unix_NFS,
844 &user_info_dc->sids[i]);
845 if (cmp == 0) {
846 bool match;
847 uint32_t hint = 0;
849 match = sid_peek_rid(&user_info_dc->sids[i], &hint);
850 if (!match) {
851 continue;
854 match = dom_sid_in_domain(&global_sid_Unix_NFS_Users,
855 &user_info_dc->sids[i]);
856 if (match) {
857 if (found_hint_uid) {
858 TALLOC_FREE(frame);
859 return NT_STATUS_INVALID_TOKEN;
861 found_hint_uid = true;
862 hint_uid = (uid_t)hint;
863 continue;
866 match = dom_sid_in_domain(&global_sid_Unix_NFS_Groups,
867 &user_info_dc->sids[i]);
868 if (match) {
869 if (found_hint_gid) {
870 TALLOC_FREE(frame);
871 return NT_STATUS_INVALID_TOKEN;
873 found_hint_gid = true;
874 hint_gid = (gid_t)hint;
875 continue;
878 match = dom_sid_in_domain(&global_sid_Unix_NFS_Mode,
879 &user_info_dc->sids[i]);
880 if (match) {
881 if (found_hint_flags) {
882 TALLOC_FREE(frame);
883 return NT_STATUS_INVALID_TOKEN;
885 found_hint_flags = true;
886 hint_flags = hint;
887 continue;
890 continue;
893 status = add_sid_to_array_unique(nt_token->sids,
894 &user_info_dc->sids[i],
895 &nt_token->sids,
896 &nt_token->num_sids);
897 if (!NT_STATUS_IS_OK(status)) {
898 TALLOC_FREE(frame);
899 return status;
904 * We need at least one usable SID
906 if (session_info->security_token->num_sids == 0) {
907 TALLOC_FREE(frame);
908 return NT_STATUS_INVALID_TOKEN;
912 * We need all tree hints: uid, gid, flags
913 * or none of them.
915 if (found_hint_uid || found_hint_gid || found_hint_flags) {
916 if (!found_hint_uid) {
917 TALLOC_FREE(frame);
918 return NT_STATUS_INVALID_TOKEN;
921 if (!found_hint_gid) {
922 TALLOC_FREE(frame);
923 return NT_STATUS_INVALID_TOKEN;
926 if (!found_hint_flags) {
927 TALLOC_FREE(frame);
928 return NT_STATUS_INVALID_TOKEN;
932 if (session_info->info->authenticated) {
933 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
936 status = finalize_local_nt_token(session_info->security_token,
937 session_info_flags);
938 if (!NT_STATUS_IS_OK(status)) {
939 TALLOC_FREE(frame);
940 return status;
944 * unless set otherwise, the session key is the user session
945 * key from the auth subsystem
947 if (user_info_dc->user_session_key.length != 0) {
948 session_info->session_key = data_blob_dup_talloc(session_info,
949 user_info_dc->user_session_key);
950 if (session_info->session_key.data == NULL) {
951 TALLOC_FREE(frame);
952 return NT_STATUS_NO_MEMORY;
956 if (!(session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)) {
957 goto done;
960 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
961 if (session_info->unix_token == NULL) {
962 TALLOC_FREE(frame);
963 return NT_STATUS_NO_MEMORY;
965 session_info->unix_token->uid = -1;
966 session_info->unix_token->gid = -1;
968 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
969 if (session_info->unix_info == NULL) {
970 TALLOC_FREE(frame);
971 return NT_STATUS_NO_MEMORY;
974 /* Convert the SIDs to uid/gids. */
976 ids = talloc_zero_array(frame, struct unixid,
977 session_info->security_token->num_sids);
978 if (ids == NULL) {
979 TALLOC_FREE(frame);
980 return NT_STATUS_NO_MEMORY;
983 if (!(hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS)) {
984 ok = sids_to_unixids(session_info->security_token->sids,
985 session_info->security_token->num_sids,
986 ids);
987 if (!ok) {
988 TALLOC_FREE(frame);
989 return NT_STATUS_NO_MEMORY;
993 if (found_hint_uid) {
994 session_info->unix_token->uid = hint_uid;
995 } else if (ids[0].type == ID_TYPE_UID) {
997 * The primary SID resolves to a UID only.
999 session_info->unix_token->uid = ids[0].id;
1000 } else if (ids[0].type == ID_TYPE_BOTH) {
1002 * The primary SID resolves to a UID and GID,
1003 * use it as uid and add it as first element
1004 * to the groups array.
1006 session_info->unix_token->uid = ids[0].id;
1008 ok = add_gid_to_array_unique(session_info->unix_token,
1009 session_info->unix_token->uid,
1010 &session_info->unix_token->groups,
1011 &session_info->unix_token->ngroups);
1012 if (!ok) {
1013 TALLOC_FREE(frame);
1014 return NT_STATUS_NO_MEMORY;
1016 } else {
1018 * It we can't get a uid, we can't imporsonate
1019 * the user.
1021 TALLOC_FREE(frame);
1022 return NT_STATUS_INVALID_TOKEN;
1025 if (found_hint_gid) {
1026 session_info->unix_token->gid = hint_gid;
1027 } else {
1028 need_getpwuid = true;
1031 if (hint_flags & AUTH3_UNIX_HINT_QUALIFIED_NAME) {
1032 session_info->unix_info->unix_name =
1033 talloc_asprintf(session_info->unix_info,
1034 "%s%c%s",
1035 session_info->info->domain_name,
1036 *lp_winbind_separator(),
1037 session_info->info->account_name);
1038 if (session_info->unix_info->unix_name == NULL) {
1039 TALLOC_FREE(frame);
1040 return NT_STATUS_NO_MEMORY;
1042 } else if (hint_flags & AUTH3_UNIX_HINT_ISLOLATED_NAME) {
1043 session_info->unix_info->unix_name =
1044 talloc_strdup(session_info->unix_info,
1045 session_info->info->account_name);
1046 if (session_info->unix_info->unix_name == NULL) {
1047 TALLOC_FREE(frame);
1048 return NT_STATUS_NO_MEMORY;
1050 } else {
1051 need_getpwuid = true;
1054 if (need_getpwuid) {
1055 struct passwd *pwd = NULL;
1058 * Ask the system for the primary gid
1059 * and the real unix name.
1061 pwd = getpwuid_alloc(frame, session_info->unix_token->uid);
1062 if (pwd == NULL) {
1063 TALLOC_FREE(frame);
1064 return NT_STATUS_INVALID_TOKEN;
1066 if (!found_hint_gid) {
1067 session_info->unix_token->gid = pwd->pw_gid;
1070 session_info->unix_info->unix_name =
1071 talloc_strdup(session_info->unix_info, pwd->pw_name);
1072 if (session_info->unix_info->unix_name == NULL) {
1073 TALLOC_FREE(frame);
1074 return NT_STATUS_NO_MEMORY;
1077 TALLOC_FREE(pwd);
1080 ok = add_gid_to_array_unique(session_info->unix_token,
1081 session_info->unix_token->gid,
1082 &session_info->unix_token->groups,
1083 &session_info->unix_token->ngroups);
1084 if (!ok) {
1085 TALLOC_FREE(frame);
1086 return NT_STATUS_NO_MEMORY;
1089 /* This is a potentially untrusted username for use in %U */
1090 session_info->unix_info->sanitized_username =
1091 talloc_alpha_strcpy(session_info->unix_info,
1092 original_user_name,
1093 SAFE_NETBIOS_CHARS "$");
1094 if (session_info->unix_info->sanitized_username == NULL) {
1095 TALLOC_FREE(frame);
1096 return NT_STATUS_NO_MEMORY;
1099 for (i=0; i < session_info->security_token->num_sids; i++) {
1101 if (ids[i].type != ID_TYPE_GID &&
1102 ids[i].type != ID_TYPE_BOTH) {
1103 struct security_token *nt_token =
1104 session_info->security_token;
1105 struct dom_sid_buf buf;
1107 DEBUG(10, ("Could not convert SID %s to gid, "
1108 "ignoring it\n",
1109 dom_sid_str_buf(&nt_token->sids[i], &buf)));
1110 continue;
1113 ok = add_gid_to_array_unique(session_info->unix_token,
1114 ids[i].id,
1115 &session_info->unix_token->groups,
1116 &session_info->unix_token->ngroups);
1117 if (!ok) {
1118 TALLOC_FREE(frame);
1119 return NT_STATUS_NO_MEMORY;
1122 TALLOC_FREE(ids);
1125 * Now we must get any groups this user has been
1126 * added to in /etc/group and merge them in.
1127 * This has to be done in every code path
1128 * that creates an NT token, as remote users
1129 * may have been added to the local /etc/group
1130 * database. Tokens created merely from the
1131 * info3 structs (via the DC or via the krb5 PAC)
1132 * won't have these local groups. Note the
1133 * groups added here will only be UNIX groups
1134 * (S-1-22-2-XXXX groups) as getgroups_unix_user()
1135 * turns off winbindd before calling getgroups().
1137 * NB. This is duplicating work already
1138 * done in the 'unix_user:' case of
1139 * create_token_from_sid() but won't
1140 * do anything other than be inefficient
1141 * in that case.
1143 if (!(hint_flags & AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS)) {
1144 ok = getgroups_unix_user(frame,
1145 session_info->unix_info->unix_name,
1146 session_info->unix_token->gid,
1147 &gids, &num_gids);
1148 if (!ok) {
1149 TALLOC_FREE(frame);
1150 return NT_STATUS_INVALID_TOKEN;
1154 for (i=0; i < num_gids; i++) {
1156 ok = add_gid_to_array_unique(session_info->unix_token,
1157 gids[i],
1158 &session_info->unix_token->groups,
1159 &session_info->unix_token->ngroups);
1160 if (!ok) {
1161 TALLOC_FREE(frame);
1162 return NT_STATUS_NO_MEMORY;
1165 TALLOC_FREE(gids);
1167 if (hint_flags & AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS) {
1169 * We should not translate the unix token uid/gids
1170 * to S-1-22-X-Y SIDs.
1172 goto done;
1176 * Add the "Unix Group" SID for each gid to catch mapped groups
1177 * and their Unix equivalent. This is to solve the backwards
1178 * compatibility problem of 'valid users = +ntadmin' where
1179 * ntadmin has been paired with "Domain Admins" in the group
1180 * mapping table. Otherwise smb.conf would need to be changed
1181 * to 'valid user = "Domain Admins"'. --jerry
1183 * For consistency we also add the "Unix User" SID,
1184 * so that the complete unix token is represented within
1185 * the nt token.
1188 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
1189 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1190 &session_info->security_token->sids,
1191 &session_info->security_token->num_sids);
1192 if (!NT_STATUS_IS_OK(status)) {
1193 TALLOC_FREE(frame);
1194 return status;
1197 gid_to_unix_groups_sid(session_info->unix_token->gid, &tmp_sid);
1198 status = add_sid_to_array_unique(session_info->security_token, &tmp_sid,
1199 &session_info->security_token->sids,
1200 &session_info->security_token->num_sids);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 TALLOC_FREE(frame);
1203 return status;
1206 for (i=0; i < session_info->unix_token->ngroups; i++ ) {
1207 struct security_token *nt_token = session_info->security_token;
1209 gid_to_unix_groups_sid(session_info->unix_token->groups[i],
1210 &tmp_sid);
1211 status = add_sid_to_array_unique(nt_token->sids,
1212 &tmp_sid,
1213 &nt_token->sids,
1214 &nt_token->num_sids);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 TALLOC_FREE(frame);
1217 return status;
1221 done:
1222 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
1223 if (session_info->unix_token != NULL) {
1224 debug_unix_user_token(DBGC_AUTH, 10,
1225 session_info->unix_token->uid,
1226 session_info->unix_token->gid,
1227 session_info->unix_token->ngroups,
1228 session_info->unix_token->groups);
1231 status = log_nt_token(session_info->security_token);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 TALLOC_FREE(frame);
1234 return status;
1237 session_info->unique_session_token = GUID_random();
1239 *session_info_out = talloc_move(mem_ctx, &session_info);
1240 TALLOC_FREE(frame);
1241 return NT_STATUS_OK;
1244 /***************************************************************************
1245 Make (and fill) a server_info struct from a 'struct passwd' by conversion
1246 to a struct samu
1247 ***************************************************************************/
1249 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
1250 const char *unix_username,
1251 const struct passwd *pwd,
1252 struct auth_serversupplied_info **server_info)
1254 NTSTATUS status;
1255 TALLOC_CTX *tmp_ctx = NULL;
1256 struct auth_serversupplied_info *result;
1258 tmp_ctx = talloc_stackframe();
1259 if (tmp_ctx == NULL) {
1260 return NT_STATUS_NO_MEMORY;
1263 result = make_server_info(tmp_ctx);
1264 if (result == NULL) {
1265 status = NT_STATUS_NO_MEMORY;
1266 goto done;
1269 status = passwd_to_SamInfo3(result,
1270 unix_username,
1271 pwd,
1272 &result->info3,
1273 &result->extra);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 goto done;
1278 result->unix_name = talloc_strdup(result, unix_username);
1279 if (result->unix_name == NULL) {
1280 status = NT_STATUS_NO_MEMORY;
1281 goto done;
1284 result->utok.uid = pwd->pw_uid;
1285 result->utok.gid = pwd->pw_gid;
1287 *server_info = talloc_steal(mem_ctx, result);
1288 status = NT_STATUS_OK;
1289 done:
1290 talloc_free(tmp_ctx);
1292 return status;
1295 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
1296 struct netr_SamInfo3 *info3)
1298 const char *guest_account = lp_guest_account();
1299 struct dom_sid domain_sid;
1300 struct passwd *pwd;
1301 const char *tmp;
1303 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
1304 if (pwd == NULL) {
1305 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
1306 "account [%s]!\n", guest_account));
1307 return NT_STATUS_NO_SUCH_USER;
1310 /* Set account name */
1311 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
1312 if (tmp == NULL) {
1313 return NT_STATUS_NO_MEMORY;
1315 init_lsa_String(&info3->base.account_name, tmp);
1317 /* Set domain name */
1318 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
1319 if (tmp == NULL) {
1320 return NT_STATUS_NO_MEMORY;
1322 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
1324 /* Domain sid */
1325 sid_copy(&domain_sid, get_global_sam_sid());
1327 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
1328 if (info3->base.domain_sid == NULL) {
1329 return NT_STATUS_NO_MEMORY;
1332 /* Guest rid */
1333 info3->base.rid = DOMAIN_RID_GUEST;
1335 /* Primary gid */
1336 info3->base.primary_gid = DOMAIN_RID_GUESTS;
1338 /* Set as guest */
1339 info3->base.user_flags = NETLOGON_GUEST;
1341 TALLOC_FREE(pwd);
1342 return NT_STATUS_OK;
1345 /***************************************************************************
1346 Make (and fill) a user_info struct for a guest login.
1347 This *must* succeed for smbd to start. If there is no mapping entry for
1348 the guest gid, then create one.
1350 The resulting structure is a 'session_info' because
1351 create_local_token() has already been called on it. This is quite
1352 nasty, as the auth subsystem isn't expect this, but the behavior is
1353 left as-is for now.
1354 ***************************************************************************/
1356 static NTSTATUS make_new_session_info_guest(TALLOC_CTX *mem_ctx,
1357 struct auth_session_info **_session_info,
1358 struct auth_serversupplied_info **_server_info)
1360 struct auth_session_info *session_info = NULL;
1361 struct auth_serversupplied_info *server_info = NULL;
1362 const char *guest_account = lp_guest_account();
1363 const char *domain = lp_netbios_name();
1364 struct netr_SamInfo3 info3;
1365 TALLOC_CTX *tmp_ctx;
1366 NTSTATUS status;
1368 tmp_ctx = talloc_stackframe();
1369 if (tmp_ctx == NULL) {
1370 return NT_STATUS_NO_MEMORY;
1373 ZERO_STRUCT(info3);
1375 status = get_guest_info3(tmp_ctx, &info3);
1376 if (!NT_STATUS_IS_OK(status)) {
1377 DEBUG(0, ("get_guest_info3 failed with %s\n",
1378 nt_errstr(status)));
1379 goto done;
1382 status = make_server_info_info3(tmp_ctx,
1383 guest_account,
1384 domain,
1385 &server_info,
1386 &info3);
1387 if (!NT_STATUS_IS_OK(status)) {
1388 DEBUG(0, ("make_server_info_info3 failed with %s\n",
1389 nt_errstr(status)));
1390 goto done;
1393 server_info->guest = true;
1395 /* This should not be done here (we should produce a server
1396 * info, and later construct a session info from it), but for
1397 * now this does not change the previous behavior */
1398 status = create_local_token(tmp_ctx, server_info, NULL,
1399 server_info->info3->base.account_name.string,
1400 &session_info);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 DEBUG(0, ("create_local_token failed: %s\n",
1403 nt_errstr(status)));
1404 goto done;
1408 * It's ugly, but for now it's
1409 * needed to force Builtin_Guests
1410 * here, because memberships of
1411 * Builtin_Guests might be incomplete.
1413 status = add_sid_to_array_unique(session_info->security_token,
1414 &global_sid_Builtin_Guests,
1415 &session_info->security_token->sids,
1416 &session_info->security_token->num_sids);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 DBG_ERR("Failed to force Builtin_Guests to nt token\n");
1419 goto done;
1422 /* annoying, but the Guest really does have a session key, and it is
1423 all zeros! */
1424 session_info->session_key = data_blob_talloc_zero(session_info, 16);
1426 *_session_info = talloc_move(mem_ctx, &session_info);
1427 *_server_info = talloc_move(mem_ctx, &server_info);
1429 status = NT_STATUS_OK;
1430 done:
1431 TALLOC_FREE(tmp_ctx);
1432 return status;
1435 /***************************************************************************
1436 Make (and fill) a auth_session_info struct for a system user login.
1437 This *must* succeed for smbd to start.
1438 ***************************************************************************/
1440 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
1441 struct auth_session_info **session_info)
1443 TALLOC_CTX *frame = talloc_stackframe();
1444 struct auth_user_info_dc *user_info_dc = NULL;
1445 uid_t uid = -1;
1446 gid_t gid = -1;
1447 uint32_t hint_flags = 0;
1448 uint32_t session_info_flags = 0;
1449 NTSTATUS status;
1451 status = auth_system_user_info_dc(frame, lp_netbios_name(),
1452 &user_info_dc);
1453 if (!NT_STATUS_IS_OK(status)) {
1454 DEBUG(0, ("auth_system_user_info_dc failed: %s\n",
1455 nt_errstr(status)));
1456 goto done;
1460 * Just get the initial uid/gid
1461 * and don't expand the unix groups.
1463 uid = sec_initial_uid();
1464 gid = sec_initial_gid();
1465 hint_flags |= AUTH3_UNIX_HINT_DONT_EXPAND_UNIX_GROUPS;
1468 * Also avoid sid mapping to gids,
1469 * as well as adding the unix_token uid/gids as
1470 * S-1-22-X-Y SIDs to the nt token.
1472 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_FROM_SIDS;
1473 hint_flags |= AUTH3_UNIX_HINT_DONT_TRANSLATE_TO_SIDS;
1476 * The unix name will be "NT AUTHORITY+SYSTEM",
1477 * where '+' is the "winbind separator" character.
1479 hint_flags |= AUTH3_UNIX_HINT_QUALIFIED_NAME;
1480 status = auth3_user_info_dc_add_hints(user_info_dc,
1481 uid,
1482 gid,
1483 hint_flags);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1486 nt_errstr(status)));
1487 goto done;
1490 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1491 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1492 status = auth3_session_info_create(mem_ctx, user_info_dc,
1493 user_info_dc->info->account_name,
1494 session_info_flags,
1495 session_info);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1498 nt_errstr(status)));
1499 goto done;
1502 done:
1503 TALLOC_FREE(frame);
1504 return status;
1507 static NTSTATUS make_new_session_info_anonymous(TALLOC_CTX *mem_ctx,
1508 struct auth_session_info **session_info)
1510 TALLOC_CTX *frame = talloc_stackframe();
1511 const char *guest_account = lp_guest_account();
1512 struct auth_user_info_dc *user_info_dc = NULL;
1513 struct passwd *pwd = NULL;
1514 uint32_t hint_flags = 0;
1515 uint32_t session_info_flags = 0;
1516 NTSTATUS status;
1519 * We use the guest account for the unix token
1520 * while we use a true anonymous nt token.
1522 * It's very important to have a separate
1523 * nt token for anonymous.
1526 pwd = Get_Pwnam_alloc(frame, guest_account);
1527 if (pwd == NULL) {
1528 DBG_ERR("Unable to locate guest account [%s]!\n",
1529 guest_account);
1530 status = NT_STATUS_NO_SUCH_USER;
1531 goto done;
1534 status = auth_anonymous_user_info_dc(frame, lp_netbios_name(),
1535 &user_info_dc);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 DEBUG(0, ("auth_anonymous_user_info_dc failed: %s\n",
1538 nt_errstr(status)));
1539 goto done;
1543 * Note we don't pass AUTH3_UNIX_HINT_QUALIFIED_NAME
1544 * nor AUTH3_UNIX_HINT_ISOLATED_NAME here
1545 * as we want the unix name be found by getpwuid_alloc().
1548 status = auth3_user_info_dc_add_hints(user_info_dc,
1549 pwd->pw_uid,
1550 pwd->pw_gid,
1551 hint_flags);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 DEBUG(0, ("auth3_user_info_dc_add_hints failed: %s\n",
1554 nt_errstr(status)));
1555 goto done;
1559 * In future we may want to remove
1560 * AUTH_SESSION_INFO_DEFAULT_GROUPS.
1562 * Similar to Windows with EveryoneIncludesAnonymous
1563 * and RestrictAnonymous.
1565 * We may introduce AUTH_SESSION_INFO_ANON_WORLD...
1567 * But for this is required to keep the existing tests
1568 * working.
1570 session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
1571 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1572 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1573 status = auth3_session_info_create(mem_ctx, user_info_dc,
1575 session_info_flags,
1576 session_info);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 DEBUG(0, ("auth3_session_info_create failed: %s\n",
1579 nt_errstr(status)));
1580 goto done;
1583 done:
1584 TALLOC_FREE(frame);
1585 return status;
1588 /****************************************************************************
1589 Fake a auth_session_info just from a username (as a
1590 session_info structure, with create_local_token() already called on
1592 ****************************************************************************/
1594 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
1595 const char *username,
1596 bool is_guest,
1597 struct auth_session_info **session_info)
1599 struct passwd *pwd;
1600 NTSTATUS status;
1601 struct auth_serversupplied_info *result;
1602 TALLOC_CTX *tmp_ctx;
1604 tmp_ctx = talloc_stackframe();
1605 if (tmp_ctx == NULL) {
1606 return NT_STATUS_NO_MEMORY;
1609 pwd = Get_Pwnam_alloc(tmp_ctx, username);
1610 if (pwd == NULL) {
1611 status = NT_STATUS_NO_SUCH_USER;
1612 goto done;
1615 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 goto done;
1620 result->nss_token = true;
1621 result->guest = is_guest;
1623 /* Now turn the server_info into a session_info with the full token etc */
1624 status = create_local_token(mem_ctx,
1625 result,
1626 NULL,
1627 pwd->pw_name,
1628 session_info);
1630 done:
1631 talloc_free(tmp_ctx);
1633 return status;
1636 /* This function MUST only used to create the cached server_info for
1637 * guest.
1639 * This is a lossy conversion. Variables known to be lost so far
1640 * include:
1642 * - nss_token (not needed because the only read doesn't happen
1643 * for the GUEST user, as this routine populates ->security_token
1645 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1647 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1649 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1650 const struct auth_session_info *src,
1651 struct auth_serversupplied_info *server_info)
1653 struct auth_serversupplied_info *dst;
1654 NTSTATUS status;
1656 dst = make_server_info(mem_ctx);
1657 if (dst == NULL) {
1658 return NULL;
1661 /* This element must be provided to convert back to an auth_serversupplied_info */
1662 SMB_ASSERT(src->unix_info);
1664 dst->guest = true;
1666 /* This element must be provided to convert back to an
1667 * auth_serversupplied_info. This needs to be from the
1668 * auth_session_info because the group values in particular
1669 * may change during create_local_token() processing */
1670 SMB_ASSERT(src->unix_token);
1671 dst->utok.uid = src->unix_token->uid;
1672 dst->utok.gid = src->unix_token->gid;
1673 dst->utok.ngroups = src->unix_token->ngroups;
1674 if (src->unix_token->ngroups != 0) {
1675 dst->utok.groups = (gid_t *)talloc_memdup(
1676 dst, src->unix_token->groups,
1677 sizeof(gid_t)*dst->utok.ngroups);
1678 } else {
1679 dst->utok.groups = NULL;
1682 /* We must have a security_token as otherwise the lossy
1683 * conversion without nss_token would cause create_local_token
1684 * to take the wrong path */
1685 SMB_ASSERT(src->security_token);
1687 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1688 src->session_key.length);
1690 /* This is OK because this functions is only used for the
1691 * GUEST account, which has all-zero keys for both values */
1692 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1693 src->session_key.length);
1695 status = copy_netr_SamInfo3(dst,
1696 server_info->info3,
1697 &dst->info3);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 TALLOC_FREE(dst);
1700 return NULL;
1703 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1704 if (!dst->unix_name) {
1705 TALLOC_FREE(dst);
1706 return NULL;
1709 dst->cached_session_info = src;
1710 return dst;
1714 * Set a new session key. Used in the rpc server where we have to override the
1715 * SMB level session key with SystemLibraryDTC
1718 bool session_info_set_session_key(struct auth_session_info *info,
1719 DATA_BLOB session_key)
1721 TALLOC_FREE(info->session_key.data);
1723 info->session_key = data_blob_talloc(
1724 info, session_key.data, session_key.length);
1726 return (info->session_key.data != NULL);
1729 static struct auth_session_info *guest_info = NULL;
1730 static struct auth_session_info *anonymous_info = NULL;
1732 static struct auth_serversupplied_info *guest_server_info = NULL;
1734 bool init_guest_session_info(TALLOC_CTX *mem_ctx)
1736 NTSTATUS status;
1738 if (guest_info != NULL)
1739 return true;
1741 status = make_new_session_info_guest(mem_ctx,
1742 &guest_info,
1743 &guest_server_info);
1744 if (!NT_STATUS_IS_OK(status)) {
1745 return false;
1748 status = make_new_session_info_anonymous(mem_ctx,
1749 &anonymous_info);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 return false;
1754 return true;
1757 bool reinit_guest_session_info(TALLOC_CTX *mem_ctx)
1759 TALLOC_FREE(guest_info);
1760 TALLOC_FREE(guest_server_info);
1761 TALLOC_FREE(anonymous_info);
1763 DBG_DEBUG("Reinitialing guest info\n");
1765 return init_guest_session_info(mem_ctx);
1768 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1769 struct auth_serversupplied_info **server_info)
1771 /* This is trickier than it would appear to need to be because
1772 * we are trying to avoid certain costly operations when the
1773 * structure is converted to a 'auth_session_info' again in
1774 * create_local_token() */
1775 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1776 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1779 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1780 struct auth_session_info **session_info)
1782 *session_info = copy_session_info(mem_ctx, guest_info);
1783 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1786 NTSTATUS make_server_info_anonymous(TALLOC_CTX *mem_ctx,
1787 struct auth_serversupplied_info **server_info)
1789 if (anonymous_info == NULL) {
1790 return NT_STATUS_UNSUCCESSFUL;
1794 * This is trickier than it would appear to need to be because
1795 * we are trying to avoid certain costly operations when the
1796 * structure is converted to a 'auth_session_info' again in
1797 * create_local_token()
1799 * We use a guest server_info, but with the anonymous session info,
1800 * which means create_local_token() will return a copy
1801 * of the anonymous token.
1803 * The server info is just used as legacy in order to
1804 * keep existing code working. Maybe some debug messages
1805 * will still refer to guest instead of anonymous.
1807 *server_info = copy_session_info_serverinfo_guest(mem_ctx, anonymous_info,
1808 guest_server_info);
1809 if (*server_info == NULL) {
1810 return NT_STATUS_NO_MEMORY;
1813 return NT_STATUS_OK;
1816 NTSTATUS make_session_info_anonymous(TALLOC_CTX *mem_ctx,
1817 struct auth_session_info **session_info)
1819 if (anonymous_info == NULL) {
1820 return NT_STATUS_UNSUCCESSFUL;
1823 *session_info = copy_session_info(mem_ctx, anonymous_info);
1824 if (*session_info == NULL) {
1825 return NT_STATUS_NO_MEMORY;
1828 return NT_STATUS_OK;
1831 static struct auth_session_info *system_info = NULL;
1833 NTSTATUS init_system_session_info(TALLOC_CTX *mem_ctx)
1835 if (system_info != NULL)
1836 return NT_STATUS_OK;
1838 return make_new_session_info_system(mem_ctx, &system_info);
1841 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1842 struct auth_session_info **session_info)
1844 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1845 *session_info = copy_session_info(mem_ctx, system_info);
1846 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1849 const struct auth_session_info *get_session_info_system(void)
1851 return system_info;
1854 /***************************************************************************
1855 Purely internal function for make_server_info_info3
1856 ***************************************************************************/
1858 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1859 const char *username, char **found_username,
1860 struct passwd **pwd,
1861 bool *username_was_mapped)
1863 char *orig_dom_user = NULL;
1864 char *dom_user = NULL;
1865 char *lower_username = NULL;
1866 char *real_username = NULL;
1867 struct passwd *passwd;
1869 lower_username = talloc_strdup(mem_ctx, username);
1870 if (!lower_username) {
1871 return NT_STATUS_NO_MEMORY;
1873 if (!strlower_m( lower_username )) {
1874 return NT_STATUS_INVALID_PARAMETER;
1877 orig_dom_user = talloc_asprintf(mem_ctx,
1878 "%s%c%s",
1879 domain,
1880 *lp_winbind_separator(),
1881 lower_username);
1882 if (!orig_dom_user) {
1883 return NT_STATUS_NO_MEMORY;
1886 /* Get the passwd struct. Try to create the account if necessary. */
1888 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1889 if (!dom_user) {
1890 return NT_STATUS_NO_MEMORY;
1893 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1894 if (!passwd) {
1895 DEBUG(3, ("Failed to find authenticated user %s via "
1896 "getpwnam(), denying access.\n", dom_user));
1897 return NT_STATUS_NO_SUCH_USER;
1900 if (!real_username) {
1901 return NT_STATUS_NO_MEMORY;
1904 *pwd = passwd;
1906 /* This is pointless -- there is no support for differing
1907 unix and windows names. Make sure to always store the
1908 one we actually looked up and succeeded. Have I mentioned
1909 why I hate the 'winbind use default domain' parameter?
1910 --jerry */
1912 *found_username = talloc_strdup( mem_ctx, real_username );
1914 return NT_STATUS_OK;
1917 /****************************************************************************
1918 Wrapper to allow the getpwnam() call to strip the domain name and
1919 try again in case a local UNIX user is already there. Also run through
1920 the username if we fallback to the username only.
1921 ****************************************************************************/
1923 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1924 char **p_save_username, bool create )
1926 struct passwd *pw = NULL;
1927 char *p = NULL;
1928 char *username = NULL;
1930 /* we only save a copy of the username it has been mangled
1931 by winbindd use default domain */
1932 *p_save_username = NULL;
1934 /* don't call map_username() here since it has to be done higher
1935 up the stack so we don't call it multiple times */
1937 username = talloc_strdup(mem_ctx, domuser);
1938 if (!username) {
1939 return NULL;
1942 p = strchr_m( username, *lp_winbind_separator() );
1944 /* code for a DOMAIN\user string */
1946 if ( p ) {
1947 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1948 if ( pw ) {
1949 /* make sure we get the case of the username correct */
1950 /* work around 'winbind use default domain = yes' */
1952 if ( lp_winbind_use_default_domain() &&
1953 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1954 char *domain;
1956 /* split the domain and username into 2 strings */
1957 *p = '\0';
1958 domain = username;
1960 *p_save_username = talloc_asprintf(mem_ctx,
1961 "%s%c%s",
1962 domain,
1963 *lp_winbind_separator(),
1964 pw->pw_name);
1965 if (!*p_save_username) {
1966 TALLOC_FREE(pw);
1967 return NULL;
1969 } else {
1970 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1973 /* whew -- done! */
1974 return pw;
1977 /* setup for lookup of just the username */
1978 /* remember that p and username are overlapping memory */
1980 p++;
1981 username = talloc_strdup(mem_ctx, p);
1982 if (!username) {
1983 return NULL;
1987 /* just lookup a plain username */
1989 pw = Get_Pwnam_alloc(mem_ctx, username);
1991 /* Create local user if requested but only if winbindd
1992 is not running. We need to protect against cases
1993 where winbindd is failing and then prematurely
1994 creating users in /etc/passwd */
1996 if ( !pw && create && !winbind_ping() ) {
1997 /* Don't add a machine account. */
1998 if (username[strlen(username)-1] == '$')
1999 return NULL;
2001 _smb_create_user(NULL, username, NULL);
2002 pw = Get_Pwnam_alloc(mem_ctx, username);
2005 /* one last check for a valid passwd struct */
2007 if (pw) {
2008 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
2010 return pw;
2013 /***************************************************************************
2014 Make a server_info struct from the info3 returned by a domain logon
2015 ***************************************************************************/
2017 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
2018 const char *sent_nt_username,
2019 const char *domain,
2020 struct auth_serversupplied_info **server_info,
2021 const struct netr_SamInfo3 *info3)
2023 NTSTATUS nt_status;
2024 char *found_username = NULL;
2025 const char *nt_domain;
2026 const char *nt_username;
2027 struct dom_sid user_sid;
2028 struct dom_sid group_sid;
2029 bool username_was_mapped;
2030 struct passwd *pwd;
2031 struct auth_serversupplied_info *result;
2032 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2035 Here is where we should check the list of
2036 trusted domains, and verify that the SID
2037 matches.
2040 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
2041 nt_status = NT_STATUS_INVALID_PARAMETER;
2042 goto out;
2045 if (!sid_compose(&group_sid, info3->base.domain_sid,
2046 info3->base.primary_gid)) {
2047 nt_status = NT_STATUS_INVALID_PARAMETER;
2048 goto out;
2051 nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
2052 if (!nt_username) {
2053 /* If the server didn't give us one, just use the one we sent
2054 * them */
2055 nt_username = sent_nt_username;
2058 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
2059 if (!nt_domain) {
2060 /* If the server didn't give us one, just use the one we sent
2061 * them */
2062 nt_domain = domain;
2065 /* If getpwnam() fails try the add user script (2.2.x behavior).
2067 We use the _unmapped_ username here in an attempt to provide
2068 consistent username mapping behavior between kerberos and NTLM[SSP]
2069 authentication in domain mode security. I.E. Username mapping
2070 should be applied to the fully qualified username
2071 (e.g. DOMAIN\user) and not just the login name. Yes this means we
2072 called map_username() unnecessarily in make_user_info_map() but
2073 that is how the current code is designed. Making the change here
2074 is the least disruptive place. -- jerry */
2076 /* this call will try to create the user if necessary */
2078 nt_status = check_account(tmp_ctx,
2079 nt_domain,
2080 nt_username,
2081 &found_username,
2082 &pwd,
2083 &username_was_mapped);
2085 if (!NT_STATUS_IS_OK(nt_status)) {
2086 /* Handle 'map to guest = Bad Uid */
2087 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
2088 (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
2089 lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
2090 DBG_NOTICE("Try to map %s to guest account",
2091 nt_username);
2092 nt_status = make_server_info_guest(tmp_ctx, &result);
2093 if (NT_STATUS_IS_OK(nt_status)) {
2094 *server_info = talloc_move(mem_ctx, &result);
2097 goto out;
2100 result = make_server_info(tmp_ctx);
2101 if (result == NULL) {
2102 DEBUG(4, ("make_server_info failed!\n"));
2103 nt_status = NT_STATUS_NO_MEMORY;
2104 goto out;
2107 result->unix_name = talloc_strdup(result, found_username);
2109 /* copy in the info3 */
2110 nt_status = copy_netr_SamInfo3(result,
2111 info3,
2112 &result->info3);
2113 if (!NT_STATUS_IS_OK(nt_status)) {
2114 goto out;
2117 /* Fill in the unix info we found on the way */
2119 result->utok.uid = pwd->pw_uid;
2120 result->utok.gid = pwd->pw_gid;
2122 /* ensure we are never given NULL session keys */
2124 if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
2125 result->session_key = data_blob_null;
2126 } else {
2127 result->session_key = data_blob_talloc(
2128 result, info3->base.key.key,
2129 sizeof(info3->base.key.key));
2132 if (all_zero(info3->base.LMSessKey.key,
2133 sizeof(info3->base.LMSessKey.key))) {
2134 result->lm_session_key = data_blob_null;
2135 } else {
2136 result->lm_session_key = data_blob_talloc(
2137 result, info3->base.LMSessKey.key,
2138 sizeof(info3->base.LMSessKey.key));
2141 result->nss_token |= username_was_mapped;
2143 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
2145 *server_info = talloc_move(mem_ctx, &result);
2147 nt_status = NT_STATUS_OK;
2148 out:
2149 talloc_free(tmp_ctx);
2151 return nt_status;
2154 /*****************************************************************************
2155 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
2156 ******************************************************************************/
2158 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
2159 const char *sent_nt_username,
2160 const char *domain,
2161 const struct wbcAuthUserInfo *info,
2162 struct auth_serversupplied_info **server_info)
2164 struct netr_SamInfo3 info3;
2165 struct netr_SamInfo6 *info6;
2167 info6 = wbcAuthUserInfo_to_netr_SamInfo6(mem_ctx, info);
2168 if (!info6) {
2169 return NT_STATUS_NO_MEMORY;
2172 info3.base = info6->base;
2173 info3.sidcount = info6->sidcount;
2174 info3.sids = info6->sids;
2176 return make_server_info_info3(mem_ctx,
2177 sent_nt_username, domain,
2178 server_info, &info3);
2182 * Verify whether or not given domain is trusted.
2184 * This should only be used on a DC.
2186 * @param domain_name name of the domain to be verified
2187 * @return true if domain is one of the trusted ones or
2188 * false if otherwise
2191 bool is_trusted_domain(const char* dom_name)
2193 bool ret;
2195 if (!IS_DC) {
2196 return false;
2199 if (dom_name == NULL || dom_name[0] == '\0') {
2200 return false;
2203 if (strequal(dom_name, get_global_sam_name())) {
2204 return false;
2207 become_root();
2208 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
2209 "[%s]\n", dom_name ));
2210 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
2211 unbecome_root();
2213 return ret;
2219 on a logon error possibly map the error to success if "map to guest"
2220 is set approriately
2222 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
2223 NTSTATUS status,
2224 const char *user,
2225 const char *domain,
2226 struct auth_serversupplied_info **server_info)
2228 user = user ? user : "";
2229 domain = domain ? domain : "";
2231 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2232 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
2233 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
2234 DEBUG(3,("No such user %s [%s] - using guest account\n",
2235 user, domain));
2236 return make_server_info_guest(mem_ctx, server_info);
2238 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2239 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
2240 DEBUG(3,("Registered username %s for guest access\n",
2241 user));
2242 return make_server_info_guest(mem_ctx, server_info);
2246 return status;
2250 Extract session key from a session info and return it in a blob
2251 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
2253 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
2254 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
2256 Note that returned session_key is referencing the original key, it is supposed to be
2257 short-lived. If original session_info->session_key is gone, the reference will be broken.
2259 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
2262 if (session_key == NULL || session_info == NULL) {
2263 return NT_STATUS_INVALID_PARAMETER;
2266 if (session_info->session_key.length == 0) {
2267 return NT_STATUS_NO_USER_SESSION_KEY;
2270 *session_key = session_info->session_key;
2271 if (intent == KEY_USE_16BYTES) {
2272 session_key->length = MIN(session_info->session_key.length, 16);
2274 return NT_STATUS_OK;