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/>.
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.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"
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"
39 #define DBGC_CLASS DBGC_AUTH
41 /****************************************************************************
42 Create a UNIX user on demand.
43 ****************************************************************************/
45 static int _smb_create_user(const char *domain
, const char *unix_username
, const char *homedir
)
47 TALLOC_CTX
*ctx
= talloc_tos();
51 add_script
= lp_adduser_script(ctx
);
52 if (!add_script
|| !*add_script
) {
55 add_script
= talloc_all_string_sub(ctx
,
63 add_script
= talloc_all_string_sub(ctx
,
72 add_script
= talloc_all_string_sub(ctx
,
80 ret
= smbrun(add_script
,NULL
);
83 ("smb_create_user: Running the command `%s' gave %d\n",
88 /****************************************************************************
89 Create an auth_usersupplied_data structure after appropriate mapping.
90 ****************************************************************************/
92 NTSTATUS
make_user_info_map(struct auth_usersupplied_info
**user_info
,
94 const char *client_domain
,
95 const char *workstation_name
,
96 const struct tsocket_address
*remote_address
,
97 const DATA_BLOB
*lm_pwd
,
98 const DATA_BLOB
*nt_pwd
,
99 const struct samr_Password
*lm_interactive_pwd
,
100 const struct samr_Password
*nt_interactive_pwd
,
101 const char *plaintext
,
102 enum auth_password_state password_state
)
107 char *internal_username
= NULL
;
109 was_mapped
= map_username(talloc_tos(), smb_name
, &internal_username
);
110 if (!internal_username
) {
111 return NT_STATUS_NO_MEMORY
;
114 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
115 client_domain
, smb_name
, workstation_name
));
117 domain
= client_domain
;
119 /* If you connect to a Windows domain member using a bogus domain name,
120 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
121 * the Windows box is a DC the name will become DOMAIN\user and be
122 * authenticated against AD, if the Windows box is a member server but
123 * not a DC the name will become WORKSTATION\user. A standalone
124 * non-domain member box will also map to WORKSTATION\user.
125 * This also deals with the client passing in a "" domain */
127 if (!is_trusted_domain(domain
) &&
128 !strequal(domain
, my_sam_name()) &&
129 !strequal(domain
, get_global_sam_name()))
131 if (lp_map_untrusted_to_domain())
132 domain
= my_sam_name();
134 domain
= get_global_sam_name();
135 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
136 "workstation [%s]\n",
137 client_domain
, domain
, smb_name
, workstation_name
));
140 /* We know that the given domain is trusted (and we are allowing them),
141 * it is our global SAM name, or for legacy behavior it is our
142 * primary domain name */
144 result
= make_user_info(user_info
, smb_name
, internal_username
,
145 client_domain
, domain
, workstation_name
,
146 remote_address
, lm_pwd
, nt_pwd
,
147 lm_interactive_pwd
, nt_interactive_pwd
,
148 plaintext
, password_state
);
149 if (NT_STATUS_IS_OK(result
)) {
150 /* We have tried mapping */
151 (*user_info
)->mapped_state
= true;
152 /* did we actually map the user to a different name? */
153 (*user_info
)->was_mapped
= was_mapped
;
158 /****************************************************************************
159 Create an auth_usersupplied_data, making the DATA_BLOBs here.
160 Decrypt and encrypt the passwords.
161 ****************************************************************************/
163 bool make_user_info_netlogon_network(struct auth_usersupplied_info
**user_info
,
164 const char *smb_name
,
165 const char *client_domain
,
166 const char *workstation_name
,
167 const struct tsocket_address
*remote_address
,
168 uint32 logon_parameters
,
169 const uchar
*lm_network_pwd
,
171 const uchar
*nt_network_pwd
,
176 DATA_BLOB lm_blob
= data_blob(lm_network_pwd
, lm_pwd_len
);
177 DATA_BLOB nt_blob
= data_blob(nt_network_pwd
, nt_pwd_len
);
179 status
= make_user_info_map(user_info
,
180 smb_name
, client_domain
,
183 lm_pwd_len
? &lm_blob
: NULL
,
184 nt_pwd_len
? &nt_blob
: NULL
,
186 AUTH_PASSWORD_RESPONSE
);
188 if (NT_STATUS_IS_OK(status
)) {
189 (*user_info
)->logon_parameters
= logon_parameters
;
191 ret
= NT_STATUS_IS_OK(status
) ? true : false;
193 data_blob_free(&lm_blob
);
194 data_blob_free(&nt_blob
);
198 /****************************************************************************
199 Create an auth_usersupplied_data, making the DATA_BLOBs here.
200 Decrypt and encrypt the passwords.
201 ****************************************************************************/
203 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info
**user_info
,
204 const char *smb_name
,
205 const char *client_domain
,
206 const char *workstation_name
,
207 const struct tsocket_address
*remote_address
,
208 uint32 logon_parameters
,
210 const uchar lm_interactive_pwd
[16],
211 const uchar nt_interactive_pwd
[16])
213 struct samr_Password lm_pwd
;
214 struct samr_Password nt_pwd
;
215 unsigned char local_lm_response
[24];
216 unsigned char local_nt_response
[24];
218 if (lm_interactive_pwd
)
219 memcpy(lm_pwd
.hash
, lm_interactive_pwd
, sizeof(lm_pwd
.hash
));
221 if (nt_interactive_pwd
)
222 memcpy(nt_pwd
.hash
, nt_interactive_pwd
, sizeof(nt_pwd
.hash
));
224 if (lm_interactive_pwd
)
225 SMBOWFencrypt(lm_pwd
.hash
, chal
,
228 if (nt_interactive_pwd
)
229 SMBOWFencrypt(nt_pwd
.hash
, chal
,
235 DATA_BLOB local_lm_blob
= data_blob_null
;
236 DATA_BLOB local_nt_blob
= data_blob_null
;
238 if (lm_interactive_pwd
) {
239 local_lm_blob
= data_blob(local_lm_response
,
240 sizeof(local_lm_response
));
243 if (nt_interactive_pwd
) {
244 local_nt_blob
= data_blob(local_nt_response
,
245 sizeof(local_nt_response
));
248 nt_status
= make_user_info_map(
250 smb_name
, client_domain
, workstation_name
,
252 lm_interactive_pwd
? &local_lm_blob
: NULL
,
253 nt_interactive_pwd
? &local_nt_blob
: NULL
,
254 lm_interactive_pwd
? &lm_pwd
: NULL
,
255 nt_interactive_pwd
? &nt_pwd
: NULL
,
256 NULL
, AUTH_PASSWORD_HASH
);
258 if (NT_STATUS_IS_OK(nt_status
)) {
259 (*user_info
)->logon_parameters
= logon_parameters
;
262 ret
= NT_STATUS_IS_OK(nt_status
) ? true : false;
263 data_blob_free(&local_lm_blob
);
264 data_blob_free(&local_nt_blob
);
270 /****************************************************************************
271 Create an auth_usersupplied_data structure
272 ****************************************************************************/
274 bool make_user_info_for_reply(struct auth_usersupplied_info
**user_info
,
275 const char *smb_name
,
276 const char *client_domain
,
277 const struct tsocket_address
*remote_address
,
279 DATA_BLOB plaintext_password
)
282 DATA_BLOB local_lm_blob
;
283 DATA_BLOB local_nt_blob
;
284 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
285 char *plaintext_password_string
;
287 * Not encrypted - do so.
290 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
292 if (plaintext_password
.data
&& plaintext_password
.length
) {
293 unsigned char local_lm_response
[24];
295 #ifdef DEBUG_PASSWORD
296 DEBUG(10,("Unencrypted password (len %d):\n",
297 (int)plaintext_password
.length
));
298 dump_data(100, plaintext_password
.data
,
299 plaintext_password
.length
);
302 SMBencrypt( (const char *)plaintext_password
.data
,
303 (const uchar
*)chal
, local_lm_response
);
304 local_lm_blob
= data_blob(local_lm_response
, 24);
306 /* We can't do an NT hash here, as the password needs to be
308 local_nt_blob
= data_blob_null
;
310 local_lm_blob
= data_blob_null
;
311 local_nt_blob
= data_blob_null
;
314 plaintext_password_string
= talloc_strndup(talloc_tos(),
315 (const char *)plaintext_password
.data
,
316 plaintext_password
.length
);
317 if (!plaintext_password_string
) {
321 ret
= make_user_info(
322 user_info
, smb_name
, smb_name
, client_domain
, client_domain
,
323 get_remote_machine_name(),
325 local_lm_blob
.data
? &local_lm_blob
: NULL
,
326 local_nt_blob
.data
? &local_nt_blob
: NULL
,
328 plaintext_password_string
,
329 AUTH_PASSWORD_PLAIN
);
331 if (plaintext_password_string
) {
332 memset(plaintext_password_string
, '\0', strlen(plaintext_password_string
));
333 talloc_free(plaintext_password_string
);
336 data_blob_free(&local_lm_blob
);
337 return NT_STATUS_IS_OK(ret
) ? true : false;
340 /****************************************************************************
341 Create an auth_usersupplied_data structure
342 ****************************************************************************/
344 NTSTATUS
make_user_info_for_reply_enc(struct auth_usersupplied_info
**user_info
,
345 const char *smb_name
,
346 const char *client_domain
,
347 const struct tsocket_address
*remote_address
,
348 DATA_BLOB lm_resp
, DATA_BLOB nt_resp
)
350 return make_user_info(user_info
, smb_name
, smb_name
,
351 client_domain
, client_domain
,
352 get_remote_machine_name(),
354 lm_resp
.data
&& (lm_resp
.length
> 0) ? &lm_resp
: NULL
,
355 nt_resp
.data
&& (nt_resp
.length
> 0) ? &nt_resp
: NULL
,
357 AUTH_PASSWORD_RESPONSE
);
360 /****************************************************************************
361 Create a guest user_info blob, for anonymous authentication.
362 ****************************************************************************/
364 bool make_user_info_guest(const struct tsocket_address
*remote_address
,
365 struct auth_usersupplied_info
**user_info
)
369 nt_status
= make_user_info(user_info
,
377 AUTH_PASSWORD_RESPONSE
);
379 return NT_STATUS_IS_OK(nt_status
) ? true : false;
382 static NTSTATUS
log_nt_token(struct security_token
*token
)
384 TALLOC_CTX
*frame
= talloc_stackframe();
389 if ((lp_log_nt_token_command(frame
) == NULL
) ||
390 (strlen(lp_log_nt_token_command(frame
)) == 0)) {
395 group_sidstr
= talloc_strdup(frame
, "");
396 for (i
=1; i
<token
->num_sids
; i
++) {
397 group_sidstr
= talloc_asprintf(
398 frame
, "%s %s", group_sidstr
,
399 sid_string_talloc(frame
, &token
->sids
[i
]));
402 command
= talloc_string_sub(
403 frame
, lp_log_nt_token_command(frame
),
404 "%s", sid_string_talloc(frame
, &token
->sids
[0]));
405 command
= talloc_string_sub(frame
, command
, "%t", group_sidstr
);
407 if (command
== NULL
) {
409 return NT_STATUS_NO_MEMORY
;
412 DEBUG(8, ("running command: [%s]\n", command
));
413 if (smbrun(command
, NULL
) != 0) {
414 DEBUG(0, ("Could not log NT token\n"));
416 return NT_STATUS_ACCESS_DENIED
;
424 * Create the token to use from server_info->info3 and
425 * server_info->sids (the info3/sam groups). Find the unix gids.
428 NTSTATUS
create_local_token(TALLOC_CTX
*mem_ctx
,
429 const struct auth_serversupplied_info
*server_info
,
430 DATA_BLOB
*session_key
,
431 const char *smb_username
, /* for ->sanitized_username, for %U subs */
432 struct auth_session_info
**session_info_out
)
434 struct security_token
*t
;
437 struct dom_sid tmp_sid
;
438 struct auth_session_info
*session_info
;
442 /* Ensure we can't possible take a code path leading to a
445 return NT_STATUS_LOGON_FAILURE
;
448 session_info
= talloc_zero(mem_ctx
, struct auth_session_info
);
450 return NT_STATUS_NO_MEMORY
;
453 session_info
->unix_token
= talloc_zero(session_info
, struct security_unix_token
);
454 if (!session_info
->unix_token
) {
455 TALLOC_FREE(session_info
);
456 return NT_STATUS_NO_MEMORY
;
459 session_info
->unix_token
->uid
= server_info
->utok
.uid
;
460 session_info
->unix_token
->gid
= server_info
->utok
.gid
;
462 session_info
->unix_info
= talloc_zero(session_info
, struct auth_user_info_unix
);
463 if (!session_info
->unix_info
) {
464 TALLOC_FREE(session_info
);
465 return NT_STATUS_NO_MEMORY
;
468 session_info
->unix_info
->unix_name
= talloc_strdup(session_info
, server_info
->unix_name
);
469 if (!session_info
->unix_info
->unix_name
) {
470 TALLOC_FREE(session_info
);
471 return NT_STATUS_NO_MEMORY
;
474 /* This is a potentially untrusted username for use in %U */
475 alpha_strcpy(tmp
, smb_username
, ". _-$", sizeof(tmp
));
476 session_info
->unix_info
->sanitized_username
=
477 talloc_strdup(session_info
->unix_info
, tmp
);
480 data_blob_free(&session_info
->session_key
);
481 session_info
->session_key
= data_blob_talloc(session_info
,
483 session_key
->length
);
484 if (!session_info
->session_key
.data
&& session_key
->length
) {
485 return NT_STATUS_NO_MEMORY
;
488 session_info
->session_key
= data_blob_talloc( session_info
, server_info
->session_key
.data
,
489 server_info
->session_key
.length
);
492 /* We need to populate session_info->info with the information found in server_info->info3 */
493 status
= make_user_info_SamBaseInfo(session_info
, "", &server_info
->info3
->base
,
494 server_info
->guest
== false,
495 &session_info
->info
);
496 if (!NT_STATUS_IS_OK(status
)) {
497 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
498 TALLOC_FREE(session_info
);
502 if (server_info
->security_token
) {
503 /* Just copy the token, it has already been finalised
504 * (nasty hack to support a cached guest/system session_info
507 session_info
->security_token
= dup_nt_token(session_info
, server_info
->security_token
);
508 if (!session_info
->security_token
) {
509 TALLOC_FREE(session_info
);
510 return NT_STATUS_NO_MEMORY
;
513 session_info
->unix_token
->ngroups
= server_info
->utok
.ngroups
;
514 if (server_info
->utok
.ngroups
!= 0) {
515 session_info
->unix_token
->groups
= (gid_t
*)talloc_memdup(
516 session_info
->unix_token
, server_info
->utok
.groups
,
517 sizeof(gid_t
)*session_info
->unix_token
->ngroups
);
519 session_info
->unix_token
->groups
= NULL
;
522 *session_info_out
= session_info
;
527 * If winbind is not around, we can not make much use of the SIDs the
528 * domain controller provided us with. Likewise if the user name was
529 * mapped to some local unix user.
532 if (((lp_server_role() == ROLE_DOMAIN_MEMBER
) && !winbind_ping()) ||
533 (server_info
->nss_token
)) {
534 char *found_username
= NULL
;
535 status
= create_token_from_username(session_info
,
536 server_info
->unix_name
,
538 &session_info
->unix_token
->uid
,
539 &session_info
->unix_token
->gid
,
541 &session_info
->security_token
);
542 if (NT_STATUS_IS_OK(status
)) {
543 session_info
->unix_info
->unix_name
= found_username
;
546 status
= create_local_nt_token_from_info3(session_info
,
550 &session_info
->security_token
);
553 if (!NT_STATUS_IS_OK(status
)) {
557 /* Convert the SIDs to gids. */
559 session_info
->unix_token
->ngroups
= 0;
560 session_info
->unix_token
->groups
= NULL
;
562 t
= session_info
->security_token
;
564 ids
= talloc_array(talloc_tos(), struct unixid
,
567 return NT_STATUS_NO_MEMORY
;
570 if (!sids_to_unixids(t
->sids
, t
->num_sids
, ids
)) {
572 return NT_STATUS_NO_MEMORY
;
575 for (i
=0; i
<t
->num_sids
; i
++) {
577 if (i
== 0 && ids
[i
].type
!= ID_TYPE_BOTH
) {
581 if (ids
[i
].type
!= ID_TYPE_GID
&&
582 ids
[i
].type
!= ID_TYPE_BOTH
) {
583 DEBUG(10, ("Could not convert SID %s to gid, "
585 sid_string_dbg(&t
->sids
[i
])));
588 if (!add_gid_to_array_unique(session_info
, ids
[i
].id
,
589 &session_info
->unix_token
->groups
,
590 &session_info
->unix_token
->ngroups
)) {
591 return NT_STATUS_NO_MEMORY
;
596 * Add the "Unix Group" SID for each gid to catch mapped groups
597 * and their Unix equivalent. This is to solve the backwards
598 * compatibility problem of 'valid users = +ntadmin' where
599 * ntadmin has been paired with "Domain Admins" in the group
600 * mapping table. Otherwise smb.conf would need to be changed
601 * to 'valid user = "Domain Admins"'. --jerry
603 * For consistency we also add the "Unix User" SID,
604 * so that the complete unix token is represented within
608 uid_to_unix_users_sid(session_info
->unix_token
->uid
, &tmp_sid
);
610 add_sid_to_array_unique(session_info
->security_token
, &tmp_sid
,
611 &session_info
->security_token
->sids
,
612 &session_info
->security_token
->num_sids
);
614 for ( i
=0; i
<session_info
->unix_token
->ngroups
; i
++ ) {
615 gid_to_unix_groups_sid(session_info
->unix_token
->groups
[i
], &tmp_sid
);
616 add_sid_to_array_unique(session_info
->security_token
, &tmp_sid
,
617 &session_info
->security_token
->sids
,
618 &session_info
->security_token
->num_sids
);
621 security_token_debug(DBGC_AUTH
, 10, session_info
->security_token
);
622 debug_unix_user_token(DBGC_AUTH
, 10,
623 session_info
->unix_token
->uid
,
624 session_info
->unix_token
->gid
,
625 session_info
->unix_token
->ngroups
,
626 session_info
->unix_token
->groups
);
628 status
= log_nt_token(session_info
->security_token
);
629 if (!NT_STATUS_IS_OK(status
)) {
633 *session_info_out
= session_info
;
637 /***************************************************************************
638 Make (and fill) a server_info struct from a 'struct passwd' by conversion
640 ***************************************************************************/
642 NTSTATUS
make_server_info_pw(struct auth_serversupplied_info
**server_info
,
647 struct samu
*sampass
= NULL
;
648 char *qualified_name
= NULL
;
649 TALLOC_CTX
*mem_ctx
= NULL
;
650 struct dom_sid u_sid
;
651 enum lsa_SidType type
;
652 struct auth_serversupplied_info
*result
;
655 * The SID returned in server_info->sam_account is based
656 * on our SAM sid even though for a pure UNIX account this should
657 * not be the case as it doesn't really exist in the SAM db.
658 * This causes lookups on "[in]valid users" to fail as they
659 * will lookup this name as a "Unix User" SID to check against
660 * the user token. Fix this by adding the "Unix User"\unix_username
661 * SID to the sid array. The correct fix should probably be
662 * changing the server_info->sam_account user SID to be a
663 * S-1-22 Unix SID, but this might break old configs where
664 * plaintext passwords were used with no SAM backend.
667 mem_ctx
= talloc_init("make_server_info_pw_tmp");
669 return NT_STATUS_NO_MEMORY
;
672 qualified_name
= talloc_asprintf(mem_ctx
, "%s\\%s",
673 unix_users_domain_name(),
675 if (!qualified_name
) {
676 TALLOC_FREE(mem_ctx
);
677 return NT_STATUS_NO_MEMORY
;
680 if (!lookup_name(mem_ctx
, qualified_name
, LOOKUP_NAME_ALL
,
683 TALLOC_FREE(mem_ctx
);
684 return NT_STATUS_NO_SUCH_USER
;
687 TALLOC_FREE(mem_ctx
);
689 if (type
!= SID_NAME_USER
) {
690 return NT_STATUS_NO_SUCH_USER
;
693 if ( !(sampass
= samu_new( NULL
)) ) {
694 return NT_STATUS_NO_MEMORY
;
697 status
= samu_set_unix( sampass
, pwd
);
698 if (!NT_STATUS_IS_OK(status
)) {
702 /* In pathological cases the above call can set the account
703 * name to the DOMAIN\username form. Reset the account name
704 * using unix_username */
705 pdb_set_username(sampass
, unix_username
, PDB_SET
);
707 /* set the user sid to be the calculated u_sid */
708 pdb_set_user_sid(sampass
, &u_sid
, PDB_SET
);
710 result
= make_server_info(NULL
);
711 if (result
== NULL
) {
712 TALLOC_FREE(sampass
);
713 return NT_STATUS_NO_MEMORY
;
716 status
= samu_to_SamInfo3(result
, sampass
, lp_netbios_name(),
717 &result
->info3
, &result
->extra
);
718 TALLOC_FREE(sampass
);
719 if (!NT_STATUS_IS_OK(status
)) {
720 DEBUG(10, ("Failed to convert samu to info3: %s\n",
726 result
->unix_name
= talloc_strdup(result
, unix_username
);
728 if (result
->unix_name
== NULL
) {
730 return NT_STATUS_NO_MEMORY
;
733 result
->utok
.uid
= pwd
->pw_uid
;
734 result
->utok
.gid
= pwd
->pw_gid
;
736 *server_info
= result
;
741 static NTSTATUS
get_system_info3(TALLOC_CTX
*mem_ctx
,
742 struct netr_SamInfo3
*info3
)
745 struct dom_sid
*system_sid
;
747 /* Set account name */
748 init_lsa_String(&info3
->base
.account_name
, "SYSTEM");
750 /* Set domain name */
751 init_lsa_StringLarge(&info3
->base
.logon_domain
, "NT AUTHORITY");
754 /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
755 /* Domain sid is NT_AUTHORITY */
757 system_sid
= dom_sid_parse_talloc(mem_ctx
, SID_NT_SYSTEM
);
758 if (system_sid
== NULL
) {
759 return NT_STATUS_NO_MEMORY
;
762 status
= dom_sid_split_rid(mem_ctx
, system_sid
, &info3
->base
.domain_sid
,
764 TALLOC_FREE(system_sid
);
765 if (!NT_STATUS_IS_OK(status
)) {
769 /* Primary gid is the same */
770 info3
->base
.primary_gid
= info3
->base
.rid
;
775 static NTSTATUS
get_guest_info3(TALLOC_CTX
*mem_ctx
,
776 struct netr_SamInfo3
*info3
)
778 const char *guest_account
= lp_guestaccount();
779 struct dom_sid domain_sid
;
783 pwd
= Get_Pwnam_alloc(mem_ctx
, guest_account
);
785 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
786 "account [%s]!\n", guest_account
));
787 return NT_STATUS_NO_SUCH_USER
;
790 /* Set account name */
791 tmp
= talloc_strdup(mem_ctx
, pwd
->pw_name
);
793 return NT_STATUS_NO_MEMORY
;
795 init_lsa_String(&info3
->base
.account_name
, tmp
);
797 /* Set domain name */
798 tmp
= talloc_strdup(mem_ctx
, get_global_sam_name());
800 return NT_STATUS_NO_MEMORY
;
802 init_lsa_StringLarge(&info3
->base
.logon_domain
, tmp
);
805 sid_copy(&domain_sid
, get_global_sam_sid());
807 info3
->base
.domain_sid
= dom_sid_dup(mem_ctx
, &domain_sid
);
808 if (info3
->base
.domain_sid
== NULL
) {
809 return NT_STATUS_NO_MEMORY
;
813 info3
->base
.rid
= DOMAIN_RID_GUEST
;
816 info3
->base
.primary_gid
= DOMAIN_RID_GUESTS
;
819 info3
->base
.user_flags
= NETLOGON_GUEST
;
825 /***************************************************************************
826 Make (and fill) a user_info struct for a guest login.
827 This *must* succeed for smbd to start. If there is no mapping entry for
828 the guest gid, then create one.
830 The resulting structure is a 'session_info' because
831 create_local_token() has already been called on it. This is quite
832 nasty, as the auth subsystem isn't expect this, but the behavior is
834 ***************************************************************************/
836 static NTSTATUS
make_new_session_info_guest(struct auth_session_info
**session_info
, struct auth_serversupplied_info
**server_info
)
838 static const char zeros
[16] = {0};
839 const char *guest_account
= lp_guestaccount();
840 const char *domain
= lp_netbios_name();
841 struct netr_SamInfo3 info3
;
845 tmp_ctx
= talloc_stackframe();
846 if (tmp_ctx
== NULL
) {
847 return NT_STATUS_NO_MEMORY
;
852 status
= get_guest_info3(tmp_ctx
, &info3
);
853 if (!NT_STATUS_IS_OK(status
)) {
854 DEBUG(0, ("get_guest_info3 failed with %s\n",
859 status
= make_server_info_info3(tmp_ctx
,
864 if (!NT_STATUS_IS_OK(status
)) {
865 DEBUG(0, ("make_server_info_info3 failed with %s\n",
870 (*server_info
)->guest
= true;
872 /* This should not be done here (we should produce a server
873 * info, and later construct a session info from it), but for
874 * now this does not change the previous behavior */
875 status
= create_local_token(tmp_ctx
, *server_info
, NULL
,
876 (*server_info
)->info3
->base
.account_name
.string
,
878 if (!NT_STATUS_IS_OK(status
)) {
879 DEBUG(0, ("create_local_token failed: %s\n",
883 talloc_steal(NULL
, *session_info
);
884 talloc_steal(NULL
, *server_info
);
886 /* annoying, but the Guest really does have a session key, and it is
888 (*session_info
)->session_key
= data_blob(zeros
, sizeof(zeros
));
890 status
= NT_STATUS_OK
;
892 TALLOC_FREE(tmp_ctx
);
896 /***************************************************************************
897 Make (and fill) a auth_session_info struct for a system user login.
898 This *must* succeed for smbd to start.
899 ***************************************************************************/
901 static NTSTATUS
make_new_session_info_system(TALLOC_CTX
*mem_ctx
,
902 struct auth_session_info
**session_info
)
905 struct auth_serversupplied_info
*server_info
;
908 tmp_ctx
= talloc_stackframe();
909 if (tmp_ctx
== NULL
) {
910 return NT_STATUS_NO_MEMORY
;
913 server_info
= make_server_info(tmp_ctx
);
915 status
= NT_STATUS_NO_MEMORY
;
916 DEBUG(0, ("failed making server_info\n"));
920 server_info
->info3
= talloc_zero(server_info
, struct netr_SamInfo3
);
921 if (!server_info
->info3
) {
922 status
= NT_STATUS_NO_MEMORY
;
923 DEBUG(0, ("talloc failed setting info3\n"));
927 status
= get_system_info3(server_info
, server_info
->info3
);
928 if (!NT_STATUS_IS_OK(status
)) {
929 DEBUG(0, ("Failed creating system info3 with %s\n",
934 server_info
->utok
.uid
= sec_initial_uid();
935 server_info
->utok
.gid
= sec_initial_gid();
936 server_info
->unix_name
= talloc_asprintf(server_info
,
937 "NT AUTHORITY%cSYSTEM",
938 *lp_winbind_separator());
940 if (!server_info
->unix_name
) {
941 status
= NT_STATUS_NO_MEMORY
;
942 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
946 server_info
->security_token
= talloc_zero(server_info
, struct security_token
);
947 if (!server_info
->security_token
) {
948 status
= NT_STATUS_NO_MEMORY
;
949 DEBUG(0, ("talloc failed setting security token\n"));
953 status
= add_sid_to_array_unique(server_info
->security_token
->sids
,
955 &server_info
->security_token
->sids
,
956 &server_info
->security_token
->num_sids
);
957 if (!NT_STATUS_IS_OK(status
)) {
961 /* SYSTEM has all privilages */
962 server_info
->security_token
->privilege_mask
= ~0;
964 /* Now turn the server_info into a session_info with the full token etc */
965 status
= create_local_token(mem_ctx
, server_info
, NULL
, "SYSTEM", session_info
);
966 talloc_free(server_info
);
968 if (!NT_STATUS_IS_OK(status
)) {
969 DEBUG(0, ("create_local_token failed: %s\n",
974 talloc_steal(mem_ctx
, *session_info
);
977 TALLOC_FREE(tmp_ctx
);
981 /****************************************************************************
982 Fake a auth_session_info just from a username (as a
983 session_info structure, with create_local_token() already called on
985 ****************************************************************************/
987 NTSTATUS
make_session_info_from_username(TALLOC_CTX
*mem_ctx
,
988 const char *username
,
990 struct auth_session_info
**session_info
)
994 struct auth_serversupplied_info
*result
;
996 pwd
= Get_Pwnam_alloc(talloc_tos(), username
);
998 return NT_STATUS_NO_SUCH_USER
;
1001 status
= make_server_info_pw(&result
, pwd
->pw_name
, pwd
);
1003 if (!NT_STATUS_IS_OK(status
)) {
1007 result
->nss_token
= true;
1008 result
->guest
= is_guest
;
1010 /* Now turn the server_info into a session_info with the full token etc */
1011 status
= create_local_token(mem_ctx
, result
, NULL
, pwd
->pw_name
, session_info
);
1012 TALLOC_FREE(result
);
1018 /* This function MUST only used to create the cached server_info for
1021 * This is a lossy conversion. Variables known to be lost so far
1024 * - nss_token (not needed because the only read doesn't happen
1025 * for the GUEST user, as this routine populates ->security_token
1027 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1029 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1031 static struct auth_serversupplied_info
*copy_session_info_serverinfo_guest(TALLOC_CTX
*mem_ctx
,
1032 const struct auth_session_info
*src
,
1033 struct auth_serversupplied_info
*server_info
)
1035 struct auth_serversupplied_info
*dst
;
1037 dst
= make_server_info(mem_ctx
);
1042 /* This element must be provided to convert back to an auth_serversupplied_info */
1043 SMB_ASSERT(src
->unix_info
);
1046 dst
->system
= false;
1048 /* This element must be provided to convert back to an
1049 * auth_serversupplied_info. This needs to be from the
1050 * auth_session_info because the group values in particular
1051 * may change during create_local_token() processing */
1052 SMB_ASSERT(src
->unix_token
);
1053 dst
->utok
.uid
= src
->unix_token
->uid
;
1054 dst
->utok
.gid
= src
->unix_token
->gid
;
1055 dst
->utok
.ngroups
= src
->unix_token
->ngroups
;
1056 if (src
->unix_token
->ngroups
!= 0) {
1057 dst
->utok
.groups
= (gid_t
*)talloc_memdup(
1058 dst
, src
->unix_token
->groups
,
1059 sizeof(gid_t
)*dst
->utok
.ngroups
);
1061 dst
->utok
.groups
= NULL
;
1064 /* We must have a security_token as otherwise the lossy
1065 * conversion without nss_token would cause create_local_token
1066 * to take the wrong path */
1067 SMB_ASSERT(src
->security_token
);
1069 dst
->security_token
= dup_nt_token(dst
, src
->security_token
);
1070 if (!dst
->security_token
) {
1075 dst
->session_key
= data_blob_talloc( dst
, src
->session_key
.data
,
1076 src
->session_key
.length
);
1078 /* This is OK because this functions is only used for the
1079 * GUEST account, which has all-zero keys for both values */
1080 dst
->lm_session_key
= data_blob_talloc(dst
, src
->session_key
.data
,
1081 src
->session_key
.length
);
1083 dst
->info3
= copy_netr_SamInfo3(dst
, server_info
->info3
);
1089 dst
->unix_name
= talloc_strdup(dst
, src
->unix_info
->unix_name
);
1090 if (!dst
->unix_name
) {
1098 struct auth_session_info
*copy_session_info(TALLOC_CTX
*mem_ctx
,
1099 const struct auth_session_info
*src
)
1101 struct auth_session_info
*dst
;
1103 enum ndr_err_code ndr_err
;
1105 ndr_err
= ndr_push_struct_blob(
1106 &blob
, talloc_tos(), src
,
1107 (ndr_push_flags_fn_t
)ndr_push_auth_session_info
);
1108 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1109 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1110 "%s\n", ndr_errstr(ndr_err
)));
1114 dst
= talloc(mem_ctx
, struct auth_session_info
);
1116 DEBUG(0, ("talloc failed\n"));
1117 TALLOC_FREE(blob
.data
);
1121 ndr_err
= ndr_pull_struct_blob(
1123 (ndr_pull_flags_fn_t
)ndr_pull_auth_session_info
);
1124 TALLOC_FREE(blob
.data
);
1126 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1127 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1128 "%s\n", ndr_errstr(ndr_err
)));
1137 * Set a new session key. Used in the rpc server where we have to override the
1138 * SMB level session key with SystemLibraryDTC
1141 bool session_info_set_session_key(struct auth_session_info
*info
,
1142 DATA_BLOB session_key
)
1144 TALLOC_FREE(info
->session_key
.data
);
1146 info
->session_key
= data_blob_talloc(
1147 info
, session_key
.data
, session_key
.length
);
1149 return (info
->session_key
.data
!= NULL
);
1152 static struct auth_session_info
*guest_info
= NULL
;
1154 static struct auth_serversupplied_info
*guest_server_info
= NULL
;
1156 bool init_guest_info(void)
1158 if (guest_info
!= NULL
)
1161 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info
, &guest_server_info
));
1164 NTSTATUS
make_server_info_guest(TALLOC_CTX
*mem_ctx
,
1165 struct auth_serversupplied_info
**server_info
)
1167 /* This is trickier than it would appear to need to be because
1168 * we are trying to avoid certain costly operations when the
1169 * structure is converted to a 'auth_session_info' again in
1170 * create_local_token() */
1171 *server_info
= copy_session_info_serverinfo_guest(mem_ctx
, guest_info
, guest_server_info
);
1172 return (*server_info
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
1175 NTSTATUS
make_session_info_guest(TALLOC_CTX
*mem_ctx
,
1176 struct auth_session_info
**session_info
)
1178 *session_info
= copy_session_info(mem_ctx
, guest_info
);
1179 return (*session_info
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
1182 static struct auth_session_info
*system_info
= NULL
;
1184 NTSTATUS
init_system_session_info(void)
1186 if (system_info
!= NULL
)
1187 return NT_STATUS_OK
;
1189 return make_new_session_info_system(NULL
, &system_info
);
1192 NTSTATUS
make_session_info_system(TALLOC_CTX
*mem_ctx
,
1193 struct auth_session_info
**session_info
)
1195 if (system_info
== NULL
) return NT_STATUS_UNSUCCESSFUL
;
1196 *session_info
= copy_session_info(mem_ctx
, system_info
);
1197 return (*session_info
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
1200 const struct auth_session_info
*get_session_info_system(void)
1205 /***************************************************************************
1206 Purely internal function for make_server_info_info3
1207 ***************************************************************************/
1209 static NTSTATUS
check_account(TALLOC_CTX
*mem_ctx
, const char *domain
,
1210 const char *username
, char **found_username
,
1211 struct passwd
**pwd
,
1212 bool *username_was_mapped
)
1214 char *orig_dom_user
= NULL
;
1215 char *dom_user
= NULL
;
1216 char *lower_username
= NULL
;
1217 char *real_username
= NULL
;
1218 struct passwd
*passwd
;
1220 lower_username
= talloc_strdup(mem_ctx
, username
);
1221 if (!lower_username
) {
1222 return NT_STATUS_NO_MEMORY
;
1224 if (!strlower_m( lower_username
)) {
1225 return NT_STATUS_INVALID_PARAMETER
;
1228 orig_dom_user
= talloc_asprintf(mem_ctx
,
1231 *lp_winbind_separator(),
1233 if (!orig_dom_user
) {
1234 return NT_STATUS_NO_MEMORY
;
1237 /* Get the passwd struct. Try to create the account if necessary. */
1239 *username_was_mapped
= map_username(mem_ctx
, orig_dom_user
, &dom_user
);
1241 return NT_STATUS_NO_MEMORY
;
1244 passwd
= smb_getpwnam(mem_ctx
, dom_user
, &real_username
, true );
1246 DEBUG(3, ("Failed to find authenticated user %s via "
1247 "getpwnam(), denying access.\n", dom_user
));
1248 return NT_STATUS_NO_SUCH_USER
;
1251 if (!real_username
) {
1252 return NT_STATUS_NO_MEMORY
;
1257 /* This is pointless -- there is no support for differing
1258 unix and windows names. Make sure to always store the
1259 one we actually looked up and succeeded. Have I mentioned
1260 why I hate the 'winbind use default domain' parameter?
1263 *found_username
= talloc_strdup( mem_ctx
, real_username
);
1265 return NT_STATUS_OK
;
1268 /****************************************************************************
1269 Wrapper to allow the getpwnam() call to strip the domain name and
1270 try again in case a local UNIX user is already there. Also run through
1271 the username if we fallback to the username only.
1272 ****************************************************************************/
1274 struct passwd
*smb_getpwnam( TALLOC_CTX
*mem_ctx
, const char *domuser
,
1275 char **p_save_username
, bool create
)
1277 struct passwd
*pw
= NULL
;
1279 char *username
= NULL
;
1281 /* we only save a copy of the username it has been mangled
1282 by winbindd use default domain */
1283 *p_save_username
= NULL
;
1285 /* don't call map_username() here since it has to be done higher
1286 up the stack so we don't call it multiple times */
1288 username
= talloc_strdup(mem_ctx
, domuser
);
1293 p
= strchr_m( username
, *lp_winbind_separator() );
1295 /* code for a DOMAIN\user string */
1298 pw
= Get_Pwnam_alloc( mem_ctx
, domuser
);
1300 /* make sure we get the case of the username correct */
1301 /* work around 'winbind use default domain = yes' */
1303 if ( lp_winbind_use_default_domain() &&
1304 !strchr_m( pw
->pw_name
, *lp_winbind_separator() ) ) {
1307 /* split the domain and username into 2 strings */
1311 *p_save_username
= talloc_asprintf(mem_ctx
,
1314 *lp_winbind_separator(),
1316 if (!*p_save_username
) {
1321 *p_save_username
= talloc_strdup(mem_ctx
, pw
->pw_name
);
1328 /* setup for lookup of just the username */
1329 /* remember that p and username are overlapping memory */
1332 username
= talloc_strdup(mem_ctx
, p
);
1338 /* just lookup a plain username */
1340 pw
= Get_Pwnam_alloc(mem_ctx
, username
);
1342 /* Create local user if requested but only if winbindd
1343 is not running. We need to protect against cases
1344 where winbindd is failing and then prematurely
1345 creating users in /etc/passwd */
1347 if ( !pw
&& create
&& !winbind_ping() ) {
1348 /* Don't add a machine account. */
1349 if (username
[strlen(username
)-1] == '$')
1352 _smb_create_user(NULL
, username
, NULL
);
1353 pw
= Get_Pwnam_alloc(mem_ctx
, username
);
1356 /* one last check for a valid passwd struct */
1359 *p_save_username
= talloc_strdup(mem_ctx
, pw
->pw_name
);
1364 /***************************************************************************
1365 Make a server_info struct from the info3 returned by a domain logon
1366 ***************************************************************************/
1368 NTSTATUS
make_server_info_info3(TALLOC_CTX
*mem_ctx
,
1369 const char *sent_nt_username
,
1371 struct auth_serversupplied_info
**server_info
,
1372 struct netr_SamInfo3
*info3
)
1374 static const char zeros
[16] = {0, };
1376 NTSTATUS nt_status
= NT_STATUS_OK
;
1377 char *found_username
= NULL
;
1378 const char *nt_domain
;
1379 const char *nt_username
;
1380 struct dom_sid user_sid
;
1381 struct dom_sid group_sid
;
1382 bool username_was_mapped
;
1384 struct auth_serversupplied_info
*result
;
1387 Here is where we should check the list of
1388 trusted domains, and verify that the SID
1392 if (!sid_compose(&user_sid
, info3
->base
.domain_sid
, info3
->base
.rid
)) {
1393 return NT_STATUS_INVALID_PARAMETER
;
1396 if (!sid_compose(&group_sid
, info3
->base
.domain_sid
,
1397 info3
->base
.primary_gid
)) {
1398 return NT_STATUS_INVALID_PARAMETER
;
1401 nt_username
= talloc_strdup(mem_ctx
, info3
->base
.account_name
.string
);
1403 /* If the server didn't give us one, just use the one we sent
1405 nt_username
= sent_nt_username
;
1408 nt_domain
= talloc_strdup(mem_ctx
, info3
->base
.logon_domain
.string
);
1410 /* If the server didn't give us one, just use the one we sent
1415 /* If getpwnam() fails try the add user script (2.2.x behavior).
1417 We use the _unmapped_ username here in an attempt to provide
1418 consistent username mapping behavior between kerberos and NTLM[SSP]
1419 authentication in domain mode security. I.E. Username mapping
1420 should be applied to the fully qualified username
1421 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1422 called map_username() unnecessarily in make_user_info_map() but
1423 that is how the current code is designed. Making the change here
1424 is the least disruptive place. -- jerry */
1426 /* this call will try to create the user if necessary */
1428 nt_status
= check_account(mem_ctx
, nt_domain
, sent_nt_username
,
1429 &found_username
, &pwd
,
1430 &username_was_mapped
);
1432 if (!NT_STATUS_IS_OK(nt_status
)) {
1436 result
= make_server_info(NULL
);
1437 if (result
== NULL
) {
1438 DEBUG(4, ("make_server_info failed!\n"));
1439 return NT_STATUS_NO_MEMORY
;
1442 result
->unix_name
= talloc_strdup(result
, found_username
);
1444 /* copy in the info3 */
1445 result
->info3
= copy_netr_SamInfo3(result
, info3
);
1446 if (result
->info3
== NULL
) {
1447 TALLOC_FREE(result
);
1448 return NT_STATUS_NO_MEMORY
;
1451 /* Fill in the unix info we found on the way */
1453 result
->utok
.uid
= pwd
->pw_uid
;
1454 result
->utok
.gid
= pwd
->pw_gid
;
1456 /* ensure we are never given NULL session keys */
1458 if (memcmp(info3
->base
.key
.key
, zeros
, sizeof(zeros
)) == 0) {
1459 result
->session_key
= data_blob_null
;
1461 result
->session_key
= data_blob_talloc(
1462 result
, info3
->base
.key
.key
,
1463 sizeof(info3
->base
.key
.key
));
1466 if (memcmp(info3
->base
.LMSessKey
.key
, zeros
, 8) == 0) {
1467 result
->lm_session_key
= data_blob_null
;
1469 result
->lm_session_key
= data_blob_talloc(
1470 result
, info3
->base
.LMSessKey
.key
,
1471 sizeof(info3
->base
.LMSessKey
.key
));
1474 result
->nss_token
|= username_was_mapped
;
1476 result
->guest
= (info3
->base
.user_flags
& NETLOGON_GUEST
);
1478 *server_info
= result
;
1480 return NT_STATUS_OK
;
1483 /*****************************************************************************
1484 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1485 ******************************************************************************/
1487 NTSTATUS
make_server_info_wbcAuthUserInfo(TALLOC_CTX
*mem_ctx
,
1488 const char *sent_nt_username
,
1490 const struct wbcAuthUserInfo
*info
,
1491 struct auth_serversupplied_info
**server_info
)
1493 struct netr_SamInfo3
*info3
;
1495 info3
= wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx
, info
);
1497 return NT_STATUS_NO_MEMORY
;
1500 return make_server_info_info3(mem_ctx
,
1501 sent_nt_username
, domain
,
1502 server_info
, info3
);
1506 * Verify whether or not given domain is trusted.
1508 * @param domain_name name of the domain to be verified
1509 * @return true if domain is one of the trusted ones or
1510 * false if otherwise
1513 bool is_trusted_domain(const char* dom_name
)
1515 struct dom_sid trustdom_sid
;
1518 /* no trusted domains for a standalone server */
1520 if ( lp_server_role() == ROLE_STANDALONE
)
1523 if (dom_name
== NULL
|| dom_name
[0] == '\0') {
1527 if (strequal(dom_name
, get_global_sam_name())) {
1531 /* if we are a DC, then check for a direct trust relationships */
1535 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1536 "[%s]\n", dom_name
));
1537 ret
= pdb_get_trusteddom_pw(dom_name
, NULL
, NULL
, NULL
);
1545 /* If winbind is around, ask it */
1547 result
= wb_is_trusted_domain(dom_name
);
1549 if (result
== WBC_ERR_SUCCESS
) {
1553 if (result
== WBC_ERR_DOMAIN_NOT_FOUND
) {
1554 /* winbind could not find the domain */
1558 /* The only other possible result is that winbind is not up
1559 and running. We need to update the trustdom_cache
1562 update_trustdom_cache();
1565 /* now the trustdom cache should be available a DC could still
1566 * have a transitive trust so fall back to the cache of trusted
1567 * domains (like a domain member would use */
1569 if ( trustdom_cache_fetch(dom_name
, &trustdom_sid
) ) {
1579 on a logon error possibly map the error to success if "map to guest"
1582 NTSTATUS
do_map_to_guest_server_info(NTSTATUS status
,
1583 struct auth_serversupplied_info
**server_info
,
1584 const char *user
, const char *domain
)
1586 user
= user
? user
: "";
1587 domain
= domain
? domain
: "";
1589 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1590 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
1591 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
1592 DEBUG(3,("No such user %s [%s] - using guest account\n",
1594 return make_server_info_guest(NULL
, server_info
);
1596 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1597 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
1598 DEBUG(3,("Registered username %s for guest access\n",
1600 return make_server_info_guest(NULL
, server_info
);
1608 Extract session key from a session info and return it in a blob
1609 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1611 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1612 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1614 Note that returned session_key is referencing the original key, it is supposed to be
1615 short-lived. If original session_info->session_key is gone, the reference will be broken.
1617 NTSTATUS
session_extract_session_key(const struct auth_session_info
*session_info
, DATA_BLOB
*session_key
, enum session_key_use_intent intent
)
1620 if (session_key
== NULL
|| session_info
== NULL
) {
1621 return NT_STATUS_INVALID_PARAMETER
;
1624 if (session_info
->session_key
.length
== 0) {
1625 return NT_STATUS_NO_USER_SESSION_KEY
;
1628 *session_key
= session_info
->session_key
;
1629 if (intent
== KEY_USE_16BYTES
) {
1630 session_key
->length
= MIN(session_info
->session_key
.length
, 16);
1632 return NT_STATUS_OK
;