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 *reason
= "Out of memory in cli_credentials_init()";
371 session_info
->credentials
= creds
;
373 ok
= cli_credentials_set_conf(creds
, lp_ctx
);
375 *reason
= "Failed to load smb.conf";
379 /* Just so we don't segfault trying to get at a username */
380 cli_credentials_set_anonymous(creds
);
382 ret
= cli_credentials_set_client_gss_creds(creds
,
388 *reason
= talloc_asprintf(mem_ctx
,
389 "Failed to set pipe forwarded "
390 "creds: %s\n", error_string
);
394 /* This credential handle isn't useful for password
395 * authentication, so ensure nobody tries to do that */
396 cli_credentials_set_kerberos_state(creds
,
397 CRED_USE_KERBEROS_REQUIRED
,
406 /* Create a auth_session_info_transport from an auth_session_info.
408 * NOTE: Members of the auth_session_info_transport structure are
409 * talloc_referenced() into this structure, and should not be changed.
411 NTSTATUS
auth_session_info_transport_from_session(TALLOC_CTX
*mem_ctx
,
412 struct auth_session_info
*session_info
,
413 struct tevent_context
*event_ctx
,
414 struct loadparm_context
*lp_ctx
,
415 struct auth_session_info_transport
**transport_out
)
418 struct auth_session_info_transport
*session_info_transport
419 = talloc_zero(mem_ctx
, struct auth_session_info_transport
);
420 if (!session_info_transport
) {
421 return NT_STATUS_NO_MEMORY
;
423 session_info_transport
->session_info
= talloc_reference(session_info_transport
, session_info
);
424 if (!session_info_transport
->session_info
) {
425 return NT_STATUS_NO_MEMORY
;
427 #ifdef HAVE_GSS_EXPORT_CRED
428 if (session_info
->credentials
) {
429 struct gssapi_creds_container
*gcc
;
431 OM_uint32 minor_status
;
432 gss_buffer_desc cred_token
;
433 const char *error_string
;
436 ret
= cli_credentials_get_client_gss_creds(session_info
->credentials
,
439 &gcc
, &error_string
);
441 *transport_out
= session_info_transport
;
445 gret
= gss_export_cred(&minor_status
,
448 if (gret
!= GSS_S_COMPLETE
) {
449 return NT_STATUS_INTERNAL_ERROR
;
452 if (cred_token
.length
) {
453 session_info_transport
->exported_gssapi_credentials
454 = data_blob_talloc(session_info_transport
,
457 gss_release_buffer(&minor_status
, &cred_token
);
458 NT_STATUS_HAVE_NO_MEMORY(session_info_transport
->exported_gssapi_credentials
.data
);
462 *transport_out
= session_info_transport
;
467 /* Produce a session_info for an arbitrary DN or principal in the local
468 * DB, assuming the local DB holds all the groups
470 * Supply either a principal or a DN
472 NTSTATUS
authsam_get_session_info_principal(TALLOC_CTX
*mem_ctx
,
473 struct loadparm_context
*lp_ctx
,
474 struct ldb_context
*sam_ctx
,
475 const char *principal
,
476 struct ldb_dn
*user_dn
,
477 uint32_t session_info_flags
,
478 struct auth_session_info
**session_info
)
481 struct auth_user_info_dc
*user_info_dc
;
482 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
484 return NT_STATUS_NO_MEMORY
;
486 nt_status
= authsam_get_user_info_dc_principal(tmp_ctx
, lp_ctx
, sam_ctx
,
489 if (!NT_STATUS_IS_OK(nt_status
)) {
490 talloc_free(tmp_ctx
);
494 nt_status
= auth_generate_session_info(tmp_ctx
, lp_ctx
, sam_ctx
,
499 if (NT_STATUS_IS_OK(nt_status
)) {
500 talloc_steal(mem_ctx
, *session_info
);
502 talloc_free(tmp_ctx
);
507 * prints a struct auth_session_info security token to debug output.
509 void auth_session_info_debug(int dbg_lev
,
510 const struct auth_session_info
*session_info
)
513 DEBUG(dbg_lev
, ("Session Info: (NULL)\n"));
517 security_token_debug(DBGC_AUTH
, dbg_lev
,
518 session_info
->security_token
);
521 NTSTATUS
encode_claims_set(TALLOC_CTX
*mem_ctx
,
522 struct CLAIMS_SET
*claims_set
,
523 DATA_BLOB
*claims_blob
)
525 TALLOC_CTX
*tmp_ctx
= NULL
;
526 enum ndr_err_code ndr_err
;
527 struct CLAIMS_SET_NDR
*claims_set_info
= NULL
;
528 struct CLAIMS_SET_METADATA
*metadata
= NULL
;
529 struct CLAIMS_SET_METADATA_NDR
*metadata_ndr
= NULL
;
531 if (claims_blob
== NULL
) {
532 return NT_STATUS_INVALID_PARAMETER_3
;
535 tmp_ctx
= talloc_new(mem_ctx
);
536 if (tmp_ctx
== NULL
) {
537 return NT_STATUS_NO_MEMORY
;
540 metadata_ndr
= talloc(tmp_ctx
, struct CLAIMS_SET_METADATA_NDR
);
541 if (metadata_ndr
== NULL
) {
542 talloc_free(tmp_ctx
);
543 return NT_STATUS_NO_MEMORY
;
546 metadata
= talloc(metadata_ndr
, struct CLAIMS_SET_METADATA
);
547 if (metadata
== NULL
) {
548 talloc_free(tmp_ctx
);
549 return NT_STATUS_NO_MEMORY
;
552 claims_set_info
= talloc(metadata
, struct CLAIMS_SET_NDR
);
553 if (claims_set_info
== NULL
) {
554 talloc_free(tmp_ctx
);
555 return NT_STATUS_NO_MEMORY
;
558 *metadata_ndr
= (struct CLAIMS_SET_METADATA_NDR
) {
559 .claims
.metadata
= metadata
,
562 *metadata
= (struct CLAIMS_SET_METADATA
) {
563 .claims_set
= claims_set_info
,
564 .compression_format
= CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF
,
567 *claims_set_info
= (struct CLAIMS_SET_NDR
) {
568 .claims
.claims
= claims_set
,
571 ndr_err
= ndr_push_struct_blob(claims_blob
, mem_ctx
, metadata_ndr
,
572 (ndr_push_flags_fn_t
)ndr_push_CLAIMS_SET_METADATA_NDR
);
573 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
574 NTSTATUS nt_status
= ndr_map_error2ntstatus(ndr_err
);
575 DBG_ERR("CLAIMS_SET_METADATA_NDR push failed: %s\n",
576 nt_errstr(nt_status
));
578 talloc_free(tmp_ctx
);
582 talloc_free(tmp_ctx
);
587 * Construct a ‘claims_data’ structure from a claims blob, such as is found in a
590 NTSTATUS
claims_data_from_encoded_claims_set(TALLOC_CTX
*claims_data_ctx
,
591 const DATA_BLOB
*encoded_claims_set
,
592 struct claims_data
**out
)
594 struct claims_data
*claims_data
= NULL
;
598 return NT_STATUS_INVALID_PARAMETER
;
603 claims_data
= talloc(claims_data_ctx
, struct claims_data
);
604 if (claims_data
== NULL
) {
605 return NT_STATUS_NO_MEMORY
;
608 if (encoded_claims_set
!= NULL
) {
610 * We make a copy of the data, for it might not be
611 * talloc‐allocated — we might have obtained it directly with
612 * krb5_pac_get_buffer().
614 data
= data_blob_dup_talloc(claims_data
, *encoded_claims_set
);
615 if (data
.length
!= encoded_claims_set
->length
) {
616 talloc_free(claims_data
);
617 return NT_STATUS_NO_MEMORY
;
621 *claims_data
= (struct claims_data
) {
622 .encoded_claims_set
= data
,
623 .flags
= CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
,
632 * Construct a ‘claims_data’ structure from a talloc‐allocated claims set, such
633 * as we might build from searching the database. If this function returns
634 * successfully, it assumes ownership of the claims set.
636 NTSTATUS
claims_data_from_claims_set(TALLOC_CTX
*claims_data_ctx
,
637 struct CLAIMS_SET
*claims_set
,
638 struct claims_data
**out
)
640 struct claims_data
*claims_data
= NULL
;
643 return NT_STATUS_INVALID_PARAMETER
;
648 claims_data
= talloc(claims_data_ctx
, struct claims_data
);
649 if (claims_data
== NULL
) {
650 return NT_STATUS_NO_MEMORY
;
652 *claims_data
= (struct claims_data
) {
653 .claims_set
= talloc_steal(claims_data
, claims_set
),
654 .flags
= CLAIMS_DATA_CLAIMS_PRESENT
,
663 * From a ‘claims_data’ structure, return an encoded claims blob that can be put
666 NTSTATUS
claims_data_encoded_claims_set(TALLOC_CTX
*mem_ctx
,
667 struct claims_data
*claims_data
,
668 DATA_BLOB
*encoded_claims_set_out
)
670 uint8_t *data
= NULL
;
673 if (encoded_claims_set_out
== NULL
) {
674 return NT_STATUS_INVALID_PARAMETER
;
677 *encoded_claims_set_out
= data_blob_null
;
679 if (claims_data
== NULL
) {
683 if (!(claims_data
->flags
& CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
)) {
686 /* See whether we have a claims set that we can encode. */
687 if (!(claims_data
->flags
& CLAIMS_DATA_CLAIMS_PRESENT
)) {
691 status
= encode_claims_set(claims_data
,
692 claims_data
->claims_set
,
693 &claims_data
->encoded_claims_set
);
694 if (!NT_STATUS_IS_OK(status
)) {
698 claims_data
->flags
|= CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
;
701 if (claims_data
->encoded_claims_set
.data
!= NULL
) {
702 data
= talloc_reference(mem_ctx
, claims_data
->encoded_claims_set
.data
);
704 return NT_STATUS_NO_MEMORY
;
707 len
= claims_data
->encoded_claims_set
.length
;
709 *encoded_claims_set_out
= data_blob_const(data
, len
);
714 * From a ‘claims_data’ structure, return an array of security claims that can
715 * be put in a security token for access checks.
717 NTSTATUS
claims_data_security_claims(TALLOC_CTX
*mem_ctx
,
718 struct claims_data
*claims_data
,
719 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
**security_claims_out
,
720 uint32_t *n_security_claims_out
)
722 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*security_claims
= NULL
;
723 uint32_t n_security_claims
;
726 if (security_claims_out
== NULL
) {
727 return NT_STATUS_INVALID_PARAMETER
;
730 if (n_security_claims_out
== NULL
) {
731 return NT_STATUS_INVALID_PARAMETER
;
734 *security_claims_out
= NULL
;
735 *n_security_claims_out
= 0;
737 if (claims_data
== NULL
) {
741 if (!(claims_data
->flags
& CLAIMS_DATA_SECURITY_CLAIMS_PRESENT
)) {
742 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*decoded_claims
= NULL
;
743 uint32_t n_decoded_claims
= 0;
745 /* See whether we have a claims set that we can convert. */
746 if (!(claims_data
->flags
& CLAIMS_DATA_CLAIMS_PRESENT
)) {
749 * See whether we have an encoded claims set that we can
752 if (!(claims_data
->flags
& CLAIMS_DATA_ENCODED_CLAIMS_PRESENT
)) {
753 /* We don’t have anything. */
757 /* Decode an existing claims set. */
759 if (claims_data
->encoded_claims_set
.length
) {
760 TALLOC_CTX
*tmp_ctx
= NULL
;
761 struct CLAIMS_SET_METADATA_NDR claims
;
762 const struct CLAIMS_SET_METADATA
*metadata
= NULL
;
763 enum ndr_err_code ndr_err
;
765 tmp_ctx
= talloc_new(claims_data
);
766 if (tmp_ctx
== NULL
) {
767 return NT_STATUS_NO_MEMORY
;
770 ndr_err
= ndr_pull_struct_blob(&claims_data
->encoded_claims_set
,
773 (ndr_pull_flags_fn_t
)ndr_pull_CLAIMS_SET_METADATA_NDR
);
774 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
775 status
= ndr_map_error2ntstatus(ndr_err
);
776 DBG_ERR("Failed to parse encoded claims set: %s\n",
778 talloc_free(tmp_ctx
);
782 metadata
= claims
.claims
.metadata
;
783 if (metadata
!= NULL
) {
784 struct CLAIMS_SET_NDR
*claims_set_ndr
= metadata
->claims_set
;
785 if (claims_set_ndr
!= NULL
) {
786 struct CLAIMS_SET
**claims_set
= &claims_set_ndr
->claims
.claims
;
788 claims_data
->claims_set
= talloc_move(claims_data
, claims_set
);
792 talloc_free(tmp_ctx
);
795 claims_data
->flags
|= CLAIMS_DATA_CLAIMS_PRESENT
;
799 * Convert the decoded claims set to the security attribute
802 status
= token_claims_to_claims_v1(claims_data
,
803 claims_data
->claims_set
,
806 if (!NT_STATUS_IS_OK(status
)) {
810 claims_data
->security_claims
= decoded_claims
;
811 claims_data
->n_security_claims
= n_decoded_claims
;
813 claims_data
->flags
|= CLAIMS_DATA_SECURITY_CLAIMS_PRESENT
;
816 if (claims_data
->security_claims
!= NULL
) {
817 security_claims
= talloc_reference(mem_ctx
, claims_data
->security_claims
);
818 if (security_claims
== NULL
) {
819 return NT_STATUS_NO_MEMORY
;
822 n_security_claims
= claims_data
->n_security_claims
;
824 *security_claims_out
= security_claims
;
825 *n_security_claims_out
= n_security_claims
;