LCOV - code coverage report
Current view: top level - responder/common - negcache.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 335 379 88.4 %
Date: 2015-10-19 Functions: 36 36 100.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    NSS Responder
       5             : 
       6             :    Copyright (C) Simo Sorce <ssorce@redhat.com>   2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "util/util.h"
      23             : #include "confdb/confdb.h"
      24             : #include "responder/common/responder.h"
      25             : #include "responder/common/negcache.h"
      26             : #include <fcntl.h>
      27             : #include <time.h>
      28             : #include "tdb.h"
      29             : 
      30             : #define NC_ENTRY_PREFIX "NCE/"
      31             : #define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
      32             : #define NC_GROUP_PREFIX NC_ENTRY_PREFIX"GROUP"
      33             : #define NC_NETGROUP_PREFIX NC_ENTRY_PREFIX"NETGR"
      34             : #define NC_SERVICE_PREFIX NC_ENTRY_PREFIX"SERVICE"
      35             : #define NC_UID_PREFIX NC_ENTRY_PREFIX"UID"
      36             : #define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
      37             : #define NC_SID_PREFIX NC_ENTRY_PREFIX"SID"
      38             : #define NC_CERT_PREFIX NC_ENTRY_PREFIX"CERT"
      39             : 
      40             : struct sss_nc_ctx {
      41             :     struct tdb_context *tdb;
      42             : };
      43             : 
      44             : typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
      45             :                                       const char *, const char *);
      46             : 
      47             : static int sss_ncache_set_ent(struct sss_nc_ctx *ctx, bool permanent,
      48             :                               struct sss_domain_info *dom, const char *name,
      49             :                               ncache_set_byname_fn_t setter);
      50             : 
      51         532 : static int string_to_tdb_data(char *str, TDB_DATA *ret)
      52             : {
      53         532 :     if (!str || !ret) return EINVAL;
      54             : 
      55         532 :     ret->dptr = (uint8_t *)str;
      56         532 :     ret->dsize = strlen(str)+1;
      57             : 
      58         532 :     return EOK;
      59             : }
      60             : 
      61         139 : int sss_ncache_init(TALLOC_CTX *memctx, struct sss_nc_ctx **_ctx)
      62             : {
      63             :     struct sss_nc_ctx *ctx;
      64             : 
      65         139 :     ctx = talloc_zero(memctx, struct sss_nc_ctx);
      66         139 :     if (!ctx) return ENOMEM;
      67             : 
      68         139 :     errno = 0;
      69             :     /* open a memory only tdb with default hash size */
      70         139 :     ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
      71         139 :     if (!ctx->tdb) return errno;
      72             : 
      73         139 :     *_ctx = ctx;
      74         139 :     return EOK;
      75             : };
      76             : 
      77         232 : static int sss_ncache_check_str(struct sss_nc_ctx *ctx, char *str, int ttl)
      78             : {
      79             :     TDB_DATA key;
      80             :     TDB_DATA data;
      81             :     unsigned long long int timestamp;
      82         232 :     bool expired = false;
      83             :     char *ep;
      84             :     int ret;
      85             : 
      86         232 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Checking negative cache for [%s]\n", str);
      87             : 
      88         232 :     data.dptr = NULL;
      89             : 
      90         232 :     ret = string_to_tdb_data(str, &key);
      91         232 :     if (ret != EOK) goto done;
      92             : 
      93         232 :     data = tdb_fetch(ctx->tdb, key);
      94             : 
      95         232 :     if (!data.dptr) {
      96         174 :         ret = ENOENT;
      97         174 :         goto done;
      98             :     }
      99             : 
     100          58 :     if (ttl == -1) {
     101             :         /* a negative ttl means: never expires */
     102           9 :         ret = EEXIST;
     103           9 :         goto done;
     104             :     }
     105             : 
     106          49 :     errno = 0;
     107          49 :     timestamp = strtoull((const char *)data.dptr, &ep, 10);
     108          49 :     if (errno != 0 || *ep != '\0') {
     109             :         /* Malformed entry, remove it and return no entry */
     110           0 :         expired = true;
     111           0 :         goto done;
     112             :     }
     113             : 
     114          49 :     if (timestamp == 0) {
     115             :         /* a 0 timestamp means this is a permanent entry */
     116          26 :         ret = EEXIST;
     117          26 :         goto done;
     118             :     }
     119             : 
     120          23 :     if (timestamp + ttl >= time(NULL)) {
     121             :         /* still valid */
     122          22 :         ret = EEXIST;
     123          22 :         goto done;
     124             :     }
     125             : 
     126           1 :     expired = true;
     127             : 
     128             : done:
     129         232 :     if (expired) {
     130             :         /* expired, remove and return no entry */
     131           1 :         tdb_delete(ctx->tdb, key);
     132           1 :         ret = ENOENT;
     133             :     }
     134             : 
     135         232 :     free(data.dptr);
     136         232 :     return ret;
     137             : }
     138             : 
     139         150 : static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
     140             :                               char *str, bool permanent)
     141             : {
     142             :     TDB_DATA key;
     143             :     TDB_DATA data;
     144             :     char *timest;
     145             :     int ret;
     146             : 
     147         150 :     ret = string_to_tdb_data(str, &key);
     148         150 :     if (ret != EOK) return ret;
     149             : 
     150         150 :     if (permanent) {
     151         101 :         timest = talloc_strdup(ctx, "0");
     152             :     } else {
     153          49 :         timest = talloc_asprintf(ctx, "%llu",
     154          49 :                                  (unsigned long long int)time(NULL));
     155             :     }
     156         150 :     if (!timest) return ENOMEM;
     157             : 
     158         150 :     ret = string_to_tdb_data(timest, &data);
     159         150 :     if (ret != EOK) goto done;
     160             : 
     161         150 :     DEBUG(SSSDBG_TRACE_FUNC, "Adding [%s] to negative cache%s\n",
     162             :               str, permanent?" permanently":"");
     163             : 
     164         150 :     ret = tdb_store(ctx->tdb, key, data, TDB_REPLACE);
     165         150 :     if (ret != 0) {
     166           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Negative cache failed to set entry: [%s]\n",
     167             :                   tdb_errorstr(ctx->tdb));
     168           0 :         ret = EFAULT;
     169             :     }
     170             : 
     171             : done:
     172         150 :     talloc_free(timest);
     173         150 :     return ret;
     174             : }
     175             : 
     176         111 : static int sss_ncache_check_user_int(struct sss_nc_ctx *ctx, int ttl,
     177             :                                      const char *domain, const char *name)
     178             : {
     179             :     char *str;
     180             :     int ret;
     181             : 
     182         111 :     if (!name || !*name) return EINVAL;
     183             : 
     184         111 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
     185         111 :     if (!str) return ENOMEM;
     186             : 
     187         111 :     ret = sss_ncache_check_str(ctx, str, ttl);
     188             : 
     189         111 :     talloc_free(str);
     190         111 :     return ret;
     191             : }
     192             : 
     193          40 : static int sss_ncache_check_group_int(struct sss_nc_ctx *ctx, int ttl,
     194             :                                       const char *domain, const char *name)
     195             : {
     196             :     char *str;
     197             :     int ret;
     198             : 
     199          40 :     if (!name || !*name) return EINVAL;
     200             : 
     201          40 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
     202          40 :     if (!str) return ENOMEM;
     203             : 
     204          40 :     ret = sss_ncache_check_str(ctx, str, ttl);
     205             : 
     206          40 :     talloc_free(str);
     207          40 :     return ret;
     208             : }
     209             : 
     210           5 : static int sss_ncache_check_netgr_int(struct sss_nc_ctx *ctx, int ttl,
     211             :                                       const char *domain, const char *name)
     212             : {
     213             :     char *str;
     214             :     int ret;
     215             : 
     216           5 :     if (!name || !*name) return EINVAL;
     217             : 
     218           5 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
     219           5 :     if (!str) return ENOMEM;
     220             : 
     221           5 :     ret = sss_ncache_check_str(ctx, str, ttl);
     222             : 
     223           5 :     talloc_free(str);
     224           5 :     return ret;
     225             : }
     226             : 
     227          10 : static int sss_ncache_check_service_int(struct sss_nc_ctx *ctx,
     228             :                                         int ttl,
     229             :                                         const char *domain,
     230             :                                         const char *name)
     231             : {
     232             :     char *str;
     233             :     int ret;
     234             : 
     235          10 :     if (!name || !*name) return EINVAL;
     236             : 
     237          10 :     str = talloc_asprintf(ctx, "%s/%s/%s",
     238             :                           NC_SERVICE_PREFIX,
     239             :                           domain,
     240             :                           name);
     241          10 :     if (!str) return ENOMEM;
     242             : 
     243          10 :     ret = sss_ncache_check_str(ctx, str, ttl);
     244             : 
     245          10 :     talloc_free(str);
     246          10 :     return ret;
     247             : }
     248             : 
     249             : typedef int (*ncache_check_byname_fn_t)(struct sss_nc_ctx *, int,
     250             :                                         const char *, const char *);
     251             : 
     252         166 : static int sss_cache_check_ent(struct sss_nc_ctx *ctx, int ttl,
     253             :                                struct sss_domain_info *dom, const char *name,
     254             :                                ncache_check_byname_fn_t checker)
     255             : {
     256             :     char *lower;
     257             :     errno_t ret;
     258             : 
     259         166 :     if (dom->case_sensitive == false) {
     260          29 :         lower = sss_tc_utf8_str_tolower(ctx, name);
     261          29 :         if (!lower) return ENOMEM;
     262          29 :         ret = checker(ctx, ttl, dom->name, lower);
     263          29 :         talloc_free(lower);
     264             :     } else {
     265         137 :         ret = checker(ctx, ttl, dom->name, name);
     266             :     }
     267             : 
     268         166 :     return ret;
     269             : }
     270             : 
     271         111 : int sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
     272             :                           struct sss_domain_info *dom, const char *name)
     273             : {
     274         111 :     return sss_cache_check_ent(ctx, ttl, dom, name,
     275             :                                sss_ncache_check_user_int);
     276             : }
     277             : 
     278          40 : int sss_ncache_check_group(struct sss_nc_ctx *ctx, int ttl,
     279             :                            struct sss_domain_info *dom, const char *name)
     280             : {
     281          40 :     return sss_cache_check_ent(ctx, ttl, dom, name,
     282             :                                sss_ncache_check_group_int);
     283             : }
     284             : 
     285           5 : int sss_ncache_check_netgr(struct sss_nc_ctx *ctx, int ttl,
     286             :                            struct sss_domain_info *dom, const char *name)
     287             : {
     288           5 :     return sss_cache_check_ent(ctx, ttl, dom, name,
     289             :                                sss_ncache_check_netgr_int);
     290             : }
     291             : 
     292           4 : static int sss_ncache_set_service_int(struct sss_nc_ctx *ctx, bool permanent,
     293             :                                       const char *domain, const char *name)
     294             : {
     295             :     char *str;
     296             :     int ret;
     297             : 
     298           4 :     if (!name || !*name) return EINVAL;
     299             : 
     300           4 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_SERVICE_PREFIX, domain, name);
     301           4 :     if (!str) return ENOMEM;
     302             : 
     303           4 :     ret = sss_ncache_set_str(ctx, str, permanent);
     304             : 
     305           4 :     talloc_free(str);
     306           4 :     return ret;
     307             : }
     308             : 
     309           2 : int sss_ncache_set_service_name(struct sss_nc_ctx *ctx, bool permanent,
     310             :                                 struct sss_domain_info *dom,
     311             :                                 const char *name, const char *proto)
     312             : {
     313             :     int ret;
     314           2 :     char *service_and_protocol = talloc_asprintf(ctx, "%s:%s",
     315             :                                                  name,
     316             :                                                  proto ? proto : "<ANY>");
     317           2 :     if (!service_and_protocol) return ENOMEM;
     318             : 
     319           2 :     ret = sss_ncache_set_ent(ctx, permanent, dom,
     320             :                              service_and_protocol,
     321             :                              sss_ncache_set_service_int);
     322           2 :     talloc_free(service_and_protocol);
     323           2 :     return ret;
     324             : }
     325             : 
     326           5 : int sss_ncache_check_service(struct sss_nc_ctx *ctx, int ttl,
     327             :                              struct sss_domain_info *dom,
     328             :                              const char *name,
     329             :                              const char *proto)
     330             : {
     331             :     int ret;
     332           5 :     char *service_and_protocol = talloc_asprintf(ctx, "%s:%s",
     333             :                                                  name,
     334             :                                                  proto ? proto : "<ANY>");
     335           5 :     if (!service_and_protocol) return ENOMEM;
     336             : 
     337           5 :     ret = sss_cache_check_ent(ctx, ttl, dom, service_and_protocol,
     338             :                               sss_ncache_check_service_int);
     339           5 :     talloc_free(service_and_protocol);
     340           5 :     return ret;
     341             : }
     342             : 
     343           2 : int sss_ncache_set_service_port(struct sss_nc_ctx *ctx, bool permanent,
     344             :                                 struct sss_domain_info *dom,
     345             :                                 uint16_t port, const char *proto)
     346             : {
     347             :     int ret;
     348           2 :     char *service_and_protocol = talloc_asprintf(ctx, "%ul:%s",
     349             :                                                  port,
     350             :                                                  proto ? proto : "<ANY>");
     351           2 :     if (!service_and_protocol) return ENOMEM;
     352             : 
     353           2 :     ret = sss_ncache_set_ent(ctx, permanent, dom,
     354             :                              service_and_protocol,
     355             :                              sss_ncache_set_service_int);
     356           2 :     talloc_free(service_and_protocol);
     357           2 :     return ret;
     358             : }
     359             : 
     360           5 : int sss_ncache_check_service_port(struct sss_nc_ctx *ctx, int ttl,
     361             :                                   struct sss_domain_info *dom,
     362             :                                   uint16_t port,
     363             :                                   const char *proto)
     364             : {
     365             :     int ret;
     366           5 :     char *service_and_protocol = talloc_asprintf(ctx, "%ul:%s",
     367             :                                                  port,
     368             :                                                  proto ? proto : "<ANY>");
     369           5 :     if (!service_and_protocol) return ENOMEM;
     370             : 
     371           5 :     ret = sss_cache_check_ent(ctx, ttl, dom, service_and_protocol,
     372             :                               sss_ncache_check_service_int);
     373           5 :     talloc_free(service_and_protocol);
     374           5 :     return ret;
     375             : }
     376             : 
     377             : 
     378             : 
     379          29 : int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl,
     380             :                          struct sss_domain_info *dom, uid_t uid)
     381             : {
     382             :     char *str;
     383             :     int ret;
     384             : 
     385          29 :     if (dom != NULL) {
     386           0 :         str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
     387             :                               uid);
     388             :     } else {
     389          29 :         str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
     390             :     }
     391          29 :     if (!str) return ENOMEM;
     392             : 
     393          29 :     ret = sss_ncache_check_str(ctx, str, ttl);
     394             : 
     395          29 :     talloc_free(str);
     396          29 :     return ret;
     397             : }
     398             : 
     399          17 : int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl,
     400             :                          struct sss_domain_info *dom, gid_t gid)
     401             : {
     402             :     char *str;
     403             :     int ret;
     404             : 
     405          17 :     if (dom != NULL) {
     406           0 :         str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
     407             :                               gid);
     408             :     } else {
     409          17 :         str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
     410             :     }
     411          17 :     if (!str) return ENOMEM;
     412             : 
     413          17 :     ret = sss_ncache_check_str(ctx, str, ttl);
     414             : 
     415          17 :     talloc_free(str);
     416          17 :     return ret;
     417             : }
     418             : 
     419          10 : int sss_ncache_check_sid(struct sss_nc_ctx *ctx, int ttl, const char *sid)
     420             : {
     421             :     char *str;
     422             :     int ret;
     423             : 
     424          10 :     str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
     425          10 :     if (!str) return ENOMEM;
     426             : 
     427          10 :     ret = sss_ncache_check_str(ctx, str, ttl);
     428             : 
     429          10 :     talloc_free(str);
     430          10 :     return ret;
     431             : }
     432             : 
     433          10 : int sss_ncache_check_cert(struct sss_nc_ctx *ctx, int ttl, const char *cert)
     434             : {
     435             :     char *str;
     436             :     int ret;
     437             : 
     438          10 :     str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
     439          10 :     if (!str) return ENOMEM;
     440             : 
     441          10 :     ret = sss_ncache_check_str(ctx, str, ttl);
     442             : 
     443          10 :     talloc_free(str);
     444          10 :     return ret;
     445             : }
     446             : 
     447             : 
     448          69 : static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
     449             :                                    const char *domain, const char *name)
     450             : {
     451             :     char *str;
     452             :     int ret;
     453             : 
     454          69 :     if (!name || !*name) return EINVAL;
     455             : 
     456          69 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
     457          69 :     if (!str) return ENOMEM;
     458             : 
     459          69 :     ret = sss_ncache_set_str(ctx, str, permanent);
     460             : 
     461          69 :     talloc_free(str);
     462          69 :     return ret;
     463             : }
     464             : 
     465          56 : static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
     466             :                                     const char *domain, const char *name)
     467             : {
     468             :     char *str;
     469             :     int ret;
     470             : 
     471          56 :     if (!name || !*name) return EINVAL;
     472             : 
     473          56 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
     474          56 :     if (!str) return ENOMEM;
     475             : 
     476          56 :     ret = sss_ncache_set_str(ctx, str, permanent);
     477             : 
     478          56 :     talloc_free(str);
     479          56 :     return ret;
     480             : }
     481             : 
     482           2 : static int sss_ncache_set_netgr_int(struct sss_nc_ctx *ctx, bool permanent,
     483             :                                     const char *domain, const char *name)
     484             : {
     485             :     char *str;
     486             :     int ret;
     487             : 
     488           2 :     if (!name || !*name) return EINVAL;
     489             : 
     490           2 :     str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
     491           2 :     if (!str) return ENOMEM;
     492             : 
     493           2 :     ret = sss_ncache_set_str(ctx, str, permanent);
     494             : 
     495           2 :     talloc_free(str);
     496           2 :     return ret;
     497             : }
     498             : 
     499         131 : static int sss_ncache_set_ent(struct sss_nc_ctx *ctx, bool permanent,
     500             :                               struct sss_domain_info *dom, const char *name,
     501             :                               ncache_set_byname_fn_t setter)
     502             : {
     503             :     char *lower;
     504             :     errno_t ret;
     505             : 
     506         131 :     if (dom->case_sensitive == false) {
     507          26 :         lower = sss_tc_utf8_str_tolower(ctx, name);
     508          26 :         if (!lower) return ENOMEM;
     509          26 :         ret = setter(ctx, permanent, dom->name, lower);
     510          26 :         talloc_free(lower);
     511             :     } else {
     512         105 :         ret = setter(ctx, permanent, dom->name, name);
     513             :     }
     514             : 
     515         131 :     return ret;
     516             : }
     517             : 
     518             : 
     519          69 : int sss_ncache_set_user(struct sss_nc_ctx *ctx, bool permanent,
     520             :                         struct sss_domain_info *dom, const char *name)
     521             : {
     522          69 :     return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_user_int);
     523             : }
     524             : 
     525          56 : int sss_ncache_set_group(struct sss_nc_ctx *ctx, bool permanent,
     526             :                          struct sss_domain_info *dom, const char *name)
     527             : {
     528          56 :     return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_group_int);
     529             : }
     530             : 
     531           2 : int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
     532             :                          struct sss_domain_info *dom, const char *name)
     533             : {
     534           2 :     return sss_ncache_set_ent(ctx, permanent, dom, name, sss_ncache_set_netgr_int);
     535             : }
     536             : 
     537           9 : int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
     538             :                        struct sss_domain_info *dom, uid_t uid)
     539             : {
     540             :     char *str;
     541             :     int ret;
     542             : 
     543           9 :     if (dom != NULL) {
     544           0 :         str = talloc_asprintf(ctx, "%s/%s/%"SPRIuid, NC_UID_PREFIX, dom->name,
     545             :                               uid);
     546             :     } else {
     547           9 :         str = talloc_asprintf(ctx, "%s/%"SPRIuid, NC_UID_PREFIX, uid);
     548             :     }
     549           9 :     if (!str) return ENOMEM;
     550             : 
     551           9 :     ret = sss_ncache_set_str(ctx, str, permanent);
     552             : 
     553           9 :     talloc_free(str);
     554           9 :     return ret;
     555             : }
     556             : 
     557           3 : int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
     558             :                        struct sss_domain_info *dom, gid_t gid)
     559             : {
     560             :     char *str;
     561             :     int ret;
     562             : 
     563           3 :     if (dom != NULL) {
     564           0 :         str = talloc_asprintf(ctx, "%s/%s/%"SPRIgid, NC_GID_PREFIX, dom->name,
     565             :                               gid);
     566             :     } else {
     567           3 :         str = talloc_asprintf(ctx, "%s/%"SPRIgid, NC_GID_PREFIX, gid);
     568             :     }
     569           3 :     if (!str) return ENOMEM;
     570             : 
     571           3 :     ret = sss_ncache_set_str(ctx, str, permanent);
     572             : 
     573           3 :     talloc_free(str);
     574           3 :     return ret;
     575             : }
     576             : 
     577           3 : int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid)
     578             : {
     579             :     char *str;
     580             :     int ret;
     581             : 
     582           3 :     str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
     583           3 :     if (!str) return ENOMEM;
     584             : 
     585           3 :     ret = sss_ncache_set_str(ctx, str, permanent);
     586             : 
     587           3 :     talloc_free(str);
     588           3 :     return ret;
     589             : }
     590             : 
     591           4 : int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
     592             :                         const char *cert)
     593             : {
     594             :     char *str;
     595             :     int ret;
     596             : 
     597           4 :     str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
     598           4 :     if (!str) return ENOMEM;
     599             : 
     600           4 :     ret = sss_ncache_set_str(ctx, str, permanent);
     601             : 
     602           4 :     talloc_free(str);
     603           4 :     return ret;
     604             : }
     605             : 
     606           9 : static int delete_permanent(struct tdb_context *tdb,
     607             :                             TDB_DATA key, TDB_DATA data, void *state)
     608             : {
     609             :     unsigned long long int timestamp;
     610           9 :     bool remove_key = false;
     611             :     char *ep;
     612             : 
     613           9 :     if (strncmp((char *)key.dptr,
     614             :                 NC_ENTRY_PREFIX, sizeof(NC_ENTRY_PREFIX) - 1) != 0) {
     615             :         /* not interested in this key */
     616           0 :         return 0;
     617             :     }
     618             : 
     619           9 :     errno = 0;
     620           9 :     timestamp = strtoull((const char *)data.dptr, &ep, 10);
     621           9 :     if (errno != 0 || *ep != '\0') {
     622             :         /* Malformed entry, remove it */
     623           0 :         remove_key = true;
     624           0 :         goto done;
     625             :     }
     626             : 
     627           9 :     if (timestamp == 0) {
     628             :         /* a 0 timestamp means this is a permanent entry */
     629           7 :         remove_key = true;
     630             :     }
     631             : 
     632             : done:
     633           9 :     if (remove_key) {
     634           7 :         return tdb_delete(tdb, key);
     635             :     }
     636             : 
     637           2 :     return 0;
     638             : }
     639             : 
     640          36 : int sss_ncache_reset_permanent(struct sss_nc_ctx *ctx)
     641             : {
     642             :     int ret;
     643             : 
     644          36 :     ret = tdb_traverse(ctx->tdb, delete_permanent, NULL);
     645          36 :     if (ret < 0)
     646           0 :         return EIO;
     647             : 
     648          36 :     return EOK;
     649             : }
     650             : 
     651          36 : errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
     652             :                                struct confdb_ctx *cdb,
     653             :                                struct resp_ctx *rctx)
     654             : {
     655             :     errno_t ret;
     656          36 :     bool filter_set = false;
     657          36 :     char **filter_list = NULL;
     658          36 :     char *name = NULL;
     659          36 :     struct sss_domain_info *dom = NULL;
     660          36 :     struct sss_domain_info *domain_list = rctx->domains;
     661          36 :     char *domainname = NULL;
     662          36 :     char *conf_path = NULL;
     663          36 :     TALLOC_CTX *tmpctx = talloc_new(NULL);
     664             :     int i;
     665             : 
     666             :     /* Populate domain-specific negative cache entries */
     667          73 :     for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
     668          37 :         conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL,
     669             :                                     dom->name);
     670          37 :         if (!conf_path) {
     671           0 :             ret = ENOMEM;
     672           0 :             goto done;
     673             :         }
     674             : 
     675          37 :         talloc_zfree(filter_list);
     676          37 :         ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
     677             :                                         CONFDB_NSS_FILTER_USERS,
     678             :                                         &filter_list);
     679          37 :         if (ret == ENOENT) continue;
     680           4 :         if (ret != EOK) goto done;
     681           4 :         filter_set = true;
     682             : 
     683          14 :         for (i = 0; (filter_list && filter_list[i]); i++) {
     684          20 :             ret = sss_parse_name_for_domains(tmpctx, domain_list,
     685          10 :                                              rctx->default_domain,
     686          10 :                                              filter_list[i],
     687             :                                              &domainname, &name);
     688          10 :             if (ret == EAGAIN) {
     689           3 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     690             :                       "cannot add [%s] to negcache because the required or "
     691             :                       "default domain are not known yet\n", filter_list[i]);
     692           7 :             } else if (ret != EOK) {
     693           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     694             :                       "Invalid name in filterUsers list: [%s] (%d)\n",
     695             :                          filter_list[i], ret);
     696           0 :                 continue;
     697             :             }
     698             : 
     699          10 :             if (domainname && strcmp(domainname, dom->name)) {
     700           4 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     701             :                       "Mismatch between domain name (%s) and name "
     702             :                           "set in FQN  (%s), skipping user %s\n",
     703             :                           dom->name, domainname, name);
     704           4 :                 continue;
     705             :             }
     706             : 
     707           6 :             ret = sss_ncache_set_user(ncache, true, dom, name);
     708           6 :             if (ret != EOK) {
     709           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     710             :                       "Failed to store permanent user filter for [%s]"
     711             :                           " (%d [%s])\n", filter_list[i],
     712             :                           ret, strerror(ret));
     713           0 :                 continue;
     714             :             }
     715             :         }
     716             :     }
     717             : 
     718          36 :     ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
     719             :                                     CONFDB_NSS_FILTER_USERS, &filter_list);
     720          36 :     if (ret == ENOENT) {
     721          34 :         if (!filter_set) {
     722          32 :             filter_list = talloc_array(tmpctx, char *, 2);
     723          32 :             if (!filter_list) {
     724           0 :                 ret = ENOMEM;
     725           0 :                 goto done;
     726             :             }
     727          32 :             filter_list[0] = talloc_strdup(tmpctx, "root");
     728          32 :             if (!filter_list[0]) {
     729           0 :                 ret = ENOMEM;
     730           0 :                 goto done;
     731             :             }
     732          32 :             filter_list[1] = NULL;
     733             :         }
     734             :     }
     735           2 :     else if (ret != EOK) goto done;
     736             : 
     737          78 :     for (i = 0; (filter_list && filter_list[i]); i++) {
     738          84 :         ret = sss_parse_name_for_domains(tmpctx, domain_list,
     739          84 :                                          rctx->default_domain, filter_list[i],
     740             :                                          &domainname, &name);
     741          42 :         if (ret == EAGAIN) {
     742           3 :             DEBUG(SSSDBG_MINOR_FAILURE,
     743             :                   "Cannot add [%s] to negcache because the required or "
     744             :                   "default domain are not known yet\n", filter_list[i]);
     745          39 :         } else if (ret != EOK) {
     746           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     747             :                   "Invalid name in filterUsers list: [%s] (%d)\n",
     748             :                      filter_list[i], ret);
     749           0 :             continue;
     750             :         }
     751          42 :         if (domainname) {
     752           9 :             dom = responder_get_domain(rctx, domainname);
     753           9 :             if (!dom) {
     754           3 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     755             :                       "Invalid domain name [%s]\n", domainname);
     756           3 :                 continue;
     757             :             }
     758             : 
     759           6 :             ret = sss_ncache_set_user(ncache, true, dom, name);
     760           6 :             if (ret != EOK) {
     761           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     762             :                       "Failed to store permanent user filter for [%s]"
     763             :                           " (%d [%s])\n", filter_list[i],
     764             :                           ret, strerror(ret));
     765           0 :                 continue;
     766             :             }
     767             :         } else {
     768          66 :             for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
     769          33 :                 ret = sss_ncache_set_user(ncache, true, dom, name);
     770          33 :                 if (ret != EOK) {
     771           0 :                    DEBUG(SSSDBG_CRIT_FAILURE,
     772             :                          "Failed to store permanent user filter for"
     773             :                              " [%s:%s] (%d [%s])\n",
     774             :                              dom->name, filter_list[i],
     775             :                              ret, strerror(ret));
     776           0 :                     continue;
     777             :                 }
     778             :             }
     779             :         }
     780             :     }
     781             : 
     782          36 :     filter_set = false;
     783          73 :     for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
     784          37 :         conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, dom->name);
     785          37 :         if (!conf_path) {
     786           0 :             ret = ENOMEM;
     787           0 :             goto done;
     788             :         }
     789             : 
     790          37 :         talloc_zfree(filter_list);
     791          37 :         ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
     792             :                                         CONFDB_NSS_FILTER_GROUPS, &filter_list);
     793          37 :         if (ret == ENOENT) continue;
     794           4 :         if (ret != EOK) goto done;
     795           4 :         filter_set = true;
     796             : 
     797          14 :         for (i = 0; (filter_list && filter_list[i]); i++) {
     798          10 :             ret = sss_parse_name(tmpctx, dom->names, filter_list[i],
     799             :                                  &domainname, &name);
     800          10 :             if (ret != EOK) {
     801           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     802             :                       "Invalid name in filterGroups list: [%s] (%d)\n",
     803             :                          filter_list[i], ret);
     804           0 :                 continue;
     805             :             }
     806             : 
     807          10 :             if (domainname && strcmp(domainname, dom->name)) {
     808           4 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     809             :                       "Mismatch betwen domain name (%s) and name "
     810             :                           "set in FQN  (%s), skipping group %s\n",
     811             :                           dom->name, domainname, name);
     812           4 :                 continue;
     813             :             }
     814             : 
     815           6 :             ret = sss_ncache_set_group(ncache, true, dom, name);
     816           6 :             if (ret != EOK) {
     817           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     818             :                       "Failed to store permanent group filter for [%s]"
     819             :                           " (%d [%s])\n", filter_list[i],
     820             :                           ret, strerror(ret));
     821           0 :                 continue;
     822             :             }
     823             :         }
     824             :     }
     825             : 
     826          36 :     ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
     827             :                                     CONFDB_NSS_FILTER_GROUPS, &filter_list);
     828          36 :     if (ret == ENOENT) {
     829          34 :         if (!filter_set) {
     830          32 :             filter_list = talloc_array(tmpctx, char *, 2);
     831          32 :             if (!filter_list) {
     832           0 :                 ret = ENOMEM;
     833           0 :                 goto done;
     834             :             }
     835          32 :             filter_list[0] = talloc_strdup(tmpctx, "root");
     836          32 :             if (!filter_list[0]) {
     837           0 :                 ret = ENOMEM;
     838           0 :                 goto done;
     839             :             }
     840          32 :             filter_list[1] = NULL;
     841             :         }
     842             :     }
     843           2 :     else if (ret != EOK) goto done;
     844             : 
     845          78 :     for (i = 0; (filter_list && filter_list[i]); i++) {
     846          84 :         ret = sss_parse_name_for_domains(tmpctx, domain_list,
     847          84 :                                          rctx->default_domain, filter_list[i],
     848             :                                          &domainname, &name);
     849          42 :         if (ret == EAGAIN) {
     850           3 :             DEBUG(SSSDBG_MINOR_FAILURE,
     851             :                   "Cannot add [%s] to negcache because the required or "
     852             :                   "default domain are not known yet\n", filter_list[i]);
     853          39 :         } else if (ret != EOK) {
     854           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     855             :                   "Invalid name in filterGroups list: [%s] (%d)\n",
     856             :                      filter_list[i], ret);
     857           0 :             continue;
     858             :         }
     859          42 :         if (domainname) {
     860           9 :             dom = responder_get_domain(rctx, domainname);
     861           9 :             if (!dom) {
     862           3 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     863             :                       "Invalid domain name [%s]\n", domainname);
     864           3 :                 continue;
     865             :             }
     866             : 
     867           6 :             ret = sss_ncache_set_group(ncache, true, dom, name);
     868           6 :             if (ret != EOK) {
     869           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     870             :                       "Failed to store permanent group filter for"
     871             :                           " [%s] (%d [%s])\n", filter_list[i],
     872             :                           ret, strerror(ret));
     873           0 :                 continue;
     874             :             }
     875             :         } else {
     876          66 :             for (dom = domain_list; dom; dom = get_next_domain(dom, false)) {
     877          33 :                 ret = sss_ncache_set_group(ncache, true, dom, name);
     878          33 :                 if (ret != EOK) {
     879           0 :                    DEBUG(SSSDBG_CRIT_FAILURE,
     880             :                          "Failed to store permanent group filter for"
     881             :                              " [%s:%s] (%d [%s])\n",
     882             :                              dom->name, filter_list[i],
     883             :                              ret, strerror(ret));
     884           0 :                     continue;
     885             :                 }
     886             :             }
     887             :         }
     888             :     }
     889             : 
     890          36 :     ret = EOK;
     891             : 
     892             : done:
     893          36 :     talloc_free(tmpctx);
     894          36 :     return ret;
     895             : }
     896             : 
     897             : /* Reset permanent negcache after checking the domains */
     898          34 : errno_t sss_ncache_reset_repopulate_permanent(struct resp_ctx *rctx,
     899             :                                               struct sss_nc_ctx *ncache)
     900             : {
     901             :     int ret;
     902             : 
     903          34 :     ret = sss_ncache_reset_permanent(ncache);
     904          34 :     if (ret == EOK) {
     905          34 :         ret = sss_ncache_prepopulate(ncache, rctx->cdb, rctx);
     906             :     }
     907             : 
     908          34 :     return ret;
     909             : }

Generated by: LCOV version 1.10