LCOV - code coverage report
Current view: top level - source4/kdc - ad_claims.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 400 545 73.4 %
Date: 2024-02-29 22:57:05 Functions: 19 20 95.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba Active Directory claims utility functions
       4             : 
       5             :    Copyright (C) Catalyst.Net Ltd 2023
       6             : 
       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.
      11             : 
      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.
      16             : 
      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/>.
      19             : */
      20             : 
      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 "source4/kdc/authn_policy_util.h"
      26             : #include "ldb_module.h"
      27             : #include "dsdb/samdb/samdb.h"
      28             : #include "dsdb/samdb/ldb_modules/util.h"
      29             : #include "librpc/gen_ndr/claims.h"
      30             : #include "librpc/gen_ndr/ndr_claims.h"
      31             : #include "librpc/gen_ndr/ndr_krb5pac.h"
      32             : #include "lib/util/binsearch.h"
      33             : #include "auth/session.h"
      34             : 
      35             : #undef strcasecmp
      36             : 
      37       30561 : bool ad_claims_are_issued(struct ldb_context *samdb)
      38             : {
      39             :         /*
      40             :          * Claims aren’t issued by Samba unless the DC is at
      41             :          * FL2012.  This is to match Windows, which will offer
      42             :          * this feature as soon as the DC is upgraded.
      43             :          */
      44       30561 :         const int functional_level = dsdb_dc_functional_level(samdb);
      45       30561 :         return functional_level >= DS_DOMAIN_FUNCTION_2012;
      46             : }
      47             : 
      48        5802 : static int acl_attr_cmp_fn(const char *a, const char * const *b)
      49             : {
      50        5802 :         return ldb_attr_cmp(a, *b);
      51             : }
      52             : 
      53             : /*
      54             :  * Add a single attribute to a list of attributes if it is not already
      55             :  * present. The list is maintained in case-insensitive sorted order.
      56             :  */
      57        3654 : static int add_attr_unique(TALLOC_CTX *mem_ctx,
      58             :                            const char **attrs,
      59             :                            unsigned *ad_claim_attrs_count,
      60             :                            const char *attr)
      61             : {
      62        3654 :         const unsigned count = *ad_claim_attrs_count;
      63        3654 :         const char * const *exact = NULL;
      64        3654 :         const char * const *next = NULL;
      65             : 
      66        9456 :         BINARY_ARRAY_SEARCH_GTE(attrs,
      67             :                                 count,
      68             :                                 attr,
      69             :                                 acl_attr_cmp_fn,
      70             :                                 exact,
      71             :                                 next);
      72        3654 :         if (exact != NULL) {
      73             :                 /* The attribute is already present; there's nothing to do. */
      74        2279 :                 return LDB_SUCCESS;
      75             :         }
      76             : 
      77             :         /* Make sure we don't overflow the array. */
      78        1375 :         SMB_ASSERT(count < talloc_array_length(attrs));
      79        1375 :         *ad_claim_attrs_count = count + 1;
      80             : 
      81        1375 :         if (next == NULL) {
      82             :                 /* Just add the new element on the end. */
      83        1077 :                 attrs[count] = attr;
      84             :         } else {
      85             :                 /* Shift all following elements over to make room. */
      86         298 :                 size_t next_idx = next - attrs;
      87         298 :                 size_t bytes_to_move = (count - next_idx) * sizeof (attrs[0]);
      88         298 :                 memmove(&attrs[next_idx + 1],
      89         298 :                         &attrs[next_idx],
      90             :                         bytes_to_move);
      91             : 
      92         298 :                 attrs[next_idx] = attr;
      93             :         }
      94             : 
      95        1375 :         return LDB_SUCCESS;
      96             : }
      97             : 
      98             : /*
      99             :  * Return true if a data_blob, interpreted as a string, is equal to another
     100             :  * string. This is more efficient than strcmp(), particularly when comparing
     101             :  * against a string constant. This assumes the data_blob's length does not
     102             :  * include the zero-terminator.
     103             :  */
     104       10587 : static inline bool data_blob_equals_str(const DATA_BLOB val, const char *str)
     105             : {
     106       10587 :         size_t len = strlen(str);
     107       10587 :         if (val.length != len) {
     108        4329 :                 return false;
     109             :         }
     110             : 
     111        6258 :         return memcmp(val.data, str, len) == 0;
     112             : }
     113             : 
     114         227 : static int fill_claim_int64(TALLOC_CTX *mem_ctx,
     115             :                             struct ldb_context *ldb,
     116             :                             const struct ldb_message_element *principal_attribute,
     117             :                             const struct ldb_val name,
     118             :                             struct CLAIM_INT64 *claim)
     119             : {
     120           0 :         uint32_t i;
     121             : 
     122         227 :         claim->value_count = 0;
     123         227 :         claim->values = talloc_array(mem_ctx,
     124             :                                      int64_t,
     125             :                                      principal_attribute->num_values);
     126         227 :         if (claim->values == NULL) {
     127           0 :                 return ldb_oom(ldb);
     128             :         }
     129             : 
     130         550 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     131         323 :                 const struct ldb_val *value = &principal_attribute->values[i];
     132         323 :                 int ret = ldb_val_as_int64(value, &claim->values[i]);
     133         323 :                 if (ret) {
     134           0 :                         char buf[1024];
     135           0 :                         const char *reason = NULL;
     136           0 :                         int err = strerror_r(ret, buf, sizeof(buf));
     137           0 :                         if (err == 0) {
     138           0 :                                 reason = buf;
     139             :                         } else {
     140           0 :                                 reason = "Unknown error";
     141             :                         }
     142           0 :                         DBG_WARNING("Failed to interpret value %s as INT64 "
     143             :                                     "while creating claim %s for attribute %s (%s); "
     144             :                                     "skipping value\n",
     145             :                                     (value->data != NULL) ? (const char *)value->data : "<unknown>",
     146             :                                     name.data, principal_attribute->name,
     147             :                                     reason);
     148           0 :                         continue;
     149             :                 }
     150             : 
     151         323 :                 ++claim->value_count;
     152             :         }
     153             : 
     154             :         /* Shrink the array to fit. */
     155         227 :         claim->values = talloc_realloc(mem_ctx,
     156             :                                        claim->values,
     157             :                                        int64_t,
     158             :                                        claim->value_count);
     159         227 :         if (claim->value_count && claim->values == NULL) {
     160           0 :                 return ldb_oom(ldb);
     161             :         }
     162             : 
     163         227 :         return LDB_SUCCESS;
     164             : }
     165             : 
     166           0 : static int fill_claim_uint64(TALLOC_CTX *mem_ctx,
     167             :                              struct ldb_context *ldb,
     168             :                              const struct ldb_message_element *principal_attribute,
     169             :                              const struct ldb_val name,
     170             :                              struct CLAIM_UINT64 *claim)
     171             : {
     172           0 :         uint32_t i;
     173             : 
     174           0 :         claim->value_count = 0;
     175           0 :         claim->values = talloc_array(mem_ctx,
     176             :                                      uint64_t,
     177             :                                      principal_attribute->num_values);
     178           0 :         if (claim->values == NULL) {
     179           0 :                 return ldb_oom(ldb);
     180             :         }
     181             : 
     182           0 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     183           0 :                 const struct ldb_val *value = &principal_attribute->values[i];
     184           0 :                 int ret = ldb_val_as_uint64(value, &claim->values[i]);
     185           0 :                 if (ret) {
     186           0 :                         char buf[1024];
     187           0 :                         const char *reason = NULL;
     188           0 :                         int err = strerror_r(ret, buf, sizeof(buf));
     189           0 :                         if (err == 0) {
     190           0 :                                 reason = buf;
     191             :                         } else {
     192           0 :                                 reason = "Unknown error";
     193             :                         }
     194           0 :                         DBG_WARNING("Failed to interpret value %s as UINT64 "
     195             :                                     "while creating claim %s for attribute %s (%s); "
     196             :                                     "skipping value\n",
     197             :                                     (value->data != NULL) ? (const char *)value->data : "<unknown>",
     198             :                                     name.data, principal_attribute->name,
     199             :                                     reason);
     200           0 :                         continue;
     201             :                 }
     202             : 
     203           0 :                 ++claim->value_count;
     204             :         }
     205             : 
     206             :         /* Shrink the array to fit. */
     207           0 :         claim->values = talloc_realloc(mem_ctx,
     208             :                                        claim->values,
     209             :                                        uint64_t,
     210             :                                        claim->value_count);
     211           0 :         if (claim->value_count && claim->values == NULL) {
     212           0 :                 return ldb_oom(ldb);
     213             :         }
     214             : 
     215           0 :         return LDB_SUCCESS;
     216             : }
     217             : 
     218          96 : static int fill_claim_uint64_oid_syntax(TALLOC_CTX *mem_ctx,
     219             :                                         struct ldb_context *ldb,
     220             :                                         const struct dsdb_schema *schema,
     221             :                                         const struct ldb_message_element *principal_attribute,
     222             :                                         const struct ldb_val name,
     223             :                                         struct CLAIM_UINT64 *claim)
     224             : {
     225           0 :         uint32_t i;
     226             : 
     227          96 :         claim->value_count = 0;
     228          96 :         claim->values = talloc_array(mem_ctx,
     229             :                                      uint64_t,
     230             :                                      principal_attribute->num_values);
     231          96 :         if (claim->values == NULL) {
     232           0 :                 return ldb_oom(ldb);
     233             :         }
     234             : 
     235         517 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     236         421 :                 const struct dsdb_class *class_val = NULL;
     237             : 
     238             :                 /*
     239             :                  * OID values for objectClass
     240             :                  * are presented in reverse
     241             :                  * order.
     242             :                  */
     243         421 :                 const struct ldb_val *display_name = &principal_attribute->values[
     244         421 :                         principal_attribute->num_values - 1 - i];
     245             : 
     246         421 :                 class_val = dsdb_class_by_lDAPDisplayName_ldb_val(schema, display_name);
     247         421 :                 if (class_val == NULL) {
     248           0 :                         DBG_WARNING("Failed to look up OID for value %s "
     249             :                                     "while creating claim %s for attribute %s; "
     250             :                                     "skipping value\n",
     251             :                                     (display_name->data != NULL) ? (const char *)display_name->data : "<unknown>",
     252             :                                     name.data, principal_attribute->name);
     253           0 :                         continue;
     254             :                 }
     255             : 
     256         421 :                 claim->values[i] = class_val->governsID_id;
     257         421 :                 ++claim->value_count;
     258             :         }
     259             : 
     260             :         /* Shrink the array to fit. */
     261          96 :         claim->values = talloc_realloc(mem_ctx,
     262             :                                        claim->values,
     263             :                                        uint64_t,
     264             :                                        claim->value_count);
     265          96 :         if (claim->value_count && claim->values == NULL) {
     266           0 :                 return ldb_oom(ldb);
     267             :         }
     268             : 
     269          96 :         return LDB_SUCCESS;
     270             : }
     271             : 
     272          29 : static int fill_claim_boolean(TALLOC_CTX *mem_ctx,
     273             :                               struct ldb_context *ldb,
     274             :                               const struct ldb_message_element *principal_attribute,
     275             :                               const struct ldb_val name,
     276             :                               struct CLAIM_UINT64 *claim)
     277             : {
     278           0 :         uint32_t i;
     279             : 
     280          29 :         claim->value_count = 0;
     281          29 :         claim->values = talloc_array(mem_ctx,
     282             :                                      uint64_t,
     283             :                                      principal_attribute->num_values);
     284          29 :         if (claim->values == NULL) {
     285           0 :                 return ldb_oom(ldb);
     286             :         }
     287             : 
     288          58 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     289          29 :                 const struct ldb_val *value = &principal_attribute->values[i];
     290          29 :                 bool val = false;
     291          29 :                 int ret = ldb_val_as_bool(value, &val);
     292          29 :                 if (ret) {
     293           0 :                         char buf[1024];
     294           0 :                         const char *reason = NULL;
     295           0 :                         int err = strerror_r(ret, buf, sizeof(buf));
     296           0 :                         if (err == 0) {
     297           0 :                                 reason = buf;
     298             :                         } else {
     299           0 :                                 reason = "Unknown error";
     300             :                         }
     301           0 :                         DBG_WARNING("Failed to interpret value %s as BOOL "
     302             :                                     "while creating claim %s for attribute %s (%s); "
     303             :                                     "skipping value\n",
     304             :                                     (value->data != NULL) ? (const char *)value->data : "<unknown>",
     305             :                                     name.data, principal_attribute->name,
     306             :                                     reason);
     307           0 :                         continue;
     308             :                 }
     309             : 
     310          29 :                 claim->values[i] = val;
     311          29 :                 ++claim->value_count;
     312             :         }
     313             : 
     314             :         /* Shrink the array to fit. */
     315          29 :         claim->values = talloc_realloc(mem_ctx,
     316             :                                        claim->values,
     317             :                                        uint64_t,
     318             :                                        claim->value_count);
     319          29 :         if (claim->value_count && claim->values == NULL) {
     320           0 :                 return ldb_oom(ldb);
     321             :         }
     322             : 
     323          29 :         return LDB_SUCCESS;
     324             : }
     325             : 
     326         683 : static int fill_claim_string(TALLOC_CTX *mem_ctx,
     327             :                              struct ldb_context *ldb,
     328             :                              const struct ldb_message_element *principal_attribute,
     329             :                              struct CLAIM_STRING *claim)
     330             : {
     331           0 :         uint32_t i;
     332             : 
     333         683 :         claim->value_count = 0;
     334         683 :         claim->values = talloc_array(mem_ctx,
     335             :                                      const char *,
     336             :                                      principal_attribute->num_values);
     337         683 :         if (claim->values == NULL) {
     338           0 :                 return ldb_oom(ldb);
     339             :         }
     340             : 
     341        1513 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     342         830 :                 const char *val = NULL;
     343         830 :                 const struct ldb_val *v = &principal_attribute->values[i];
     344             : 
     345         830 :                 if (v == NULL || v->data == NULL) {
     346           0 :                         continue;
     347             :                 }
     348             : 
     349         830 :                 val = talloc_strndup(claim->values,
     350         830 :                                      (const char *)v->data,
     351         830 :                                      v->length);
     352         830 :                 if (val == NULL) {
     353           0 :                         return ldb_oom(ldb);
     354             :                 }
     355             : 
     356         830 :                 claim->values[i] = val;
     357         830 :                 ++claim->value_count;
     358             :         }
     359             : 
     360             :         /* Shrink the array to fit. */
     361         683 :         claim->values = talloc_realloc(mem_ctx,
     362             :                                        claim->values,
     363             :                                        const char *,
     364             :                                        claim->value_count);
     365         683 :         if (claim->value_count && claim->values == NULL) {
     366           0 :                 return ldb_oom(ldb);
     367             :         }
     368             : 
     369         683 :         return LDB_SUCCESS;
     370             : }
     371             : 
     372           7 : static int fill_claim_string_sec_desc_syntax(TALLOC_CTX *mem_ctx,
     373             :                                              struct ldb_context *ldb,
     374             :                                              const struct ldb_message_element *principal_attribute,
     375             :                                              struct CLAIM_STRING *claim)
     376             : {
     377           7 :         TALLOC_CTX *tmp_ctx = NULL;
     378           7 :         const struct dom_sid *domain_sid = NULL;
     379           0 :         uint32_t i;
     380             : 
     381           7 :         claim->value_count = 0;
     382           7 :         claim->values = talloc_array(mem_ctx,
     383             :                                      const char *,
     384             :                                      principal_attribute->num_values);
     385           7 :         if (claim->values == NULL) {
     386           0 :                 return ldb_oom(ldb);
     387             :         }
     388             : 
     389           7 :         domain_sid = samdb_domain_sid(ldb);
     390           7 :         if (domain_sid == NULL) {
     391           0 :                 return ldb_oom(ldb);
     392             :         }
     393             : 
     394           7 :         tmp_ctx = talloc_new(mem_ctx);
     395           7 :         if (tmp_ctx == NULL) {
     396           0 :                 return ldb_oom(ldb);
     397             :         }
     398             : 
     399          14 :         for (i = 0; i < principal_attribute->num_values; ++i) {
     400           7 :                 const struct ldb_val *v = &principal_attribute->values[i];
     401             : 
     402           0 :                 enum ndr_err_code ndr_err;
     403           7 :                 struct security_descriptor desc = {};
     404           7 :                 const char *sddl = NULL;
     405             : 
     406           7 :                 if (v == NULL || v->data == NULL) {
     407           0 :                         continue;
     408             :                 }
     409             : 
     410           7 :                 ndr_err = ndr_pull_struct_blob(v,
     411             :                                                tmp_ctx,
     412             :                                                &desc,
     413             :                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     414           7 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     415           0 :                         NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     416           0 :                         DBG_ERR("security_descriptor pull failed: %s\n",
     417             :                                 nt_errstr(nt_status));
     418           0 :                         talloc_free(tmp_ctx);
     419           0 :                         return ldb_operr(ldb);
     420             :                 }
     421             : 
     422           7 :                 sddl = sddl_encode(mem_ctx,
     423             :                                    &desc,
     424             :                                    domain_sid);
     425           7 :                 if (sddl == NULL) {
     426           0 :                         talloc_free(tmp_ctx);
     427           0 :                         return ldb_oom(ldb);
     428             :                 }
     429             : 
     430           7 :                 claim->values[i] = sddl;
     431           7 :                 ++claim->value_count;
     432             :         }
     433             : 
     434           7 :         talloc_free(tmp_ctx);
     435             : 
     436             :         /* Shrink the array to fit. */
     437           7 :         claim->values = talloc_realloc(mem_ctx,
     438             :                                        claim->values,
     439             :                                        const char *,
     440             :                                        claim->value_count);
     441           7 :         if (claim->value_count && claim->values == NULL) {
     442           0 :                 return ldb_oom(ldb);
     443             :         }
     444             : 
     445           7 :         return LDB_SUCCESS;
     446             : }
     447             : 
     448        1042 : static int fill_claim_entry(TALLOC_CTX *mem_ctx,
     449             :                             struct ldb_context *ldb,
     450             :                             const struct dsdb_schema *schema,
     451             :                             const struct ldb_message_element *principal_attribute,
     452             :                             const struct ldb_val name,
     453             :                             const DATA_BLOB syntax,
     454             :                             enum CLAIM_TYPE claim_type,
     455             :                             struct CLAIM_ENTRY *claim_entry)
     456             : {
     457             : 
     458        2084 :         claim_entry->id = talloc_strndup(mem_ctx,
     459        1042 :                                      (const char *)name.data,
     460        1042 :                                      name.length);
     461        1042 :         if (claim_entry->id == NULL) {
     462           0 :                 return ldb_oom(ldb);
     463             :         }
     464             : 
     465        1042 :         claim_entry->type = claim_type;
     466             : 
     467        1042 :         switch (claim_type) {
     468         227 :         case CLAIM_TYPE_INT64:
     469         227 :                 return fill_claim_int64(mem_ctx,
     470             :                                         ldb,
     471             :                                         principal_attribute,
     472             :                                         name,
     473             :                                         &claim_entry->values.claim_int64);
     474          96 :         case CLAIM_TYPE_UINT64:
     475          96 :                 if (syntax.data != NULL && data_blob_equals_str(syntax, "2.5.5.2")) {
     476          96 :                         return fill_claim_uint64_oid_syntax(mem_ctx,
     477             :                                                  ldb,
     478             :                                                  schema,
     479             :                                                  principal_attribute,
     480             :                                                  name,
     481             :                                                  &claim_entry->values.claim_uint64);
     482             :                 } else {
     483           0 :                         return fill_claim_uint64(mem_ctx,
     484             :                                                  ldb,
     485             :                                                  principal_attribute,
     486             :                                                  name,
     487             :                                                  &claim_entry->values.claim_uint64);
     488             :                 }
     489          29 :         case CLAIM_TYPE_BOOLEAN:
     490          29 :                 return fill_claim_boolean(mem_ctx,
     491             :                                           ldb,
     492             :                                           principal_attribute,
     493             :                                           name,
     494             :                                           &claim_entry->values.claim_boolean);
     495         690 :         case CLAIM_TYPE_STRING:
     496             :         default:
     497         690 :                 if (syntax.data != NULL && data_blob_equals_str(syntax, "2.5.5.15")) {
     498           7 :                         return fill_claim_string_sec_desc_syntax(mem_ctx,
     499             :                                                                  ldb,
     500             :                                                                  principal_attribute,
     501             :                                                                  &claim_entry->values.claim_string);
     502             :                 } else {
     503         683 :                         return fill_claim_string(mem_ctx,
     504             :                                                  ldb,
     505             :                                                  principal_attribute,
     506             :                                                  &claim_entry->values.claim_string);
     507             :                 }
     508             :         }
     509             : }
     510             : 
     511             : /*
     512             :  * Determine whether a claim applies to the most specific objectClass of the
     513             :  * principal.
     514             :  */
     515       25385 : static int claim_applies_to_class(TALLOC_CTX *mem_ctx,
     516             :                                   struct ldb_context *ldb,
     517             :                                   const struct dsdb_schema *schema,
     518             :                                   const struct ldb_message *claim_msg,
     519             :                                   const uint32_t principal_class_id,
     520             :                                   bool *applies)
     521             : {
     522       25385 :         struct ldb_message_element *applies_to_class = NULL;
     523        1170 :         unsigned i;
     524             : 
     525       25385 :         applies_to_class = ldb_msg_find_element(claim_msg,
     526             :                                                 "msDS-ClaimTypeAppliesToClass");
     527       25385 :         if (applies_to_class == NULL) {
     528         117 :                 *applies = false;
     529         117 :                 return LDB_SUCCESS;
     530             :         }
     531             : 
     532       66417 :         for (i = 0; i < applies_to_class->num_values; ++i) {
     533       63763 :                 struct ldb_dn *class_dn = NULL;
     534       63763 :                 const struct dsdb_class *class_val = NULL;
     535       63763 :                 const struct ldb_val *class_rdn = NULL;
     536             : 
     537       65261 :                 class_dn = ldb_dn_from_ldb_val(mem_ctx,
     538             :                                                ldb,
     539       63763 :                                                &applies_to_class->values[i]);
     540       63763 :                 if (class_dn == NULL) {
     541           0 :                         return ldb_oom(ldb);
     542             :                 }
     543             : 
     544       63763 :                 class_rdn = ldb_dn_get_rdn_val(class_dn);
     545       63763 :                 if (class_rdn == NULL) {
     546           0 :                         TALLOC_FREE(class_dn);
     547           0 :                         continue;
     548             :                 }
     549             : 
     550       63763 :                 class_val = dsdb_class_by_cn_ldb_val(schema, class_rdn);
     551       63763 :                 TALLOC_FREE(class_dn);
     552       63763 :                 if (class_val == NULL) {
     553           0 :                         continue;
     554             :                 }
     555             : 
     556       63763 :                 if (class_val->governsID_id == principal_class_id) {
     557       22614 :                         *applies = true;
     558       22614 :                         return LDB_SUCCESS;
     559             :                 }
     560             :         }
     561             : 
     562        2654 :         *applies = false;
     563        2654 :         return LDB_SUCCESS;
     564             : }
     565             : 
     566             : struct assigned_silo {
     567             :         const char *name;
     568             :         bool is_initialised;
     569             :         bool is_assigned;
     570             : };
     571             : 
     572       15825 : static struct assigned_silo new_assigned_silo(void)
     573             : {
     574       15825 :         return (struct assigned_silo) {
     575             :                 .name = NULL,
     576             :                 .is_initialised = false,
     577             :                 .is_assigned = false,
     578             :         };
     579             : }
     580             : 
     581       16858 : static bool silo_is_maybe_assigned(struct assigned_silo silo)
     582             : {
     583       15688 :         return !silo.is_initialised || silo.is_assigned;
     584             : }
     585             : 
     586       16819 : static int get_assigned_silo(struct ldb_context *ldb,
     587             :                              TALLOC_CTX *mem_ctx,
     588             :                              const struct ldb_message *principal,
     589             :                              struct assigned_silo *assigned_silo)
     590             : {
     591       16819 :         TALLOC_CTX *tmp_ctx = NULL;
     592        1170 :         int ret;
     593             : 
     594       16819 :         const struct ldb_message *silo_msg = NULL;
     595        1170 :         static const char * const silo_attrs[] = {
     596             :                 "msDS-AuthNPolicySiloEnforced",
     597             :                 "msDS-AuthNPolicySiloMembers",
     598             :                 "name",
     599             :                 NULL
     600             :         };
     601             : 
     602       16819 :         bool is_silo_enforced = false;
     603       16819 :         const char *silo_name = NULL;
     604             : 
     605       16819 :         if (assigned_silo->is_initialised) {
     606           0 :                 return LDB_SUCCESS;
     607             :         }
     608             : 
     609       16819 :         tmp_ctx = talloc_new(mem_ctx);
     610       16819 :         if (tmp_ctx == NULL) {
     611           0 :                 return ldb_oom(ldb);
     612             :         }
     613             : 
     614       16819 :         if (!authn_policy_silos_and_policies_in_effect(ldb)) {
     615             :                 /* No assigned silo. */
     616           0 :                 assigned_silo->is_assigned = false;
     617           0 :                 assigned_silo->is_initialised = true;
     618             : 
     619           0 :                 talloc_free(tmp_ctx);
     620           0 :                 return LDB_SUCCESS;
     621             :         }
     622             : 
     623             :         /* Check whether the user is assigned to an enforced silo. */
     624       16819 :         ret = authn_policy_get_assigned_silo(ldb,
     625             :                                              tmp_ctx,
     626             :                                              principal,
     627             :                                              silo_attrs,
     628             :                                              &silo_msg,
     629             :                                              &is_silo_enforced);
     630       16819 :         if (ret) {
     631           0 :                 talloc_free(tmp_ctx);
     632           0 :                 return ret;
     633             :         }
     634             : 
     635       16819 :         if (silo_msg == NULL || !is_silo_enforced) {
     636             :                 /* No assigned silo. */
     637       16797 :                 assigned_silo->is_assigned = false;
     638       16797 :                 assigned_silo->is_initialised = true;
     639             : 
     640       16797 :                 talloc_free(tmp_ctx);
     641       16797 :                 return LDB_SUCCESS;
     642             :         }
     643             : 
     644             :         /* The user does belong to a silo, so return the name of the silo. */
     645          22 :         silo_name = ldb_msg_find_attr_as_string(silo_msg,
     646             :                                                 "name",
     647             :                                                 NULL);
     648          22 :         assigned_silo->name = talloc_steal(mem_ctx, silo_name);
     649          22 :         assigned_silo->is_assigned = true;
     650          22 :         assigned_silo->is_initialised = true;
     651             : 
     652          22 :         talloc_free(tmp_ctx);
     653          22 :         return LDB_SUCCESS;
     654             : }
     655             : 
     656             : static inline struct ldb_val talloc_steal_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_val val)
     657             : {
     658             :         val.data = talloc_steal(mem_ctx, val.data);
     659             :         return val;
     660             : }
     661             : 
     662        1042 : static uint32_t claim_get_value_count(const struct CLAIM_ENTRY *claim)
     663             : {
     664        1042 :         switch (claim->type) {
     665         227 :         case CLAIM_TYPE_INT64:
     666         227 :                 return claim->values.claim_int64.value_count;
     667          96 :         case CLAIM_TYPE_UINT64:
     668          96 :                 return claim->values.claim_uint64.value_count;
     669         690 :         case CLAIM_TYPE_STRING:
     670         690 :                 return claim->values.claim_string.value_count;
     671          29 :         case CLAIM_TYPE_BOOLEAN:
     672          29 :                 return claim->values.claim_boolean.value_count;
     673             :         }
     674             : 
     675           0 :         smb_panic(__location__ ": unknown claim type");
     676             :         return 0;
     677             : }
     678             : 
     679        5083 : static bool is_schema_dn(struct ldb_dn *dn,
     680             :                          struct ldb_dn *schema_dn)
     681             : {
     682        5083 :         if (ldb_dn_get_comp_num(dn) != (ldb_dn_get_comp_num(schema_dn) + 1)) {
     683           0 :                 return false;
     684             :         }
     685             : 
     686        5083 :         return ldb_dn_compare_base(schema_dn, dn) == 0;
     687             : }
     688             : 
     689        5083 : static bool is_valid_claim_attribute_syntax(const DATA_BLOB source_syntax,
     690             :                                             uint64_t claim_value_type)
     691             : {
     692        5083 :         switch (claim_value_type) {
     693        3518 :         case CLAIM_TYPE_STRING:
     694        3518 :                 if (data_blob_equals_str(source_syntax, "2.5.5.1")) {
     695         155 :                         return true;
     696             :                 }
     697        3363 :                 if (data_blob_equals_str(source_syntax, "2.5.5.12")) {
     698        2370 :                         return true;
     699             :                 }
     700         993 :                 if (data_blob_equals_str(source_syntax, "2.5.5.15")) {
     701          33 :                         return true;
     702             :                 }
     703         960 :                 break;
     704         244 :         case CLAIM_TYPE_UINT64:
     705         244 :                 if (data_blob_equals_str(source_syntax, "2.5.5.2")) {
     706          96 :                         return true;
     707             :                 }
     708         148 :                 break;
     709         761 :         case CLAIM_TYPE_INT64:
     710         761 :                 if (data_blob_equals_str(source_syntax, "2.5.5.9")) {
     711         399 :                         return true;
     712             :                 }
     713         362 :                 if (data_blob_equals_str(source_syntax, "2.5.5.16")) {
     714         176 :                         return true;
     715             :                 }
     716         186 :                 break;
     717         560 :         case CLAIM_TYPE_BOOLEAN:
     718             :                 /* Note: MS-ADTS has a typo (2.2.5.8 instead of 2.5.5.8) */
     719         560 :                 if (data_blob_equals_str(source_syntax, "2.5.5.8")) {
     720         425 :                         return true;
     721             :                 }
     722         135 :                 break;
     723           0 :         default:
     724           0 :                 break;
     725             :         }
     726             : 
     727        1429 :         return false;
     728             : }
     729             : 
     730       16995 : static int get_all_claims(struct ldb_context *ldb,
     731             :                           TALLOC_CTX *mem_ctx,
     732             :                           const struct ldb_message *principal,
     733             :                           uint32_t principal_class_id,
     734             :                           struct CLAIMS_SET **claims_set_out)
     735             : {
     736       16995 :         TALLOC_CTX *tmp_ctx = NULL;
     737             : 
     738       16995 :         const struct dsdb_schema *schema = NULL;
     739             : 
     740       16995 :         struct ldb_dn *claim_config_container = NULL;
     741       16995 :         struct ldb_dn *claim_types_child = NULL;
     742       16995 :         struct ldb_dn *config_dn = ldb_get_config_basedn(ldb);
     743       16995 :         struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
     744        1170 :         bool ok;
     745        1170 :         int ret;
     746       16995 :         struct ldb_result *res = NULL;
     747        1170 :         static const char * const attrs[] = {
     748             :                 "Enabled",
     749             :                 "msDS-ClaimAttributeSource",
     750             :                 "msDS-ClaimSource",
     751             :                 "msDS-ClaimSourceType",
     752             :                 "msDS-ClaimTypeAppliesToClass",
     753             :                 "msDS-ClaimValueType",
     754             :                 "name",
     755             :                 NULL
     756             :         };
     757             : 
     758       16995 :         const char **ad_claim_attrs = NULL;
     759        1170 :         unsigned int ad_claim_attrs_count;
     760        1170 :         struct ad_claim_info {
     761             :                 struct ldb_val name;
     762             :                 DATA_BLOB syntax;
     763             :                 const char *attribute;
     764             :                 enum CLAIM_TYPE claim_type;
     765       16995 :         } *ad_claims = NULL;
     766        1170 :         unsigned ad_claims_count;
     767             : 
     768        1170 :         unsigned i;
     769             : 
     770             :         /* The structure which we'll use to build up the claims. */
     771       16995 :         struct CLAIMS_SET *claims_set = NULL;
     772             : 
     773       16995 :         struct CLAIMS_ARRAY *ad_sourced_constructed = NULL;
     774             : 
     775       16995 :         struct assigned_silo assigned_silo = new_assigned_silo();
     776             : 
     777       16995 :         *claims_set_out = NULL;
     778             : 
     779       16995 :         tmp_ctx = talloc_new(mem_ctx);
     780       16995 :         if (tmp_ctx == NULL) {
     781           0 :                 return ldb_oom(ldb);
     782             :         }
     783             : 
     784       16995 :         claims_set = talloc_zero(tmp_ctx, struct CLAIMS_SET);
     785       16995 :         if (claims_set == NULL) {
     786           0 :                 talloc_free(tmp_ctx);
     787           0 :                 return ldb_oom(ldb);
     788             :         }
     789             : 
     790       16995 :         schema = dsdb_get_schema(ldb, tmp_ctx);
     791       16995 :         if (schema == NULL) {
     792           0 :                 talloc_free(tmp_ctx);
     793           0 :                 return ldb_operr(ldb);
     794             :         }
     795             : 
     796             :         /* Get the DN of the claims container. */
     797       16995 :         claim_config_container = ldb_dn_copy(tmp_ctx, config_dn);
     798       16995 :         if (claim_config_container == NULL) {
     799           0 :                 talloc_free(tmp_ctx);
     800           0 :                 return ldb_oom(ldb);
     801             :         }
     802             : 
     803       16995 :         claim_types_child = ldb_dn_new(tmp_ctx, ldb,
     804             :                                        "CN=Claim Types,CN=Claims Configuration,CN=Services");
     805       16995 :         if (claim_types_child == NULL) {
     806           0 :                 talloc_free(tmp_ctx);
     807           0 :                 return ldb_oom(ldb);
     808             :         }
     809             : 
     810       16995 :         ok = ldb_dn_add_child(claim_config_container, claim_types_child);
     811       16995 :         TALLOC_FREE(claim_types_child);
     812       16995 :         if (!ok) {
     813           0 :                 talloc_free(tmp_ctx);
     814           0 :                 return ldb_operr(ldb);
     815             :         }
     816             : 
     817             :         /* Search for the claims container's children. */
     818       16995 :         ret = ldb_search(ldb, tmp_ctx, &res,
     819             :                          claim_config_container,
     820             :                          LDB_SCOPE_ONELEVEL,
     821             :                          attrs, NULL);
     822       16995 :         if (ret) {
     823         176 :                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     824         176 :                         ret = LDB_SUCCESS;
     825             :                 }
     826             : 
     827         176 :                 talloc_free(tmp_ctx);
     828         176 :                 return ret;
     829             :         }
     830             : 
     831             :         /*
     832             :          * Allocate enough space for all AD claim attributes, followed by space
     833             :          * for a NULL marker (so it can be passed as the attributes filter to an
     834             :          * LDB search).
     835             :          */
     836       16819 :         ad_claim_attrs = talloc_array(tmp_ctx,
     837             :                                       const char *,
     838             :                                       res->count + 1);
     839       16819 :         if (ad_claim_attrs == NULL) {
     840           0 :                 talloc_free(tmp_ctx);
     841           0 :                 return ldb_oom(ldb);
     842             :         }
     843       16819 :         ad_claims = talloc_array(tmp_ctx,
     844             :                                  struct ad_claim_info,
     845             :                                  res->count);
     846       16819 :         if (ad_claims == NULL) {
     847           0 :                 talloc_free(tmp_ctx);
     848           0 :                 return ldb_oom(ldb);
     849             :         }
     850       16819 :         ad_claims_count = ad_claim_attrs_count = 0;
     851             : 
     852             :         /* Loop through each child of the claims container. */
     853       42204 :         for (i = 0; i < res->count; ++i) {
     854       25385 :                 bool claim_applies = false;
     855             : 
     856        1170 :                 int enabled;
     857        1170 :                 uint64_t claim_value_type;
     858             : 
     859       25385 :                 const char *claim_source_type = NULL;
     860       25385 :                 const struct ldb_val *claim_attribute_source = NULL;
     861       25385 :                 const char *claim_source = NULL;
     862             : 
     863             :                 /*
     864             :                  * Does this claim apply to the most specific objectClass of the
     865             :                  * principal?
     866             :                  */
     867       26555 :                 ret = claim_applies_to_class(tmp_ctx,
     868             :                                              ldb,
     869             :                                              schema,
     870       25385 :                                              res->msgs[i],
     871             :                                              principal_class_id,
     872             :                                              &claim_applies);
     873       25385 :                 if (ret) {
     874           0 :                         talloc_free(tmp_ctx);
     875           0 :                         return ret;
     876             :                 }
     877       25385 :                 if (!claim_applies) {
     878             :                         /* If the claim doesn't apply, skip it. */
     879       21670 :                         continue;
     880             :                 }
     881             : 
     882       22614 :                 enabled = ldb_msg_find_attr_as_bool(res->msgs[i], "Enabled", 0);
     883       22614 :                 if (!enabled) {
     884             :                         /* If the claim isn't enabled, skip it. */
     885         360 :                         continue;
     886             :                 }
     887             : 
     888       22254 :                 claim_value_type = ldb_msg_find_attr_as_uint64(res->msgs[i],
     889             :                                                                "msDS-ClaimValueType",
     890             :                                                                0);
     891       22254 :                 if (!claim_value_type) {
     892         210 :                         continue;
     893             :                 }
     894             : 
     895       22044 :                 claim_source_type = ldb_msg_find_attr_as_string(res->msgs[i],
     896             :                                                                 "msDS-ClaimSourceType",
     897             :                                                                 "");
     898             : 
     899             :                 /* Get the attribute used by the claim. */
     900       22044 :                 claim_attribute_source = ldb_msg_find_ldb_val(res->msgs[i],
     901             :                                                               "msDS-ClaimAttributeSource");
     902             : 
     903       22044 :                 claim_source = ldb_msg_find_attr_as_string(res->msgs[i],
     904             :                                                            "msDS-ClaimSource",
     905             :                                                            NULL);
     906             : 
     907       22044 :                 if (strcasecmp(claim_source_type, "AD") == 0) {
     908        5186 :                         struct ldb_dn *claim_attribute_source_dn = NULL;
     909        5186 :                         const struct ldb_val *claim_attribute_source_rdn = NULL;
     910        5186 :                         const struct dsdb_attribute *claim_attribute_source_class = NULL;
     911             : 
     912           0 :                         DATA_BLOB source_syntax;
     913        5186 :                         const char *attribute = NULL;
     914        5186 :                         const struct ldb_val *name = NULL;
     915             : 
     916        5186 :                         if (claim_attribute_source == NULL) {
     917        1532 :                                 continue;
     918             :                         }
     919             : 
     920        5083 :                         claim_attribute_source_dn = ldb_val_as_dn(ldb,
     921             :                                                                   tmp_ctx,
     922             :                                                                   claim_attribute_source);
     923        5083 :                         if (claim_attribute_source_dn == NULL) {
     924           0 :                                 talloc_free(tmp_ctx);
     925           0 :                                 return ldb_operr(ldb);
     926             :                         }
     927             : 
     928        5083 :                         if (!is_schema_dn(claim_attribute_source_dn, schema_dn)) {
     929             :                                 /* This DN doesn't belong to the schema. */
     930           0 :                                 continue;
     931             :                         }
     932             : 
     933        5083 :                         claim_attribute_source_rdn = ldb_dn_get_rdn_val(claim_attribute_source_dn);
     934        5083 :                         if (claim_attribute_source_rdn == NULL) {
     935             :                                 /* No RDN, skip it. */
     936           0 :                                 continue;
     937             :                         }
     938             : 
     939        5083 :                         claim_attribute_source_class = dsdb_attribute_by_cn_ldb_val(schema,
     940             :                                                                                     claim_attribute_source_rdn);
     941        5083 :                         claim_attribute_source_rdn = NULL;
     942        5083 :                         TALLOC_FREE(claim_attribute_source_dn);
     943        5083 :                         if (claim_attribute_source_class == NULL) {
     944           0 :                                 continue;
     945             :                         }
     946             : 
     947        5083 :                         source_syntax = data_blob_string_const(claim_attribute_source_class->attributeSyntax_oid);
     948        5083 :                         if (source_syntax.data == NULL) {
     949           0 :                                 continue;
     950             :                         }
     951             : 
     952        5083 :                         if (!is_valid_claim_attribute_syntax(source_syntax, claim_value_type)) {
     953        1429 :                                 continue;
     954             :                         }
     955             : 
     956        3654 :                         attribute = claim_attribute_source_class->lDAPDisplayName;
     957        3654 :                         if (attribute == NULL) {
     958           0 :                                 continue;
     959             :                         }
     960             : 
     961        3654 :                         ret = add_attr_unique(tmp_ctx,
     962             :                                               ad_claim_attrs,
     963             :                                               &ad_claim_attrs_count,
     964             :                                               attribute);
     965        3654 :                         if (ret) {
     966           0 :                                 talloc_free(tmp_ctx);
     967           0 :                                 return ret;
     968             :                         }
     969             : 
     970        3654 :                         name = ldb_msg_find_ldb_val(res->msgs[i], "name");
     971        3654 :                         if (name == NULL) {
     972           0 :                                 name = &data_blob_null;
     973             :                         }
     974             : 
     975        3654 :                         ad_claims[ad_claims_count++] = (struct ad_claim_info) {
     976        3654 :                                 .name = *name,
     977             :                                 .syntax = source_syntax,
     978             :                                 .attribute = attribute,
     979             :                                 .claim_type = claim_value_type,
     980             :                         };
     981       16858 :                 } else if (silo_is_maybe_assigned(assigned_silo)
     982       16858 :                            && strcasecmp(claim_source_type, "Constructed") == 0)
     983             :                 {
     984       16819 :                         const struct ldb_val *name = NULL;
     985       16819 :                         struct CLAIM_STRING *claim = NULL;
     986       16819 :                         struct CLAIM_ENTRY *claim_entry = NULL;
     987       16819 :                         const char *claim_value = NULL;
     988             : 
     989       16819 :                         if (claim_attribute_source != NULL) {
     990           0 :                                 continue;
     991             :                         }
     992             : 
     993       16819 :                         if (claim_source != NULL) {
     994           0 :                                 continue;
     995             :                         }
     996             : 
     997       16819 :                         name = ldb_msg_find_ldb_val(res->msgs[i], "name");
     998       16819 :                         if (name == NULL || name->data == NULL) {
     999           0 :                                 continue;
    1000             :                         }
    1001             :                         /* Does the claim ID match exactly in case? */
    1002       16819 :                         if (strcmp((const char *)name->data, "ad://ext/AuthenticationSilo") != 0) {
    1003           0 :                                 continue;
    1004             :                         }
    1005             : 
    1006       16819 :                         ret = get_assigned_silo(ldb, tmp_ctx, principal, &assigned_silo);
    1007       16819 :                         if (ret) {
    1008           0 :                                 talloc_free(tmp_ctx);
    1009           0 :                                 return ret;
    1010             :                         }
    1011       16819 :                         if (!assigned_silo.is_assigned) {
    1012       16797 :                                 continue;
    1013             :                         }
    1014             : 
    1015          22 :                         if (ad_sourced_constructed == NULL) {
    1016          22 :                                 claims_set->claims_arrays = talloc_realloc(claims_set,
    1017             :                                                                                claims_set->claims_arrays,
    1018             :                                                                                struct CLAIMS_ARRAY,
    1019             :                                                                                claims_set->claims_array_count + 1);
    1020          22 :                                 if (claims_set->claims_arrays == NULL) {
    1021           0 :                                         talloc_free(tmp_ctx);
    1022           0 :                                         return ldb_oom(ldb);
    1023             :                                 }
    1024             : 
    1025          22 :                                 ad_sourced_constructed = &claims_set->claims_arrays[claims_set->claims_array_count++];
    1026          22 :                                 *ad_sourced_constructed = (struct CLAIMS_ARRAY) {
    1027             :                                         .claims_source_type = CLAIMS_SOURCE_TYPE_AD,
    1028             :                                 };
    1029             :                         }
    1030             : 
    1031             :                         /* Add the claim to the array. */
    1032          22 :                         ad_sourced_constructed->claim_entries = talloc_realloc(
    1033             :                                 claims_set->claims_arrays,
    1034             :                                 ad_sourced_constructed->claim_entries,
    1035             :                                 struct CLAIM_ENTRY,
    1036             :                                 ad_sourced_constructed->claims_count + 1);
    1037          22 :                         if (ad_sourced_constructed->claim_entries == NULL) {
    1038           0 :                                 talloc_free(tmp_ctx);
    1039           0 :                                 return ldb_oom(ldb);
    1040             :                         }
    1041             : 
    1042          22 :                         claim_entry = &ad_sourced_constructed->claim_entries[ad_sourced_constructed->claims_count++];
    1043             : 
    1044             :                         /* Fill in the claim details and return the claim. */
    1045          22 :                         claim_entry->id = "ad://ext/AuthenticationSilo";
    1046          22 :                         claim_entry->type = CLAIM_TYPE_STRING;
    1047             : 
    1048          22 :                         claim = &claim_entry->values.claim_string;
    1049             : 
    1050          22 :                         claim->value_count = 1;
    1051          22 :                         claim->values = talloc_array(ad_sourced_constructed->claim_entries,
    1052             :                                                      const char *,
    1053             :                                                      claim->value_count);
    1054          22 :                         if (claim->values == NULL) {
    1055           0 :                                 talloc_free(tmp_ctx);
    1056           0 :                                 return ldb_oom(ldb);
    1057             :                         }
    1058             : 
    1059          22 :                         claim_value = talloc_strdup(claim->values, assigned_silo.name);
    1060          22 :                         if (claim_value == NULL) {
    1061           0 :                                 talloc_free(tmp_ctx);
    1062           0 :                                 return ldb_oom(ldb);
    1063             :                         }
    1064             : 
    1065          22 :                         claim->values[0] = claim_value;
    1066             :                 }
    1067             :         }
    1068             : 
    1069       16819 :         if (ad_claims_count) {
    1070         505 :                 struct ldb_message *principal_msg = NULL;
    1071             : 
    1072             :                 /* Shrink the arrays to remove any unused space. */
    1073         505 :                 ad_claim_attrs = talloc_realloc(tmp_ctx,
    1074             :                                                 ad_claim_attrs,
    1075             :                                                 const char *,
    1076             :                                                 ad_claim_attrs_count + 1);
    1077         505 :                 if (ad_claim_attrs == NULL) {
    1078           0 :                         talloc_free(tmp_ctx);
    1079           0 :                         return ldb_oom(ldb);
    1080             :                 }
    1081         505 :                 ad_claim_attrs[ad_claim_attrs_count] = NULL;
    1082             : 
    1083         505 :                 ad_claims = talloc_realloc(tmp_ctx,
    1084             :                                            ad_claims,
    1085             :                                            struct ad_claim_info,
    1086             :                                            ad_claims_count);
    1087         505 :                 if (ad_claims == NULL) {
    1088           0 :                         talloc_free(tmp_ctx);
    1089           0 :                         return ldb_oom(ldb);
    1090             :                 }
    1091             : 
    1092         505 :                 ret = dsdb_search_one(ldb,
    1093             :                                       tmp_ctx,
    1094             :                                       &principal_msg,
    1095         505 :                                       principal->dn,
    1096             :                                       LDB_SCOPE_BASE,
    1097             :                                       ad_claim_attrs,
    1098             :                                       0,
    1099             :                                       NULL);
    1100         505 :                 if (ret != LDB_SUCCESS) {
    1101           0 :                         const char *dn = ldb_dn_get_linearized(principal->dn);
    1102           0 :                         DBG_ERR("Failed to find principal %s to construct claims\n",
    1103             :                                 dn != NULL ? dn : "<NULL>");
    1104           0 :                         talloc_free(tmp_ctx);
    1105           0 :                         return ret;
    1106             :                 }
    1107             : 
    1108             :                 /*
    1109             :                  * Ensure that only the attrs we asked for end up in the results
    1110             :                  * (it's fine if some are missing)
    1111             :                  */
    1112         505 :                 SMB_ASSERT(principal_msg->num_elements <= ad_claim_attrs_count);
    1113             : 
    1114        4159 :                 for (i = 0; i < ad_claims_count; ++i) {
    1115        3654 :                         const struct ldb_message_element *principal_attribute = NULL;
    1116        3654 :                         struct CLAIM_ENTRY *claim_entry = NULL;
    1117        3654 :                         uint32_t new_claims_array_count = claims_set->claims_array_count;
    1118             : 
    1119             :                         /* Get the value of the claim attribute for the principal. */
    1120        3654 :                         principal_attribute = ldb_msg_find_element(principal_msg,
    1121        3654 :                                                                    ad_claims[i].attribute);
    1122        3654 :                         if (principal_attribute == NULL) {
    1123        2612 :                                 continue;
    1124             :                         }
    1125             : 
    1126             :                         /* Add the claim to the array. */
    1127             : 
    1128        1042 :                         if (ad_sourced_constructed == NULL) {
    1129         302 :                                 claims_set->claims_arrays = talloc_realloc(claims_set,
    1130             :                                                                                claims_set->claims_arrays,
    1131             :                                                                                struct CLAIMS_ARRAY,
    1132             :                                                                                new_claims_array_count + 1);
    1133         302 :                                 if (claims_set->claims_arrays == NULL) {
    1134           0 :                                         talloc_free(tmp_ctx);
    1135           0 :                                         return ldb_oom(ldb);
    1136             :                                 }
    1137             : 
    1138         302 :                                 ad_sourced_constructed = &claims_set->claims_arrays[new_claims_array_count++];
    1139         302 :                                 *ad_sourced_constructed = (struct CLAIMS_ARRAY) {
    1140             :                                         .claims_source_type = CLAIMS_SOURCE_TYPE_AD,
    1141             :                                 };
    1142             :                         }
    1143             : 
    1144        1042 :                         ad_sourced_constructed->claim_entries = talloc_realloc(
    1145             :                                 claims_set->claims_arrays,
    1146             :                                 ad_sourced_constructed->claim_entries,
    1147             :                                 struct CLAIM_ENTRY,
    1148             :                                 ad_sourced_constructed->claims_count + 1);
    1149        1042 :                         if (ad_sourced_constructed->claim_entries == NULL) {
    1150           0 :                                 talloc_free(tmp_ctx);
    1151           0 :                                 return ldb_oom(ldb);
    1152             :                         }
    1153             : 
    1154        1042 :                         claim_entry = &ad_sourced_constructed->claim_entries[
    1155        1042 :                                 ad_sourced_constructed->claims_count];
    1156             : 
    1157        1042 :                         ret = fill_claim_entry(ad_sourced_constructed->claim_entries,
    1158             :                                                ldb,
    1159             :                                                schema,
    1160             :                                                principal_attribute,
    1161        1042 :                                                ad_claims[i].name,
    1162        1042 :                                                ad_claims[i].syntax,
    1163        1042 :                                                ad_claims[i].claim_type,
    1164             :                                                claim_entry);
    1165        1042 :                         if (ret != LDB_SUCCESS) {
    1166           0 :                                 talloc_free(tmp_ctx);
    1167           0 :                                 return ret;
    1168             :                         }
    1169             : 
    1170        1042 :                         if (claim_get_value_count(claim_entry) > 0) {
    1171             :                                 /*
    1172             :                                  * If the claim contains values, add it to the
    1173             :                                  * array(s).
    1174             :                                  */
    1175        1042 :                                 ++ad_sourced_constructed->claims_count;
    1176        1042 :                                 claims_set->claims_array_count = new_claims_array_count;
    1177             :                         }
    1178             :                 }
    1179             :         }
    1180             : 
    1181       16819 :         if (claims_set->claims_array_count) {
    1182         324 :                 *claims_set_out = talloc_steal(mem_ctx, claims_set);
    1183             :         }
    1184             : 
    1185       16819 :         talloc_free(tmp_ctx);
    1186       16819 :         return LDB_SUCCESS;
    1187             : }
    1188             : 
    1189       30561 : int get_claims_set_for_principal(struct ldb_context *ldb,
    1190             :                                  TALLOC_CTX *mem_ctx,
    1191             :                                  const struct ldb_message *principal,
    1192             :                                  struct CLAIMS_SET **claims_set_out)
    1193             : {
    1194       30561 :         struct ldb_message_element *principal_class_el = NULL;
    1195       30561 :         struct dsdb_schema *schema = NULL;
    1196       30561 :         const struct dsdb_class *principal_class = NULL;
    1197             : 
    1198       30561 :         *claims_set_out = NULL;
    1199             : 
    1200       30561 :         if (!ad_claims_are_issued(ldb)) {
    1201       13566 :                 return LDB_SUCCESS;
    1202             :         }
    1203             : 
    1204       16995 :         principal_class_el = ldb_msg_find_element(principal,
    1205             :                                                   "objectClass");
    1206       16995 :         if (principal_class_el == NULL) {
    1207           0 :                 return ldb_operr(ldb);
    1208             :         }
    1209             : 
    1210       16995 :         schema = dsdb_get_schema(ldb, mem_ctx);
    1211       16995 :         if (schema == NULL) {
    1212           0 :                 return ldb_operr(ldb);
    1213             :         }
    1214             : 
    1215       16995 :         principal_class = dsdb_get_last_structural_class(schema, principal_class_el);
    1216       16995 :         if (principal_class == NULL) {
    1217           0 :                 return ldb_operr(ldb);
    1218             :         }
    1219             : 
    1220       16995 :         return get_all_claims(ldb,
    1221             :                               mem_ctx,
    1222             :                               principal,
    1223       16995 :                               principal_class->governsID_id,
    1224             :                               claims_set_out);
    1225             : }

Generated by: LCOV version 1.14