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

Generated by: LCOV version 1.14