LCOV - code coverage report
Current view: top level - lib/idmap - sss_idmap.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 315 451 69.8 %
Date: 2015-10-19 Functions: 32 43 74.4 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     ID-mapping library
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2012 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <string.h>
      26             : #include <stdio.h>
      27             : #include <errno.h>
      28             : 
      29             : #include "lib/idmap/sss_idmap.h"
      30             : #include "lib/idmap/sss_idmap_private.h"
      31             : #include "util/murmurhash3.h"
      32             : 
      33             : #define SID_FMT "%s-%d"
      34             : #define SID_STR_MAX_LEN 1024
      35             : 
      36             : struct idmap_domain_info {
      37             :     char *name;
      38             :     char *sid;
      39             :     struct sss_idmap_range *range;
      40             :     struct idmap_domain_info *next;
      41             :     uint32_t first_rid;
      42             :     char *range_id;
      43             :     bool external_mapping;
      44             : };
      45             : 
      46           1 : static void *default_alloc(size_t size, void *pvt)
      47             : {
      48           1 :     return malloc(size);
      49             : }
      50             : 
      51           1 : static void default_free(void *ptr, void *pvt)
      52             : {
      53           1 :     free(ptr);
      54           1 : }
      55             : 
      56          97 : static char *idmap_strdup(struct sss_idmap_ctx *ctx, const char *str)
      57             : {
      58          97 :     char *new = NULL;
      59             :     size_t len;
      60             : 
      61          97 :     CHECK_IDMAP_CTX(ctx, NULL);
      62             : 
      63          97 :     len = strlen(str) + 1;
      64             : 
      65          97 :     new = ctx->alloc_func(len, ctx->alloc_pvt);
      66          97 :     if (new == NULL) {
      67           0 :         return NULL;
      68             :     }
      69             : 
      70          97 :     memcpy(new, str, len);
      71             : 
      72          97 :     return new;
      73             : }
      74             : 
      75          51 : static struct sss_idmap_range *idmap_range_dup(struct sss_idmap_ctx *ctx,
      76             :                                                struct sss_idmap_range *range)
      77             : {
      78          51 :     struct sss_idmap_range *new = NULL;
      79             : 
      80          51 :     CHECK_IDMAP_CTX(ctx, NULL);
      81             : 
      82             : 
      83          51 :     new = ctx->alloc_func(sizeof(struct sss_idmap_range), ctx->alloc_pvt);
      84          51 :     if (new == NULL) {
      85           0 :         return NULL;
      86             :     }
      87             : 
      88          51 :     memset(new, 0, sizeof(struct sss_idmap_range));
      89             : 
      90          51 :     new->min = range->min;
      91          51 :     new->max = range->max;
      92             : 
      93          51 :     return new;
      94             : }
      95             : 
      96          16 : static bool id_is_in_range(uint32_t id, struct idmap_domain_info *dom,
      97             :                            uint32_t *rid)
      98             : {
      99          16 :     if (id == 0 || dom == NULL || dom->range == NULL) {
     100           0 :         return false;
     101             :     }
     102             : 
     103          16 :     if (id >= dom->range->min && id <= dom->range->max) {
     104           7 :         if (rid != NULL) {
     105           7 :             *rid = dom->first_rid + (id - dom->range->min);
     106             :         }
     107             : 
     108           7 :         return true;
     109             :     }
     110             : 
     111           9 :     return false;
     112             : }
     113             : 
     114           0 : const char *idmap_error_string(enum idmap_error_code err)
     115             : {
     116           0 :     switch (err) {
     117             :         case IDMAP_SUCCESS:
     118           0 :             return "IDMAP operation successful";
     119             :             break;
     120             :         case IDMAP_NOT_IMPLEMENTED:
     121           0 :             return "IDMAP Function is not yet implemented";
     122             :             break;
     123             :         case IDMAP_ERROR:
     124           0 :             return "IDMAP general error";
     125             :             break;
     126             :         case IDMAP_OUT_OF_MEMORY:
     127           0 :             return "IDMAP operation ran out of memory";
     128             :             break;
     129             :         case IDMAP_NO_DOMAIN:
     130           0 :             return "IDMAP domain not found";
     131             :             break;
     132             :         case IDMAP_CONTEXT_INVALID:
     133           0 :             return "IDMAP context is invalid";
     134             :             break;
     135             :         case IDMAP_SID_INVALID:
     136           0 :             return "IDMAP SID is invalid";
     137             :             break;
     138             :         case IDMAP_SID_UNKNOWN:
     139           0 :             return "IDMAP SID not found";
     140             :             break;
     141             :         case IDMAP_NO_RANGE:
     142           0 :             return "IDMAP range not found";
     143             :         default:
     144           0 :             return "IDMAP unknown error code";
     145             :     }
     146             : }
     147             : 
     148          53 : bool is_domain_sid(const char *sid)
     149             : {
     150             :     const char *p;
     151             :     long long a;
     152             :     char *endptr;
     153             :     size_t c;
     154             : 
     155          53 :     if (sid == NULL || strncmp(sid, DOM_SID_PREFIX, DOM_SID_PREFIX_LEN) != 0) {
     156           4 :         return false;
     157             :     }
     158             : 
     159          49 :     p = sid + DOM_SID_PREFIX_LEN;
     160          49 :     c = 0;
     161             : 
     162             :     do {
     163         141 :         errno = 0;
     164         141 :         a = strtoull(p, &endptr, 10);
     165         141 :         if (errno != 0 || a > UINT32_MAX) {
     166           1 :             return false;
     167             :         }
     168             : 
     169         140 :         if (*endptr == '-') {
     170          93 :             p = endptr + 1;
     171          47 :         } else if (*endptr != '\0') {
     172           2 :             return false;
     173             :         }
     174         138 :         c++;
     175         138 :     } while(c < 3 && *endptr != '\0');
     176             : 
     177          46 :     if (c != 3 || *endptr != '\0') {
     178           2 :         return false;
     179             :     }
     180             : 
     181          44 :     return true;
     182             : }
     183             : 
     184          85 : enum idmap_error_code sss_idmap_init(idmap_alloc_func *alloc_func,
     185             :                                      void *alloc_pvt,
     186             :                                      idmap_free_func *free_func,
     187             :                                      struct sss_idmap_ctx **_ctx)
     188             : {
     189             :     struct sss_idmap_ctx *ctx;
     190             : 
     191          85 :     if (alloc_func == NULL) {
     192           1 :         alloc_func = default_alloc;
     193             :     }
     194             : 
     195          85 :     ctx = alloc_func(sizeof(struct sss_idmap_ctx), alloc_pvt);
     196          85 :     if (ctx == NULL) {
     197           0 :         return IDMAP_OUT_OF_MEMORY;
     198             :     }
     199          85 :     memset(ctx, 0, sizeof(struct sss_idmap_ctx));
     200             : 
     201          85 :     ctx->alloc_func = alloc_func;
     202          85 :     ctx->alloc_pvt = alloc_pvt;
     203          85 :     ctx->free_func = (free_func == NULL) ? default_free : free_func;
     204             : 
     205             :     /* Set default values. */
     206          85 :     ctx->idmap_opts.autorid_mode = SSS_IDMAP_DEFAULT_AUTORID;
     207          85 :     ctx->idmap_opts.idmap_lower = SSS_IDMAP_DEFAULT_LOWER;
     208          85 :     ctx->idmap_opts.idmap_upper = SSS_IDMAP_DEFAULT_UPPER;
     209          85 :     ctx->idmap_opts.rangesize = SSS_IDMAP_DEFAULT_RANGESIZE;
     210             : 
     211          85 :     *_ctx = ctx;
     212             : 
     213          85 :     return IDMAP_SUCCESS;
     214             : }
     215             : 
     216          24 : static void sss_idmap_free_domain(struct sss_idmap_ctx *ctx,
     217             :                                   struct idmap_domain_info *dom)
     218             : {
     219          24 :     if (ctx == NULL || dom == NULL) {
     220           0 :         return;
     221             :     }
     222             : 
     223          24 :     ctx->free_func(dom->range_id, ctx->alloc_pvt);
     224          24 :     ctx->free_func(dom->range, ctx->alloc_pvt);
     225          24 :     ctx->free_func(dom->name, ctx->alloc_pvt);
     226          24 :     ctx->free_func(dom->sid, ctx->alloc_pvt);
     227          24 :     ctx->free_func(dom, ctx->alloc_pvt);
     228             : }
     229             : 
     230          21 : enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx)
     231             : {
     232             :     struct idmap_domain_info *dom;
     233             :     struct idmap_domain_info *next;
     234             : 
     235          21 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     236             : 
     237          21 :     next = ctx->idmap_domain_info;
     238          53 :     while (next) {
     239          11 :         dom = next;
     240          11 :         next = dom->next;
     241          11 :         sss_idmap_free_domain(ctx, dom);
     242             :     }
     243             : 
     244          21 :     ctx->free_func(ctx, ctx->alloc_pvt);
     245             : 
     246          21 :     return IDMAP_SUCCESS;
     247             : }
     248             : 
     249          36 : static enum idmap_error_code sss_idmap_free_ptr(struct sss_idmap_ctx *ctx,
     250             :                                                 void *ptr)
     251             : {
     252          36 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     253             : 
     254          36 :     if (ptr != NULL) {
     255          36 :         ctx->free_func(ptr, ctx->alloc_pvt);
     256             :     }
     257             : 
     258          36 :     return IDMAP_SUCCESS;
     259             : }
     260             : 
     261           9 : enum idmap_error_code sss_idmap_free_sid(struct sss_idmap_ctx *ctx,
     262             :                                          char *sid)
     263             : {
     264           9 :     return sss_idmap_free_ptr(ctx, sid);
     265             : }
     266             : 
     267           6 : enum idmap_error_code sss_idmap_free_dom_sid(struct sss_idmap_ctx *ctx,
     268             :                                              struct sss_dom_sid *dom_sid)
     269             : {
     270           6 :     return sss_idmap_free_ptr(ctx, dom_sid);
     271             : }
     272             : 
     273           8 : enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx,
     274             :                                              struct dom_sid *smb_sid)
     275             : {
     276           8 :     return sss_idmap_free_ptr(ctx, smb_sid);
     277             : }
     278             : 
     279          13 : enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx,
     280             :                                              uint8_t *bin_sid)
     281             : {
     282          13 :     return sss_idmap_free_ptr(ctx, bin_sid);
     283             : }
     284             : 
     285           0 : enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx,
     286             :                                                 const char *dom_sid,
     287             :                                                 id_t *slice_num,
     288             :                                                 struct sss_idmap_range *_range)
     289             : {
     290             :     id_t max_slices;
     291             :     id_t orig_slice;
     292           0 :     id_t new_slice = 0;
     293             :     id_t min;
     294             :     id_t max;
     295             :     id_t idmap_lower;
     296             :     id_t idmap_upper;
     297             :     id_t rangesize;
     298             :     bool autorid_mode;
     299             :     uint32_t hash_val;
     300             :     struct idmap_domain_info *dom;
     301             : 
     302           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     303             : 
     304           0 :     idmap_lower = ctx->idmap_opts.idmap_lower;
     305           0 :     idmap_upper = ctx->idmap_opts.idmap_upper;
     306           0 :     rangesize = ctx->idmap_opts.rangesize;
     307           0 :     autorid_mode = ctx->idmap_opts.autorid_mode;
     308             : 
     309           0 :     max_slices = (idmap_upper - idmap_lower) / rangesize;
     310             : 
     311           0 :     if (slice_num && *slice_num != -1) {
     312             :         /* The slice is being set explicitly.
     313             :          * This may happen at system startup when we're loading
     314             :          * previously-determined slices. In the future, we may also
     315             :          * permit configuration to select the slice for a domain
     316             :          * explicitly.
     317             :          */
     318           0 :         new_slice = *slice_num;
     319             :     } else {
     320             :         /* If slice is -1, we're being asked to pick a new slice */
     321             : 
     322           0 :         if (autorid_mode) {
     323             :             /* In autorid compatibility mode, always start at 0 and find the
     324             :              * first free value.
     325             :              */
     326           0 :             orig_slice = 0;
     327             :         } else {
     328             :             /* Hash the domain sid string */
     329           0 :             hash_val = murmurhash3(dom_sid, strlen(dom_sid), 0xdeadbeef);
     330             : 
     331             :             /* Now get take the modulus of the hash val and the max_slices
     332             :              * to determine its optimal position in the range.
     333             :              */
     334           0 :             new_slice = hash_val % max_slices;
     335           0 :             orig_slice = new_slice;
     336             :         }
     337             : 
     338           0 :         min = (rangesize * new_slice) + idmap_lower;
     339           0 :         max = min + rangesize;
     340             :         /* Verify that this slice is not already in use */
     341             :         do {
     342           0 :             for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) {
     343           0 :                 if ((dom->range->min <= min && dom->range->max >= max) ||
     344           0 :                     (dom->range->min >= min && dom->range->min <= max) ||
     345           0 :                     (dom->range->max >= min && dom->range->max <= max)) {
     346             :                     /* This range overlaps one already registered
     347             :                      * We'll try the next available slot
     348             :                      */
     349           0 :                     new_slice++;
     350           0 :                     if (new_slice >= max_slices) {
     351             :                         /* loop around to the beginning if necessary */
     352           0 :                         new_slice = 0;
     353             :                     }
     354             : 
     355           0 :                     min = (rangesize * new_slice) + idmap_lower;
     356           0 :                     max = min + rangesize;
     357           0 :                     break;
     358             :                 }
     359             :             }
     360             : 
     361             :             /* Keep trying until dom is NULL (meaning we got to the end
     362             :              * without matching) or we have run out of slices and gotten
     363             :              * back to the first one we tried.
     364             :              */
     365           0 :         } while (dom && new_slice != orig_slice);
     366             : 
     367           0 :         if (dom) {
     368             :             /* We looped all the way through and found no empty slots */
     369           0 :             return IDMAP_OUT_OF_SLICES;
     370             :         }
     371             :     }
     372             : 
     373           0 :     _range->min = (rangesize * new_slice) + idmap_lower;
     374           0 :     _range->max = _range->min + rangesize;
     375             : 
     376           0 :     if (slice_num) {
     377           0 :         *slice_num = new_slice;
     378             :     }
     379             : 
     380           0 :     return IDMAP_SUCCESS;
     381             : }
     382             : 
     383          43 : enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name,
     384             :                                                 const char *o_sid,
     385             :                                                 struct sss_idmap_range *o_range,
     386             :                                                 uint32_t o_first_rid,
     387             :                                                 const char *o_range_id,
     388             :                                                 bool o_external_mapping,
     389             :                                                 const char *n_name,
     390             :                                                 const char *n_sid,
     391             :                                                 struct sss_idmap_range *n_range,
     392             :                                                 uint32_t n_first_rid,
     393             :                                                 const char *n_range_id,
     394             :                                                 bool n_external_mapping)
     395             : {
     396             :     bool names_equal;
     397             :     bool sids_equal;
     398             : 
     399             :     /* TODO: if both ranges have the same ID check if an update is
     400             :      * needed. */
     401             : 
     402             :     /* Check if ID ranges overlap.
     403             :      * ID ranges with external mapping may overlap. */
     404          43 :     if ((!n_external_mapping && !o_external_mapping)
     405          19 :         && ((n_range->min >= o_range->min
     406          19 :                 && n_range->min <= o_range->max)
     407          13 :             || (n_range->max >= o_range->min
     408          13 :                 && n_range->max <= o_range->max))) {
     409           6 :         return IDMAP_COLLISION;
     410             :     }
     411             : 
     412          37 :     names_equal = (strcasecmp(n_name, o_name) == 0);
     413          39 :     sids_equal = ((n_sid == NULL && o_sid == NULL)
     414          92 :                     || (n_sid != NULL && o_sid != NULL
     415          35 :                         && strcasecmp(n_sid, o_sid) == 0));
     416             : 
     417             :     /* check if domain name and SID are consistent */
     418          37 :     if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) {
     419           8 :         return IDMAP_COLLISION;
     420             :     }
     421             : 
     422             :     /* check if external_mapping is consistent */
     423          29 :     if (names_equal && sids_equal
     424          14 :             && n_external_mapping != o_external_mapping) {
     425           2 :         return IDMAP_COLLISION;
     426             :     }
     427             : 
     428             :     /* check if RID ranges overlap */
     429          27 :     if (names_equal && sids_equal
     430          12 :             && n_external_mapping == false
     431           7 :             && n_first_rid >= o_first_rid
     432           7 :             && n_first_rid <= o_first_rid + (o_range->max - o_range->min)) {
     433           2 :         return IDMAP_COLLISION;
     434             :     }
     435             : 
     436          25 :     return IDMAP_SUCCESS;
     437             : }
     438             : 
     439           0 : enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx,
     440             :                                                 char *n_name, char *n_sid,
     441             :                                                 struct sss_idmap_range *n_range,
     442             :                                                 uint32_t n_first_rid,
     443             :                                                 char *n_range_id,
     444             :                                                 bool n_external_mapping)
     445             : {
     446             :     struct idmap_domain_info *dom;
     447             :     enum idmap_error_code err;
     448             : 
     449           0 :     for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) {
     450           0 :         err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range,
     451           0 :                                            dom->first_rid, dom->range_id,
     452           0 :                                            dom->external_mapping,
     453             :                                            n_name, n_sid, n_range, n_first_rid,
     454             :                                            n_range_id, n_external_mapping);
     455           0 :         if (err != IDMAP_SUCCESS) {
     456           0 :             return err;
     457             :         }
     458             :     }
     459           0 :     return IDMAP_SUCCESS;
     460             : }
     461             : 
     462          51 : static enum idmap_error_code dom_check_collision(
     463             :                                              struct idmap_domain_info *dom_list,
     464             :                                              struct idmap_domain_info *new_dom)
     465             : {
     466             :     struct idmap_domain_info *dom;
     467             :     enum idmap_error_code err;
     468             : 
     469          72 :     for (dom = dom_list; dom != NULL; dom = dom->next) {
     470         136 :         err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range,
     471          34 :                                            dom->first_rid, dom->range_id,
     472          34 :                                            dom->external_mapping,
     473          34 :                                            new_dom->name, new_dom->sid,
     474             :                                            new_dom->range, new_dom->first_rid,
     475          34 :                                            new_dom->range_id,
     476          34 :                                            new_dom->external_mapping);
     477          34 :         if (err != IDMAP_SUCCESS) {
     478          13 :             return err;
     479             :         }
     480             :     }
     481          38 :     return IDMAP_SUCCESS;
     482             : }
     483             : 
     484          52 : enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx,
     485             :                                               const char *domain_name,
     486             :                                               const char *domain_sid,
     487             :                                               struct sss_idmap_range *range,
     488             :                                               const char *range_id,
     489             :                                               uint32_t rid,
     490             :                                               bool external_mapping)
     491             : {
     492          52 :     struct idmap_domain_info *dom = NULL;
     493             :     enum idmap_error_code err;
     494             : 
     495          52 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     496             : 
     497          52 :     if (domain_name == NULL) {
     498           0 :         return IDMAP_NO_DOMAIN;
     499             :     }
     500             : 
     501          52 :     if (range == NULL) {
     502           0 :         return IDMAP_NO_RANGE;
     503             :     }
     504             : 
     505             :     /* For algorithmic mapping a valid domain SID is required, for external
     506             :      * mapping it may be NULL, but if set it should be valid. */
     507          52 :     if ((!external_mapping && !is_domain_sid(domain_sid))
     508          51 :             || (external_mapping
     509          21 :                 && domain_sid != NULL
     510          13 :                 && !is_domain_sid(domain_sid))) {
     511           1 :         return IDMAP_SID_INVALID;
     512             :     }
     513             : 
     514          51 :     dom = ctx->alloc_func(sizeof(struct idmap_domain_info), ctx->alloc_pvt);
     515          51 :     if (dom == NULL) {
     516           0 :         return IDMAP_OUT_OF_MEMORY;
     517             :     }
     518          51 :     memset(dom, 0, sizeof(struct idmap_domain_info));
     519             : 
     520          51 :     dom->name = idmap_strdup(ctx, domain_name);
     521          51 :     if (dom->name == NULL) {
     522           0 :         err = IDMAP_OUT_OF_MEMORY;
     523           0 :         goto fail;
     524             :     }
     525             : 
     526          51 :     if (domain_sid != NULL) {
     527          43 :         dom->sid = idmap_strdup(ctx, domain_sid);
     528          43 :         if (dom->sid == NULL) {
     529           0 :             err = IDMAP_OUT_OF_MEMORY;
     530           0 :             goto fail;
     531             :         }
     532             :     }
     533             : 
     534          51 :     dom->range = idmap_range_dup(ctx, range);
     535          51 :     if (dom->range == NULL) {
     536           0 :         err = IDMAP_OUT_OF_MEMORY;
     537           0 :         goto fail;
     538             :     }
     539             : 
     540          51 :     if (range_id != NULL) {
     541           3 :         dom->range_id = idmap_strdup(ctx, range_id);
     542           3 :         if (dom->range_id == NULL) {
     543           0 :             err = IDMAP_OUT_OF_MEMORY;
     544           0 :             goto fail;
     545             :         }
     546             :     }
     547             : 
     548          51 :     dom->first_rid = rid;
     549          51 :     dom->external_mapping = external_mapping;
     550             : 
     551          51 :     err = dom_check_collision(ctx->idmap_domain_info, dom);
     552          51 :     if (err != IDMAP_SUCCESS) {
     553          13 :         goto fail;
     554             :     }
     555             : 
     556          38 :     dom->next = ctx->idmap_domain_info;
     557          38 :     ctx->idmap_domain_info = dom;
     558             : 
     559          38 :     return IDMAP_SUCCESS;
     560             : 
     561             : fail:
     562          13 :     sss_idmap_free_domain(ctx, dom);
     563             : 
     564          13 :     return err;
     565             : }
     566             : 
     567          14 : enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
     568             :                                            const char *domain_name,
     569             :                                            const char *domain_sid,
     570             :                                            struct sss_idmap_range *range)
     571             : {
     572          14 :     return sss_idmap_add_domain_ex(ctx, domain_name, domain_sid, range, NULL,
     573             :                                    0, false);
     574             : }
     575             : 
     576          23 : static bool sss_idmap_sid_is_builtin(const char *sid)
     577             : {
     578          23 :     if (strncmp(sid, "S-1-5-32-", 9) == 0) {
     579           0 :         return true;
     580             :     }
     581             : 
     582          23 :     return false;
     583             : }
     584             : 
     585          13 : enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx,
     586             :                                             const char *sid,
     587             :                                             uint32_t *_id)
     588             : {
     589             :     struct idmap_domain_info *idmap_domain_info;
     590             :     size_t dom_len;
     591             :     long long rid;
     592             :     char *endptr;
     593             :     uint32_t id;
     594          13 :     bool no_range = false;
     595             : 
     596          13 :     if (sid == NULL || _id == NULL) {
     597           0 :         return IDMAP_ERROR;
     598             :     }
     599             : 
     600          13 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     601             : 
     602          13 :     idmap_domain_info = ctx->idmap_domain_info;
     603             : 
     604          13 :     if (sss_idmap_sid_is_builtin(sid)) {
     605           0 :         return IDMAP_BUILTIN_SID;
     606             :     }
     607             : 
     608          35 :     while (idmap_domain_info != NULL) {
     609          17 :         if (idmap_domain_info->sid != NULL) {
     610          17 :             dom_len = strlen(idmap_domain_info->sid);
     611          17 :             if (strlen(sid) > dom_len && sid[dom_len] == '-'
     612          12 :                     && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) {
     613             : 
     614          12 :                 if (idmap_domain_info->external_mapping == true) {
     615           3 :                     return IDMAP_EXTERNAL;
     616             :                 }
     617             : 
     618           9 :                 errno = 0;
     619           9 :                 rid = strtoull(sid + dom_len + 1, &endptr, 10);
     620           9 :                 if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') {
     621           0 :                     return IDMAP_SID_INVALID;
     622             :                 }
     623             : 
     624           9 :                 if (rid >= idmap_domain_info->first_rid) {
     625          14 :                     id = idmap_domain_info->range->min
     626           7 :                             + (rid - idmap_domain_info->first_rid);
     627           7 :                     if (id <= idmap_domain_info->range->max) {
     628           5 :                         *_id = id;
     629           5 :                         return IDMAP_SUCCESS;
     630             :                     }
     631             :                 }
     632             : 
     633           4 :                 no_range = true;
     634             :             }
     635             :         }
     636             : 
     637           9 :         idmap_domain_info = idmap_domain_info->next;
     638             :     }
     639             : 
     640           5 :     return no_range ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN;
     641             : }
     642             : 
     643          10 : enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx,
     644             :                                                const char *sid,
     645             :                                                uint32_t id)
     646             : {
     647             :     struct idmap_domain_info *idmap_domain_info;
     648             :     size_t dom_len;
     649          10 :     bool no_range = false;
     650             : 
     651          10 :     if (sid == NULL) {
     652           0 :         return IDMAP_ERROR;
     653             :     }
     654             : 
     655          10 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     656             : 
     657          10 :     if (ctx->idmap_domain_info == NULL) {
     658           0 :         return IDMAP_NO_DOMAIN;
     659             :     }
     660             : 
     661          10 :     idmap_domain_info = ctx->idmap_domain_info;
     662             : 
     663          10 :     if (sss_idmap_sid_is_builtin(sid)) {
     664           0 :         return IDMAP_BUILTIN_SID;
     665             :     }
     666             : 
     667          34 :     while (idmap_domain_info != NULL) {
     668          18 :         if (idmap_domain_info->sid != NULL) {
     669          18 :             dom_len = strlen(idmap_domain_info->sid);
     670          18 :             if (strlen(sid) > dom_len && sid[dom_len] == '-'
     671          14 :                     && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) {
     672             : 
     673          14 :                 if (id >= idmap_domain_info->range->min
     674           8 :                     && id <= idmap_domain_info->range->max) {
     675           4 :                     return IDMAP_SUCCESS;
     676             :                 }
     677             : 
     678          10 :                 no_range = true;
     679             :             }
     680             :         }
     681             : 
     682          14 :         idmap_domain_info = idmap_domain_info->next;
     683             :     }
     684             : 
     685           6 :     return no_range ? IDMAP_NO_RANGE : IDMAP_SID_UNKNOWN;
     686             : }
     687             : 
     688          12 : enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx,
     689             :                                             uint32_t id,
     690             :                                             char **_sid)
     691             : {
     692             :     struct idmap_domain_info *idmap_domain_info;
     693             :     int len;
     694             :     int ret;
     695             :     uint32_t rid;
     696          12 :     char *sid = NULL;
     697             : 
     698          12 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     699             : 
     700          12 :     idmap_domain_info = ctx->idmap_domain_info;
     701             : 
     702          33 :     while (idmap_domain_info != NULL) {
     703          16 :         if (id_is_in_range(id, idmap_domain_info, &rid)) {
     704             : 
     705           7 :             if (idmap_domain_info->external_mapping == true
     706           5 :                     || idmap_domain_info->sid == NULL) {
     707           2 :                 return IDMAP_EXTERNAL;
     708             :             }
     709             : 
     710           5 :             len = snprintf(NULL, 0, SID_FMT, idmap_domain_info->sid, rid);
     711           5 :             if (len <= 0 || len > SID_STR_MAX_LEN) {
     712           0 :                 return IDMAP_ERROR;
     713             :             }
     714             : 
     715           5 :             sid = ctx->alloc_func(len + 1, ctx->alloc_pvt);
     716           5 :             if (sid == NULL) {
     717           0 :                 return IDMAP_OUT_OF_MEMORY;
     718             :             }
     719             : 
     720           5 :             ret = snprintf(sid, len + 1, SID_FMT, idmap_domain_info->sid, rid);
     721           5 :             if (ret != len) {
     722           0 :                 ctx->free_func(sid, ctx->alloc_pvt);
     723           0 :                 return IDMAP_ERROR;
     724             :             }
     725             : 
     726           5 :             *_sid = sid;
     727           5 :             return IDMAP_SUCCESS;
     728             :         }
     729             : 
     730           9 :         idmap_domain_info = idmap_domain_info->next;
     731             :     }
     732             : 
     733           5 :     return IDMAP_NO_DOMAIN;
     734             : }
     735             : 
     736           1 : enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx,
     737             :                                                 struct sss_dom_sid *dom_sid,
     738             :                                                 uint32_t *id)
     739             : {
     740             :     enum idmap_error_code err;
     741             :     char *sid;
     742             : 
     743           1 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     744             : 
     745           1 :     err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid);
     746           1 :     if (err != IDMAP_SUCCESS) {
     747           0 :         goto done;
     748             :     }
     749             : 
     750           1 :     err = sss_idmap_sid_to_unix(ctx, sid, id);
     751             : 
     752             : done:
     753           1 :     ctx->free_func(sid, ctx->alloc_pvt);
     754             : 
     755           1 :     return err;
     756             : }
     757             : 
     758           1 : enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx,
     759             :                                                 uint8_t *bin_sid,
     760             :                                                 size_t length,
     761             :                                                 uint32_t *id)
     762             : {
     763             :     enum idmap_error_code err;
     764             :     char *sid;
     765             : 
     766           1 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     767             : 
     768           1 :     err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid);
     769           1 :     if (err != IDMAP_SUCCESS) {
     770           0 :         goto done;
     771             :     }
     772             : 
     773           1 :     err = sss_idmap_sid_to_unix(ctx, sid, id);
     774             : 
     775             : done:
     776           1 :     ctx->free_func(sid, ctx->alloc_pvt);
     777             : 
     778           1 :     return err;
     779             : }
     780             : 
     781           0 : enum idmap_error_code sss_idmap_smb_sid_to_unix(struct sss_idmap_ctx *ctx,
     782             :                                                 struct dom_sid *smb_sid,
     783             :                                                 uint32_t *id)
     784             : {
     785             :     enum idmap_error_code err;
     786             :     char *sid;
     787             : 
     788           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     789             : 
     790           0 :     err = sss_idmap_smb_sid_to_sid(ctx, smb_sid, &sid);
     791           0 :     if (err != IDMAP_SUCCESS) {
     792           0 :         goto done;
     793             :     }
     794             : 
     795           0 :     err = sss_idmap_sid_to_unix(ctx, sid, id);
     796             : 
     797             : done:
     798           0 :     ctx->free_func(sid, ctx->alloc_pvt);
     799             : 
     800           0 :     return err;
     801             : }
     802             : 
     803           0 : enum idmap_error_code sss_idmap_check_dom_sid_to_unix(struct sss_idmap_ctx *ctx,
     804             :                                                     struct sss_dom_sid *dom_sid,
     805             :                                                     uint32_t id)
     806             : {
     807             :     enum idmap_error_code err;
     808             :     char *sid;
     809             : 
     810           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     811             : 
     812           0 :     err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid);
     813           0 :     if (err != IDMAP_SUCCESS) {
     814           0 :         goto done;
     815             :     }
     816             : 
     817           0 :     err = sss_idmap_check_sid_unix(ctx, sid, id);
     818             : 
     819             : done:
     820           0 :     ctx->free_func(sid, ctx->alloc_pvt);
     821             : 
     822           0 :     return err;
     823             : }
     824             : 
     825           0 : enum idmap_error_code sss_idmap_check_bin_sid_unix(struct sss_idmap_ctx *ctx,
     826             :                                                    uint8_t *bin_sid,
     827             :                                                    size_t length,
     828             :                                                    uint32_t id)
     829             : {
     830             :     enum idmap_error_code err;
     831             :     char *sid;
     832             : 
     833           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     834             : 
     835           0 :     err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid);
     836           0 :     if (err != IDMAP_SUCCESS) {
     837           0 :         goto done;
     838             :     }
     839             : 
     840           0 :     err = sss_idmap_check_sid_unix(ctx, sid, id);
     841             : 
     842             : done:
     843           0 :     ctx->free_func(sid, ctx->alloc_pvt);
     844             : 
     845           0 :     return err;
     846             : }
     847             : 
     848           0 : enum idmap_error_code sss_idmap_check_smb_sid_unix(struct sss_idmap_ctx *ctx,
     849             :                                                    struct dom_sid *smb_sid,
     850             :                                                    uint32_t id)
     851             : {
     852             :     enum idmap_error_code err;
     853             :     char *sid;
     854             : 
     855           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     856             : 
     857           0 :     err = sss_idmap_smb_sid_to_sid(ctx, smb_sid, &sid);
     858           0 :     if (err != IDMAP_SUCCESS) {
     859           0 :         goto done;
     860             :     }
     861             : 
     862           0 :     err = sss_idmap_check_sid_unix(ctx, sid, id);
     863             : 
     864             : done:
     865           0 :     ctx->free_func(sid, ctx->alloc_pvt);
     866             : 
     867           0 :     return err;
     868             : }
     869           2 : enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx,
     870             :                                                 uint32_t id,
     871             :                                                 struct sss_dom_sid **_dom_sid)
     872             : {
     873             :     enum idmap_error_code err;
     874           2 :     char *sid = NULL;
     875           2 :     struct sss_dom_sid *dom_sid = NULL;
     876             : 
     877           2 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     878             : 
     879           2 :     err = sss_idmap_unix_to_sid(ctx, id, &sid);
     880           2 :     if (err != IDMAP_SUCCESS) {
     881           1 :         goto done;
     882             :     }
     883             : 
     884           1 :     err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid);
     885           1 :     if (err != IDMAP_SUCCESS) {
     886           0 :         goto done;
     887             :     }
     888             : 
     889           1 :     *_dom_sid = dom_sid;
     890           1 :     err = IDMAP_SUCCESS;
     891             : 
     892             : done:
     893           2 :     ctx->free_func(sid, ctx->alloc_pvt);
     894           2 :     if (err != IDMAP_SUCCESS) {
     895           1 :         ctx->free_func(dom_sid, ctx->alloc_pvt);
     896             :     }
     897             : 
     898           2 :     return err;
     899             : }
     900             : 
     901           2 : enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx,
     902             :                                                 uint32_t id,
     903             :                                                 uint8_t **_bin_sid,
     904             :                                                 size_t *_length)
     905             : {
     906             :     enum idmap_error_code err;
     907           2 :     char *sid = NULL;
     908           2 :     uint8_t *bin_sid = NULL;
     909             :     size_t length;
     910             : 
     911           2 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     912             : 
     913           2 :     err = sss_idmap_unix_to_sid(ctx, id, &sid);
     914           2 :     if (err != IDMAP_SUCCESS) {
     915           1 :         goto done;
     916             :     }
     917             : 
     918           1 :     err = sss_idmap_sid_to_bin_sid(ctx, sid, &bin_sid, &length);
     919           1 :     if (err != IDMAP_SUCCESS) {
     920           0 :         goto done;
     921             :     }
     922             : 
     923           1 :     *_bin_sid = bin_sid;
     924           1 :     *_length = length;
     925           1 :     err = IDMAP_SUCCESS;
     926             : 
     927             : done:
     928           2 :     ctx->free_func(sid, ctx->alloc_pvt);
     929           2 :     if (err != IDMAP_SUCCESS) {
     930           1 :         ctx->free_func(bin_sid, ctx->alloc_pvt);
     931             :     }
     932             : 
     933           2 :     return err;
     934             : 
     935             : }
     936             : 
     937             : enum idmap_error_code
     938           7 : sss_idmap_ctx_set_autorid(struct sss_idmap_ctx *ctx, bool use_autorid)
     939             : {
     940           7 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     941           7 :     ctx->idmap_opts.autorid_mode = use_autorid;
     942           7 :     return IDMAP_SUCCESS;
     943             : }
     944             : 
     945             : enum idmap_error_code
     946           7 : sss_idmap_ctx_set_lower(struct sss_idmap_ctx *ctx, id_t lower)
     947             : {
     948           7 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     949           7 :     ctx->idmap_opts.idmap_lower = lower;
     950           7 :     return IDMAP_SUCCESS;
     951             : }
     952             : 
     953             : enum idmap_error_code
     954           7 : sss_idmap_ctx_set_upper(struct sss_idmap_ctx *ctx, id_t upper)
     955             : {
     956           7 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     957           7 :     ctx->idmap_opts.idmap_upper = upper;
     958           7 :     return IDMAP_SUCCESS;
     959             : }
     960             : 
     961             : enum idmap_error_code
     962           7 : sss_idmap_ctx_set_rangesize(struct sss_idmap_ctx *ctx, id_t rangesize)
     963             : {
     964           7 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     965           7 :     ctx->idmap_opts.rangesize = rangesize;
     966           7 :     return IDMAP_SUCCESS;
     967             : }
     968             : 
     969             : enum idmap_error_code
     970           0 : sss_idmap_ctx_get_autorid(struct sss_idmap_ctx *ctx, bool *_autorid)
     971             : {
     972           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     973           0 :      *_autorid = ctx->idmap_opts.autorid_mode;
     974           0 :      return IDMAP_SUCCESS;
     975             : }
     976             : 
     977             : enum idmap_error_code
     978           0 : sss_idmap_ctx_get_lower(struct sss_idmap_ctx *ctx, id_t *_lower)
     979             : {
     980           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     981           0 :     *_lower = ctx->idmap_opts.idmap_lower;
     982           0 :     return IDMAP_SUCCESS;
     983             : }
     984             : 
     985             : enum idmap_error_code
     986           0 : sss_idmap_ctx_get_upper(struct sss_idmap_ctx *ctx, id_t *_upper)
     987             : {
     988           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     989           0 :     *_upper = ctx->idmap_opts.idmap_upper;
     990           0 :     return IDMAP_SUCCESS;
     991             : }
     992             : 
     993             : enum idmap_error_code
     994           0 : sss_idmap_ctx_get_rangesize(struct sss_idmap_ctx *ctx, id_t *_rangesize)
     995             : {
     996           0 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
     997           0 :     *_rangesize =  ctx->idmap_opts.rangesize;
     998           0 :     return IDMAP_SUCCESS;
     999             : }
    1000             : 
    1001             : enum idmap_error_code
    1002          22 : sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
    1003             :                                          const char *dom_sid,
    1004             :                                          bool *has_algorithmic_mapping)
    1005             : {
    1006             :     struct idmap_domain_info *idmap_domain_info;
    1007             :     size_t len;
    1008             :     size_t dom_sid_len;
    1009             : 
    1010          22 :     if (dom_sid == NULL) {
    1011          17 :         return IDMAP_SID_INVALID;
    1012             :     }
    1013             : 
    1014           5 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
    1015             : 
    1016           4 :     if (ctx->idmap_domain_info == NULL) {
    1017           0 :         return IDMAP_NO_DOMAIN;
    1018             :     }
    1019             : 
    1020           4 :     idmap_domain_info = ctx->idmap_domain_info;
    1021             : 
    1022          14 :     while (idmap_domain_info != NULL) {
    1023           9 :         if (idmap_domain_info->sid != NULL) {
    1024           9 :             len = strlen(idmap_domain_info->sid);
    1025           9 :             dom_sid_len = strlen(dom_sid);
    1026           9 :             if (((dom_sid_len > len && dom_sid[len] == '-')
    1027           9 :                         || dom_sid_len == len)
    1028           5 :                     && strncmp(dom_sid, idmap_domain_info->sid, len) == 0) {
    1029             : 
    1030           3 :                 *has_algorithmic_mapping = !idmap_domain_info->external_mapping;
    1031           3 :                 return IDMAP_SUCCESS;
    1032             : 
    1033             :             }
    1034             :         }
    1035             : 
    1036           6 :         idmap_domain_info = idmap_domain_info->next;
    1037             :     }
    1038             : 
    1039           1 :     return IDMAP_SID_UNKNOWN;
    1040             : }
    1041             : 
    1042             : enum idmap_error_code
    1043          21 : sss_idmap_domain_by_name_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
    1044             :                                                  const char *dom_name,
    1045             :                                                  bool *has_algorithmic_mapping)
    1046             : {
    1047             :     struct idmap_domain_info *idmap_domain_info;
    1048             : 
    1049          21 :     if (dom_name == NULL) {
    1050           2 :         return IDMAP_ERROR;
    1051             :     }
    1052             : 
    1053          19 :     CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
    1054             : 
    1055          18 :     if (ctx->idmap_domain_info == NULL) {
    1056           0 :         return IDMAP_NO_DOMAIN;
    1057             :     }
    1058             : 
    1059          18 :     idmap_domain_info = ctx->idmap_domain_info;
    1060             : 
    1061          42 :     while (idmap_domain_info != NULL) {
    1062          23 :         if (idmap_domain_info->name != NULL
    1063          23 :                 && strcmp(dom_name, idmap_domain_info->name) == 0) {
    1064             : 
    1065          17 :             *has_algorithmic_mapping = !idmap_domain_info->external_mapping;
    1066          17 :             return IDMAP_SUCCESS;
    1067             :         }
    1068             : 
    1069           6 :         idmap_domain_info = idmap_domain_info->next;
    1070             :     }
    1071             : 
    1072           1 :     return IDMAP_NAME_UNKNOWN;
    1073             : }

Generated by: LCOV version 1.10