LCOV - code coverage report
Current view: top level - responder/common - negcache.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 340 388 87.6 %
Date: 2016-06-29 Functions: 36 37 97.3 %

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

Generated by: LCOV version 1.10