LCOV - code coverage report
Current view: top level - db - sysdb_sudo.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 338 0.0 %
Date: 2015-10-19 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Jakub Hrozek <jhrozek@redhat.com>
       4             : 
       5             :     Copyright (C) 2011 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "config.h"
      22             : 
      23             : #include <talloc.h>
      24             : #include <time.h>
      25             : 
      26             : #include "db/sysdb.h"
      27             : #include "db/sysdb_private.h"
      28             : #include "db/sysdb_sudo.h"
      29             : 
      30             : #define NULL_CHECK(val, rval, label) do { \
      31             :     if (!val) {                           \
      32             :         rval = ENOMEM;                    \
      33             :         goto label;                       \
      34             :     }                                     \
      35             : } while(0)
      36             : 
      37             : /* ====================  Utility functions ==================== */
      38             : 
      39           0 : static errno_t sysdb_sudo_convert_time(const char *str, time_t *unix_time)
      40             : {
      41             :     struct tm tm;
      42           0 :     char *tret = NULL;
      43             : 
      44             :     /* SUDO requires times to be in generalized time format:
      45             :      * YYYYMMDDHHMMSS[.|,fraction][(+|-HHMM)|Z]
      46             :      *
      47             :      * We need to use more format strings to parse this with strptime().
      48             :      */
      49           0 :     const char **format = NULL;
      50           0 :     const char *formats[] = {"%Y%m%d%H%M%SZ",    /* 201212121300Z */
      51             :                              "%Y%m%d%H%M%S%z",   /* 201212121300+-0200 */
      52             :                              "%Y%m%d%H%M%S.0Z",
      53             :                              "%Y%m%d%H%M%S.0%z",
      54             :                              "%Y%m%d%H%M%S,0Z",
      55             :                              "%Y%m%d%H%M%S,0%z",
      56             :                              NULL};
      57             : 
      58           0 :     for (format = formats; *format != NULL; format++) {
      59             :         /* strptime() may leave some fields uninitialized */
      60           0 :         memset(&tm, 0, sizeof(struct tm));
      61           0 :         tret = strptime(str, *format, &tm);
      62           0 :         if (tret != NULL && *tret == '\0') {
      63           0 :             *unix_time = mktime(&tm);
      64           0 :             return EOK;
      65             :         }
      66             :     }
      67             : 
      68           0 :     return EINVAL;
      69             : }
      70             : 
      71           0 : static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule,
      72             :                                      time_t now,
      73             :                                      bool *result)
      74             : {
      75           0 :     TALLOC_CTX *tmp_ctx = NULL;
      76           0 :     const char **values = NULL;
      77           0 :     const char *name = NULL;
      78           0 :     time_t notBefore = 0;
      79           0 :     time_t notAfter = 0;
      80             :     time_t converted;
      81             :     errno_t ret;
      82             :     int i;
      83             : 
      84           0 :     if (!result) return EINVAL;
      85           0 :     *result = false;
      86             : 
      87           0 :     tmp_ctx = talloc_new(NULL);
      88           0 :     NULL_CHECK(tmp_ctx, ret, done);
      89             : 
      90           0 :     ret = sysdb_attrs_get_string(rule, SYSDB_SUDO_CACHE_AT_CN, &name);
      91           0 :     if (ret == ENOENT) {
      92           0 :         name = "<missing>";
      93           0 :     } else if(ret != EOK) {
      94           0 :         goto done;
      95             :     }
      96             : 
      97             :     /*
      98             :      * From man sudoers.ldap:
      99             :      *
     100             :      * If multiple sudoNotBefore entries are present, the *earliest* is used.
     101             :      * If multiple sudoNotAfter entries are present, the *last one* is used.
     102             :      *
     103             :      * From sudo sources, ldap.c:
     104             :      * If either the sudoNotAfter or sudoNotBefore attributes are missing,
     105             :      * no time restriction shall be imposed.
     106             :      */
     107             : 
     108             :     /* check for sudoNotBefore */
     109           0 :     ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTBEFORE,
     110             :                                        tmp_ctx, &values);
     111           0 :     if (ret == EOK) {
     112           0 :         for (i=0; values[i] ; i++) {
     113           0 :             ret = sysdb_sudo_convert_time(values[i], &converted);
     114           0 :             if (ret != EOK) {
     115           0 :                 DEBUG(SSSDBG_MINOR_FAILURE, "Invalid time format in rule [%s]!\n",
     116             :                       name);
     117           0 :                 goto done;
     118             :             }
     119             : 
     120             :             /* Grab the earliest */
     121           0 :             if (!notBefore) {
     122           0 :                 notBefore = converted;
     123           0 :             } else if (notBefore > converted) {
     124           0 :                 notBefore = converted;
     125             :             }
     126             :         }
     127           0 :     } else if (ret != ENOENT) {
     128           0 :         goto done;
     129             :     }
     130             : 
     131             :     /* check for sudoNotAfter */
     132           0 :     ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTAFTER,
     133             :                                        tmp_ctx, &values);
     134           0 :     if (ret == EOK) {
     135           0 :         for (i=0; values[i] ; i++) {
     136           0 :             ret = sysdb_sudo_convert_time(values[i], &converted);
     137           0 :             if (ret != EOK) {
     138           0 :                 DEBUG(SSSDBG_MINOR_FAILURE, "Invalid time format in rule [%s]!\n",
     139             :                       name);
     140           0 :                 goto done;
     141             :             }
     142             : 
     143             :             /* Grab the latest */
     144           0 :             if (!notAfter) {
     145           0 :                 notAfter = converted;
     146           0 :             } else if (notAfter < converted) {
     147           0 :                 notAfter = converted;
     148             :             }
     149             :         }
     150           0 :     } else if (ret != ENOENT) {
     151           0 :         goto done;
     152             :     }
     153             : 
     154           0 :     if ((notBefore == 0 || now >= notBefore)
     155           0 :         && (notAfter == 0 || now <= notAfter)) {
     156           0 :         *result = true;
     157             :     }
     158             : 
     159           0 :     if (*result) {
     160           0 :         DEBUG(SSSDBG_TRACE_ALL, "Rule [%s] matches time restrictions\n",
     161             :                                  name);
     162             :     } else {
     163           0 :         DEBUG(SSSDBG_TRACE_ALL, "Rule [%s] does not match time "
     164             :                                  "restrictions\n", name);
     165             :     }
     166             : 
     167           0 :     ret = EOK;
     168             : done:
     169           0 :     talloc_free(tmp_ctx);
     170           0 :     return ret;
     171             : }
     172             : 
     173           0 : errno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
     174             :                                         uint32_t in_num_rules,
     175             :                                         struct sysdb_attrs **in_rules,
     176             :                                         time_t now,
     177             :                                         uint32_t *_num_rules,
     178             :                                         struct sysdb_attrs ***_rules)
     179             : {
     180           0 :     uint32_t num_rules = 0;
     181           0 :     struct sysdb_attrs **rules = NULL;
     182           0 :     TALLOC_CTX *tmp_ctx = NULL;
     183           0 :     bool allowed = false;
     184             :     errno_t ret;
     185             :     int i;
     186             : 
     187           0 :     tmp_ctx = talloc_new(NULL);
     188           0 :     NULL_CHECK(tmp_ctx, ret, done);
     189             : 
     190           0 :     if (now == 0) {
     191           0 :         now = time(NULL);
     192             :     }
     193             : 
     194           0 :     for (i = 0; i < in_num_rules; i++) {
     195           0 :         ret = sysdb_sudo_check_time(in_rules[i], now, &allowed);
     196           0 :         if (ret == EOK && allowed) {
     197           0 :             num_rules++;
     198           0 :             rules = talloc_realloc(tmp_ctx, rules, struct sysdb_attrs *,
     199             :                                    num_rules);
     200           0 :             NULL_CHECK(rules, ret, done);
     201             : 
     202           0 :             rules[num_rules - 1] = in_rules[i];
     203             :         }
     204             :     }
     205             : 
     206           0 :     *_num_rules = num_rules;
     207           0 :     *_rules = talloc_steal(mem_ctx, rules);
     208             : 
     209           0 :     ret = EOK;
     210             : 
     211             : done:
     212           0 :     talloc_free(tmp_ctx);
     213           0 :     return ret;
     214             : }
     215             : 
     216             : errno_t
     217           0 : sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
     218             :                       uid_t uid, char **groupnames, unsigned int flags,
     219             :                       char **_filter)
     220             : {
     221           0 :     TALLOC_CTX *tmp_ctx = NULL;
     222           0 :     char *filter = NULL;
     223           0 :     char *specific_filter = NULL;
     224           0 :     char *sanitized = NULL;
     225             :     time_t now;
     226             :     errno_t ret;
     227             :     int i;
     228             : 
     229           0 :     tmp_ctx = talloc_new(NULL);
     230           0 :     NULL_CHECK(tmp_ctx, ret, done);
     231             : 
     232             :     /* build specific filter */
     233             : 
     234           0 :     specific_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
     235           0 :     NULL_CHECK(specific_filter, ret, done);
     236             : 
     237           0 :     if (flags & SYSDB_SUDO_FILTER_INCLUDE_ALL) {
     238           0 :         specific_filter = talloc_asprintf_append(specific_filter, "(%s=ALL)",
     239             :                                                  SYSDB_SUDO_CACHE_AT_USER);
     240           0 :         NULL_CHECK(specific_filter, ret, done);
     241             :     }
     242             : 
     243           0 :     if (flags & SYSDB_SUDO_FILTER_INCLUDE_DFL) {
     244           0 :         specific_filter = talloc_asprintf_append(specific_filter, "(%s=defaults)",
     245             :                                                  SYSDB_NAME);
     246           0 :         NULL_CHECK(specific_filter, ret, done);
     247             :     }
     248             : 
     249           0 :     if ((flags & SYSDB_SUDO_FILTER_USERNAME) && (username != NULL)) {
     250           0 :         ret = sss_filter_sanitize(tmp_ctx, username, &sanitized);
     251           0 :         if (ret != EOK) {
     252           0 :             goto done;
     253             :         }
     254             : 
     255           0 :         specific_filter = talloc_asprintf_append(specific_filter, "(%s=%s)",
     256             :                                                  SYSDB_SUDO_CACHE_AT_USER,
     257             :                                                  sanitized);
     258           0 :         NULL_CHECK(specific_filter, ret, done);
     259             :     }
     260             : 
     261           0 :     if ((flags & SYSDB_SUDO_FILTER_UID) && (uid != 0)) {
     262           0 :         specific_filter = talloc_asprintf_append(specific_filter, "(%s=#%llu)",
     263             :                                                  SYSDB_SUDO_CACHE_AT_USER,
     264             :                                                  (unsigned long long) uid);
     265           0 :         NULL_CHECK(specific_filter, ret, done);
     266             :     }
     267             : 
     268           0 :     if ((flags & SYSDB_SUDO_FILTER_GROUPS) && (groupnames != NULL)) {
     269           0 :         for (i=0; groupnames[i] != NULL; i++) {
     270           0 :             ret = sss_filter_sanitize(tmp_ctx, groupnames[i], &sanitized);
     271           0 :             if (ret != EOK) {
     272           0 :                 goto done;
     273             :             }
     274             : 
     275           0 :             specific_filter = talloc_asprintf_append(specific_filter, "(%s=%%%s)",
     276             :                                                      SYSDB_SUDO_CACHE_AT_USER,
     277             :                                                      sanitized);
     278           0 :             NULL_CHECK(specific_filter, ret, done);
     279             :         }
     280             :     }
     281             : 
     282           0 :     if (flags & SYSDB_SUDO_FILTER_NGRS) {
     283           0 :         specific_filter = talloc_asprintf_append(specific_filter, "(%s=+*)",
     284             :                                                  SYSDB_SUDO_CACHE_AT_USER);
     285           0 :         NULL_CHECK(specific_filter, ret, done);
     286             :     }
     287             : 
     288             :     /* build global filter */
     289             : 
     290           0 :     filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)",
     291             :                              SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
     292           0 :     NULL_CHECK(filter, ret, done);
     293             : 
     294           0 :     if (specific_filter[0] != '\0') {
     295           0 :         filter = talloc_asprintf_append(filter, "(|%s)", specific_filter);
     296           0 :         NULL_CHECK(filter, ret, done);
     297             :     }
     298             : 
     299           0 :     if (flags & SYSDB_SUDO_FILTER_ONLY_EXPIRED) {
     300           0 :         now = time(NULL);
     301           0 :         filter = talloc_asprintf_append(filter, "(&(%s<=%lld))",
     302             :                                         SYSDB_CACHE_EXPIRE, (long long)now);
     303           0 :         NULL_CHECK(filter, ret, done);
     304             :     }
     305             : 
     306           0 :     filter = talloc_strdup_append(filter, ")");
     307           0 :     NULL_CHECK(filter, ret, done);
     308             : 
     309           0 :     ret = EOK;
     310           0 :     *_filter = talloc_steal(mem_ctx, filter);
     311             : 
     312             : done:
     313           0 :     talloc_free(tmp_ctx);
     314           0 :     return ret;
     315             : }
     316             : 
     317             : errno_t
     318           0 : sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
     319             :                          struct sss_domain_info *domain,
     320             :                          const char *username, uid_t *_uid,
     321             :                          char ***groupnames)
     322             : {
     323             :     TALLOC_CTX *tmp_ctx;
     324             :     errno_t ret;
     325             :     struct ldb_message *msg;
     326           0 :     struct ldb_message *group_msg = NULL;
     327           0 :     char **sysdb_groupnames = NULL;
     328           0 :     const char *primary_group = NULL;
     329             :     struct ldb_message_element *groups;
     330           0 :     uid_t uid = 0;
     331           0 :     gid_t gid = 0;
     332           0 :     size_t num_groups = 0;
     333             :     int i;
     334           0 :     const char *attrs[] = { SYSDB_MEMBEROF,
     335             :                             SYSDB_GIDNUM,
     336             :                             SYSDB_UIDNUM,
     337             :                             NULL };
     338           0 :     const char *group_attrs[] = { SYSDB_NAME,
     339             :                                   NULL };
     340             : 
     341           0 :     tmp_ctx = talloc_new(NULL);
     342           0 :     NULL_CHECK(tmp_ctx, ret, done);
     343             : 
     344           0 :     ret = sysdb_search_user_by_name(tmp_ctx, domain, username, attrs, &msg);
     345           0 :     if (ret != EOK) {
     346           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up user %s\n", username);
     347           0 :         goto done;
     348             :     }
     349             : 
     350           0 :     if (_uid != NULL) {
     351           0 :         uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
     352           0 :         if (!uid) {
     353           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "A user with no UID?\n");
     354           0 :             ret = EIO;
     355           0 :             goto done;
     356             :         }
     357             :     }
     358             : 
     359             :     /* resolve secondary groups */
     360           0 :     if (groupnames != NULL) {
     361           0 :         groups = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
     362           0 :         if (!groups || groups->num_values == 0) {
     363             :             /* No groups for this user in sysdb currently */
     364           0 :             sysdb_groupnames = NULL;
     365           0 :             num_groups = 0;
     366             :         } else {
     367           0 :             num_groups = groups->num_values;
     368           0 :             sysdb_groupnames = talloc_array(tmp_ctx, char *, num_groups + 1);
     369           0 :             NULL_CHECK(sysdb_groupnames, ret, done);
     370             : 
     371             :             /* Get a list of the groups by groupname only */
     372           0 :             for (i = 0; i < groups->num_values; i++) {
     373           0 :                 ret = sysdb_group_dn_name(domain->sysdb,
     374             :                                           sysdb_groupnames,
     375           0 :                                           (const char *)groups->values[i].data,
     376           0 :                                           &sysdb_groupnames[i]);
     377           0 :                 if (ret != EOK) {
     378           0 :                     ret = ENOMEM;
     379           0 :                     goto done;
     380             :                 }
     381             :             }
     382           0 :             sysdb_groupnames[groups->num_values] = NULL;
     383             :         }
     384             :     }
     385             : 
     386             :     /* resolve primary group */
     387           0 :     gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
     388           0 :     if (gid != 0) {
     389           0 :         ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, group_attrs,
     390             :                                         &group_msg);
     391           0 :         if (ret == EOK) {
     392           0 :             primary_group = ldb_msg_find_attr_as_string(group_msg, SYSDB_NAME,
     393             :                                                         NULL);
     394           0 :             if (primary_group == NULL) {
     395           0 :                 ret = ENOMEM;
     396           0 :                 goto done;
     397             :             }
     398             : 
     399           0 :             num_groups++;
     400           0 :             sysdb_groupnames = talloc_realloc(tmp_ctx, sysdb_groupnames,
     401             :                                               char *, num_groups + 1);
     402           0 :             NULL_CHECK(sysdb_groupnames, ret, done);
     403             : 
     404           0 :             sysdb_groupnames[num_groups - 1] = talloc_strdup(sysdb_groupnames,
     405             :                                                              primary_group);
     406           0 :             NULL_CHECK(sysdb_groupnames[num_groups - 1], ret, done);
     407             : 
     408           0 :             sysdb_groupnames[num_groups] = NULL;
     409           0 :         } else if (ret != ENOENT) {
     410           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up group [%d]: %s\n",
     411             :                                         ret, strerror(ret));
     412           0 :             goto done;
     413             :         }
     414             :     }
     415             : 
     416           0 :     ret = EOK;
     417             : 
     418           0 :     if (_uid != NULL) {
     419           0 :         *_uid = uid;
     420             :     }
     421             : 
     422           0 :     if (groupnames != NULL) {
     423           0 :         *groupnames = talloc_steal(mem_ctx, sysdb_groupnames);
     424             :     }
     425             : done:
     426           0 :     talloc_free(tmp_ctx);
     427           0 :     return ret;
     428             : }
     429             : 
     430             : errno_t
     431           0 : sysdb_save_sudorule(struct sss_domain_info *domain,
     432             :                     const char *rule_name,
     433             :                     struct sysdb_attrs *attrs)
     434             : {
     435             :     errno_t ret;
     436             : 
     437           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", rule_name);
     438             : 
     439           0 :     ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
     440             :                                  SYSDB_SUDO_CACHE_OC);
     441           0 :     if (ret != EOK) {
     442           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not set rule object class [%d]: %s\n",
     443             :               ret, strerror(ret));
     444           0 :         return ret;
     445             :     }
     446             : 
     447           0 :     ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, rule_name);
     448           0 :     if (ret != EOK) {
     449           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not set name attribute [%d]: %s\n",
     450             :               ret, strerror(ret));
     451           0 :         return ret;
     452             :     }
     453             : 
     454           0 :     ret = sysdb_store_custom(domain, rule_name,
     455             :                              SUDORULE_SUBDIR, attrs);
     456           0 :     if (ret != EOK) {
     457           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_custom failed [%d]: %s\n",
     458             :               ret, strerror(ret));
     459           0 :         return ret;
     460             :     }
     461             : 
     462           0 :     return EOK;
     463             : }
     464             : 
     465           0 : static errno_t sysdb_sudo_set_refresh_time(struct sss_domain_info *domain,
     466             :                                            const char *attr_name,
     467             :                                            time_t value)
     468             : {
     469             :     TALLOC_CTX *tmp_ctx;
     470             :     struct ldb_dn *dn;
     471           0 :     struct ldb_message *msg = NULL;
     472           0 :     struct ldb_result *res = NULL;
     473             :     errno_t ret;
     474             :     int lret;
     475             : 
     476           0 :     tmp_ctx = talloc_new(NULL);
     477           0 :     if (!tmp_ctx) {
     478           0 :         ret = ENOMEM;
     479           0 :         goto done;
     480             :     }
     481             : 
     482           0 :     dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
     483             :                         SYSDB_TMPL_CUSTOM_SUBTREE,
     484             :                         SUDORULE_SUBDIR, domain->name);
     485           0 :     if (!dn) {
     486           0 :         ret = ENOMEM;
     487           0 :         goto done;
     488             :     }
     489             : 
     490           0 :     lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
     491             :                       NULL, NULL);
     492           0 :     if (lret != LDB_SUCCESS) {
     493           0 :         ret = sysdb_error_to_errno(lret);
     494           0 :         goto done;
     495             :     }
     496             : 
     497           0 :     msg = ldb_msg_new(tmp_ctx);
     498           0 :     if (msg == NULL) {
     499           0 :         ret = ENOMEM;
     500           0 :         goto done;
     501             :     }
     502           0 :     msg->dn = dn;
     503             : 
     504           0 :     if (res->count == 0) {
     505           0 :         lret = ldb_msg_add_string(msg, "cn", SUDORULE_SUBDIR);
     506           0 :         if (lret != LDB_SUCCESS) {
     507           0 :             ret = sysdb_error_to_errno(lret);
     508           0 :             goto done;
     509             :         }
     510           0 :     } else if (res->count != 1) {
     511           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     512             :               "Got more than one reply for base search!\n");
     513           0 :         ret = EIO;
     514           0 :         goto done;
     515             :     } else {
     516           0 :         lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
     517           0 :         if (lret != LDB_SUCCESS) {
     518           0 :             ret = sysdb_error_to_errno(lret);
     519           0 :             goto done;
     520             :         }
     521             :     }
     522             : 
     523           0 :     lret = ldb_msg_add_fmt(msg, attr_name, "%lld", (long long)value);
     524           0 :     if (lret != LDB_SUCCESS) {
     525           0 :         ret = sysdb_error_to_errno(lret);
     526           0 :         goto done;
     527             :     }
     528             : 
     529           0 :     if (res->count) {
     530           0 :         lret = ldb_modify(domain->sysdb->ldb, msg);
     531             :     } else {
     532           0 :         lret = ldb_add(domain->sysdb->ldb, msg);
     533             :     }
     534             : 
     535           0 :     if (lret != LDB_SUCCESS) {
     536           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     537             :               "ldb operation failed: [%s](%d)[%s]\n",
     538             :               ldb_strerror(lret), lret, ldb_errstring(domain->sysdb->ldb));
     539             :     }
     540           0 :     ret = sysdb_error_to_errno(lret);
     541             : 
     542             : done:
     543           0 :     talloc_free(tmp_ctx);
     544           0 :     return ret;
     545             : }
     546             : 
     547           0 : static errno_t sysdb_sudo_get_refresh_time(struct sss_domain_info *domain,
     548             :                                            const char *attr_name,
     549             :                                            time_t *value)
     550             : {
     551             :     TALLOC_CTX *tmp_ctx;
     552             :     struct ldb_dn *dn;
     553             :     struct ldb_result *res;
     554             :     errno_t ret;
     555             :     int lret;
     556           0 :     const char *attrs[2] = {attr_name, NULL};
     557             : 
     558           0 :     tmp_ctx = talloc_new(NULL);
     559           0 :     if (tmp_ctx == NULL) {
     560           0 :         return ENOMEM;
     561             :     }
     562             : 
     563           0 :     dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
     564             :                         SUDORULE_SUBDIR, domain->name);
     565           0 :     if (!dn) {
     566           0 :         ret = ENOMEM;
     567           0 :         goto done;
     568             :     }
     569             : 
     570           0 :     lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
     571             :                       attrs, NULL);
     572           0 :     if (lret != LDB_SUCCESS) {
     573           0 :         ret = sysdb_error_to_errno(lret);
     574           0 :         goto done;
     575             :     }
     576             : 
     577           0 :     if (res->count == 0) {
     578             :         /* This entry has not been populated in LDB
     579             :          * This is a common case, as unlike LDAP,
     580             :          * LDB does not need to have all of its parent
     581             :          * objects actually exist.
     582             :          */
     583           0 :         *value = 0;
     584           0 :         ret = EOK;
     585           0 :         goto done;
     586           0 :     } else if (res->count != 1) {
     587           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     588             :               "Got more than one reply for base search!\n");
     589           0 :         ret = EIO;
     590           0 :         goto done;
     591             :     }
     592             : 
     593           0 :     *value = ldb_msg_find_attr_as_int(res->msgs[0], attr_name, 0);
     594             : 
     595           0 :     ret = EOK;
     596             : 
     597             : done:
     598           0 :     talloc_free(tmp_ctx);
     599           0 :     return ret;
     600             : }
     601             : 
     602           0 : errno_t sysdb_sudo_set_last_full_refresh(struct sss_domain_info *domain,
     603             :                                          time_t value)
     604             : {
     605           0 :     return sysdb_sudo_set_refresh_time(domain,
     606             :                                        SYSDB_SUDO_AT_LAST_FULL_REFRESH, value);
     607             : }
     608             : 
     609           0 : errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain,
     610             :                                          time_t *value)
     611             : {
     612           0 :     return sysdb_sudo_get_refresh_time(domain,
     613             :                                        SYSDB_SUDO_AT_LAST_FULL_REFRESH, value);
     614             : }
     615             : 
     616             : /* ====================  Purge functions ==================== */
     617             : 
     618           0 : static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain)
     619             : {
     620           0 :     struct ldb_dn *base_dn = NULL;
     621           0 :     TALLOC_CTX *tmp_ctx = NULL;
     622             :     errno_t ret;
     623             : 
     624           0 :     tmp_ctx = talloc_new(NULL);
     625           0 :     NULL_CHECK(tmp_ctx, ret, done);
     626             : 
     627           0 :     base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, SUDORULE_SUBDIR);
     628           0 :     NULL_CHECK(base_dn, ret, done);
     629             : 
     630           0 :     ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
     631           0 :     if (ret != EOK) {
     632           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
     633           0 :         goto done;
     634             :     }
     635             : 
     636           0 :     ret = EOK;
     637             : done:
     638           0 :     talloc_free(tmp_ctx);
     639           0 :     return ret;
     640             : }
     641             : 
     642           0 : errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain,
     643             :                                 const char *name)
     644             : {
     645           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Deleting sudo rule %s\n", name);
     646           0 :     return sysdb_delete_custom(domain, name, SUDORULE_SUBDIR);
     647             : }
     648             : 
     649           0 : errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
     650             :                                   const char *filter)
     651             : {
     652             :     TALLOC_CTX *tmp_ctx;
     653             :     size_t count;
     654             :     struct ldb_message **msgs;
     655             :     const char *name;
     656             :     int i;
     657             :     errno_t ret;
     658             :     errno_t sret;
     659           0 :     bool in_transaction = false;
     660           0 :     const char *attrs[] = { SYSDB_OBJECTCLASS,
     661             :                             SYSDB_NAME,
     662             :                             SYSDB_SUDO_CACHE_AT_CN,
     663             :                             NULL };
     664             : 
     665             :     /* just purge all if there's no filter */
     666           0 :     if (!filter) {
     667           0 :         return sysdb_sudo_purge_all(domain);
     668             :     }
     669             : 
     670           0 :     tmp_ctx = talloc_new(NULL);
     671           0 :     NULL_CHECK(tmp_ctx, ret, done);
     672             : 
     673             :     /* match entries based on the filter and remove them one by one */
     674           0 :     ret = sysdb_search_custom(tmp_ctx, domain, filter,
     675             :                               SUDORULE_SUBDIR, attrs,
     676             :                               &count, &msgs);
     677           0 :     if (ret == ENOENT) {
     678           0 :         DEBUG(SSSDBG_TRACE_FUNC, "No rules matched\n");
     679           0 :         ret = EOK;
     680           0 :         goto done;
     681           0 :     } else if (ret != EOK) {
     682           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
     683           0 :         goto done;
     684             :     }
     685             : 
     686           0 :     ret = sysdb_transaction_start(domain->sysdb);
     687           0 :     if (ret != EOK) {
     688           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     689           0 :         goto done;
     690             :     }
     691           0 :     in_transaction = true;
     692             : 
     693           0 :     for (i = 0; i < count; i++) {
     694           0 :         name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
     695           0 :         if (name == NULL) {
     696           0 :             DEBUG(SSSDBG_OP_FAILURE, "A rule without a name?\n");
     697             :             /* skip this one but still delete other entries */
     698           0 :             continue;
     699             :         }
     700             : 
     701           0 :         ret = sysdb_sudo_purge_byname(domain, name);
     702           0 :         if (ret != EOK) {
     703           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not delete rule %s\n", name);
     704           0 :             goto done;
     705             :         }
     706             :     }
     707             : 
     708           0 :     ret = sysdb_transaction_commit(domain->sysdb);
     709           0 :     if (ret != EOK) {
     710           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
     711           0 :         goto done;
     712             :     }
     713           0 :     in_transaction = false;
     714             : 
     715             : done:
     716           0 :     if (in_transaction) {
     717           0 :         sret = sysdb_transaction_cancel(domain->sysdb);
     718           0 :         if (sret != EOK) {
     719           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
     720             :         }
     721             :     }
     722             : 
     723           0 :     talloc_free(tmp_ctx);
     724           0 :     return ret;
     725             : }

Generated by: LCOV version 1.10