LCOV - code coverage report
Current view: top level - providers - be_refresh.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 152 0.0 %
Date: 2016-06-29 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2013 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 <tevent.h>
      22             : #include <talloc.h>
      23             : #include <time.h>
      24             : #include <ldb.h>
      25             : 
      26             : #include "providers/backend.h"
      27             : #include "providers/be_ptask.h"
      28             : #include "providers/be_refresh.h"
      29             : #include "util/util_errors.h"
      30             : #include "db/sysdb.h"
      31             : 
      32           0 : static errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
      33             :                                         struct sss_domain_info *domain,
      34             :                                         time_t period,
      35             :                                         const char *objectclass,
      36             :                                         struct ldb_dn *base_dn,
      37             :                                         const char *attr,
      38             :                                         char ***_values)
      39             : {
      40           0 :     TALLOC_CTX *tmp_ctx = NULL;
      41           0 :     const char *attrs[] = {attr, NULL};
      42           0 :     const char *filter = NULL;
      43           0 :     char **values = NULL;
      44           0 :     struct ldb_message **msgs = NULL;
      45           0 :     struct sysdb_attrs **records = NULL;
      46             :     size_t count;
      47           0 :     time_t now = time(NULL);
      48             :     errno_t ret;
      49             : 
      50           0 :     tmp_ctx = talloc_new(NULL);
      51           0 :     if (tmp_ctx == NULL) {
      52           0 :         return ENOMEM;
      53             :     }
      54             : 
      55           0 :     filter = talloc_asprintf(tmp_ctx, "(&(%s<=%lld))",
      56             :                              SYSDB_CACHE_EXPIRE, (long long) now + period);
      57           0 :     if (filter == NULL) {
      58           0 :         ret = ENOMEM;
      59           0 :         goto done;
      60             :     }
      61             : 
      62           0 :     ret = sysdb_search_entry(tmp_ctx, domain->sysdb, base_dn,
      63             :                              LDB_SCOPE_SUBTREE, filter, attrs,
      64             :                              &count, &msgs);
      65           0 :     if (ret == ENOENT) {
      66           0 :         count = 0;
      67           0 :     } else if (ret != EOK) {
      68           0 :         goto done;
      69             :     }
      70             : 
      71           0 :     ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &records);
      72           0 :     if (ret != EOK) {
      73           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      74             :               "Could not convert ldb message to sysdb_attrs\n");
      75           0 :         goto done;
      76             :     }
      77             : 
      78           0 :     ret = sysdb_attrs_to_list(tmp_ctx, records, count, attr, &values);
      79           0 :     if (ret != EOK) {
      80           0 :         goto done;
      81             :     }
      82             : 
      83           0 :     *_values = talloc_steal(mem_ctx, values);
      84           0 :     ret = EOK;
      85             : 
      86             : done:
      87           0 :     talloc_free(tmp_ctx);
      88             : 
      89           0 :     return ret;
      90             : }
      91             : 
      92           0 : static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
      93             :                                      enum be_refresh_type type,
      94             :                                      struct sss_domain_info *domain,
      95             :                                      time_t period,
      96             :                                      char ***_values)
      97             : {
      98           0 :     struct ldb_dn *base_dn = NULL;
      99           0 :     const char *class = NULL;
     100             :     errno_t ret;
     101             : 
     102           0 :     switch (type) {
     103             :     case BE_REFRESH_TYPE_USERS:
     104           0 :         base_dn = sysdb_user_base_dn(mem_ctx, domain);
     105           0 :         class = SYSDB_USER_CLASS;
     106           0 :         break;
     107             :     case BE_REFRESH_TYPE_GROUPS:
     108           0 :         base_dn = sysdb_group_base_dn(mem_ctx, domain);
     109           0 :         class = SYSDB_GROUP_CLASS;
     110           0 :         break;
     111             :     case BE_REFRESH_TYPE_NETGROUPS:
     112           0 :         base_dn = sysdb_netgroup_base_dn(mem_ctx, domain);
     113           0 :         class = SYSDB_NETGROUP_CLASS;
     114           0 :         break;
     115             :     case BE_REFRESH_TYPE_SENTINEL:
     116           0 :         return ERR_INTERNAL;
     117             :         break;
     118             :     }
     119             : 
     120           0 :     if (base_dn == NULL) {
     121           0 :         return ENOMEM;
     122             :     }
     123             : 
     124           0 :     ret = be_refresh_get_values_ex(mem_ctx, domain, period, class,
     125             :                                    base_dn, SYSDB_NAME, _values);
     126             : 
     127           0 :     talloc_free(base_dn);
     128           0 :     return ret;
     129             : }
     130             : 
     131             : struct be_refresh_cb {
     132             :     const char *name;
     133             :     bool enabled;
     134             :     be_refresh_send_t send_fn;
     135             :     be_refresh_recv_t recv_fn;
     136             :     void *pvt;
     137             : };
     138             : 
     139             : struct be_refresh_ctx {
     140             :     struct be_refresh_cb callbacks[BE_REFRESH_TYPE_SENTINEL];
     141             : };
     142             : 
     143           0 : struct be_refresh_ctx *be_refresh_ctx_init(TALLOC_CTX *mem_ctx)
     144             : {
     145           0 :     struct be_refresh_ctx *ctx = NULL;
     146             : 
     147           0 :     ctx = talloc_zero(mem_ctx, struct be_refresh_ctx);
     148           0 :     if (ctx == NULL) {
     149           0 :         return NULL;
     150             :     }
     151             : 
     152           0 :     ctx->callbacks[BE_REFRESH_TYPE_USERS].name = "users";
     153           0 :     ctx->callbacks[BE_REFRESH_TYPE_GROUPS].name = "groups";
     154           0 :     ctx->callbacks[BE_REFRESH_TYPE_NETGROUPS].name = "netgroups";
     155             : 
     156           0 :     return ctx;
     157             : }
     158             : 
     159           0 : errno_t be_refresh_add_cb(struct be_refresh_ctx *ctx,
     160             :                           enum be_refresh_type type,
     161             :                           be_refresh_send_t send_fn,
     162             :                           be_refresh_recv_t recv_fn,
     163             :                           void *pvt)
     164             : {
     165           0 :     if (ctx == NULL || send_fn == NULL || recv_fn == NULL
     166           0 :             || type >= BE_REFRESH_TYPE_SENTINEL) {
     167           0 :         return EINVAL;
     168             :     }
     169             : 
     170           0 :     if (ctx->callbacks[type].enabled) {
     171           0 :         return EEXIST;
     172             :     }
     173             : 
     174           0 :     ctx->callbacks[type].enabled = true;
     175           0 :     ctx->callbacks[type].send_fn = send_fn;
     176           0 :     ctx->callbacks[type].recv_fn = recv_fn;
     177           0 :     ctx->callbacks[type].pvt = pvt;
     178             : 
     179           0 :     return EOK;
     180             : }
     181             : 
     182             : struct be_refresh_state {
     183             :     struct tevent_context *ev;
     184             :     struct be_ctx *be_ctx;
     185             :     struct be_refresh_ctx *ctx;
     186             :     struct be_refresh_cb *cb;
     187             : 
     188             :     struct sss_domain_info *domain;
     189             :     enum be_refresh_type index;
     190             :     time_t period;
     191             : };
     192             : 
     193             : static errno_t be_refresh_step(struct tevent_req *req);
     194             : static void be_refresh_done(struct tevent_req *subreq);
     195             : 
     196           0 : struct tevent_req *be_refresh_send(TALLOC_CTX *mem_ctx,
     197             :                                    struct tevent_context *ev,
     198             :                                    struct be_ctx *be_ctx,
     199             :                                    struct be_ptask *be_ptask,
     200             :                                    void *pvt)
     201             : {
     202           0 :     struct be_refresh_state *state = NULL;
     203           0 :     struct tevent_req *req = NULL;
     204             :     errno_t ret;
     205             : 
     206           0 :     req = tevent_req_create(mem_ctx, &state,
     207             :                             struct be_refresh_state);
     208           0 :     if (req == NULL) {
     209           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     210           0 :         return NULL;
     211             :     }
     212             : 
     213           0 :     state->ev = ev;
     214           0 :     state->be_ctx = be_ctx;
     215           0 :     state->domain = be_ctx->domain;
     216           0 :     state->period = be_ptask_get_period(be_ptask);
     217           0 :     state->ctx = talloc_get_type(pvt, struct be_refresh_ctx);
     218           0 :     if (state->ctx == NULL) {
     219           0 :         ret = EINVAL;
     220           0 :         goto immediately;
     221             :     }
     222             : 
     223           0 :     ret = be_refresh_step(req);
     224           0 :     if (ret == EOK) {
     225           0 :         goto immediately;
     226           0 :     } else if (ret != EAGAIN) {
     227           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_refresh_step() failed [%d]: %s\n",
     228             :                                     ret, sss_strerror(ret));
     229           0 :         goto immediately;
     230             :     }
     231             : 
     232           0 :     return req;
     233             : 
     234             : immediately:
     235           0 :     if (ret == EOK) {
     236           0 :         tevent_req_done(req);
     237             :     } else {
     238           0 :         tevent_req_error(req, ret);
     239             :     }
     240           0 :     tevent_req_post(req, ev);
     241             : 
     242           0 :     return req;
     243             : }
     244             : 
     245           0 : static errno_t be_refresh_step(struct tevent_req *req)
     246             : {
     247           0 :     struct be_refresh_state *state = NULL;
     248           0 :     struct tevent_req *subreq = NULL;
     249           0 :     char **values = NULL;
     250             :     errno_t ret;
     251             : 
     252           0 :     state = tevent_req_data(req, struct be_refresh_state);
     253             : 
     254           0 :     while (state->domain != NULL) {
     255             :         /* find first enabled callback */
     256           0 :         state->cb = &state->ctx->callbacks[state->index];
     257           0 :         while (state->index != BE_REFRESH_TYPE_SENTINEL && !state->cb->enabled) {
     258           0 :             state->index++;
     259           0 :             state->cb = &state->ctx->callbacks[state->index];
     260             :         }
     261             : 
     262             :         /* if not found than continue with next domain */
     263           0 :         if (state->index == BE_REFRESH_TYPE_SENTINEL) {
     264           0 :             state->domain = get_next_domain(state->domain, 0);
     265           0 :             continue;
     266             :         }
     267             : 
     268           0 :         if (state->cb->send_fn == NULL || state->cb->recv_fn == NULL) {
     269           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Invalid parameters!\n");
     270           0 :             ret = ERR_INTERNAL;
     271           0 :             goto done;
     272             :         }
     273             : 
     274           0 :         ret = be_refresh_get_values(state, state->index, state->domain,
     275             :                                     state->period, &values);
     276           0 :         if (ret != EOK) {
     277           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain DN list [%d]: %s\n",
     278             :                                         ret, sss_strerror(ret));
     279           0 :             goto done;
     280             :         }
     281             : 
     282           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Refreshing %s in domain %s\n",
     283             :               state->cb->name, state->domain->name);
     284             : 
     285           0 :         subreq = state->cb->send_fn(state, state->ev, state->be_ctx,
     286           0 :                                     state->domain, values, state->cb->pvt);
     287           0 :         if (subreq == NULL) {
     288           0 :             ret = ENOMEM;
     289           0 :             goto done;
     290             :         }
     291             : 
     292             :         /* make the list disappear with subreq */
     293           0 :         talloc_steal(subreq, values);
     294             : 
     295           0 :         tevent_req_set_callback(subreq, be_refresh_done, req);
     296             : 
     297           0 :         state->index++;
     298           0 :         ret = EAGAIN;
     299           0 :         goto done;
     300             :     }
     301             : 
     302           0 :     ret = EOK;
     303             : 
     304             : done:
     305           0 :     if (ret != EOK && ret != EAGAIN) {
     306           0 :         talloc_free(values);
     307             :     }
     308             : 
     309           0 :     return ret;
     310             : }
     311             : 
     312           0 : static void be_refresh_done(struct tevent_req *subreq)
     313             : {
     314           0 :     struct be_refresh_state *state = NULL;
     315           0 :     struct tevent_req *req = NULL;
     316             :     errno_t ret;
     317             : 
     318           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     319           0 :     state = tevent_req_data(req, struct be_refresh_state);
     320             : 
     321           0 :     ret = state->cb->recv_fn(subreq);
     322           0 :     talloc_zfree(subreq);
     323           0 :     if (ret != EOK) {
     324           0 :         goto done;
     325             :     }
     326             : 
     327           0 :     ret = be_refresh_step(req);
     328           0 :     if (ret == EAGAIN) {
     329           0 :         return;
     330             :     }
     331             : 
     332             : done:
     333           0 :     if (ret != EOK) {
     334           0 :         tevent_req_error(req, ret);
     335           0 :         return;
     336             :     }
     337             : 
     338           0 :     tevent_req_done(req);
     339             : }
     340             : 
     341           0 : errno_t be_refresh_recv(struct tevent_req *req)
     342             : {
     343           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     344             : 
     345           0 :     return EOK;
     346             : }

Generated by: LCOV version 1.10