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

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     LDAP Enumeration Module
       5             : 
       6             :     Authors:
       7             :         Simo Sorce <ssorce@redhat.com>
       8             :         Jakub Hrozek <jhrozek@redhat.com>
       9             : 
      10             :     Copyright (C) 2013 Red Hat
      11             : 
      12             :     This program is free software; you can redistribute it and/or modify
      13             :     it under the terms of the GNU General Public License as published by
      14             :     the Free Software Foundation; either version 3 of the License, or
      15             :     (at your option) any later version.
      16             : 
      17             :     This program is distributed in the hope that it will be useful,
      18             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :     GNU General Public License for more details.
      21             : 
      22             :     You should have received a copy of the GNU General Public License
      23             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include <errno.h>
      27             : 
      28             : #include "util/util.h"
      29             : #include "db/sysdb.h"
      30             : #include "providers/ldap/ldap_common.h"
      31             : #include "providers/ldap/sdap_async.h"
      32             : #include "providers/ldap/sdap_async_enum.h"
      33             : #include "providers/ldap/sdap_idmap.h"
      34             : 
      35             : static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
      36             :                                           struct tevent_context *ev,
      37             :                                           struct sdap_id_ctx *ctx,
      38             :                                           struct sdap_domain *sdom,
      39             :                                           struct sdap_id_op *op,
      40             :                                           bool purge);
      41             : static errno_t enum_users_recv(struct tevent_req *req);
      42             : 
      43             : static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
      44             :                                           struct tevent_context *ev,
      45             :                                           struct sdap_id_ctx *ctx,
      46             :                                           struct sdap_domain *sdom,
      47             :                                           struct sdap_id_op *op,
      48             :                                           bool purge);
      49             : static errno_t enum_groups_recv(struct tevent_req *req);
      50             : 
      51             : /* ==Enumeration-Request-with-connections=================================== */
      52             : struct sdap_dom_enum_ex_state {
      53             :     struct tevent_context *ev;
      54             :     struct sdap_id_ctx *ctx;
      55             :     struct sdap_domain *sdom;
      56             : 
      57             :     struct sdap_id_conn_ctx *user_conn;
      58             :     struct sdap_id_conn_ctx *group_conn;
      59             :     struct sdap_id_conn_ctx *svc_conn;
      60             :     struct sdap_id_op *user_op;
      61             :     struct sdap_id_op *group_op;
      62             :     struct sdap_id_op *svc_op;
      63             : 
      64             :     bool purge;
      65             : };
      66             : 
      67             : static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
      68             :                                       struct sdap_id_op *op,
      69             :                                       tevent_req_fn tcb);
      70             : static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq);
      71             : static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq);
      72             : static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq);
      73             : static errno_t sdap_dom_enum_search_users(struct tevent_req *req);
      74             : static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq);
      75             : static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq);
      76             : static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq);
      77             : static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq);
      78             : static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq);
      79             : 
      80             : struct tevent_req *
      81           0 : sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
      82             :                       struct tevent_context *ev,
      83             :                       struct sdap_id_ctx *ctx,
      84             :                       struct sdap_domain *sdom,
      85             :                       struct sdap_id_conn_ctx *user_conn,
      86             :                       struct sdap_id_conn_ctx *group_conn,
      87             :                       struct sdap_id_conn_ctx *svc_conn)
      88             : {
      89             :     struct tevent_req *req;
      90             :     struct sdap_dom_enum_ex_state *state;
      91             :     int t;
      92             :     errno_t ret;
      93             : 
      94           0 :     req = tevent_req_create(memctx, &state, struct sdap_dom_enum_ex_state);
      95           0 :     if (req == NULL) return NULL;
      96             : 
      97           0 :     state->ev = ev;
      98           0 :     state->ctx = ctx;
      99           0 :     state->sdom = sdom;
     100           0 :     state->user_conn = user_conn;
     101           0 :     state->group_conn = group_conn;
     102           0 :     state->svc_conn = svc_conn;
     103           0 :     sdom->last_enum = tevent_timeval_current();
     104             : 
     105           0 :     t = dp_opt_get_int(ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT);
     106           0 :     if ((sdom->last_purge.tv_sec + t) < sdom->last_enum.tv_sec) {
     107           0 :         state->purge = true;
     108             :     }
     109             : 
     110           0 :     state->user_op = sdap_id_op_create(state, user_conn->conn_cache);
     111           0 :     if (state->user_op == NULL) {
     112           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for users\n");
     113           0 :         ret = EIO;
     114           0 :         goto fail;
     115             :     }
     116             : 
     117           0 :     ret = sdap_dom_enum_ex_retry(req, state->user_op,
     118             :                                  sdap_dom_enum_ex_get_users);
     119           0 :     if (ret != EOK) {
     120           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_ex_retry failed\n");
     121           0 :         goto fail;
     122             :     }
     123             : 
     124           0 :     return req;
     125             : 
     126             : fail:
     127           0 :     tevent_req_error(req, ret);
     128           0 :     tevent_req_post(req, ev);
     129           0 :     return req;
     130             : }
     131             : 
     132           0 : static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
     133             :                                       struct sdap_id_op *op,
     134             :                                       tevent_req_fn tcb)
     135             : {
     136           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     137             :                                                 struct sdap_dom_enum_ex_state);
     138             :     struct tevent_req *subreq;
     139             :     errno_t ret;
     140             : 
     141           0 :     subreq = sdap_id_op_connect_send(op, state, &ret);
     142           0 :     if (subreq == NULL) {
     143           0 :         DEBUG(SSSDBG_OP_FAILURE,
     144             :               "sdap_id_op_connect_send failed: %d\n", ret);
     145           0 :         return ret;
     146             :     }
     147             : 
     148           0 :     tevent_req_set_callback(subreq, tcb, req);
     149           0 :     return EOK;
     150             : }
     151             : 
     152           0 : static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq)
     153             : {
     154             :     errno_t ret;
     155             :     int dp_error;
     156           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     157             :                                                       struct tevent_req);
     158             : 
     159           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     160           0 :     talloc_zfree(subreq);
     161           0 :     if (ret != EOK) {
     162           0 :         if (dp_error == DP_ERR_OFFLINE) {
     163           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     164             :                   "Backend is marked offline, retry later!\n");
     165           0 :             tevent_req_done(req);
     166             :         } else {
     167           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     168             :                   "Domain enumeration failed to connect to " \
     169             :                    "LDAP server: (%d)[%s]\n", ret, strerror(ret));
     170           0 :             tevent_req_error(req, ret);
     171             :         }
     172           0 :         return false;
     173             :     }
     174             : 
     175           0 :     return true;
     176             : }
     177             : 
     178           0 : static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq)
     179             : {
     180           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     181             :                                                       struct tevent_req);
     182           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     183             :                                                 struct sdap_dom_enum_ex_state);
     184             :     bool use_id_mapping;
     185             :     errno_t ret;
     186             : 
     187           0 :     if (sdap_dom_enum_ex_connected(subreq) == false) {
     188           0 :         return;
     189             :     }
     190             : 
     191           0 :     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
     192           0 :                                             state->ctx->opts->idmap_ctx,
     193           0 :                                             state->sdom->dom->name,
     194           0 :                                             state->sdom->dom->domain_id);
     195             : 
     196             :     /* If POSIX attributes have been requested with an AD server and we
     197             :      * have no idea about POSIX attributes support, run a one-time check
     198             :      */
     199           0 :     if (use_id_mapping == false &&
     200           0 :             state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
     201           0 :             state->ctx->srv_opts &&
     202           0 :             state->ctx->srv_opts->posix_checked == false) {
     203           0 :         subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
     204             :                                        sdap_id_op_handle(state->user_op),
     205           0 :                                        state->sdom->user_search_bases,
     206           0 :                                        dp_opt_get_int(state->ctx->opts->basic,
     207             :                                                       SDAP_SEARCH_TIMEOUT));
     208           0 :         if (subreq == NULL) {
     209           0 :             tevent_req_error(req, ENOMEM);
     210           0 :             return;
     211             :         }
     212           0 :         tevent_req_set_callback(subreq,
     213             :                                 sdap_dom_enum_ex_posix_check_done, req);
     214           0 :         return;
     215             :     }
     216             : 
     217             : 
     218           0 :     ret = sdap_dom_enum_search_users(req);
     219           0 :     if (ret != EOK) {
     220           0 :         tevent_req_error(req, ret);
     221           0 :         return;
     222             :     }
     223             :     /* Execution resumes in sdap_dom_enum_ex_users_done */
     224             : }
     225             : 
     226           0 : static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq)
     227             : {
     228             :     errno_t ret;
     229             :     bool has_posix;
     230             :     int dp_error;
     231             : 
     232           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     233             :                                                       struct tevent_req);
     234           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     235             :                                                 struct sdap_dom_enum_ex_state);
     236             : 
     237           0 :     ret = sdap_posix_check_recv(subreq, &has_posix);
     238           0 :     talloc_zfree(subreq);
     239           0 :     if (ret != EOK && ret != ERR_NO_POSIX) {
     240             :         /* We can only finish the id_op on error as the connection
     241             :          * is re-used by the user search
     242             :          */
     243           0 :         ret = sdap_id_op_done(state->user_op, ret, &dp_error);
     244           0 :         if (dp_error == DP_ERR_OK && ret != EOK) {
     245             :             /* retry */
     246           0 :             ret = sdap_dom_enum_ex_retry(req, state->user_op,
     247             :                                          sdap_dom_enum_ex_get_users);
     248           0 :             if (ret != EOK) {
     249           0 :                 tevent_req_error(req, ret);
     250             :             }
     251           0 :             return;
     252           0 :         } else if (dp_error == DP_ERR_OFFLINE) {
     253           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
     254           0 :             tevent_req_done(req);
     255           0 :             return;
     256             :         } else {
     257             :             /* Non-recoverable error */
     258           0 :             DEBUG(SSSDBG_OP_FAILURE,
     259             :                 "POSIX check failed: %d: %s\n", ret, sss_strerror(ret));
     260           0 :             tevent_req_error(req, ret);
     261           0 :             return;
     262             :         }
     263             :     }
     264             : 
     265           0 :     state->ctx->srv_opts->posix_checked = true;
     266             : 
     267             :     /* If the check ran to completion, we know for certain about the attributes
     268             :      */
     269           0 :     if (has_posix == false) {
     270           0 :         tevent_req_error(req, ERR_NO_POSIX);
     271           0 :         return;
     272             :     }
     273             : 
     274             : 
     275           0 :     ret = sdap_dom_enum_search_users(req);
     276           0 :     if (ret != EOK) {
     277           0 :         tevent_req_error(req, ret);
     278           0 :         return;
     279             :     }
     280             :     /* Execution resumes in sdap_dom_enum_ex_users_done */
     281             : }
     282             : 
     283           0 : static errno_t sdap_dom_enum_search_users(struct tevent_req *req)
     284             : {
     285           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     286             :                                                 struct sdap_dom_enum_ex_state);
     287             :     struct tevent_req *subreq;
     288             : 
     289           0 :     subreq = enum_users_send(state, state->ev,
     290             :                              state->ctx, state->sdom,
     291           0 :                              state->user_op, state->purge);
     292           0 :     if (subreq == NULL) {
     293           0 :         return ENOMEM;
     294             :     }
     295           0 :     tevent_req_set_callback(subreq, sdap_dom_enum_ex_users_done, req);
     296           0 :     return EOK;
     297             : }
     298             : 
     299           0 : static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq)
     300             : {
     301           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     302             :                                                       struct tevent_req);
     303           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     304             :                                                 struct sdap_dom_enum_ex_state);
     305             :     errno_t ret;
     306             :     int dp_error;
     307             : 
     308           0 :     ret = enum_users_recv(subreq);
     309           0 :     talloc_zfree(subreq);
     310           0 :     ret = sdap_id_op_done(state->user_op, ret, &dp_error);
     311           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     312             :         /* retry */
     313           0 :         ret = sdap_dom_enum_ex_retry(req, state->user_op,
     314             :                                      sdap_dom_enum_ex_get_users);
     315           0 :         if (ret != EOK) {
     316           0 :             tevent_req_error(req, ret);
     317           0 :             return;
     318             :         }
     319           0 :         return;
     320           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
     321           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
     322           0 :         tevent_req_done(req);
     323           0 :         return;
     324           0 :     } else if (ret != EOK && ret != ENOENT) {
     325             :         /* Non-recoverable error */
     326           0 :         DEBUG(SSSDBG_OP_FAILURE,
     327             :               "User enumeration failed: %d: %s\n", ret, sss_strerror(ret));
     328           0 :         tevent_req_error(req, ret);
     329           0 :         return;
     330             :     }
     331             : 
     332           0 :     state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache);
     333           0 :     if (state->group_op == NULL) {
     334           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for groups\n");
     335           0 :         tevent_req_error(req, EIO);
     336           0 :         return;
     337             :     }
     338             : 
     339           0 :     ret = sdap_dom_enum_ex_retry(req, state->group_op,
     340             :                                  sdap_dom_enum_ex_get_groups);
     341           0 :     if (ret != EOK) {
     342           0 :         tevent_req_error(req, ret);
     343           0 :         return;
     344             :     }
     345             : 
     346             :     /* Continues to sdap_dom_enum_ex_get_groups */
     347             : }
     348             : 
     349           0 : static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq)
     350             : {
     351           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     352             :                                                       struct tevent_req);
     353           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     354             :                                                 struct sdap_dom_enum_ex_state);
     355             : 
     356           0 :     if (sdap_dom_enum_ex_connected(subreq) == false) {
     357           0 :         return;
     358             :     }
     359             : 
     360           0 :     subreq = enum_groups_send(state, state->ev, state->ctx,
     361             :                               state->sdom,
     362           0 :                               state->group_op, state->purge);
     363           0 :     if (subreq == NULL) {
     364           0 :         tevent_req_error(req, ENOMEM);
     365           0 :         return;
     366             :     }
     367           0 :     tevent_req_set_callback(subreq, sdap_dom_enum_ex_groups_done, req);
     368             : }
     369             : 
     370           0 : static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq)
     371             : {
     372           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     373             :                                                       struct tevent_req);
     374           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     375             :                                                 struct sdap_dom_enum_ex_state);
     376             :     int ret;
     377             :     int dp_error;
     378             : 
     379           0 :     ret = enum_groups_recv(subreq);
     380           0 :     talloc_zfree(subreq);
     381           0 :     ret = sdap_id_op_done(state->group_op, ret, &dp_error);
     382           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     383             :         /* retry */
     384           0 :         ret = sdap_dom_enum_ex_retry(req, state->group_op,
     385             :                                      sdap_dom_enum_ex_get_groups);
     386           0 :         if (ret != EOK) {
     387           0 :             tevent_req_error(req, ret);
     388           0 :             return;
     389             :         }
     390           0 :         return;
     391           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
     392           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
     393           0 :         tevent_req_done(req);
     394           0 :         return;
     395           0 :     } else if (ret != EOK && ret != ENOENT) {
     396             :         /* Non-recoverable error */
     397           0 :         DEBUG(SSSDBG_OP_FAILURE,
     398             :               "Group enumeration failed: %d: %s\n", ret, sss_strerror(ret));
     399           0 :         tevent_req_error(req, ret);
     400           0 :         return;
     401             :     }
     402             : 
     403             : 
     404           0 :     state->svc_op = sdap_id_op_create(state, state->svc_conn->conn_cache);
     405           0 :     if (state->svc_op == NULL) {
     406           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for svcs\n");
     407           0 :         tevent_req_error(req, EIO);
     408           0 :         return;
     409             :     }
     410             : 
     411           0 :     ret = sdap_dom_enum_ex_retry(req, state->svc_op,
     412             :                                  sdap_dom_enum_ex_get_svcs);
     413           0 :     if (ret != EOK) {
     414           0 :         tevent_req_error(req, ret);
     415           0 :         return;
     416             :     }
     417             : }
     418             : 
     419           0 : static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq)
     420             : {
     421           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     422             :                                                       struct tevent_req);
     423           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     424             :                                                 struct sdap_dom_enum_ex_state);
     425             : 
     426           0 :     if (sdap_dom_enum_ex_connected(subreq) == false) {
     427           0 :         return;
     428             :     }
     429             : 
     430           0 :     subreq = enum_services_send(state, state->ev, state->ctx,
     431           0 :                                 state->svc_op, state->purge);
     432           0 :     if (!subreq) {
     433           0 :         tevent_req_error(req, ENOMEM);
     434           0 :         return;
     435             :     }
     436           0 :     tevent_req_set_callback(subreq, sdap_dom_enum_ex_svcs_done, req);
     437             : }
     438             : 
     439           0 : static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq)
     440             : {
     441           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     442             :                                                       struct tevent_req);
     443           0 :     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
     444             :                                                 struct sdap_dom_enum_ex_state);
     445             :     int ret;
     446             :     int dp_error;
     447             : 
     448           0 :     ret = enum_services_recv(subreq);
     449           0 :     talloc_zfree(subreq);
     450           0 :     ret = sdap_id_op_done(state->svc_op, ret, &dp_error);
     451           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     452             :         /* retry */
     453           0 :         ret = sdap_dom_enum_ex_retry(req, state->user_op,
     454             :                                      sdap_dom_enum_ex_get_svcs);
     455           0 :         if (ret != EOK) {
     456           0 :             tevent_req_error(req, ret);
     457           0 :             return;
     458             :         }
     459           0 :         return;
     460           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
     461           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
     462           0 :         tevent_req_done(req);
     463           0 :         return;
     464           0 :     } else if (ret != EOK && ret != ENOENT) {
     465             :         /* Non-recoverable error */
     466           0 :         DEBUG(SSSDBG_OP_FAILURE,
     467             :               "Service enumeration failed: %d: %s\n", ret, sss_strerror(ret));
     468           0 :         tevent_req_error(req, ret);
     469           0 :         return;
     470             :     }
     471             : 
     472             :     /* Ok, we've completed an enumeration. Save this to the
     473             :      * sysdb so we can postpone starting up the enumeration
     474             :      * process on the next SSSD service restart (to avoid
     475             :      * slowing down system boot-up
     476             :      */
     477           0 :     ret = sysdb_set_enumerated(state->sdom->dom, true);
     478           0 :     if (ret != EOK) {
     479           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     480             :               "Could not mark domain as having enumerated.\n");
     481             :         /* This error is non-fatal, so continue */
     482             :     }
     483             : 
     484           0 :     if (state->purge) {
     485           0 :         ret = ldap_id_cleanup(state->ctx->opts, state->sdom);
     486           0 :         if (ret != EOK) {
     487             :             /* Not fatal, worst case we'll have stale entries that would be
     488             :              * removed on a subsequent online lookup
     489             :              */
     490           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Cleanup failed: [%d]: %s\n",
     491             :                   ret, sss_strerror(ret));
     492             :         }
     493             :     }
     494             : 
     495           0 :     tevent_req_done(req);
     496             : }
     497             : 
     498           0 : errno_t sdap_dom_enum_ex_recv(struct tevent_req *req)
     499             : {
     500           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     501             : 
     502           0 :     return EOK;
     503             : }
     504             : 
     505             : /* ==Enumeration-Request==================================================== */
     506             : struct tevent_req *
     507           0 : sdap_dom_enum_send(TALLOC_CTX *memctx,
     508             :                    struct tevent_context *ev,
     509             :                    struct sdap_id_ctx *ctx,
     510             :                    struct sdap_domain *sdom,
     511             :                    struct sdap_id_conn_ctx *conn)
     512             : {
     513           0 :     return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom, conn, conn, conn);
     514             : }
     515             : 
     516           0 : errno_t sdap_dom_enum_recv(struct tevent_req *req)
     517             : {
     518           0 :     return sdap_dom_enum_ex_recv(req);
     519             : }
     520             : 
     521             : /* ==User-Enumeration===================================================== */
     522             : struct enum_users_state {
     523             :     struct tevent_context *ev;
     524             :     struct sdap_id_ctx *ctx;
     525             :     struct sdap_domain *sdom;
     526             :     struct sdap_id_op *op;
     527             : 
     528             :     char *filter;
     529             :     const char **attrs;
     530             : };
     531             : 
     532             : static void enum_users_done(struct tevent_req *subreq);
     533             : 
     534           0 : static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
     535             :                                           struct tevent_context *ev,
     536             :                                           struct sdap_id_ctx *ctx,
     537             :                                           struct sdap_domain *sdom,
     538             :                                           struct sdap_id_op *op,
     539             :                                           bool purge)
     540             : {
     541             :     struct tevent_req *req, *subreq;
     542             :     struct enum_users_state *state;
     543             :     int ret;
     544             :     bool use_mapping;
     545             : 
     546           0 :     req = tevent_req_create(memctx, &state, struct enum_users_state);
     547           0 :     if (!req) return NULL;
     548             : 
     549           0 :     state->ev = ev;
     550           0 :     state->sdom = sdom;
     551           0 :     state->ctx = ctx;
     552           0 :     state->op = op;
     553             : 
     554           0 :     use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
     555           0 :                                                         ctx->opts->idmap_ctx,
     556           0 :                                                         sdom->dom->name,
     557           0 :                                                         sdom->dom->domain_id);
     558             : 
     559             :     /* We always want to filter on objectclass and an available name */
     560           0 :     state->filter = talloc_asprintf(state,
     561             :                                   "(&(objectclass=%s)(%s=*)",
     562           0 :                                   ctx->opts->user_map[SDAP_OC_USER].name,
     563           0 :                                   ctx->opts->user_map[SDAP_AT_USER_NAME].name);
     564           0 :     if (!state->filter) {
     565           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     566             :               "Failed to build base filter\n");
     567           0 :         ret = ENOMEM;
     568           0 :         goto fail;
     569             :     }
     570             : 
     571           0 :     if (use_mapping) {
     572             :         /* If we're ID-mapping, check for the objectSID as well */
     573           0 :         state->filter = talloc_asprintf_append_buffer(
     574           0 :                 state->filter, "(%s=*)",
     575           0 :                 ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name);
     576             :     } else {
     577             :         /* We're not ID-mapping, so make sure to only get entries
     578             :          * that have UID and GID
     579             :          */
     580           0 :         state->filter = talloc_asprintf_append_buffer(
     581           0 :                 state->filter, "(%s=*)(%s=*)",
     582           0 :                 ctx->opts->user_map[SDAP_AT_USER_UID].name,
     583           0 :                 ctx->opts->user_map[SDAP_AT_USER_GID].name);
     584             :     }
     585           0 :     if (!state->filter) {
     586           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     587             :               "Failed to build base filter\n");
     588           0 :         ret = ENOMEM;
     589           0 :         goto fail;
     590             :     }
     591             : 
     592           0 :     if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) {
     593             :         /* If we have lastUSN available and we're not doing a full
     594             :          * refresh, limit to changes with a higher entryUSN value.
     595             :          */
     596           0 :         state->filter = talloc_asprintf_append_buffer(
     597           0 :                 state->filter,
     598             :                 "(%s>=%s)(!(%s=%s))",
     599           0 :                 ctx->opts->user_map[SDAP_AT_USER_USN].name,
     600           0 :                 ctx->srv_opts->max_user_value,
     601           0 :                 ctx->opts->user_map[SDAP_AT_USER_USN].name,
     602           0 :                 ctx->srv_opts->max_user_value);
     603             : 
     604           0 :         if (!state->filter) {
     605           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     606             :                   "Failed to build base filter\n");
     607           0 :             ret = ENOMEM;
     608           0 :             goto fail;
     609             :         }
     610             :     }
     611             : 
     612             :     /* Terminate the search filter */
     613           0 :     state->filter = talloc_asprintf_append_buffer(state->filter, ")");
     614           0 :     if (!state->filter) {
     615           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to build base filter\n");
     616           0 :         ret = ENOMEM;
     617           0 :         goto fail;
     618             :     }
     619             : 
     620             :     /* TODO: handle attrs_type */
     621           0 :     ret = build_attrs_from_map(state, ctx->opts->user_map,
     622           0 :                                ctx->opts->user_map_cnt,
     623           0 :                                NULL, &state->attrs, NULL);
     624           0 :     if (ret != EOK) goto fail;
     625             : 
     626             :     /* TODO: restrict the enumerations to using a single
     627             :      * search base at a time.
     628             :      */
     629             : 
     630           0 :     subreq = sdap_get_users_send(state, state->ev,
     631           0 :                                  state->sdom->dom,
     632           0 :                                  state->sdom->dom->sysdb,
     633           0 :                                  state->ctx->opts,
     634           0 :                                  state->sdom->user_search_bases,
     635           0 :                                  sdap_id_op_handle(state->op),
     636           0 :                                  state->attrs, state->filter,
     637           0 :                                  dp_opt_get_int(state->ctx->opts->basic,
     638             :                                                 SDAP_ENUM_SEARCH_TIMEOUT),
     639             :                                  SDAP_LOOKUP_ENUMERATE);
     640           0 :     if (!subreq) {
     641           0 :         ret = ENOMEM;
     642           0 :         goto fail;
     643             :     }
     644           0 :     tevent_req_set_callback(subreq, enum_users_done, req);
     645             : 
     646           0 :     return req;
     647             : 
     648             : fail:
     649           0 :     tevent_req_error(req, ret);
     650           0 :     tevent_req_post(req, ev);
     651           0 :     return req;
     652             : }
     653             : 
     654           0 : static void enum_users_done(struct tevent_req *subreq)
     655             : {
     656           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     657             :                                                       struct tevent_req);
     658           0 :     struct enum_users_state *state = tevent_req_data(req,
     659             :                                                      struct enum_users_state);
     660             :     char *usn_value;
     661           0 :     char *endptr = NULL;
     662             :     unsigned usn_number;
     663             :     int ret;
     664             : 
     665           0 :     ret = sdap_get_users_recv(subreq, state, &usn_value);
     666           0 :     talloc_zfree(subreq);
     667           0 :     if (ret) {
     668           0 :         tevent_req_error(req, ret);
     669           0 :         return;
     670             :     }
     671             : 
     672           0 :     if (usn_value) {
     673           0 :         talloc_zfree(state->ctx->srv_opts->max_user_value);
     674           0 :         state->ctx->srv_opts->max_user_value =
     675           0 :                                         talloc_steal(state->ctx, usn_value);
     676             : 
     677           0 :         usn_number = strtoul(usn_value, &endptr, 10);
     678           0 :         if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
     679           0 :             && (usn_number > state->ctx->srv_opts->last_usn)) {
     680           0 :             state->ctx->srv_opts->last_usn = usn_number;
     681             :         }
     682             :     }
     683             : 
     684           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Users higher USN value: [%s]\n",
     685             :               state->ctx->srv_opts->max_user_value);
     686             : 
     687           0 :     tevent_req_done(req);
     688             : }
     689             : 
     690           0 : static errno_t enum_users_recv(struct tevent_req *req)
     691             : {
     692           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     693             : 
     694           0 :     return EOK;
     695             : }
     696             : 
     697             : /* =Group-Enumeration===================================================== */
     698             : struct enum_groups_state {
     699             :     struct tevent_context *ev;
     700             :     struct sdap_id_ctx *ctx;
     701             :     struct sdap_domain *sdom;
     702             :     struct sdap_id_op *op;
     703             : 
     704             :     char *filter;
     705             :     const char **attrs;
     706             : };
     707             : 
     708             : static void enum_groups_done(struct tevent_req *subreq);
     709             : 
     710           0 : static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
     711             :                                           struct tevent_context *ev,
     712             :                                           struct sdap_id_ctx *ctx,
     713             :                                           struct sdap_domain *sdom,
     714             :                                           struct sdap_id_op *op,
     715             :                                           bool purge)
     716             : {
     717             :     struct tevent_req *req, *subreq;
     718             :     struct enum_groups_state *state;
     719             :     int ret;
     720             :     bool use_mapping;
     721             :     char *oc_list;
     722             : 
     723           0 :     req = tevent_req_create(memctx, &state, struct enum_groups_state);
     724           0 :     if (!req) return NULL;
     725             : 
     726           0 :     state->ev = ev;
     727           0 :     state->sdom = sdom;
     728           0 :     state->ctx = ctx;
     729           0 :     state->op = op;
     730             : 
     731           0 :     use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
     732           0 :                                                         ctx->opts->idmap_ctx,
     733           0 :                                                         sdom->dom->name,
     734           0 :                                                         sdom->dom->domain_id);
     735             : 
     736             :     /* We always want to filter on objectclass and an available name */
     737           0 :     oc_list = sdap_make_oc_list(state, ctx->opts->group_map);
     738           0 :     if (oc_list == NULL) {
     739           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
     740           0 :         ret = ENOMEM;
     741           0 :         goto fail;
     742             :     }
     743             : 
     744           0 :     state->filter = talloc_asprintf(state, "(&(%s)(%s=*)", oc_list,
     745           0 :                                ctx->opts->group_map[SDAP_AT_GROUP_NAME].name);
     746           0 :     if (!state->filter) {
     747           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     748             :               "Failed to build base filter\n");
     749           0 :         ret = ENOMEM;
     750           0 :         goto fail;
     751             :     }
     752             : 
     753           0 :     if (use_mapping) {
     754             :         /* If we're ID-mapping, check for the objectSID as well */
     755           0 :         state->filter = talloc_asprintf_append_buffer(
     756           0 :                 state->filter, "(%s=*)",
     757           0 :                 ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name);
     758             :     } else {
     759             :         /* We're not ID-mapping, so make sure to only get entries
     760             :          * that have a non-zero GID.
     761             :          */
     762           0 :         state->filter = talloc_asprintf_append_buffer(
     763           0 :                 state->filter, "(&(%s=*)(!(%s=0)))",
     764           0 :                 ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
     765           0 :                 ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
     766             :     }
     767           0 :     if (!state->filter) {
     768           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     769             :               "Failed to build base filter\n");
     770           0 :         ret = ENOMEM;
     771           0 :         goto fail;
     772             :     }
     773             : 
     774           0 :     if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) {
     775           0 :         state->filter = talloc_asprintf_append_buffer(
     776           0 :                 state->filter,
     777             :                 "(%s>=%s)(!(%s=%s))",
     778           0 :                 ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
     779           0 :                 ctx->srv_opts->max_group_value,
     780           0 :                 ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
     781           0 :                 ctx->srv_opts->max_group_value);
     782           0 :         if (!state->filter) {
     783           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     784             :                   "Failed to build base filter\n");
     785           0 :             ret = ENOMEM;
     786           0 :             goto fail;
     787             :         }
     788             :     }
     789             : 
     790             :     /* Terminate the search filter */
     791           0 :     state->filter = talloc_asprintf_append_buffer(state->filter, ")");
     792           0 :     if (!state->filter) {
     793           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     794             :               "Failed to build base filter\n");
     795           0 :         ret = ENOMEM;
     796           0 :         goto fail;
     797             :     }
     798             : 
     799             :     /* TODO: handle attrs_type */
     800           0 :     ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
     801           0 :                                NULL, &state->attrs, NULL);
     802           0 :     if (ret != EOK) goto fail;
     803             : 
     804             :     /* TODO: restrict the enumerations to using a single
     805             :      * search base at a time.
     806             :      */
     807             : 
     808           0 :     subreq = sdap_get_groups_send(state, state->ev,
     809           0 :                                   state->sdom,
     810           0 :                                   state->ctx->opts,
     811           0 :                                   sdap_id_op_handle(state->op),
     812           0 :                                   state->attrs, state->filter,
     813           0 :                                   dp_opt_get_int(state->ctx->opts->basic,
     814             :                                                  SDAP_ENUM_SEARCH_TIMEOUT),
     815             :                                   SDAP_LOOKUP_ENUMERATE, false);
     816           0 :     if (!subreq) {
     817           0 :         ret = ENOMEM;
     818           0 :         goto fail;
     819             :     }
     820           0 :     tevent_req_set_callback(subreq, enum_groups_done, req);
     821             : 
     822           0 :     return req;
     823             : 
     824             : fail:
     825           0 :     tevent_req_error(req, ret);
     826           0 :     tevent_req_post(req, ev);
     827           0 :     return req;
     828             : }
     829             : 
     830           0 : static void enum_groups_done(struct tevent_req *subreq)
     831             : {
     832           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     833             :                                                       struct tevent_req);
     834           0 :     struct enum_groups_state *state = tevent_req_data(req,
     835             :                                                  struct enum_groups_state);
     836             :     char *usn_value;
     837           0 :     char *endptr = NULL;
     838             :     unsigned usn_number;
     839             :     int ret;
     840             : 
     841           0 :     ret = sdap_get_groups_recv(subreq, state, &usn_value);
     842           0 :     talloc_zfree(subreq);
     843           0 :     if (ret) {
     844           0 :         tevent_req_error(req, ret);
     845           0 :         return;
     846             :     }
     847             : 
     848           0 :     if (usn_value) {
     849           0 :         talloc_zfree(state->ctx->srv_opts->max_group_value);
     850           0 :         state->ctx->srv_opts->max_group_value =
     851           0 :                                         talloc_steal(state->ctx, usn_value);
     852           0 :         usn_number = strtoul(usn_value, &endptr, 10);
     853           0 :         if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
     854           0 :             && (usn_number > state->ctx->srv_opts->last_usn)) {
     855           0 :             state->ctx->srv_opts->last_usn = usn_number;
     856             :         }
     857             :     }
     858             : 
     859           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Groups higher USN value: [%s]\n",
     860             :               state->ctx->srv_opts->max_group_value);
     861             : 
     862           0 :     tevent_req_done(req);
     863             : }
     864             : 
     865           0 : static errno_t enum_groups_recv(struct tevent_req *req)
     866             : {
     867           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     868             : 
     869           0 :     return EOK;
     870             : }

Generated by: LCOV version 1.10