2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001-2010
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Stefan Metzmacher 2005
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/>.
25 #include "auth/auth.h"
26 #include "auth/auth_sam.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/credentials/credentials_krb5.h"
29 #include "libcli/security/security.h"
30 #include "libcli/security/claims-conversions.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "librpc/gen_ndr/claims.h"
33 #include "librpc/gen_ndr/ndr_claims.h"
34 #include "dsdb/samdb/samdb.h"
35 #include "auth/session_proto.h"
36 #include "system/kerberos.h"
37 #include <gssapi/gssapi.h>
38 #include "libcli/wbclient/wbclient.h"
41 #define DBGC_CLASS DBGC_AUTH
43 _PUBLIC_
struct auth_session_info
*anonymous_session(TALLOC_CTX
*mem_ctx
,
44 struct loadparm_context
*lp_ctx
)
47 struct auth_session_info
*session_info
= NULL
;
48 nt_status
= auth_anonymous_session_info(mem_ctx
, lp_ctx
, &session_info
);
49 if (!NT_STATUS_IS_OK(nt_status
)) {
55 _PUBLIC_ NTSTATUS
auth_generate_security_token(TALLOC_CTX
*mem_ctx
,
56 struct loadparm_context
*lp_ctx
, /* Optional, if you don't want privileges */
57 struct ldb_context
*sam_ctx
, /* Optional, if you don't want local groups */
58 const struct auth_user_info_dc
*user_info_dc
,
59 const struct auth_user_info_dc
*device_info_dc
,
60 const struct auth_claims auth_claims
,
61 uint32_t session_info_flags
,
62 struct security_token
**_security_token
)
64 struct security_token
*security_token
= NULL
;
67 uint32_t num_sids
= 0;
68 uint32_t num_device_sids
= 0;
69 const char *filter
= NULL
;
70 struct auth_SidAttr
*sids
= NULL
;
71 struct auth_SidAttr
*device_sids
= NULL
;
73 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
74 if (tmp_ctx
== NULL
) {
75 return NT_STATUS_NO_MEMORY
;
78 sids
= talloc_array(tmp_ctx
, struct auth_SidAttr
, user_info_dc
->num_sids
);
81 return NT_STATUS_NO_MEMORY
;
84 num_sids
= user_info_dc
->num_sids
;
86 for (i
=0; i
< user_info_dc
->num_sids
; i
++) {
87 sids
[i
] = user_info_dc
->sids
[i
];
91 * Finally add the "standard" sids.
92 * The only difference between guest and "anonymous"
93 * is the addition of Authenticated_Users.
96 if (session_info_flags
& AUTH_SESSION_INFO_DEFAULT_GROUPS
) {
97 sids
= talloc_realloc(tmp_ctx
, sids
, struct auth_SidAttr
, num_sids
+ 2);
100 return NT_STATUS_NO_MEMORY
;
103 sid_copy(&sids
[num_sids
].sid
, &global_sid_World
);
104 sids
[num_sids
].attrs
= SE_GROUP_DEFAULT_FLAGS
;
107 sid_copy(&sids
[num_sids
].sid
, &global_sid_Network
);
108 sids
[num_sids
].attrs
= SE_GROUP_DEFAULT_FLAGS
;
112 if (session_info_flags
& AUTH_SESSION_INFO_AUTHENTICATED
) {
113 sids
= talloc_realloc(tmp_ctx
, sids
, struct auth_SidAttr
, num_sids
+ 1);
115 TALLOC_FREE(tmp_ctx
);
116 return NT_STATUS_NO_MEMORY
;
119 sid_copy(&sids
[num_sids
].sid
, &global_sid_Authenticated_Users
);
120 sids
[num_sids
].attrs
= SE_GROUP_DEFAULT_FLAGS
;
124 if (session_info_flags
& AUTH_SESSION_INFO_NTLM
) {
125 sids
= talloc_realloc(tmp_ctx
, sids
, struct auth_SidAttr
, num_sids
+ 1);
127 TALLOC_FREE(tmp_ctx
);
128 return NT_STATUS_NO_MEMORY
;
131 if (!dom_sid_parse(SID_NT_NTLM_AUTHENTICATION
, &sids
[num_sids
].sid
)) {
132 TALLOC_FREE(tmp_ctx
);
133 return NT_STATUS_INTERNAL_ERROR
;
135 sids
[num_sids
].attrs
= SE_GROUP_DEFAULT_FLAGS
;
140 if (num_sids
> PRIMARY_USER_SID_INDEX
&& dom_sid_equal(&global_sid_Anonymous
, &sids
[PRIMARY_USER_SID_INDEX
].sid
)) {
141 /* Don't expand nested groups of system, anonymous etc*/
142 } else if (num_sids
> PRIMARY_USER_SID_INDEX
&& dom_sid_equal(&global_sid_System
, &sids
[PRIMARY_USER_SID_INDEX
].sid
)) {
143 /* Don't expand nested groups of system, anonymous etc*/
144 } else if (sam_ctx
!= NULL
) {
145 filter
= talloc_asprintf(tmp_ctx
, "(&(objectClass=group)(groupType:"LDB_OID_COMPARATOR_AND
":=%u))",
146 GROUP_TYPE_BUILTIN_LOCAL_GROUP
);
148 /* Search for each group in the token */
149 for (i
= 0; i
< num_sids
; i
++) {
150 struct dom_sid_buf buf
;
154 sid_dn
= talloc_asprintf(
157 dom_sid_str_buf(&sids
[i
].sid
, &buf
));
158 if (sid_dn
== NULL
) {
159 TALLOC_FREE(tmp_ctx
);
160 return NT_STATUS_NO_MEMORY
;
162 sid_blob
= data_blob_string_const(sid_dn
);
164 /* This function takes in memberOf values and expands
165 * them, as long as they meet the filter - so only
168 * We already have the SID in the token, so set
169 * 'only childs' flag to true */
170 nt_status
= dsdb_expand_nested_groups(sam_ctx
, &sid_blob
, true, filter
,
171 tmp_ctx
, &sids
, &num_sids
);
172 if (!NT_STATUS_IS_OK(nt_status
)) {
173 talloc_free(tmp_ctx
);
179 if (device_info_dc
!= NULL
) {
181 * Make a copy of the device SIDs in case we need to add extra SIDs on
182 * the end. One can never have too much copying.
184 num_device_sids
= device_info_dc
->num_sids
;
185 device_sids
= talloc_array(tmp_ctx
,
188 if (device_sids
== NULL
) {
189 TALLOC_FREE(tmp_ctx
);
190 return NT_STATUS_NO_MEMORY
;
193 for (i
= 0; i
< num_device_sids
; i
++) {
194 device_sids
[i
] = device_info_dc
->sids
[i
];
197 if (session_info_flags
& AUTH_SESSION_INFO_DEVICE_DEFAULT_GROUPS
) {
198 device_sids
= talloc_realloc(tmp_ctx
,
201 num_device_sids
+ 2);
202 if (device_sids
== NULL
) {
203 TALLOC_FREE(tmp_ctx
);
204 return NT_STATUS_NO_MEMORY
;
207 device_sids
[num_device_sids
++] = (struct auth_SidAttr
) {
208 .sid
= global_sid_World
,
209 .attrs
= SE_GROUP_DEFAULT_FLAGS
,
211 device_sids
[num_device_sids
++] = (struct auth_SidAttr
) {
212 .sid
= global_sid_Network
,
213 .attrs
= SE_GROUP_DEFAULT_FLAGS
,
217 if (session_info_flags
& AUTH_SESSION_INFO_DEVICE_AUTHENTICATED
) {
218 device_sids
= talloc_realloc(tmp_ctx
,
221 num_device_sids
+ 1);
222 if (device_sids
== NULL
) {
223 TALLOC_FREE(tmp_ctx
);
224 return NT_STATUS_NO_MEMORY
;
227 device_sids
[num_device_sids
++] = (struct auth_SidAttr
) {
228 .sid
= global_sid_Authenticated_Users
,
229 .attrs
= SE_GROUP_DEFAULT_FLAGS
,
234 nt_status
= security_token_create(mem_ctx
,
243 if (!NT_STATUS_IS_OK(nt_status
)) {
244 TALLOC_FREE(tmp_ctx
);
248 talloc_steal(mem_ctx
, security_token
);
249 *_security_token
= security_token
;
250 talloc_free(tmp_ctx
);
254 _PUBLIC_ NTSTATUS
auth_generate_session_info(TALLOC_CTX
*mem_ctx
,
255 struct loadparm_context
*lp_ctx
, /* Optional, if you don't want privileges */
256 struct ldb_context
*sam_ctx
, /* Optional, if you don't want local groups */
257 const struct auth_user_info_dc
*user_info_dc
,
258 uint32_t session_info_flags
,
259 struct auth_session_info
**_session_info
)
261 struct auth_session_info
*session_info
;
264 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
265 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
267 session_info
= talloc_zero(tmp_ctx
, struct auth_session_info
);
268 if (session_info
== NULL
) {
269 TALLOC_FREE(tmp_ctx
);
270 return NT_STATUS_NO_MEMORY
;
273 session_info
->info
= talloc_reference(session_info
, user_info_dc
->info
);
274 if (session_info
->info
== NULL
) {
275 TALLOC_FREE(tmp_ctx
);
276 return NT_STATUS_NO_MEMORY
;
279 session_info
->torture
= talloc_zero(session_info
, struct auth_user_info_torture
);
280 if (session_info
->torture
== NULL
) {
281 TALLOC_FREE(tmp_ctx
);
282 return NT_STATUS_NO_MEMORY
;
284 session_info
->torture
->num_dc_sids
= user_info_dc
->num_sids
;
285 session_info
->torture
->dc_sids
= talloc_reference(session_info
, user_info_dc
->sids
);
286 if (session_info
->torture
->dc_sids
== NULL
) {
287 TALLOC_FREE(tmp_ctx
);
288 return NT_STATUS_NO_MEMORY
;
291 /* unless set otherwise, the session key is the user session
292 * key from the auth subsystem */
293 session_info
->session_key
= data_blob_talloc(session_info
, user_info_dc
->user_session_key
.data
, user_info_dc
->user_session_key
.length
);
294 if (!session_info
->session_key
.data
&& user_info_dc
->user_session_key
.length
) {
295 TALLOC_FREE(tmp_ctx
);
296 return NT_STATUS_NO_MEMORY
;
299 nt_status
= auth_generate_security_token(session_info
,
303 NULL
/*device_info_dc */,
304 (struct auth_claims
) {},
306 &session_info
->security_token
);
307 if (!NT_STATUS_IS_OK(nt_status
)) {
308 TALLOC_FREE(tmp_ctx
);
312 session_info
->unique_session_token
= GUID_random();
314 session_info
->credentials
= NULL
;
316 session_info
->ticket_type
= user_info_dc
->ticket_type
;
318 talloc_steal(mem_ctx
, session_info
);
319 *_session_info
= session_info
;
320 talloc_free(tmp_ctx
);
325 /* Fill out the auth_session_info with a cli_credentials based on the
326 * auth_session_info we were forwarded over named pipe forwarding.
328 * NOTE: The structure members of session_info_transport are stolen
329 * with talloc_move() into auth_session_info for long term use
331 struct auth_session_info
*auth_session_info_from_transport(TALLOC_CTX
*mem_ctx
,
332 struct auth_session_info_transport
*session_info_transport
,
333 struct loadparm_context
*lp_ctx
,
336 struct auth_session_info
*session_info
;
337 session_info
= talloc_steal(mem_ctx
, session_info_transport
->session_info
);
339 * This is to allow us to check the type of this pointer using
342 talloc_set_name(session_info
, "struct auth_session_info");
343 #ifdef HAVE_GSS_IMPORT_CRED
344 if (session_info_transport
->exported_gssapi_credentials
.length
) {
345 struct cli_credentials
*creds
;
346 OM_uint32 minor_status
;
347 gss_buffer_desc cred_token
;
348 gss_cred_id_t cred_handle
;
349 const char *error_string
;
353 DEBUG(10, ("Delegated credentials supplied by client\n"));
355 cred_token
.value
= session_info_transport
->exported_gssapi_credentials
.data
;
356 cred_token
.length
= session_info_transport
->exported_gssapi_credentials
.length
;
358 ret
= gss_import_cred(&minor_status
,
361 if (ret
!= GSS_S_COMPLETE
) {
362 *reason
= "Internal error in gss_import_cred()";
366 creds
= cli_credentials_init(session_info
);
368 gss_release_cred(&minor_status
, &cred_handle
);
369 *reason
= "Out of memory in cli_credentials_init()";
372 session_info
->credentials
= creds
;
374 ok
= cli_credentials_set_conf(creds
, lp_ctx
);
376 gss_release_cred(&minor_status
, &cred_handle
);
377 *reason
= "Failed to load smb.conf";
381 /* Just so we don't segfault trying to get at a username */
382 cli_credentials_set_anonymous(creds
);
384 ret
= cli_credentials_set_client_gss_creds(creds
,
390 gss_release_cred(&minor_status
, &cred_handle
);
391 *reason
= talloc_asprintf(mem_ctx
,
392 "Failed to set pipe forwarded "
393 "creds: %s\n", error_string
);
397 /* This credential handle isn't useful for password
398 * authentication, so ensure nobody tries to do that */
399 cli_credentials_set_kerberos_state(creds
,
400 CRED_USE_KERBEROS_REQUIRED
,
409 /* Create a auth_session_info_transport from an auth_session_info.
411 * NOTE: Members of the auth_session_info_transport structure are
412 * talloc_referenced() into this structure, and should not be changed.
414 NTSTATUS
auth_session_info_transport_from_session(TALLOC_CTX
*mem_ctx
,
415 struct auth_session_info
*session_info
,
416 struct tevent_context
*event_ctx
,
417 struct loadparm_context
*lp_ctx
,
418 struct auth_session_info_transport
**transport_out
)
421 struct auth_session_info_transport
*session_info_transport
422 = talloc_zero(mem_ctx
, struct auth_session_info_transport
);
423 if (!session_info_transport
) {
424 return NT_STATUS_NO_MEMORY
;
426 session_info_transport
->session_info
= talloc_reference(session_info_transport
, session_info
);
427 if (!session_info_transport
->session_info
) {
428 return NT_STATUS_NO_MEMORY
;
430 #ifdef HAVE_GSS_EXPORT_CRED
431 if (session_info
->credentials
) {
432 struct gssapi_creds_container
*gcc
;
434 OM_uint32 minor_status
;
435 gss_buffer_desc cred_token
;
436 const char *error_string
;
439 ret
= cli_credentials_get_client_gss_creds(session_info
->credentials
,
442 &gcc
, &error_string
);
444 *transport_out
= session_info_transport
;
448 gret
= gss_export_cred(&minor_status
,
451 if (gret
!= GSS_S_COMPLETE
) {
452 return NT_STATUS_INTERNAL_ERROR
;
455 if (cred_token
.length
) {
456 session_info_transport
->exported_gssapi_credentials
457 = data_blob_talloc(session_info_transport
,
460 gss_release_buffer(&minor_status
, &cred_token
);
461 NT_STATUS_HAVE_NO_MEMORY(session_info_transport
->exported_gssapi_credentials
.data
);
465 *transport_out
= session_info_transport
;
470 /* Produce a session_info for an arbitrary DN or principal in the local
471 * DB, assuming the local DB holds all the groups
473 * Supply either a principal or a DN
475 NTSTATUS
authsam_get_session_info_principal(TALLOC_CTX
*mem_ctx
,
476 struct loadparm_context
*lp_ctx
,
477 struct ldb_context
*sam_ctx
,
478 const char *principal
,
479 struct ldb_dn
*user_dn
,
480 uint32_t session_info_flags
,
481 struct auth_session_info
**session_info
)
484 struct auth_user_info_dc
*user_info_dc
;
485 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
487 return NT_STATUS_NO_MEMORY
;
489 nt_status
= authsam_get_user_info_dc_principal(tmp_ctx
, lp_ctx
, sam_ctx
,
492 if (!NT_STATUS_IS_OK(nt_status
)) {
493 talloc_free(tmp_ctx
);
497 nt_status
= auth_generate_session_info(tmp_ctx
, lp_ctx
, sam_ctx
,
502 if (NT_STATUS_IS_OK(nt_status
)) {
503 talloc_steal(mem_ctx
, *session_info
);
505 talloc_free(tmp_ctx
);
510 * prints a struct auth_session_info security token to debug output.
512 void auth_session_info_debug(int dbg_lev
,
513 const struct auth_session_info
*session_info
)
516 DEBUG(dbg_lev
, ("Session Info: (NULL)\n"));
520 security_token_debug(DBGC_AUTH
, dbg_lev
,
521 session_info
->security_token
);
524 NTSTATUS
encode_claims_set(TALLOC_CTX
*mem_ctx
,
525 struct CLAIMS_SET
*claims_set
,
526 DATA_BLOB
*claims_blob
)
528 TALLOC_CTX
*tmp_ctx
= NULL
;
529 enum ndr_err_code ndr_err
;
530 struct CLAIMS_SET_NDR
*claims_set_info
= NULL
;
531 struct CLAIMS_SET_METADATA
*metadata
= NULL
;
532 struct CLAIMS_SET_METADATA_NDR
*metadata_ndr
= NULL
;
534 if (claims_blob
== NULL
) {
535 return NT_STATUS_INVALID_PARAMETER_3
;
538 tmp_ctx
= talloc_new(mem_ctx
);
539 if (tmp_ctx
== NULL
) {
540 return NT_STATUS_NO_MEMORY
;
543 metadata_ndr
= talloc(tmp_ctx
, struct CLAIMS_SET_METADATA_NDR
);
544 if (metadata_ndr
== NULL
) {
545 talloc_free(tmp_ctx
);
546 return NT_STATUS_NO_MEMORY
;
549 metadata
= talloc(metadata_ndr
, struct CLAIMS_SET_METADATA
);
550 if (metadata
== NULL
) {
551 talloc_free(tmp_ctx
);
552 return NT_STATUS_NO_MEMORY
;
555 claims_set_info
= talloc(metadata
, struct CLAIMS_SET_NDR
);
556 if (claims_set_info
== NULL
) {
557 talloc_free(tmp_ctx
);
558 return NT_STATUS_NO_MEMORY
;
561 *metadata_ndr
= (struct CLAIMS_SET_METADATA_NDR
) {
562 .claims
.metadata
= metadata
,
565 *metadata
= (struct CLAIMS_SET_METADATA
) {
566 .claims_set
= claims_set_info
,
567 .compression_format
= CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF
,
570 *claims_set_info
= (struct CLAIMS_SET_NDR
) {
571 .claims
.claims
= claims_set
,
574 ndr_err
= ndr_push_struct_blob(claims_blob
, mem_ctx
, metadata_ndr
,
575 (ndr_push_flags_fn_t
)ndr_push_CLAIMS_SET_METADATA_NDR
);
576 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
577 NTSTATUS nt_status
= ndr_map_error2ntstatus(ndr_err
);
578 DBG_ERR("CLAIMS_SET_METADATA_NDR push failed: %s\n",
579 nt_errstr(nt_status
));
581 talloc_free(tmp_ctx
);
585 talloc_free(tmp_ctx
);
590 * Construct a ‘claims_data’ structure from a claims blob, such as is found in a
593 NTSTATUS
claims_data_from_encoded_claims_set(TALLOC_CTX
*claims_data_ctx
,
594 const DATA_BLOB
*encoded_claims_set
,
595 struct claims_data
**out
)
597 struct claims_data
*claims_data
= NULL
;
601 return NT_STATUS_INVALID_PARAMETER
;
606 claims_data
= talloc(claims_data_ctx
, struct claims_data
);
607 if (claims_data
== NULL
) {
608 return NT_STATUS_NO_MEMORY
;
611 if (encoded_claims_set
!= NULL
) {
613 * We make a copy of the data, for it might not be
614 * talloc‐allocated — we might have obtained it directly with
615 * krb5_pac_get_buffer().
617 data
= data_blob_dup_talloc(claims_data
, *encoded_claims_set
);
618 if (data
.length
!= encoded_claims_set
->length
) {
619 talloc_free(claims_data
);
620 return NT_STATUS_NO_MEMORY
;
624 *claims_data
= (struct claims_data
) {
625 .encoded_claims_set
= data
,
626 .flags
= CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
,
635 * Construct a ‘claims_data’ structure from a talloc‐allocated claims set, such
636 * as we might build from searching the database. If this function returns
637 * successfully, it assumes ownership of the claims set.
639 NTSTATUS
claims_data_from_claims_set(TALLOC_CTX
*claims_data_ctx
,
640 struct CLAIMS_SET
*claims_set
,
641 struct claims_data
**out
)
643 struct claims_data
*claims_data
= NULL
;
646 return NT_STATUS_INVALID_PARAMETER
;
651 claims_data
= talloc(claims_data_ctx
, struct claims_data
);
652 if (claims_data
== NULL
) {
653 return NT_STATUS_NO_MEMORY
;
655 *claims_data
= (struct claims_data
) {
656 .claims_set
= talloc_steal(claims_data
, claims_set
),
657 .flags
= CLAIMS_DATA_CLAIMS_PRESENT
,
666 * From a ‘claims_data’ structure, return an encoded claims blob that can be put
669 NTSTATUS
claims_data_encoded_claims_set(TALLOC_CTX
*mem_ctx
,
670 struct claims_data
*claims_data
,
671 DATA_BLOB
*encoded_claims_set_out
)
673 uint8_t *data
= NULL
;
676 if (encoded_claims_set_out
== NULL
) {
677 return NT_STATUS_INVALID_PARAMETER
;
680 *encoded_claims_set_out
= data_blob_null
;
682 if (claims_data
== NULL
) {
686 if (!(claims_data
->flags
& CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
)) {
689 /* See whether we have a claims set that we can encode. */
690 if (!(claims_data
->flags
& CLAIMS_DATA_CLAIMS_PRESENT
)) {
694 status
= encode_claims_set(claims_data
,
695 claims_data
->claims_set
,
696 &claims_data
->encoded_claims_set
);
697 if (!NT_STATUS_IS_OK(status
)) {
701 claims_data
->flags
|= CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
;
704 if (claims_data
->encoded_claims_set
.data
!= NULL
) {
705 data
= talloc_reference(mem_ctx
, claims_data
->encoded_claims_set
.data
);
707 return NT_STATUS_NO_MEMORY
;
710 len
= claims_data
->encoded_claims_set
.length
;
712 *encoded_claims_set_out
= data_blob_const(data
, len
);
717 * From a ‘claims_data’ structure, return an array of security claims that can
718 * be put in a security token for access checks.
720 NTSTATUS
claims_data_security_claims(TALLOC_CTX
*mem_ctx
,
721 struct claims_data
*claims_data
,
722 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
**security_claims_out
,
723 uint32_t *n_security_claims_out
)
725 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*security_claims
= NULL
;
726 uint32_t n_security_claims
;
729 if (security_claims_out
== NULL
) {
730 return NT_STATUS_INVALID_PARAMETER
;
733 if (n_security_claims_out
== NULL
) {
734 return NT_STATUS_INVALID_PARAMETER
;
737 *security_claims_out
= NULL
;
738 *n_security_claims_out
= 0;
740 if (claims_data
== NULL
) {
744 if (!(claims_data
->flags
& CLAIMS_DATA_SECURITY_CLAIMS_PRESENT
)) {
745 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*decoded_claims
= NULL
;
746 uint32_t n_decoded_claims
= 0;
748 /* See whether we have a claims set that we can convert. */
749 if (!(claims_data
->flags
& CLAIMS_DATA_CLAIMS_PRESENT
)) {
752 * See whether we have an encoded claims set that we can
755 if (!(claims_data
->flags
& CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
)) {
756 /* We don’t have anything. */
760 /* Decode an existing claims set. */
762 if (claims_data
->encoded_claims_set
.length
) {
763 TALLOC_CTX
*tmp_ctx
= NULL
;
764 struct CLAIMS_SET_METADATA_NDR claims
;
765 const struct CLAIMS_SET_METADATA
*metadata
= NULL
;
766 enum ndr_err_code ndr_err
;
768 tmp_ctx
= talloc_new(claims_data
);
769 if (tmp_ctx
== NULL
) {
770 return NT_STATUS_NO_MEMORY
;
773 ndr_err
= ndr_pull_struct_blob(&claims_data
->encoded_claims_set
,
776 (ndr_pull_flags_fn_t
)ndr_pull_CLAIMS_SET_METADATA_NDR
);
777 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
778 status
= ndr_map_error2ntstatus(ndr_err
);
779 DBG_ERR("Failed to parse encoded claims set: %s\n",
781 talloc_free(tmp_ctx
);
785 metadata
= claims
.claims
.metadata
;
786 if (metadata
!= NULL
) {
787 struct CLAIMS_SET_NDR
*claims_set_ndr
= metadata
->claims_set
;
788 if (claims_set_ndr
!= NULL
) {
789 struct CLAIMS_SET
**claims_set
= &claims_set_ndr
->claims
.claims
;
791 claims_data
->claims_set
= talloc_move(claims_data
, claims_set
);
795 talloc_free(tmp_ctx
);
798 claims_data
->flags
|= CLAIMS_DATA_CLAIMS_PRESENT
;
802 * Convert the decoded claims set to the security attribute
805 status
= token_claims_to_claims_v1(claims_data
,
806 claims_data
->claims_set
,
809 if (!NT_STATUS_IS_OK(status
)) {
813 claims_data
->security_claims
= decoded_claims
;
814 claims_data
->n_security_claims
= n_decoded_claims
;
816 claims_data
->flags
|= CLAIMS_DATA_SECURITY_CLAIMS_PRESENT
;
819 if (claims_data
->security_claims
!= NULL
) {
820 security_claims
= talloc_reference(mem_ctx
, claims_data
->security_claims
);
821 if (security_claims
== NULL
) {
822 return NT_STATUS_NO_MEMORY
;
825 n_security_claims
= claims_data
->n_security_claims
;
827 *security_claims_out
= security_claims
;
828 *n_security_claims_out
= n_security_claims
;