LCOV - code coverage report
Current view: top level - source3/lib - namemap_cache.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 104 147 70.7 %
Date: 2021-09-23 10:06:22 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * Utils for caching sid2name and name2sid
       4             :  * Copyright (C) Volker Lendecke 2017
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "replace.h"
      21             : #include "namemap_cache.h"
      22             : #include "source3/lib/gencache.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/strv.h"
      25             : #include "lib/util/util.h"
      26             : #include "lib/util/talloc_stack.h"
      27             : #include "lib/util/charset/charset.h"
      28             : #include "libcli/security/dom_sid.h"
      29             : #include "lib/util/smb_strtox.h"
      30             : 
      31           3 : bool namemap_cache_set_sid2name(const struct dom_sid *sid,
      32             :                                 const char *domain, const char *name,
      33             :                                 enum lsa_SidType type, time_t timeout)
      34             : {
      35             :         char typebuf[16];
      36             :         struct dom_sid_buf sidbuf;
      37             :         char keybuf[sizeof(sidbuf.buf)+10];
      38           3 :         char *val = NULL;
      39             :         DATA_BLOB data;
      40             :         int ret;
      41           3 :         bool ok = false;
      42             : 
      43           3 :         if ((sid == NULL) || is_null_sid(sid)) {
      44           0 :                 return true;
      45             :         }
      46           3 :         if (domain == NULL) {
      47           0 :                 domain = "";
      48             :         }
      49           3 :         if (name == NULL) {
      50           0 :                 name = "";
      51             :         }
      52           3 :         if (type == SID_NAME_UNKNOWN) {
      53           0 :                 domain = "";
      54           0 :                 name = "";
      55             :         }
      56             : 
      57           6 :         snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
      58             : 
      59           3 :         ret = strv_add(talloc_tos(), &val, domain);
      60           3 :         if (ret != 0) {
      61           0 :                 DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
      62           0 :                 goto fail;
      63             :         }
      64           3 :         ret = strv_add(NULL, &val, name);
      65           3 :         if (ret != 0) {
      66           0 :                 DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
      67           0 :                 goto fail;
      68             :         }
      69           3 :         ret = strv_add(NULL, &val, typebuf);
      70           3 :         if (ret != 0) {
      71           0 :                 DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
      72           0 :                 goto fail;
      73             :         }
      74             : 
      75           3 :         dom_sid_str_buf(sid, &sidbuf);
      76           3 :         snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
      77             : 
      78           3 :         data = data_blob_const(val, talloc_get_size(val));
      79             : 
      80           3 :         ok = gencache_set_data_blob(keybuf, data, timeout);
      81           3 :         if (!ok) {
      82           0 :                 DBG_DEBUG("gencache_set_data_blob failed\n");
      83             :         }
      84           6 : fail:
      85           3 :         TALLOC_FREE(val);
      86           0 :         return ok;
      87             : }
      88             : 
      89             : struct namemap_cache_find_sid_state {
      90             :         void (*fn)(const char *domain,
      91             :                    const char *name,
      92             :                    enum lsa_SidType type,
      93             :                    bool expired,
      94             :                    void *private_data);
      95             :         void *private_data;
      96             :         bool ok;
      97             : };
      98             : 
      99           4 : static void namemap_cache_find_sid_parser(
     100             :         const struct gencache_timeout *timeout,
     101             :         DATA_BLOB blob,
     102             :         void *private_data)
     103             : {
     104           4 :         struct namemap_cache_find_sid_state *state = private_data;
     105           4 :         const char *strv = (const char *)blob.data;
     106           4 :         size_t strv_len = blob.length;
     107             :         const char *domain;
     108             :         const char *name;
     109             :         const char *typebuf;
     110           4 :         int error = 0;
     111             :         unsigned long type;
     112             : 
     113           4 :         state->ok = false;
     114             : 
     115           4 :         domain = strv_len_next(strv, strv_len, NULL);
     116           4 :         if (domain == NULL) {
     117           1 :                 return;
     118             :         }
     119           4 :         name = strv_len_next(strv, strv_len, domain);
     120           4 :         if (name == NULL) {
     121           0 :                 return;
     122             :         }
     123           3 :         typebuf = strv_len_next(strv, strv_len, name);
     124           3 :         if (typebuf == NULL) {
     125           0 :                 return;
     126             :         }
     127             : 
     128           3 :         type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
     129           3 :         if (error != 0) {
     130           0 :                 return;
     131             :         }
     132             : 
     133           6 :         state->fn(domain,
     134             :                   name,
     135             :                   (enum lsa_SidType)type,
     136           3 :                   gencache_timeout_expired(timeout),
     137             :                   state->private_data);
     138             : 
     139           3 :         state->ok = true;
     140             : }
     141             : 
     142           4 : bool namemap_cache_find_sid(const struct dom_sid *sid,
     143             :                             void (*fn)(const char *domain,
     144             :                                        const char *name,
     145             :                                        enum lsa_SidType type,
     146             :                                        bool expired,
     147             :                                        void *private_data),
     148             :                             void *private_data)
     149             : {
     150           4 :         struct namemap_cache_find_sid_state state = {
     151             :                 .fn = fn, .private_data = private_data
     152             :         };
     153             :         struct dom_sid_buf sidbuf;
     154             :         char keybuf[sizeof(sidbuf.buf)+10];
     155             :         bool ok;
     156             : 
     157           4 :         dom_sid_str_buf(sid, &sidbuf);
     158           4 :         snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
     159             : 
     160           4 :         ok = gencache_parse(keybuf, namemap_cache_find_sid_parser, &state);
     161           4 :         if (!ok) {
     162           0 :                 DBG_DEBUG("gencache_parse(%s) failed\n", keybuf);
     163           0 :                 return false;
     164             :         }
     165             : 
     166           4 :         if (!state.ok) {
     167           1 :                 DBG_DEBUG("Could not parse %s, deleting\n", keybuf);
     168           1 :                 gencache_del(keybuf);
     169           1 :                 return false;
     170             :         }
     171             : 
     172           0 :         return true;
     173             : }
     174             : 
     175         508 : bool namemap_cache_set_name2sid(const char *domain, const char *name,
     176             :                                 const struct dom_sid *sid,
     177             :                                 enum lsa_SidType type,
     178             :                                 time_t timeout)
     179             : {
     180             :         char typebuf[16];
     181         508 :         struct dom_sid_buf sidbuf = {{0}};
     182             :         char *key;
     183             :         char *key_upper;
     184         508 :         char *val = NULL;
     185             :         DATA_BLOB data;
     186             :         int ret;
     187         508 :         bool ok = false;
     188             : 
     189         508 :         if (domain == NULL) {
     190           0 :                 domain = "";
     191             :         }
     192         508 :         if (name == NULL) {
     193           0 :                 name = "";
     194             :         }
     195         508 :         if (type != SID_NAME_UNKNOWN) {
     196         508 :                 dom_sid_str_buf(sid, &sidbuf);
     197             :         }
     198             : 
     199         511 :         snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
     200             : 
     201         508 :         key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
     202         508 :         if (key == NULL) {
     203           0 :                 DBG_DEBUG("talloc_asprintf failed\n");
     204           0 :                 goto fail;
     205             :         }
     206         508 :         key_upper = strupper_talloc(key, key);
     207         508 :         if (key_upper == NULL) {
     208           0 :                 DBG_DEBUG("strupper_talloc failed\n");
     209           0 :                 goto fail;
     210             :         }
     211             : 
     212         508 :         ret = strv_add(key, &val, sidbuf.buf);
     213         508 :         if (ret != 0) {
     214           0 :                 DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
     215           0 :                 goto fail;
     216             :         }
     217         508 :         ret = strv_add(NULL, &val, typebuf);
     218         508 :         if (ret != 0) {
     219           0 :                 DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
     220           0 :                 goto fail;
     221             :         }
     222             : 
     223         508 :         data = data_blob_const(val, talloc_get_size(val));
     224             : 
     225         508 :         ok = gencache_set_data_blob(key_upper, data, timeout);
     226         508 :         if (!ok) {
     227           0 :                 DBG_DEBUG("gencache_set_data_blob failed\n");
     228             :         }
     229         765 : fail:
     230         508 :         TALLOC_FREE(key);
     231         508 :         return ok;
     232             : }
     233             : 
     234             : struct namemap_cache_find_name_state {
     235             :         void (*fn)(const struct dom_sid *sid,
     236             :                    enum lsa_SidType type,
     237             :                    bool expired,
     238             :                    void *private_data);
     239             :         void *private_data;
     240             :         bool ok;
     241             : };
     242             : 
     243           3 : static void namemap_cache_find_name_parser(
     244             :         const struct gencache_timeout *timeout,
     245             :         DATA_BLOB blob,
     246             :         void *private_data)
     247             : {
     248           3 :         struct namemap_cache_find_name_state *state = private_data;
     249           3 :         const char *strv = (const char *)blob.data;
     250           3 :         size_t strv_len = blob.length;
     251             :         const char *sidbuf;
     252             :         const char *sid_endptr;
     253             :         const char *typebuf;
     254           3 :         int error = 0;
     255             :         struct dom_sid sid;
     256             :         unsigned long type;
     257             :         bool ok;
     258             : 
     259           3 :         state->ok = false;
     260             : 
     261           3 :         sidbuf = strv_len_next(strv, strv_len, NULL);
     262           3 :         if (sidbuf == NULL) {
     263           0 :                 return;
     264             :         }
     265           3 :         typebuf = strv_len_next(strv, strv_len, sidbuf);
     266           3 :         if (typebuf == NULL) {
     267           0 :                 return;
     268             :         }
     269             : 
     270           3 :         ok = dom_sid_parse_endp(sidbuf, &sid, &sid_endptr);
     271           3 :         if (!ok) {
     272           0 :                 return;
     273             :         }
     274           3 :         if (*sid_endptr != '\0') {
     275           0 :                 return;
     276             :         }
     277             : 
     278           3 :         type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
     279           3 :         if (error != 0) {
     280           0 :                 return;
     281             :         }
     282             : 
     283           6 :         state->fn(&sid,
     284             :                   (enum lsa_SidType)type,
     285           3 :                   gencache_timeout_expired(timeout),
     286             :                   state->private_data);
     287             : 
     288           3 :         state->ok = true;
     289             : }
     290             : 
     291           4 : bool namemap_cache_find_name(const char *domain,
     292             :                              const char *name,
     293             :                              void (*fn)(const struct dom_sid *sid,
     294             :                                         enum lsa_SidType type,
     295             :                                         bool expired,
     296             :                                         void *private_data),
     297             :                              void *private_data)
     298             : {
     299           4 :         struct namemap_cache_find_name_state state = {
     300             :                 .fn = fn, .private_data = private_data
     301             :         };
     302             :         char *key;
     303             :         char *key_upper;
     304           4 :         bool ret = false;
     305             :         bool ok;
     306             : 
     307           4 :         key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
     308           4 :         if (key == NULL) {
     309           0 :                 DBG_DEBUG("talloc_asprintf failed\n");
     310           0 :                 return false;
     311             :         }
     312           4 :         key_upper = strupper_talloc(key, key);
     313           4 :         if (key_upper == NULL) {
     314           0 :                 DBG_DEBUG("strupper_talloc failed\n");
     315           0 :                 goto fail;
     316             :         }
     317             : 
     318           4 :         ok = gencache_parse(key_upper, namemap_cache_find_name_parser, &state);
     319           4 :         if (!ok) {
     320           1 :                 DBG_DEBUG("gencache_parse(%s) failed\n", key_upper);
     321           0 :                 goto fail;
     322             :         }
     323             : 
     324           3 :         if (!state.ok) {
     325           0 :                 DBG_DEBUG("Could not parse %s, deleting\n", key_upper);
     326           0 :                 goto fail;
     327             :         }
     328             : 
     329           0 :         ret = true;
     330           4 : fail:
     331           4 :         TALLOC_FREE(key);
     332           4 :         return ret;
     333             : }

Generated by: LCOV version 1.13