LCOV - code coverage report
Current view: top level - libcli/security - claims-conversions.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 418 539 77.6 %
Date: 2024-01-11 09:59:51 Functions: 20 22 90.9 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB implementation.
       3             :  *  Utility functions for converting between claims formats.
       4             :  *
       5             :  *  This program is free software; you can redistribute it and/or modify
       6             :  *  it under the terms of the GNU General Public License as published by
       7             :  *  the Free Software Foundation; either version 3 of the License, or
       8             :  *  (at your option) any later version.
       9             :  *
      10             :  *  This program is distributed in the hope that it will be useful,
      11             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  *  GNU General Public License for more details.
      14             :  *
      15             :  *  You should have received a copy of the GNU General Public License
      16             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : #include "replace.h"
      20             : #include "librpc/gen_ndr/ndr_security.h"
      21             : #include "librpc/gen_ndr/ndr_conditional_ace.h"
      22             : #include "libcli/security/claims-conversions.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/stable_sort.h"
      25             : 
      26             : #include "librpc/gen_ndr/conditional_ace.h"
      27             : #include "librpc/gen_ndr/claims.h"
      28             : 
      29             : /*
      30             :  * We support three formats for claims, all slightly different.
      31             :  *
      32             :  * 1. MS-ADTS 2.2.18.* claims sets, blobs, arrays, or whatever, which
      33             :  *    are used in the PAC.
      34             :  *
      35             :  * 2. MS-DTYP 2.4.10.1 CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
      36             :  *    structures, used in security tokens and resource SACL ACEs.
      37             :  *
      38             :  * 3. MS-DTYP 2.4.4.17 Conditional ACE tokens.
      39             :  *
      40             :  * The types don't map perfectly onto each other -- in particular,
      41             :  * Conditional ACEs don't have unsigned integer or boolean types, but
      42             :  * do have short integer types which the other forms don't.
      43             :  *
      44             :  * We don't support the format used by the Win32 API function
      45             :  * AddResourceAttributeAce(), which is called CLAIM_SECURITY_ATTRIBUTE_V1.
      46             :  * Nobody has ever used that function in public, and the format is not used
      47             :  * on the wire.
      48             :  */
      49             : 
      50             : 
      51        4929 : static bool claim_v1_string_to_ace_string(
      52             :         TALLOC_CTX *mem_ctx,
      53             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
      54             :         size_t offset,
      55             :         struct ace_condition_token *result)
      56             : {
      57        9431 :         char *s = talloc_strdup(mem_ctx,
      58        4929 :                                 claim->values[offset].string_value);
      59        4929 :         if (s == NULL) {
      60           0 :                 return false;
      61             :         }
      62             : 
      63        4929 :         result->type = CONDITIONAL_ACE_TOKEN_UNICODE;
      64        4929 :         result->data.unicode.value = s;
      65        4929 :         return true;
      66             : }
      67             : 
      68             : 
      69           6 : static bool claim_v1_octet_string_to_ace_octet_string(
      70             :         TALLOC_CTX *mem_ctx,
      71             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
      72             :         size_t offset,
      73             :         struct ace_condition_token *result)
      74             : {
      75           6 :         DATA_BLOB *v = NULL;
      76           6 :         DATA_BLOB w = data_blob_null;
      77             : 
      78           6 :         v = claim->values[offset].octet_value;
      79             : 
      80           6 :         if (v->length > CONDITIONAL_ACE_MAX_LENGTH) {
      81           0 :                 DBG_WARNING("claim has octet string of unexpected length %zu "
      82             :                             "(expected range 1 - %u)\n",
      83             :                             v->length, CONDITIONAL_ACE_MAX_LENGTH);
      84           0 :                 return false;
      85             :         }
      86           6 :         if (v->length != 0) {
      87           6 :                 w = data_blob_talloc(mem_ctx, v->data, v->length);
      88           6 :                 if (w.data == NULL) {
      89           0 :                         return false;
      90             :                 }
      91             :         }
      92             : 
      93           6 :         result->type = CONDITIONAL_ACE_TOKEN_OCTET_STRING;
      94           6 :         result->data.bytes = w;
      95           6 :         return true;
      96             : }
      97             : 
      98             : 
      99          34 : static bool blob_string_sid_to_sid(DATA_BLOB *blob,
     100             :                                    struct dom_sid *sid)
     101             : {
     102             :         /*
     103             :          * Resource ACE claim SIDs are stored as SID strings in
     104             :          * CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_RELATIVE blobs. These are in
     105             :          * ACEs, which means we don't quite know who wrote them, and it is
     106             :          * unspecified whether the blob should contain a terminating NUL byte.
     107             :          * Therefore we accept either form, copying into a temporary buffer if
     108             :          * there is no '\0'. Apart from this special case, we don't accept
     109             :          * SIDs that are shorter than the blob.
     110             :          *
     111             :          * It doesn't seem like SDDL short SIDs ("WD") are accepted here. This
     112             :          * isn't SDDL.
     113             :          */
     114          34 :         bool ok;
     115          34 :         size_t len = blob->length;
     116          34 :         char buf[DOM_SID_STR_BUFLEN + 1];   /* 191 + 1 */
     117          34 :         const char *end = NULL;
     118          34 :         char *str = NULL;
     119             : 
     120          34 :         if (len < 5 || len >= DOM_SID_STR_BUFLEN) {
     121           0 :                 return false;
     122             :         }
     123          34 :         if (blob->data[len - 1] == '\0') {
     124           0 :                 str = (char *)blob->data;
     125           0 :                 len--;
     126             :         } else {
     127          34 :                 memcpy(buf, blob->data, len);
     128          34 :                 buf[len] = 0;
     129          34 :                 str = buf;
     130             :         }
     131             : 
     132          34 :         ok = dom_sid_parse_endp(str, sid, &end);
     133          34 :         if (!ok) {
     134           0 :                 return false;
     135             :         }
     136             : 
     137          34 :         if (end - str != len) {
     138           0 :                 return false;
     139             :         }
     140           0 :         return true;
     141             : }
     142             : 
     143             : 
     144           8 : static bool claim_v1_sid_to_ace_sid(
     145             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     146             :         size_t offset,
     147             :         struct ace_condition_token *result)
     148             : {
     149             :         /*
     150             :          * In the _V1 struct, SIDs are stored as octet string blobs,
     151             :          * as *SID strings*.
     152             :          *
     153             :          * In the conditional ACE they are stored as struct dom_sid.
     154             :          *
     155             :          * There are no SIDs in ADTS claims, but there can be in
     156             :          * resource ACEs.
     157             :          */
     158           8 :         DATA_BLOB *v = NULL;
     159           8 :         bool ok;
     160             : 
     161           8 :         v = claim->values[offset].sid_value;
     162             : 
     163           8 :         ok = blob_string_sid_to_sid(v, &result->data.sid.sid);
     164           8 :         if (! ok) {
     165           0 :                 DBG_WARNING("claim has invalid SID string of length %zu.\n",
     166             :                             v->length);
     167           0 :                 return false;
     168             :         }
     169             : 
     170           8 :         result->type = CONDITIONAL_ACE_TOKEN_SID;
     171           8 :         return true;
     172             : }
     173             : 
     174             : 
     175          13 : static bool claim_v1_int_to_ace_int(
     176             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     177             :         size_t offset,
     178             :         struct ace_condition_token *result)
     179             : {
     180          13 :         int64_t v = *claim->values[offset].int_value;
     181          13 :         result->type = CONDITIONAL_ACE_TOKEN_INT64;
     182          13 :         result->data.int64.base = CONDITIONAL_ACE_INT_BASE_10;
     183          13 :         result->data.int64.value = v;
     184             : 
     185             :         /*
     186             :          * The sign flag (and the base flag above) determines how the
     187             :          * ACE token will be displayed if converted to SDDL. These
     188             :          * values are not likely to end up as SDDL, but we might as
     189             :          * well get it right. A negative flag means it will be
     190             :          * displayed with a minus sign, and a positive flag means a
     191             :          * plus sign is shown. The none flag means no + or -.
     192             :          */
     193          13 :         if (v < 0) {
     194           0 :                 result->data.int64.sign = CONDITIONAL_ACE_INT_SIGN_NEGATIVE;
     195             :         } else {
     196          13 :                 result->data.int64.sign = CONDITIONAL_ACE_INT_SIGN_NONE;
     197             :         }
     198             : 
     199          11 :         return true;
     200             : }
     201             : 
     202             : 
     203          26 : static bool claim_v1_unsigned_int_to_ace_int(
     204             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     205             :         size_t offset,
     206             :         struct ace_condition_token *result)
     207             : {
     208          26 :         uint64_t v = *claim->values[offset].uint_value;
     209          26 :         if (v > INT64_MAX) {
     210             :                 /*
     211             :                  * The unsigned value can't be represented in a
     212             :                  * conditional ACE type.
     213             :                  *
     214             :                  * XXX or can it? does the positive flag make it
     215             :                  * unsigned?
     216             :                  */
     217           0 :                 return false;
     218             :         }
     219          26 :         result->type = CONDITIONAL_ACE_TOKEN_INT64;
     220          26 :         result->data.int64.base = CONDITIONAL_ACE_INT_BASE_10;
     221          26 :         result->data.int64.sign = CONDITIONAL_ACE_INT_SIGN_POSITIVE;
     222          26 :         result->data.int64.value = v;
     223          26 :         return true;
     224             : }
     225             : 
     226             : 
     227          54 : static bool claim_v1_bool_to_ace_int(
     228             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     229             :         size_t offset,
     230             :         struct ace_condition_token *result)
     231             : {
     232          54 :         uint64_t v = *claim->values[offset].uint_value;
     233          54 :         result->type = CONDITIONAL_ACE_TOKEN_INT64;
     234          54 :         result->data.int64.base = CONDITIONAL_ACE_INT_BASE_10;
     235          54 :         result->data.int64.sign = CONDITIONAL_ACE_INT_SIGN_NONE;
     236          54 :         result->data.int64.value = v ? 1 : 0;
     237          54 :         return true;
     238             : }
     239             : 
     240             : 
     241        5036 : static bool claim_v1_offset_to_ace_token(
     242             :         TALLOC_CTX *mem_ctx,
     243             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     244             :         size_t offset,
     245             :         struct ace_condition_token *result)
     246             : {
     247             :         /*
     248             :          * A claim structure has an array of claims of a certain type,
     249             :          * and this converts a single one into a conditional ACE token.
     250             :          *
     251             :          * For example, if offset is 3, claim->values[3] will be
     252             :          * turned into *result.
     253             :          *
     254             :          * conditional ace token will have flags to indicate that it
     255             :          * comes from a claim attribute, and whether or not that
     256             :          * attribute should be compared case-sensitively (only
     257             :          * affecting unicode strings).
     258             :          *
     259             :          * The CLAIM_SECURITY_ATTRIBUTE_CASE_SENSITIVE (from the
     260             :          * claim_flags enum in security.idl) is used for both.
     261             :          */
     262        5036 :         uint8_t f = claim->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
     263        5036 :         result->flags = f | CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR;
     264             : 
     265        5036 :         switch (claim->value_type) {
     266          11 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
     267          13 :                 return claim_v1_int_to_ace_int(claim, offset, result);
     268          25 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
     269          26 :                 return claim_v1_unsigned_int_to_ace_int(claim, offset, result);
     270         427 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
     271        4929 :                 return claim_v1_string_to_ace_string(mem_ctx, claim, offset,
     272             :                                                      result);
     273           8 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
     274           8 :                 return claim_v1_sid_to_ace_sid(claim, offset, result);
     275          54 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN:
     276          54 :                 return claim_v1_bool_to_ace_int(claim, offset, result);
     277           6 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
     278           6 :                 return claim_v1_octet_string_to_ace_octet_string(mem_ctx,
     279             :                                                                  claim,
     280             :                                                                  offset,
     281             :                                                                  result);
     282           0 :         default:
     283           0 :                 return false;
     284             :         }
     285             : }
     286             : 
     287             : 
     288             : static bool claim_v1_copy(
     289             :         TALLOC_CTX *mem_ctx,
     290             :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *dest,
     291             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *src);
     292             : 
     293             : 
     294             : 
     295         203 : bool claim_v1_to_ace_composite_unchecked(
     296             :         TALLOC_CTX *mem_ctx,
     297             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     298             :         struct ace_condition_token *result)
     299             : {
     300             :         /*
     301             :          * This converts a claim object into a conditional ACE
     302             :          * composite without checking whether it is a valid and sorted
     303             :          * claim. It is called in two places:
     304             :          *
     305             :          * 1. claim_v1_to_ace_token() below (which does do those
     306             :          * checks, and is the function you want).
     307             :          *
     308             :          * 2. sddl_resource_attr_from_claim() in which a resource
     309             :          * attribute claim needs to pass through a conditional ACE
     310             :          * composite structure on its way to becoming SDDL. In that
     311             :          * case we don't want to check validity.
     312             :          */
     313          92 :         size_t i;
     314         203 :         struct ace_condition_token *tokens = NULL;
     315          92 :         bool ok;
     316             : 
     317         203 :         tokens = talloc_array(mem_ctx,
     318             :                               struct ace_condition_token,
     319             :                               claim->value_count);
     320         203 :         if (tokens == NULL) {
     321           0 :                 return false;
     322             :         }
     323             : 
     324        4937 :         for (i = 0; i < claim->value_count; i++) {
     325        9228 :                 ok = claim_v1_offset_to_ace_token(tokens,
     326             :                                                   claim,
     327             :                                                   i,
     328        4734 :                                                   &tokens[i]);
     329        4734 :                 if (! ok) {
     330           0 :                         TALLOC_FREE(tokens);
     331           0 :                         return false;
     332             :                 }
     333             :         }
     334             : 
     335         203 :         result->type = CONDITIONAL_ACE_TOKEN_COMPOSITE;
     336         203 :         result->data.composite.tokens = tokens;
     337         203 :         result->data.composite.n_members = claim->value_count;
     338         203 :         result->flags = claim->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
     339         203 :         return true;
     340             : }
     341             : 
     342             : 
     343         512 : bool claim_v1_to_ace_token(TALLOC_CTX *mem_ctx,
     344             :                            const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     345             :                            struct ace_condition_token *result)
     346             : {
     347         512 :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim_copy = NULL;
     348         512 :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *sorted_claim = NULL;
     349         117 :         NTSTATUS status;
     350         117 :         bool ok;
     351         512 :         bool case_sensitive = claim->flags &                     \
     352             :                 CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
     353             : 
     354         512 :         if (claim->value_count < 1 ||
     355         389 :             claim->value_count >= CONDITIONAL_ACE_MAX_TOKENS) {
     356          10 :                 DBG_WARNING("rejecting claim with %"PRIu32" tokens\n",
     357             :                             claim->value_count);
     358          10 :                 return false;
     359             :         }
     360             :         /*
     361             :          * if there is one, we return a single thing of that type; if
     362             :          * there are many, we return a composite.
     363             :          */
     364             : 
     365         502 :         if (claim->value_count == 1) {
     366         302 :                 return claim_v1_offset_to_ace_token(mem_ctx,
     367             :                                                     claim,
     368             :                                                     0,
     369             :                                                     result);
     370             :         }
     371             : 
     372         200 :         if (claim->flags & CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED) {
     373             :                 /*
     374             :                  * We can avoid making a sorted copy.
     375             :                  *
     376             :                  * This is normal case for wire claims, where the
     377             :                  * sorting and duplicate checking happens earlier in
     378             :                  * token_claims_to_claims_v1().
     379             :                 */
     380         111 :                 sorted_claim = claim;
     381             :         } else {
     382             :                 /*
     383             :                  * This is presumably a resource attribute ACE, which
     384             :                  * is stored in the ACE as struct
     385             :                  * CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, and we don't
     386             :                  * really want to mutate that copy -- even if there
     387             :                  * aren't currently realistic pathways that read an
     388             :                  * ACE, trigger this, and write it back (outside of
     389             :                  * tests).
     390             :                  */
     391          62 :                 claim_copy = talloc(mem_ctx, struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1);
     392          62 :                 if (claim_copy == NULL) {
     393           0 :                         return false;
     394             :                 }
     395             : 
     396          62 :                 ok = claim_v1_copy(claim_copy, claim_copy, claim);
     397          62 :                 if (!ok) {
     398           0 :                         TALLOC_FREE(claim_copy);
     399           0 :                         return false;
     400             :                 }
     401             : 
     402          62 :                 status = claim_v1_check_and_sort(claim_copy, claim_copy,
     403             :                                                  case_sensitive);
     404          62 :                 if (!NT_STATUS_IS_OK(status)) {
     405           4 :                         DBG_WARNING("resource attribute claim sort failed with %s\n",
     406             :                                     nt_errstr(status));
     407           4 :                         TALLOC_FREE(claim_copy);
     408           4 :                         return false;
     409             :                 }
     410           0 :                 sorted_claim = claim_copy;
     411             :         }
     412         196 :         ok = claim_v1_to_ace_composite_unchecked(mem_ctx, sorted_claim, result);
     413         196 :         if (! ok) {
     414           0 :                 TALLOC_FREE(claim_copy);
     415           0 :                 return false;
     416             :         }
     417             : 
     418             :         /*
     419             :          * The multiple values will get turned into a composite
     420             :          * literal in the conditional ACE. Each element of the
     421             :          * composite will have flags set by
     422             :          * claim_v1_offset_to_ace_token(), but they also need to be
     423             :          * set here (at least the _FROM_ATTR flag) or the child values
     424             :          * will not be reached.
     425             :          */
     426         196 :         result->flags |= (
     427             :                 CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR |
     428             :                 CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED);
     429             : 
     430         196 :         return true;
     431             : }
     432             : 
     433             : 
     434             : 
     435         478 : static bool ace_int_to_claim_v1_int(TALLOC_CTX *mem_ctx,
     436             :                                     const struct ace_condition_token *tok,
     437             :                                     struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     438             :                                     size_t offset)
     439             : {
     440         956 :         int64_t *v = talloc(mem_ctx, int64_t);
     441         478 :         if (v == NULL) {
     442           0 :                 return false;
     443             :         }
     444         478 :         *v = tok->data.int64.value;
     445         478 :         claim->values[offset].int_value = v;
     446         478 :         return true;
     447             : }
     448             : 
     449             : 
     450         356 : static bool ace_string_to_claim_v1_string(TALLOC_CTX *mem_ctx,
     451             :                                           const struct ace_condition_token *tok,
     452             :                                           struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     453             :                                           size_t offset)
     454             : {
     455         712 :         const char *s = talloc_strdup(mem_ctx,
     456         356 :                                       tok->data.unicode.value);
     457         356 :         if (s == NULL) {
     458           0 :                 return false;
     459             :         }
     460         356 :         claim->values[offset].string_value = s;
     461         356 :         return true;
     462             : 
     463             : }
     464             : 
     465             : 
     466          11 : static bool ace_sid_to_claim_v1_sid(TALLOC_CTX *mem_ctx,
     467             :                                     const struct ace_condition_token *tok,
     468             :                                     struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     469             :                                     size_t offset)
     470             : {
     471             :         /* claim_v1 sid is an "S-1-*" string data blob, not struct dom_sid. */
     472          11 :         char *s = NULL;
     473             : 
     474          11 :         DATA_BLOB *blob = NULL;
     475          11 :         blob = talloc(mem_ctx, DATA_BLOB);
     476          11 :         if (blob == NULL) {
     477           0 :                 return false;
     478             :         }
     479          11 :         s = dom_sid_string(blob, &tok->data.sid.sid);
     480          11 :         if (s == NULL) {
     481           0 :                 TALLOC_FREE(blob);
     482           0 :                 return false;
     483             :         }
     484          11 :         *blob = data_blob_string_const(s);
     485          11 :         claim->values[offset].sid_value = blob;
     486          11 :         return true;
     487             : }
     488             : 
     489         522 : static bool ace_octet_string_to_claim_v1_octet_string(
     490             :         TALLOC_CTX *mem_ctx,
     491             :         const struct ace_condition_token *tok,
     492             :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     493             :         size_t offset)
     494             : {
     495         522 :         DATA_BLOB *v = talloc(mem_ctx, DATA_BLOB);
     496         522 :         if (v == NULL) {
     497           0 :                 return false;
     498             :         }
     499             : 
     500         522 :         *v = data_blob_talloc(v,
     501             :                               tok->data.bytes.data,
     502             :                               tok->data.bytes.length);
     503         522 :         if (v->data == NULL) {
     504           0 :                 return false;
     505             :         }
     506             : 
     507         522 :         claim->values[offset].octet_value = v;
     508         522 :         return true;
     509             : }
     510             : 
     511             : 
     512             : 
     513        1367 : static bool ace_token_to_claim_v1_offset(TALLOC_CTX *mem_ctx,
     514             :                                          const struct ace_condition_token *tok,
     515             :                                          struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     516             :                                          size_t offset)
     517             : {
     518             :         /*
     519             :          * A claim structure has an array of claims of a certain type,
     520             :          * and this converts a single one into a conditional ACE token.
     521             :          *
     522             :          * For example, if offset is 3, claim->values[3] will be
     523             :          * turned into *result.
     524             :          */
     525        1367 :         if (offset >= claim->value_count) {
     526           0 :                 return false;
     527             :         }
     528        1367 :         switch (claim->value_type) {
     529           0 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
     530             :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
     531         478 :                 return ace_int_to_claim_v1_int(mem_ctx, tok, claim, offset);
     532           0 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
     533         356 :                 return ace_string_to_claim_v1_string(mem_ctx, tok, claim, offset);
     534          11 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
     535          11 :                 return ace_sid_to_claim_v1_sid(mem_ctx, tok, claim, offset);
     536         522 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
     537         522 :                 return ace_octet_string_to_claim_v1_octet_string(mem_ctx,
     538             :                                                                  tok,
     539             :                                                                  claim,
     540             :                                                                  offset);
     541           0 :         default:
     542             :                 /*bool unimplemented, because unreachable */
     543           0 :                 return false;
     544             :         }
     545             : }
     546             : 
     547             : 
     548         145 : bool ace_token_to_claim_v1(TALLOC_CTX *mem_ctx,
     549             :                            const char *name,
     550             :                            const struct ace_condition_token *tok,
     551             :                            struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 **claim,
     552             :                            uint32_t flags)
     553             : {
     554         145 :         size_t i;
     555         145 :         bool ok;
     556         145 :         bool is_comp = false;
     557         145 :         int claim_type = -1;
     558         145 :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *_claim = NULL;
     559         145 :         uint32_t value_count;
     560             : 
     561         145 :         if (name == NULL || claim == NULL || tok == NULL) {
     562           0 :                 return false;
     563             :         }
     564         145 :         *claim = NULL;
     565             : 
     566         145 :         if (tok->type == CONDITIONAL_ACE_TOKEN_COMPOSITE) {
     567         102 :                 is_comp = true;
     568             :                 /* there must be values, all of the same type */
     569         102 :                 if (tok->data.composite.n_members == 0) {
     570           0 :                         DBG_WARNING("Empty ACE composite list\n");
     571           0 :                         return false;
     572             :                 }
     573         102 :                 if (tok->data.composite.n_members > 1) {
     574        1324 :                         for (i = 1; i < tok->data.composite.n_members; i++) {
     575        1222 :                                 if (tok->data.composite.tokens[i].type !=
     576        1222 :                                     tok->data.composite.tokens[0].type) {
     577           0 :                                         DBG_WARNING(
     578             :                                                 "ACE composite list has varying "
     579             :                                                 "types (at least %u and %u)\n",
     580             :                                                 tok->data.composite.tokens[i].type,
     581             :                                                 tok->data.composite.tokens[0].type);
     582           0 :                                         return false;
     583             :                                 }
     584             :                         }
     585             :                 }
     586         102 :                 value_count = tok->data.composite.n_members;
     587             : 
     588         102 :                 switch (tok->data.composite.tokens[0].type) {
     589           0 :                 case CONDITIONAL_ACE_TOKEN_INT8:
     590             :                 case CONDITIONAL_ACE_TOKEN_INT16:
     591             :                 case CONDITIONAL_ACE_TOKEN_INT32:
     592             :                 case CONDITIONAL_ACE_TOKEN_INT64:
     593           0 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64;
     594           0 :                         break;
     595          46 :                 case CONDITIONAL_ACE_TOKEN_UNICODE:
     596          46 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING;
     597          46 :                         break;
     598          13 :                 case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
     599          13 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING;
     600          13 :                         break;
     601           5 :                 case CONDITIONAL_ACE_TOKEN_SID:
     602           5 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_SID;
     603           5 :                         break;
     604           0 :                 default:
     605             :                         /* reject nested composites, no uint or bool. */
     606           0 :                         DBG_WARNING("ACE composite list has invalid type %u\n",
     607             :                                     tok->data.composite.tokens[0].type);
     608           0 :                         return false;
     609             :                 }
     610             :         } else {
     611          43 :                 value_count = 1;
     612          43 :                 switch(tok->type) {
     613           0 :                 case CONDITIONAL_ACE_TOKEN_INT8:
     614             :                 case CONDITIONAL_ACE_TOKEN_INT16:
     615             :                 case CONDITIONAL_ACE_TOKEN_INT32:
     616             :                 case CONDITIONAL_ACE_TOKEN_INT64:
     617           0 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64;
     618           0 :                         break;
     619          21 :                 case CONDITIONAL_ACE_TOKEN_UNICODE:
     620          21 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING;
     621          21 :                         break;
     622           1 :                 case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
     623           1 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING;
     624           1 :                         break;
     625           0 :                 case CONDITIONAL_ACE_TOKEN_SID:
     626           0 :                         claim_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_SID;
     627           0 :                         break;
     628           0 :                 default:
     629             :                         /*
     630             :                          * no way of creating bool or uint values,
     631             :                          * composite is handled above.
     632             :                          */
     633           0 :                         DBG_WARNING("ACE token has invalid type %u\n",
     634             :                                     tok->data.composite.tokens[0].type);
     635           0 :                         return false;
     636             :                 }
     637             :         }
     638             : 
     639         145 :         _claim = talloc(mem_ctx, struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1);
     640         145 :         if (_claim == NULL) {
     641           0 :                 return false;
     642             :         }
     643             : 
     644         145 :         _claim->value_count = value_count;
     645         145 :         _claim->value_type = claim_type;
     646         145 :         _claim->flags = flags;
     647         145 :         _claim->name = talloc_strdup(mem_ctx, name);
     648         145 :         if (_claim->name == NULL) {
     649           0 :                 TALLOC_FREE(_claim);
     650           0 :                 return false;
     651             :         }
     652             :         /*
     653             :          * The values array is actually an array of pointers to
     654             :          * values, even when the values are ints or bools.
     655             :          */
     656         145 :         _claim->values = talloc_array(_claim, union claim_values, value_count);
     657         145 :         if (_claim->values == NULL) {
     658           0 :                 TALLOC_FREE(_claim);
     659           0 :                 return false;
     660             :         }
     661         145 :         if (! is_comp) {
     662             :                 /* there is one value, not a list */
     663          43 :                 ok = ace_token_to_claim_v1_offset(_claim,
     664             :                                                   tok,
     665             :                                                   _claim,
     666             :                                                   0);
     667          43 :                 if (! ok) {
     668           0 :                         TALLOC_FREE(_claim);
     669           0 :                         return false;
     670             :                 }
     671             :         } else {
     672             :                 /* a composite list of values */
     673        1426 :                 for (i = 0; i < value_count; i++) {
     674        1324 :                         struct ace_condition_token *t = &tok->data.composite.tokens[i];
     675        1324 :                         ok = ace_token_to_claim_v1_offset(mem_ctx,
     676             :                                                           t,
     677             :                                                           _claim,
     678             :                                                           i);
     679        1324 :                         if (! ok) {
     680           0 :                                 TALLOC_FREE(_claim);
     681           0 :                                 return false;
     682             :                         }
     683             :                 }
     684             :         }
     685             : 
     686             : 
     687         145 :         if (_claim->value_type == CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64) {
     688             :                 /*
     689             :                  * Conditional ACE tokens don't have a UINT type but
     690             :                  * claims do. Windows tends to use UINT types in
     691             :                  * claims when it can, so so do we.
     692             :                  */
     693         427 :                 bool could_be_uint = true;
     694         427 :                 for (i = 0; i < value_count; i++) {
     695         374 :                         if (*_claim->values[i].int_value < 0) {
     696           0 :                                 could_be_uint = false;
     697           0 :                                 break;
     698             :                         }
     699             :                 }
     700          59 :                 if (could_be_uint) {
     701          53 :                         _claim->value_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64;
     702             :                 }
     703             :         }
     704             : 
     705         145 :         *claim = _claim;
     706         145 :         return true;
     707             : }
     708             : 
     709             : 
     710             : 
     711         102 : static bool claim_v1_copy(
     712             :         TALLOC_CTX *mem_ctx,
     713             :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *dest,
     714             :         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *src)
     715             : {
     716         102 :         DATA_BLOB blob = {0};
     717         102 :         enum ndr_err_code ndr_err;
     718             : 
     719             :         /*
     720             :          * FIXME, could be more efficient! but copying these
     721             :          * structures is fiddly, and it might be worth coming up
     722             :          * with a better API for adding claims.
     723             :          */
     724             : 
     725         102 :         ndr_err = ndr_push_struct_blob(
     726             :                 &blob, mem_ctx, src,
     727             :                 (ndr_push_flags_fn_t)ndr_push_CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1);
     728             : 
     729         102 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     730           0 :                 return false;
     731             :         }
     732             : 
     733         102 :         ndr_err = ndr_pull_struct_blob(
     734             :                 &blob, mem_ctx, dest,
     735             :                 (ndr_pull_flags_fn_t)ndr_pull_CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1);
     736             : 
     737         102 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     738           0 :                 TALLOC_FREE(blob.data);
     739           0 :                 return false;
     740             :         }
     741         102 :         TALLOC_FREE(blob.data);
     742           0 :         return true;
     743             : }
     744             : 
     745             : 
     746             : 
     747          40 : bool add_claim_to_token(TALLOC_CTX *mem_ctx,
     748             :                         struct security_token *token,
     749             :                         const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     750             :                         const char *claim_type)
     751             : {
     752          40 :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *tmp = NULL;
     753          40 :         NTSTATUS status;
     754          40 :         uint32_t *n = NULL;
     755          40 :         bool ok;
     756          40 :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 **list = NULL;
     757          40 :         if (strcmp(claim_type, "device") == 0) {
     758          38 :                 n = &token->num_device_claims;
     759          38 :                 list = &token->device_claims;
     760           2 :         } else if (strcmp(claim_type, "local") == 0) {
     761           0 :                 n = &token->num_local_claims;
     762           0 :                 list = &token->local_claims;
     763           2 :         } else if (strcmp(claim_type, "user") == 0) {
     764           2 :                 n = &token->num_user_claims;
     765           2 :                 list = &token->user_claims;
     766             :         } else {
     767           0 :                 return false;
     768             :         }
     769          40 :         if ((*n) == UINT32_MAX) {
     770           0 :                 return false;
     771             :         }
     772             : 
     773          40 :         tmp = talloc_realloc(mem_ctx,
     774             :                              *list,
     775             :                              struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1,
     776             :                              (*n) + 1);
     777          40 :         if (tmp == NULL) {
     778           0 :                 return false;
     779             :         }
     780             : 
     781          40 :         ok = claim_v1_copy(mem_ctx, &tmp[*n], claim);
     782          40 :         if (! ok ) {
     783           0 :                 TALLOC_FREE(tmp);
     784           0 :                 return false;
     785             :         }
     786             : 
     787          40 :         status = claim_v1_check_and_sort(tmp, &tmp[*n],
     788          40 :                                          claim->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE);
     789          40 :         if (!NT_STATUS_IS_OK(status)) {
     790           2 :                 DBG_WARNING("resource attribute claim sort failed with %s\n",
     791             :                             nt_errstr(status));
     792           2 :                 TALLOC_FREE(tmp);
     793           2 :                 return false;
     794             :         }
     795             : 
     796          38 :         (*n)++;
     797          38 :         *list = tmp;
     798          38 :         return true;
     799             : }
     800             : 
     801             : 
     802          54 : static NTSTATUS claim_v1_check_and_sort_boolean(
     803             :         TALLOC_CTX *mem_ctx,
     804             :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim)
     805             : {
     806             :         /*
     807             :          * There are so few valid orders in a boolean claim that we can
     808             :          * enumerate them all.
     809             :          */
     810          54 :         switch (claim->value_count) {
     811           4 :         case 0:
     812          49 :                 return NT_STATUS_OK;
     813          44 :         case 1:
     814          44 :                 if (*claim->values[0].uint_value == 0 ||
     815          23 :                     *claim->values[0].uint_value == 1) {
     816          43 :                         return NT_STATUS_OK;
     817             :                 }
     818           1 :                 break;
     819           6 :         case 2:
     820           6 :                 if (*claim->values[0].uint_value == 1) {
     821             :                         /* switch the order. */
     822           1 :                         *claim->values[0].uint_value = *claim->values[1].uint_value;
     823           1 :                         *claim->values[1].uint_value = 1;
     824             :                 }
     825           6 :                 if (*claim->values[0].uint_value == 0 &&
     826           6 :                     *claim->values[1].uint_value == 1) {
     827           2 :                         return NT_STATUS_OK;
     828             :                 }
     829           4 :                 break;
     830           0 :         default:
     831             :                 /* 3 or more must have duplicates. */
     832           0 :                 break;
     833             :         }
     834           5 :         return NT_STATUS_INVALID_PARAMETER;
     835             : }
     836             : 
     837             : 
     838             : struct claim_sort_context {
     839             :         uint16_t value_type;
     840             :         bool failed;
     841             :         bool case_sensitive;
     842             : };
     843             : 
     844      929208 : static int claim_sort_cmp(const union claim_values *lhs,
     845             :                           const union claim_values *rhs,
     846             :                           struct claim_sort_context *ctx)
     847             : {
     848             :         /*
     849             :          * These comparisons have to match those used in
     850             :          * conditional_ace.c.
     851             :          */
     852       34458 :         int cmp;
     853             : 
     854      929208 :         switch (ctx->value_type) {
     855      894246 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
     856             :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
     857             :         {
     858             :                 /*
     859             :                  * We sort as signed integers, even for uint64,
     860             :                  * because a) we don't actually care about the true
     861             :                  * order, just uniqueness, and b) the conditional ACEs
     862             :                  * only know of signed values.
     863             :                  */
     864           0 :                 int64_t a, b;
     865      894246 :                 if (ctx->value_type == CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64) {
     866          14 :                         a = *lhs->int_value;
     867          14 :                         b = *rhs->int_value;
     868             :                 } else {
     869      894232 :                         a = (int64_t)*lhs->uint_value;
     870      894232 :                         b = (int64_t)*rhs->uint_value;
     871             :                 }
     872      894246 :                 if (a < b) {
     873      808504 :                         return -1;
     874             :                 }
     875       85742 :                 if (a == b) {
     876          18 :                         return 0;
     877             :                 }
     878       85724 :                 return 1;
     879             :         }
     880       34949 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
     881             :         {
     882       34949 :                 const char *a = lhs->string_value;
     883       34949 :                 const char *b = rhs->string_value;
     884       34949 :                 if (ctx->case_sensitive) {
     885        1359 :                         return strcmp(a, b);
     886             :                 }
     887       33590 :                 return strcasecmp_m(a, b);
     888             :         }
     889             : 
     890          13 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
     891             :         {
     892             :                 /*
     893             :                  * The blobs in a claim are "S-1-.." strings, not struct
     894             :                  * dom_sid as used in conditional ACEs, and to sort them the
     895             :                  * same as ACEs we need to make temporary structs.
     896             :                  *
     897             :                  * We don't accept SID claims over the wire -- these
     898             :                  * are resource attribute ACEs only.
     899             :                  */
     900          13 :                 struct dom_sid a, b;
     901          13 :                 bool lhs_ok, rhs_ok;
     902             : 
     903          13 :                 lhs_ok = blob_string_sid_to_sid(lhs->sid_value, &a);
     904          13 :                 rhs_ok = blob_string_sid_to_sid(rhs->sid_value, &b);
     905          13 :                 if (!(lhs_ok && rhs_ok)) {
     906           0 :                         ctx->failed = true;
     907           0 :                         return -1;
     908             :                 }
     909          13 :                 cmp = dom_sid_compare(&a, &b);
     910          13 :                 return cmp;
     911             :         }
     912           0 :         case CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
     913             :         {
     914           0 :                 const DATA_BLOB *a = lhs->octet_value;
     915           0 :                 const DATA_BLOB *b = rhs->octet_value;
     916           0 :                 return data_blob_cmp(a, b);
     917             :         }
     918           0 :         default:
     919           0 :                 ctx->failed = true;
     920           0 :                 break;
     921             :         }
     922           0 :         return -1;
     923             : }
     924             : 
     925             : 
     926         861 : NTSTATUS claim_v1_check_and_sort(TALLOC_CTX *mem_ctx,
     927             :                                  struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
     928             :                                  bool case_sensitive)
     929             : {
     930         116 :         bool ok;
     931         116 :         uint32_t i;
     932         861 :         struct claim_sort_context sort_ctx = {
     933             :                 .failed = false,
     934         861 :                 .value_type = claim->value_type,
     935             :                 .case_sensitive = case_sensitive
     936             :         };
     937             : 
     938         861 :         if (claim->value_type == CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN) {
     939          54 :                 NTSTATUS status = claim_v1_check_and_sort_boolean(mem_ctx, claim);
     940          54 :                 if (NT_STATUS_IS_OK(status)) {
     941          49 :                         claim->flags |= CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED;
     942             :                 }
     943          54 :                 return status;
     944             :         }
     945             : 
     946         923 :         ok =  stable_sort_talloc_r(mem_ctx,
     947         807 :                                    claim->values,
     948         807 :                                    claim->value_count,
     949             :                                    sizeof(union claim_values),
     950             :                                    (samba_compare_with_context_fn_t)claim_sort_cmp,
     951             :                                    &sort_ctx);
     952         807 :         if (!ok) {
     953           0 :                 return NT_STATUS_NO_MEMORY;
     954             :         }
     955             : 
     956         807 :         if (sort_ctx.failed) {
     957             :                 /* this failure probably means a bad SID string */
     958           0 :                 DBG_WARNING("claim sort of %"PRIu32" members, type %"PRIu16" failed\n",
     959             :                             claim->value_count,
     960             :                             claim->value_type);
     961           0 :                 return NT_STATUS_INVALID_PARAMETER;
     962             :         }
     963             : 
     964      105462 :         for (i = 1; i < claim->value_count; i++) {
     965      109082 :                 int cmp = claim_sort_cmp(&claim->values[i - 1],
     966      104673 :                                          &claim->values[i],
     967             :                                          &sort_ctx);
     968      104673 :                 if (cmp == 0) {
     969          18 :                         DBG_WARNING("duplicate values in claim\n");
     970          18 :                         return NT_STATUS_INVALID_PARAMETER;
     971             :                 }
     972      104655 :                 if (cmp > 0) {
     973           0 :                         DBG_ERR("claim sort failed!\n");
     974           0 :                         return NT_STATUS_INVALID_PARAMETER;
     975             :                 }
     976             :         }
     977         789 :         if (case_sensitive) {
     978           8 :                 claim->flags |= CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
     979             :         }
     980         789 :         claim->flags |= CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED;
     981         789 :         return NT_STATUS_OK;
     982             : }
     983             : 
     984             : 
     985         304 : NTSTATUS token_claims_to_claims_v1(TALLOC_CTX *mem_ctx,
     986             :                                    const struct CLAIMS_SET *claims_set,
     987             :                                    struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 **out_claims,
     988             :                                    uint32_t *out_n_claims)
     989             : {
     990         304 :         struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claims = NULL;
     991         304 :         uint32_t n_claims = 0;
     992         304 :         uint32_t expected_n_claims = 0;
     993           6 :         uint32_t i;
     994           6 :         NTSTATUS status;
     995             : 
     996         304 :         if (out_claims == NULL) {
     997           0 :                 return NT_STATUS_INVALID_PARAMETER;
     998             :         }
     999         304 :         if (out_n_claims == NULL) {
    1000           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1001             :         }
    1002             : 
    1003         304 :         *out_claims = NULL;
    1004         304 :         *out_n_claims = 0;
    1005             : 
    1006         304 :         if (claims_set == NULL) {
    1007           0 :                 return NT_STATUS_OK;
    1008             :         }
    1009             : 
    1010             :         /*
    1011             :          * The outgoing number of claims is (at most) the sum of the
    1012             :          * claims_counts of each claims_array.
    1013             :          */
    1014         618 :         for (i = 0; i < claims_set->claims_array_count; ++i) {
    1015         314 :                 uint32_t count = claims_set->claims_arrays[i].claims_count;
    1016         314 :                 expected_n_claims += count;
    1017         314 :                 if (expected_n_claims < count) {
    1018           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1019             :                 }
    1020             :         }
    1021             : 
    1022         304 :         claims = talloc_array(mem_ctx,
    1023             :                               struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1,
    1024             :                               expected_n_claims);
    1025         304 :         if (claims == NULL) {
    1026           0 :                 return NT_STATUS_NO_MEMORY;
    1027             :         }
    1028             : 
    1029         601 :         for (i = 0; i < claims_set->claims_array_count; ++i) {
    1030         314 :                 const struct CLAIMS_ARRAY *claims_array = &claims_set->claims_arrays[i];
    1031           6 :                 uint32_t j;
    1032             : 
    1033         314 :                 switch (claims_array->claims_source_type) {
    1034         302 :                 case CLAIMS_SOURCE_TYPE_AD:
    1035             :                 case CLAIMS_SOURCE_TYPE_CERTIFICATE:
    1036         302 :                         break;
    1037           7 :                 default:
    1038             :                         /* Ignore any claims of a type we don’t recognize. */
    1039           7 :                         continue;
    1040             :                 }
    1041             : 
    1042        1053 :                 for (j = 0; j < claims_array->claims_count; ++j) {
    1043         763 :                         const struct CLAIM_ENTRY *claim_entry = &claims_array->claim_entries[j];
    1044         763 :                         const char *name = NULL;
    1045         763 :                         union claim_values *claim_values = NULL;
    1046          14 :                         uint32_t n_values;
    1047          14 :                         enum security_claim_value_type value_type;
    1048             : 
    1049         763 :                         switch (claim_entry->type) {
    1050          15 :                         case CLAIM_TYPE_INT64:
    1051             :                         {
    1052          15 :                                 const struct CLAIM_INT64 *values = &claim_entry->values.claim_int64;
    1053           0 :                                 uint32_t k;
    1054          15 :                                 int64_t *claim_values_int64 = NULL;
    1055             : 
    1056          15 :                                 n_values = values->value_count;
    1057          15 :                                 value_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64;
    1058             : 
    1059          15 :                                 claim_values = talloc_array(claims,
    1060             :                                                             union claim_values,
    1061             :                                                             n_values);
    1062          15 :                                 if (claim_values == NULL) {
    1063           0 :                                         talloc_free(claims);
    1064           0 :                                         return NT_STATUS_NO_MEMORY;
    1065             :                                 }
    1066          15 :                                 claim_values_int64 = talloc_array(claims,
    1067             :                                                                   int64_t,
    1068             :                                                                   n_values);
    1069          15 :                                 if (claim_values_int64 == NULL) {
    1070           0 :                                         talloc_free(claims);
    1071           0 :                                         return NT_STATUS_NO_MEMORY;
    1072             :                                 }
    1073             : 
    1074          36 :                                 for (k = 0; k < n_values; ++k) {
    1075          21 :                                         claim_values_int64[k] = values->values[k];
    1076          21 :                                         claim_values[k].int_value = &claim_values_int64[k];
    1077             :                                 }
    1078             : 
    1079          15 :                                 break;
    1080             :                         }
    1081          81 :                         case CLAIM_TYPE_UINT64:
    1082             :                         case CLAIM_TYPE_BOOLEAN:
    1083             :                         {
    1084          81 :                                 const struct CLAIM_UINT64 *values = &claim_entry->values.claim_uint64;
    1085           1 :                                 uint32_t k;
    1086          81 :                                 uint64_t *claim_values_uint64 = NULL;
    1087             : 
    1088          81 :                                 n_values = values->value_count;
    1089         162 :                                 value_type = (claim_entry->type == CLAIM_TYPE_UINT64)
    1090             :                                         ? CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64
    1091          81 :                                         : CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN;
    1092             : 
    1093          81 :                                 claim_values = talloc_array(claims,
    1094             :                                                             union claim_values,
    1095             :                                                             n_values);
    1096          81 :                                 if (claim_values == NULL) {
    1097           0 :                                         talloc_free(claims);
    1098           0 :                                         return NT_STATUS_NO_MEMORY;
    1099             :                                 }
    1100             : 
    1101          81 :                                 claim_values_uint64 = talloc_array(claims,
    1102             :                                                                    uint64_t,
    1103             :                                                                    n_values);
    1104          81 :                                 if (claim_values_uint64 == NULL) {
    1105           0 :                                         talloc_free(claims);
    1106           0 :                                         return NT_STATUS_NO_MEMORY;
    1107             :                                 }
    1108             : 
    1109      100175 :                                 for (k = 0; k < n_values; ++k) {
    1110      100094 :                                         claim_values_uint64[k] = values->values[k];
    1111      100094 :                                         claim_values[k].uint_value = &claim_values_uint64[k];
    1112             :                                 }
    1113             : 
    1114          80 :                                 break;
    1115             :                         }
    1116         663 :                         case CLAIM_TYPE_STRING:
    1117             :                         {
    1118         663 :                                 const struct CLAIM_STRING *values = &claim_entry->values.claim_string;
    1119          13 :                                 uint32_t k, m;
    1120         663 :                                 bool seen_empty = false;
    1121         663 :                                 n_values = values->value_count;
    1122         663 :                                 value_type = CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING;
    1123             : 
    1124         663 :                                 claim_values = talloc_array(claims,
    1125             :                                                             union claim_values,
    1126             :                                                             n_values);
    1127         663 :                                 if (claim_values == NULL) {
    1128           0 :                                         talloc_free(claims);
    1129           0 :                                         return NT_STATUS_NO_MEMORY;
    1130             :                                 }
    1131             : 
    1132         650 :                                 m = 0;
    1133        1572 :                                 for (k = 0; k < n_values; ++k) {
    1134         909 :                                         const char *string_value = NULL;
    1135             : 
    1136         909 :                                         if (values->values[k] != NULL) {
    1137         909 :                                                 string_value = talloc_strdup(claim_values, values->values[k]);
    1138         909 :                                                 if (string_value == NULL) {
    1139           0 :                                                         talloc_free(claims);
    1140           0 :                                                         return NT_STATUS_NO_MEMORY;
    1141             :                                                 }
    1142         909 :                                                 claim_values[m].string_value = string_value;
    1143         909 :                                                 m++;
    1144             :                                         } else {
    1145             :                                                 /*
    1146             :                                                  * We allow one NULL string
    1147             :                                                  * per claim, but not two,
    1148             :                                                  * because two would be a
    1149             :                                                  * duplicate, and we don't
    1150             :                                                  * want those (duplicates in
    1151             :                                                  * actual values are checked
    1152             :                                                  * later).
    1153             :                                                  */
    1154           0 :                                                 if (seen_empty) {
    1155           0 :                                                         talloc_free(claims);
    1156           0 :                                                         return NT_STATUS_INVALID_PARAMETER;
    1157             :                                                 }
    1158           0 :                                                 seen_empty = true;
    1159             :                                         }
    1160             :                                 }
    1161         650 :                                 n_values = m;
    1162         650 :                                 break;
    1163             :                         }
    1164           4 :                         default:
    1165             :                                 /*
    1166             :                                  * Other claim types are unsupported — just skip
    1167             :                                  * them.
    1168             :                                  */
    1169           4 :                                 continue;
    1170             :                         }
    1171             : 
    1172         759 :                         if (claim_entry->id != NULL) {
    1173         759 :                                 name = talloc_strdup(claims, claim_entry->id);
    1174         759 :                                 if (name == NULL) {
    1175           0 :                                         talloc_free(claims);
    1176           0 :                                         return NT_STATUS_NO_MEMORY;
    1177             :                                 }
    1178             :                         }
    1179             : 
    1180         759 :                         claims[n_claims] = (struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1) {
    1181             :                                 .name = name,
    1182             :                                 .value_type = value_type,
    1183             :                                 .flags = 0,
    1184             :                                 .value_count = n_values,
    1185             :                                 .values = claim_values,
    1186             :                         };
    1187             : 
    1188         759 :                         status = claim_v1_check_and_sort(claims, &claims[n_claims],
    1189             :                                                          false);
    1190         759 :                         if (!NT_STATUS_IS_OK(status)) {
    1191          17 :                                 talloc_free(claims);
    1192          17 :                                 DBG_WARNING("claim sort and uniqueness test failed with %s\n",
    1193             :                                             nt_errstr(status));
    1194          17 :                                 return status;
    1195             :                         }
    1196         742 :                         n_claims++;
    1197             :                 }
    1198             :         }
    1199         287 :         *out_claims = claims;
    1200         287 :         *out_n_claims = n_claims;
    1201             : 
    1202         287 :         return NT_STATUS_OK;
    1203             : }

Generated by: LCOV version 1.14