ldb-samba: ldif_read_objectSid avoids VLA
[Samba.git] / source4 / auth / session.c
blob9c9d8c4aaffdb3339f52836227ea3de36d203662
1 /*
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/>.
24 #include "includes.h"
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"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_AUTH
43 _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx,
44 struct loadparm_context *lp_ctx)
46 NTSTATUS nt_status;
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)) {
50 return NULL;
52 return session_info;
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;
65 NTSTATUS nt_status;
66 uint32_t i;
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);
79 if (sids == NULL) {
80 TALLOC_FREE(tmp_ctx);
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);
98 if (sids == NULL) {
99 TALLOC_FREE(tmp_ctx);
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;
105 num_sids++;
107 sid_copy(&sids[num_sids].sid, &global_sid_Network);
108 sids[num_sids].attrs = SE_GROUP_DEFAULT_FLAGS;
109 num_sids++;
112 if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
113 sids = talloc_realloc(tmp_ctx, sids, struct auth_SidAttr, num_sids + 1);
114 if (sids == NULL) {
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;
121 num_sids++;
124 if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
125 sids = talloc_realloc(tmp_ctx, sids, struct auth_SidAttr, num_sids + 1);
126 if (sids == NULL) {
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;
136 num_sids++;
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;
151 const char *sid_dn;
152 DATA_BLOB sid_blob;
154 sid_dn = talloc_asprintf(
155 tmp_ctx,
156 "<SID=%s>",
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
166 * builtin groups
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);
174 return nt_status;
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,
186 struct auth_SidAttr,
187 num_device_sids);
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,
199 device_sids,
200 struct auth_SidAttr,
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,
219 device_sids,
220 struct auth_SidAttr,
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,
235 lp_ctx,
236 num_sids,
237 sids,
238 num_device_sids,
239 device_sids,
240 auth_claims,
241 session_info_flags,
242 &security_token);
243 if (!NT_STATUS_IS_OK(nt_status)) {
244 TALLOC_FREE(tmp_ctx);
245 return nt_status;
248 talloc_steal(mem_ctx, security_token);
249 *_security_token = security_token;
250 talloc_free(tmp_ctx);
251 return NT_STATUS_OK;
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;
262 NTSTATUS nt_status;
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,
300 lp_ctx,
301 sam_ctx,
302 user_info_dc,
303 NULL /*device_info_dc */,
304 (struct auth_claims) {},
305 session_info_flags,
306 &session_info->security_token);
307 if (!NT_STATUS_IS_OK(nt_status)) {
308 TALLOC_FREE(tmp_ctx);
309 return nt_status;
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);
321 return NT_STATUS_OK;
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,
334 const char **reason)
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
340 * talloc_get_type()
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;
350 int ret;
351 bool ok;
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,
359 &cred_token,
360 &cred_handle);
361 if (ret != GSS_S_COMPLETE) {
362 *reason = "Internal error in gss_import_cred()";
363 return NULL;
366 creds = cli_credentials_init(session_info);
367 if (!creds) {
368 *reason = "Out of memory in cli_credentials_init()";
369 return NULL;
371 session_info->credentials = creds;
373 ok = cli_credentials_set_conf(creds, lp_ctx);
374 if (!ok) {
375 *reason = "Failed to load smb.conf";
376 return NULL;
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,
383 lp_ctx,
384 cred_handle,
385 CRED_SPECIFIED,
386 &error_string);
387 if (ret) {
388 *reason = talloc_asprintf(mem_ctx,
389 "Failed to set pipe forwarded "
390 "creds: %s\n", error_string);
391 return NULL;
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,
398 CRED_SPECIFIED);
401 #endif
402 return session_info;
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;
430 OM_uint32 gret;
431 OM_uint32 minor_status;
432 gss_buffer_desc cred_token;
433 const char *error_string;
434 int ret;
436 ret = cli_credentials_get_client_gss_creds(session_info->credentials,
437 event_ctx,
438 lp_ctx,
439 &gcc, &error_string);
440 if (ret != 0) {
441 *transport_out = session_info_transport;
442 return NT_STATUS_OK;
445 gret = gss_export_cred(&minor_status,
446 gcc->creds,
447 &cred_token);
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,
455 cred_token.value,
456 cred_token.length);
457 gss_release_buffer(&minor_status, &cred_token);
458 NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
461 #endif
462 *transport_out = session_info_transport;
463 return NT_STATUS_OK;
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)
480 NTSTATUS nt_status;
481 struct auth_user_info_dc *user_info_dc;
482 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
483 if (!tmp_ctx) {
484 return NT_STATUS_NO_MEMORY;
486 nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
487 principal, user_dn,
488 &user_info_dc);
489 if (!NT_STATUS_IS_OK(nt_status)) {
490 talloc_free(tmp_ctx);
491 return nt_status;
494 nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
495 user_info_dc,
496 session_info_flags,
497 session_info);
499 if (NT_STATUS_IS_OK(nt_status)) {
500 talloc_steal(mem_ctx, *session_info);
502 talloc_free(tmp_ctx);
503 return nt_status;
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)
512 if (!session_info) {
513 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
514 return;
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);
579 return nt_status;
582 talloc_free(tmp_ctx);
583 return NT_STATUS_OK;
587 * Construct a ‘claims_data’ structure from a claims blob, such as is found in a
588 * PAC.
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;
595 DATA_BLOB data = {};
597 if (out == NULL) {
598 return NT_STATUS_INVALID_PARAMETER;
601 *out = NULL;
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,
626 *out = claims_data;
628 return NT_STATUS_OK;
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;
642 if (out == NULL) {
643 return NT_STATUS_INVALID_PARAMETER;
646 *out = NULL;
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,
657 *out = claims_data;
659 return NT_STATUS_OK;
663 * From a ‘claims_data’ structure, return an encoded claims blob that can be put
664 * into a PAC.
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;
671 size_t len;
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) {
680 return NT_STATUS_OK;
683 if (!(claims_data->flags & CLAIMS_DATA_ENCODED_CLAIMS_PRESENT)) {
684 NTSTATUS status;
686 /* See whether we have a claims set that we can encode. */
687 if (!(claims_data->flags & CLAIMS_DATA_CLAIMS_PRESENT)) {
688 return NT_STATUS_OK;
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)) {
695 return 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);
703 if (data == NULL) {
704 return NT_STATUS_NO_MEMORY;
707 len = claims_data->encoded_claims_set.length;
709 *encoded_claims_set_out = data_blob_const(data, len);
710 return NT_STATUS_OK;
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;
724 NTSTATUS status;
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) {
738 return NT_STATUS_OK;
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
750 * decode.
752 if (!(claims_data->flags & CLAIMS_DATA_ENCODED_CLAIMS_PRESENT)) {
753 /* We don’t have anything. */
754 return NT_STATUS_OK;
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,
771 tmp_ctx,
772 &claims,
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",
777 nt_errstr(status));
778 talloc_free(tmp_ctx);
779 return status;
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
800 * claims format.
802 status = token_claims_to_claims_v1(claims_data,
803 claims_data->claims_set,
804 &decoded_claims,
805 &n_decoded_claims);
806 if (!NT_STATUS_IS_OK(status)) {
807 return 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;
827 return NT_STATUS_OK;