2 Unix SMB/CIFS implementation.
3 Samba Active Directory claims utility functions
5 Copyright (C) Catalyst.Net Ltd 2023
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/replace/replace.h"
22 #include "lib/util/debug.h"
23 #include "lib/util/samba_util.h"
24 #include "source4/kdc/ad_claims.h"
25 #include "ldb_module.h"
26 #include "libcli/security/security.h"
27 #include "libcli/util/werror.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "dsdb/samdb/ldb_modules/util.h"
30 #include "librpc/gen_ndr/claims.h"
31 #include "librpc/gen_ndr/ndr_claims.h"
32 #include "librpc/gen_ndr/krb5pac.h"
33 #include "librpc/gen_ndr/ndr_krb5pac.h"
34 #include "lzxpress_huffman.h"
35 #include "lib/util/binsearch.h"
39 static int acl_attr_cmp_fn(const char *a, const char * const *b)
41 return ldb_attr_cmp(a, *b);
45 * Add a single attribute to a list of attributes if it is not already
46 * present. The list is maintained in case-insensitive sorted order.
48 static int add_attr_unique(TALLOC_CTX *mem_ctx,
50 unsigned *ad_claim_attrs_count,
53 const unsigned count = *ad_claim_attrs_count;
54 const char * const *exact = NULL;
55 const char * const *next = NULL;
57 BINARY_ARRAY_SEARCH_GTE(attrs,
64 /* The attribute is already present; there's nothing to do. */
68 /* Make sure we don't overflow the array. */
69 SMB_ASSERT(count < talloc_array_length(attrs));
70 *ad_claim_attrs_count = count + 1;
73 /* Just add the new element on the end. */
76 /* Shift all following elements over to make room. */
77 size_t next_idx = next - attrs;
78 size_t bytes_to_move = (count - next_idx) * sizeof (attrs[0]);
79 memmove(&attrs[next_idx + 1],
83 attrs[next_idx] = attr;
90 * Return true if a data_blob, interpreted as a string, is equal to another
91 * string. This is more efficient than strcmp(), particularly when comparing
92 * against a string constant. This assumes the data_blob's length does not
93 * include the zero-terminator.
95 static inline bool data_blob_equals_str(const DATA_BLOB val, const char *str)
97 size_t len = strlen(str);
98 if (val.length != len) {
102 return memcmp(val.data, str, len) == 0;
105 static int fill_claim_int64(TALLOC_CTX *mem_ctx,
106 struct ldb_context *ldb,
107 const struct ldb_message_element *principal_attribute,
108 const struct ldb_val name,
109 struct CLAIM_INT64 *claim)
113 claim->value_count = 0;
114 claim->values = talloc_array(mem_ctx,
116 principal_attribute->num_values);
117 if (claim->values == NULL) {
121 for (i = 0; i < principal_attribute->num_values; ++i) {
122 const struct ldb_val *value = &principal_attribute->values[i];
123 int ret = ldb_val_as_int64(value, &claim->values[i]);
126 const char *reason = NULL;
127 int err = strerror_r(ret, buf, sizeof(buf));
131 reason = "Unknown error";
133 DBG_WARNING("Failed to interpret value %s as INT64 "
134 "while creating claim %s for attribute %s (%s); "
136 (value->data != NULL) ? (const char *)value->data : "<unknown>",
137 name.data, principal_attribute->name,
142 ++claim->value_count;
145 /* Shrink the array to fit. */
146 claim->values = talloc_realloc(mem_ctx,
150 if (claim->value_count && claim->values == NULL) {
157 static int fill_claim_uint64(TALLOC_CTX *mem_ctx,
158 struct ldb_context *ldb,
159 const struct ldb_message_element *principal_attribute,
160 const struct ldb_val name,
161 struct CLAIM_UINT64 *claim)
165 claim->value_count = 0;
166 claim->values = talloc_array(mem_ctx,
168 principal_attribute->num_values);
169 if (claim->values == NULL) {
173 for (i = 0; i < principal_attribute->num_values; ++i) {
174 const struct ldb_val *value = &principal_attribute->values[i];
175 int ret = ldb_val_as_uint64(value, &claim->values[i]);
178 const char *reason = NULL;
179 int err = strerror_r(ret, buf, sizeof(buf));
183 reason = "Unknown error";
185 DBG_WARNING("Failed to interpret value %s as UINT64 "
186 "while creating claim %s for attribute %s (%s); "
188 (value->data != NULL) ? (const char *)value->data : "<unknown>",
189 name.data, principal_attribute->name,
194 ++claim->value_count;
197 /* Shrink the array to fit. */
198 claim->values = talloc_realloc(mem_ctx,
202 if (claim->value_count && claim->values == NULL) {
209 static int fill_claim_uint64_oid_syntax(TALLOC_CTX *mem_ctx,
210 struct ldb_context *ldb,
211 const struct dsdb_schema *schema,
212 const struct ldb_message_element *principal_attribute,
213 const struct ldb_val name,
214 struct CLAIM_UINT64 *claim)
218 claim->value_count = 0;
219 claim->values = talloc_array(mem_ctx,
221 principal_attribute->num_values);
222 if (claim->values == NULL) {
226 for (i = 0; i < principal_attribute->num_values; ++i) {
227 const struct dsdb_class *class_val = NULL;
230 * OID values for objectClass
231 * are presented in reverse
234 const struct ldb_val *display_name = &principal_attribute->values[
235 principal_attribute->num_values - 1 - i];
237 class_val = dsdb_class_by_lDAPDisplayName_ldb_val(schema, display_name);
238 if (class_val == NULL) {
239 DBG_WARNING("Failed to look up OID for value %s "
240 "while creating claim %s for attribute %s; "
242 (display_name->data != NULL) ? (const char *)display_name->data : "<unknown>",
243 name.data, principal_attribute->name);
247 claim->values[i] = class_val->governsID_id;
248 ++claim->value_count;
251 /* Shrink the array to fit. */
252 claim->values = talloc_realloc(mem_ctx,
256 if (claim->value_count && claim->values == NULL) {
263 static int fill_claim_boolean(TALLOC_CTX *mem_ctx,
264 struct ldb_context *ldb,
265 const struct ldb_message_element *principal_attribute,
266 const struct ldb_val name,
267 struct CLAIM_UINT64 *claim)
271 claim->value_count = 0;
272 claim->values = talloc_array(mem_ctx,
274 principal_attribute->num_values);
275 if (claim->values == NULL) {
279 for (i = 0; i < principal_attribute->num_values; ++i) {
280 const struct ldb_val *value = &principal_attribute->values[i];
282 int ret = ldb_val_as_bool(value, &val);
285 const char *reason = NULL;
286 int err = strerror_r(ret, buf, sizeof(buf));
290 reason = "Unknown error";
292 DBG_WARNING("Failed to interpret value %s as BOOL "
293 "while creating claim %s for attribute %s (%s); "
295 (value->data != NULL) ? (const char *)value->data : "<unknown>",
296 name.data, principal_attribute->name,
301 claim->values[i] = val;
302 ++claim->value_count;
305 /* Shrink the array to fit. */
306 claim->values = talloc_realloc(mem_ctx,
310 if (claim->value_count && claim->values == NULL) {
317 static int fill_claim_string(TALLOC_CTX *mem_ctx,
318 struct ldb_context *ldb,
319 const struct ldb_message_element *principal_attribute,
320 struct CLAIM_STRING *claim)
324 claim->value_count = 0;
325 claim->values = talloc_array(mem_ctx,
327 principal_attribute->num_values);
328 if (claim->values == NULL) {
332 for (i = 0; i < principal_attribute->num_values; ++i) {
333 const char *val = NULL;
334 const struct ldb_val *v = &principal_attribute->values[i];
336 if (v == NULL || v->data == NULL) {
340 val = talloc_strndup(claim->values,
341 (const char *)v->data,
347 claim->values[i] = val;
348 ++claim->value_count;
351 /* Shrink the array to fit. */
352 claim->values = talloc_realloc(mem_ctx,
356 if (claim->value_count && claim->values == NULL) {
363 static int fill_claim_string_sec_desc_syntax(TALLOC_CTX *mem_ctx,
364 struct ldb_context *ldb,
365 const struct ldb_message_element *principal_attribute,
366 struct CLAIM_STRING *claim)
368 TALLOC_CTX *tmp_ctx = NULL;
369 const struct dom_sid *domain_sid = NULL;
372 claim->value_count = 0;
373 claim->values = talloc_array(mem_ctx,
375 principal_attribute->num_values);
376 if (claim->values == NULL) {
380 domain_sid = samdb_domain_sid(ldb);
381 if (domain_sid == NULL) {
385 tmp_ctx = talloc_new(mem_ctx);
386 if (tmp_ctx == NULL) {
390 for (i = 0; i < principal_attribute->num_values; ++i) {
391 const struct ldb_val *v = &principal_attribute->values[i];
393 enum ndr_err_code ndr_err;
394 struct security_descriptor desc = {};
395 const char *sddl = NULL;
397 if (v == NULL || v->data == NULL) {
401 ndr_err = ndr_pull_struct_blob(v,
404 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
406 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
407 DBG_ERR("security_descriptor pull failed: %s\n",
408 nt_errstr(nt_status));
409 talloc_free(tmp_ctx);
410 return ldb_operr(ldb);
413 sddl = sddl_encode(mem_ctx,
417 talloc_free(tmp_ctx);
421 claim->values[i] = sddl;
422 ++claim->value_count;
425 talloc_free(tmp_ctx);
427 /* Shrink the array to fit. */
428 claim->values = talloc_realloc(mem_ctx,
432 if (claim->value_count && claim->values == NULL) {
439 static int fill_claim_entry(TALLOC_CTX *mem_ctx,
440 struct ldb_context *ldb,
441 const struct dsdb_schema *schema,
442 const struct ldb_message_element *principal_attribute,
443 const struct ldb_val name,
444 const DATA_BLOB syntax,
445 enum CLAIM_TYPE claim_type,
446 struct CLAIM_ENTRY *claim_entry)
449 claim_entry->id = (const char *)name.data;
450 claim_entry->type = claim_type;
452 switch (claim_type) {
453 case CLAIM_TYPE_INT64:
454 return fill_claim_int64(mem_ctx,
458 &claim_entry->values.claim_int64);
459 case CLAIM_TYPE_UINT64:
460 if (syntax.data != NULL && data_blob_equals_str(syntax, "2.5.5.2")) {
461 return fill_claim_uint64_oid_syntax(mem_ctx,
466 &claim_entry->values.claim_uint64);
468 return fill_claim_uint64(mem_ctx,
472 &claim_entry->values.claim_uint64);
474 case CLAIM_TYPE_BOOLEAN:
475 return fill_claim_boolean(mem_ctx,
479 &claim_entry->values.claim_boolean);
480 case CLAIM_TYPE_STRING:
482 if (syntax.data != NULL && data_blob_equals_str(syntax, "2.5.5.15")) {
483 return fill_claim_string_sec_desc_syntax(mem_ctx,
486 &claim_entry->values.claim_string);
488 return fill_claim_string(mem_ctx,
491 &claim_entry->values.claim_string);
497 * Determine wheter a claim applies to the most specific objectClass of the
500 static int claim_applies_to_class(TALLOC_CTX *mem_ctx,
501 struct ldb_context *ldb,
502 const struct dsdb_schema *schema,
503 const struct ldb_message *claim_msg,
504 const uint32_t principal_class_id,
507 struct ldb_message_element *applies_to_class = NULL;
510 applies_to_class = ldb_msg_find_element(claim_msg,
511 "msDS-ClaimTypeAppliesToClass");
512 if (applies_to_class == NULL) {
517 for (i = 0; i < applies_to_class->num_values; ++i) {
518 struct ldb_dn *class_dn = NULL;
519 const struct dsdb_class *class_val = NULL;
520 const struct ldb_val *class_rdn = NULL;
522 class_dn = ldb_dn_from_ldb_val(mem_ctx,
524 &applies_to_class->values[i]);
525 if (class_dn == NULL) {
529 class_rdn = ldb_dn_get_rdn_val(class_dn);
530 if (class_rdn == NULL) {
531 TALLOC_FREE(class_dn);
535 class_val = dsdb_class_by_cn_ldb_val(schema, class_rdn);
536 TALLOC_FREE(class_dn);
537 if (class_val == NULL) {
541 if (class_val->governsID_id == principal_class_id) {
551 static inline struct ldb_val talloc_steal_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_val val)
553 val.data = talloc_steal(mem_ctx, val.data);
557 static uint32_t claim_get_value_count(const struct CLAIM_ENTRY *claim)
559 switch (claim->type) {
560 case CLAIM_TYPE_INT64:
561 return claim->values.claim_int64.value_count;
562 case CLAIM_TYPE_UINT64:
563 return claim->values.claim_uint64.value_count;
564 case CLAIM_TYPE_STRING:
565 return claim->values.claim_string.value_count;
566 case CLAIM_TYPE_BOOLEAN:
567 return claim->values.claim_boolean.value_count;
570 smb_panic(__location__ ": unknown claim type");
574 static int encode_claims_set(struct ldb_context *ldb,
576 struct CLAIMS_SET *claims_set,
577 DATA_BLOB *claims_blob)
579 TALLOC_CTX *tmp_ctx = NULL;
580 enum ndr_err_code ndr_err;
581 struct CLAIMS_SET_NDR *claims_set_info = NULL;
582 struct CLAIMS_SET_METADATA *metadata = NULL;
583 struct CLAIMS_SET_METADATA_NDR *metadata_ndr = NULL;
585 tmp_ctx = talloc_new(mem_ctx);
586 if (tmp_ctx == NULL) {
590 metadata_ndr = talloc_zero(tmp_ctx, struct CLAIMS_SET_METADATA_NDR);
591 if (metadata_ndr == NULL) {
592 talloc_free(tmp_ctx);
596 metadata = talloc_zero(metadata_ndr, struct CLAIMS_SET_METADATA);
597 if (metadata == NULL) {
598 talloc_free(tmp_ctx);
602 claims_set_info = talloc_zero(metadata, struct CLAIMS_SET_NDR);
603 if (claims_set_info == NULL) {
604 talloc_free(tmp_ctx);
608 metadata_ndr->claims.metadata = metadata;
610 metadata->claims_set = claims_set_info;
611 metadata->compression_format = CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF;
613 claims_set_info->claims.claims = claims_set;
615 ndr_err = ndr_push_struct_blob(claims_blob, mem_ctx, metadata_ndr,
616 (ndr_push_flags_fn_t)ndr_push_CLAIMS_SET_METADATA_NDR);
617 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
618 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
619 DBG_ERR("CLAIMS_SET_METADATA_NDR push failed: %s\n",
620 nt_errstr(nt_status));
622 talloc_free(tmp_ctx);
623 return ldb_operr(ldb);
626 talloc_free(tmp_ctx);
630 static bool is_schema_dn(struct ldb_dn *dn,
631 struct ldb_dn *schema_dn)
633 if (ldb_dn_get_comp_num(dn) != (ldb_dn_get_comp_num(schema_dn) + 1)) {
637 return ldb_dn_compare_base(schema_dn, dn) == 0;
640 static bool is_valid_claim_attribute_syntax(const DATA_BLOB source_syntax,
641 uint64_t claim_value_type)
643 switch (claim_value_type) {
644 case CLAIM_TYPE_STRING:
645 if (data_blob_equals_str(source_syntax, "2.5.5.1")) {
648 if (data_blob_equals_str(source_syntax, "2.5.5.12")) {
651 if (data_blob_equals_str(source_syntax, "2.5.5.15")) {
655 case CLAIM_TYPE_UINT64:
656 if (data_blob_equals_str(source_syntax, "2.5.5.2")) {
660 case CLAIM_TYPE_INT64:
661 if (data_blob_equals_str(source_syntax, "2.5.5.9")) {
664 if (data_blob_equals_str(source_syntax, "2.5.5.16")) {
668 case CLAIM_TYPE_BOOLEAN:
669 /* Note: MS-ADTS has a typo (2.2.5.8 instead of 2.5.5.8) */
670 if (data_blob_equals_str(source_syntax, "2.5.5.8")) {
681 static int get_all_claims(struct ldb_context *ldb,
683 struct ldb_dn *principal_dn,
684 uint32_t principal_class_id,
685 DATA_BLOB *claims_blob)
687 TALLOC_CTX *tmp_ctx = NULL;
689 const struct dsdb_schema *schema = NULL;
691 struct ldb_dn *claim_config_container = NULL;
692 struct ldb_dn *claim_types_child = NULL;
693 struct ldb_dn *config_dn = ldb_get_config_basedn(ldb);
694 struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
697 struct ldb_result *res = NULL;
698 static const char * const attrs[] = {
700 "msDS-ClaimAttributeSource",
702 "msDS-ClaimSourceType",
703 "msDS-ClaimTypeAppliesToClass",
704 "msDS-ClaimValueType",
709 const char **ad_claim_attrs = NULL;
710 unsigned int ad_claim_attrs_count;
711 struct ad_claim_info {
714 const char *attribute;
715 enum CLAIM_TYPE claim_type;
717 unsigned ad_claims_count;
721 /* The structure which we'll use to build up the claims. */
722 struct CLAIMS_SET claims_set = {};
724 struct CLAIMS_ARRAY *ad_sourced_constructed = NULL;
726 *claims_blob = data_blob_null;
728 tmp_ctx = talloc_new(mem_ctx);
729 if (tmp_ctx == NULL) {
733 schema = dsdb_get_schema(ldb, tmp_ctx);
734 if (schema == NULL) {
735 talloc_free(tmp_ctx);
736 return ldb_operr(ldb);
739 /* Get the DN of the claims container. */
740 claim_config_container = ldb_dn_copy(tmp_ctx, config_dn);
741 if (claim_config_container == NULL) {
742 talloc_free(tmp_ctx);
746 claim_types_child = ldb_dn_new(tmp_ctx, ldb,
747 "CN=Claim Types,CN=Claims Configuration,CN=Services");
748 if (claim_types_child == NULL) {
749 talloc_free(tmp_ctx);
753 ok = ldb_dn_add_child(claim_config_container, claim_types_child);
754 TALLOC_FREE(claim_types_child);
756 talloc_free(tmp_ctx);
757 return ldb_operr(ldb);
760 /* Search for the claims container's children. */
761 ret = ldb_search(ldb, tmp_ctx, &res,
762 claim_config_container,
766 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
770 talloc_free(tmp_ctx);
775 * Allocate enough space for all AD claim attributes, followed by space
776 * for a NULL marker (so it can be passed as the attributes filter to
779 ad_claim_attrs = talloc_array(tmp_ctx,
782 if (ad_claim_attrs == NULL) {
783 talloc_free(tmp_ctx);
786 ad_claims = talloc_array(tmp_ctx,
787 struct ad_claim_info,
789 if (ad_claims == NULL) {
790 talloc_free(tmp_ctx);
793 ad_claims_count = ad_claim_attrs_count = 0;
795 /* Loop through each child of the claims container. */
796 for (i = 0; i < res->count; ++i) {
797 bool claim_applies = false;
800 uint64_t claim_value_type;
802 const char *claim_source_type = NULL;
803 const struct ldb_val *claim_attribute_source = NULL;
806 * Does this claim apply to the most specific objectClass of the
809 ret = claim_applies_to_class(tmp_ctx,
816 talloc_free(tmp_ctx);
819 if (!claim_applies) {
820 /* If the claim doesn't apply, skip it. */
824 enabled = ldb_msg_find_attr_as_bool(res->msgs[i], "Enabled", 0);
826 /* If the claim isn't enabled, skip it. */
830 claim_value_type = ldb_msg_find_attr_as_uint64(res->msgs[i],
831 "msDS-ClaimValueType",
833 if (!claim_value_type) {
837 claim_source_type = ldb_msg_find_attr_as_string(res->msgs[i],
838 "msDS-ClaimSourceType",
841 /* Get the attribute used by the claim. */
842 claim_attribute_source = ldb_msg_find_ldb_val(res->msgs[i],
843 "msDS-ClaimAttributeSource");
845 if (strcasecmp(claim_source_type, "AD") == 0) {
846 struct ldb_dn *claim_attribute_source_dn = NULL;
847 const struct ldb_val *claim_attribute_source_rdn = NULL;
848 const struct dsdb_attribute *claim_attribute_source_class = NULL;
850 DATA_BLOB source_syntax;
851 const char *attribute = NULL;
852 const struct ldb_val *name = NULL;
854 if (claim_attribute_source == NULL) {
858 claim_attribute_source_dn = ldb_val_as_dn(ldb,
860 claim_attribute_source);
861 if (claim_attribute_source_dn == NULL) {
862 talloc_free(tmp_ctx);
863 return ldb_operr(ldb);
866 if (!is_schema_dn(claim_attribute_source_dn, schema_dn)) {
867 /* This DN doesn't belong to the schema. */
871 claim_attribute_source_rdn = ldb_dn_get_rdn_val(claim_attribute_source_dn);
872 if (claim_attribute_source_rdn == NULL) {
873 /* No RDN, skip it. */
877 claim_attribute_source_class = dsdb_attribute_by_cn_ldb_val(schema,
878 claim_attribute_source_rdn);
879 claim_attribute_source_rdn = NULL;
880 TALLOC_FREE(claim_attribute_source_dn);
881 if (claim_attribute_source_class == NULL) {
885 source_syntax = data_blob_string_const(claim_attribute_source_class->attributeSyntax_oid);
886 if (source_syntax.data == NULL) {
890 if (!is_valid_claim_attribute_syntax(source_syntax, claim_value_type)) {
894 attribute = claim_attribute_source_class->lDAPDisplayName;
895 if (attribute == NULL) {
899 ret = add_attr_unique(tmp_ctx,
901 &ad_claim_attrs_count,
904 talloc_free(tmp_ctx);
908 name = ldb_msg_find_ldb_val(res->msgs[i], "name");
910 name = &data_blob_null;
913 ad_claims[ad_claims_count++] = (struct ad_claim_info) {
915 .syntax = source_syntax,
916 .attribute = attribute,
917 .claim_type = claim_value_type,
922 if (ad_claims_count) {
923 struct ldb_result *principal_res = NULL;
924 const struct ldb_message *principal_msg = NULL;
926 /* Shrink the arrays to remove any unused space. */
927 ad_claim_attrs = talloc_realloc(tmp_ctx,
930 ad_claim_attrs_count + 1);
931 if (ad_claim_attrs == NULL) {
932 talloc_free(tmp_ctx);
935 ad_claim_attrs[ad_claim_attrs_count] = NULL;
937 ad_claims = talloc_realloc(tmp_ctx,
939 struct ad_claim_info,
941 if (ad_claims == NULL) {
942 talloc_free(tmp_ctx);
946 ret = ldb_search(ldb, tmp_ctx, &principal_res,
949 ad_claim_attrs, NULL);
950 if (ret != LDB_SUCCESS) {
951 DBG_ERR("Failed to find principal %s to construct claims\n",
952 ldb_dn_get_linearized(principal_dn));
953 talloc_free(tmp_ctx);
957 principal_msg = principal_res->msgs[0];
960 * Ensure that only the attrs we asked for end up in the results
961 * (it's fine if some are missing)
963 SMB_ASSERT(principal_msg->num_elements <= ad_claim_attrs_count);
965 for (i = 0; i < ad_claims_count; ++i) {
966 const struct ldb_message_element *principal_attribute = NULL;
967 struct CLAIM_ENTRY *claim_entry = NULL;
968 uint32_t new_claims_array_count = claims_set.claims_array_count;
970 /* Get the value of the claim attribute for the principal. */
971 principal_attribute = ldb_msg_find_element(principal_res->msgs[0],
972 ad_claims[i].attribute);
973 if (principal_attribute == NULL) {
977 /* Add the claim to the array. */
979 if (ad_sourced_constructed == NULL) {
980 claims_set.claims_arrays = talloc_realloc(tmp_ctx,
981 claims_set.claims_arrays,
983 new_claims_array_count + 1);
984 if (claims_set.claims_arrays == NULL) {
985 talloc_free(tmp_ctx);
989 ad_sourced_constructed = &claims_set.claims_arrays[new_claims_array_count++];
990 *ad_sourced_constructed = (struct CLAIMS_ARRAY) {
991 .claims_source_type = CLAIMS_SOURCE_TYPE_AD,
995 ad_sourced_constructed->claim_entries = talloc_realloc(
997 ad_sourced_constructed->claim_entries,
999 ad_sourced_constructed->claims_count + 1);
1000 if (ad_sourced_constructed->claim_entries == NULL) {
1001 talloc_free(tmp_ctx);
1002 return ldb_oom(ldb);
1005 claim_entry = &ad_sourced_constructed->claim_entries[
1006 ad_sourced_constructed->claims_count];
1008 ret = fill_claim_entry(ad_sourced_constructed->claim_entries,
1011 principal_attribute,
1013 ad_claims[i].syntax,
1014 ad_claims[i].claim_type,
1016 if (ret != LDB_SUCCESS) {
1017 talloc_free(tmp_ctx);
1021 if (claim_get_value_count(claim_entry) > 0) {
1023 * If the claim contains values, add it to the
1026 ++ad_sourced_constructed->claims_count;
1027 claims_set.claims_array_count = new_claims_array_count;
1032 if (claims_set.claims_array_count == 0) {
1033 /* If we have no claims, we're done. */
1034 talloc_free(tmp_ctx);
1038 /* Encode the claims ready to go into a PAC buffer. */
1039 ret = encode_claims_set(ldb, mem_ctx, &claims_set, claims_blob);
1041 talloc_free(tmp_ctx);
1045 int get_claims_for_principal(struct ldb_context *ldb,
1046 TALLOC_CTX *mem_ctx,
1047 struct ldb_dn *principal_dn,
1048 DATA_BLOB *claims_blob)
1050 struct ldb_result *principal_res = NULL;
1051 static const char * const principal_attrs[] = {
1056 struct ldb_message_element *principal_class_el = NULL;
1057 struct dsdb_schema *schema = NULL;
1058 const struct dsdb_class *principal_class = NULL;
1062 *claims_blob = data_blob_null;
1064 ret = ldb_search(ldb, mem_ctx, &principal_res,
1067 principal_attrs, NULL);
1068 if (ret != LDB_SUCCESS) {
1072 principal_class_el = ldb_msg_find_element(principal_res->msgs[0],
1074 if (principal_class_el == NULL) {
1075 return ldb_operr(ldb);
1078 schema = dsdb_get_schema(ldb, mem_ctx);
1079 if (schema == NULL) {
1080 return ldb_operr(ldb);
1083 principal_class = dsdb_get_last_structural_class(schema, principal_class_el);
1084 if (principal_class == NULL) {
1085 return ldb_operr(ldb);
1088 return get_all_claims(ldb,
1091 principal_class->governsID_id,