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

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     LDAP Identity Backend Module
       5             : 
       6             :     Authors:
       7             :         Simo Sorce <ssorce@redhat.com>
       8             : 
       9             :     Copyright (C) 2008 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <errno.h>
      26             : #include <time.h>
      27             : #include <sys/time.h>
      28             : 
      29             : #include "util/util.h"
      30             : #include "util/probes.h"
      31             : #include "util/strtonum.h"
      32             : #include "util/cert.h"
      33             : #include "db/sysdb.h"
      34             : #include "providers/ldap/ldap_common.h"
      35             : #include "providers/ldap/sdap_async.h"
      36             : #include "providers/ldap/sdap_idmap.h"
      37             : #include "providers/ldap/sdap_users.h"
      38             : #include "providers/ad/ad_common.h"
      39             : 
      40             : /* =Users-Related-Functions-(by-name,by-uid)============================== */
      41             : 
      42             : struct users_get_state {
      43             :     struct tevent_context *ev;
      44             :     struct sdap_id_ctx *ctx;
      45             :     struct sdap_domain *sdom;
      46             :     struct sdap_id_conn_ctx *conn;
      47             :     struct sdap_id_op *op;
      48             :     struct sysdb_ctx *sysdb;
      49             :     struct sss_domain_info *domain;
      50             : 
      51             :     const char *name;
      52             :     int filter_type;
      53             : 
      54             :     char *filter;
      55             :     const char **attrs;
      56             :     bool use_id_mapping;
      57             : 
      58             :     int dp_error;
      59             :     int sdap_ret;
      60             :     bool noexist_delete;
      61             : };
      62             : 
      63             : static int users_get_retry(struct tevent_req *req);
      64             : static void users_get_connect_done(struct tevent_req *subreq);
      65             : static void users_get_posix_check_done(struct tevent_req *subreq);
      66             : static void users_get_search(struct tevent_req *req);
      67             : static void users_get_done(struct tevent_req *subreq);
      68             : 
      69           0 : struct tevent_req *users_get_send(TALLOC_CTX *memctx,
      70             :                                   struct tevent_context *ev,
      71             :                                   struct sdap_id_ctx *ctx,
      72             :                                   struct sdap_domain *sdom,
      73             :                                   struct sdap_id_conn_ctx *conn,
      74             :                                   const char *name,
      75             :                                   int filter_type,
      76             :                                   const char *extra_value,
      77             :                                   int attrs_type,
      78             :                                   bool noexist_delete)
      79             : {
      80             :     struct tevent_req *req;
      81             :     struct users_get_state *state;
      82           0 :     const char *attr_name = NULL;
      83           0 :     char *clean_name = NULL;
      84             :     char *endptr;
      85             :     int ret;
      86             :     uid_t uid;
      87             :     enum idmap_error_code err;
      88             :     char *sid;
      89           0 :     char *user_filter = NULL;
      90             : 
      91           0 :     req = tevent_req_create(memctx, &state, struct users_get_state);
      92           0 :     if (!req) return NULL;
      93             : 
      94           0 :     state->ev = ev;
      95           0 :     state->ctx = ctx;
      96           0 :     state->sdom = sdom;
      97           0 :     state->conn = conn;
      98           0 :     state->dp_error = DP_ERR_FATAL;
      99           0 :     state->noexist_delete = noexist_delete;
     100             : 
     101           0 :     state->op = sdap_id_op_create(state, state->conn->conn_cache);
     102           0 :     if (!state->op) {
     103           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     104           0 :         ret = ENOMEM;
     105           0 :         goto done;
     106             :     }
     107             : 
     108           0 :     state->domain = sdom->dom;
     109           0 :     state->sysdb = sdom->dom->sysdb;
     110           0 :     state->name = name;
     111           0 :     state->filter_type = filter_type;
     112             : 
     113           0 :     state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
     114           0 :                                                           ctx->opts->idmap_ctx,
     115           0 :                                                           sdom->dom->name,
     116           0 :                                                           sdom->dom->domain_id);
     117           0 :     switch (filter_type) {
     118             :     case BE_FILTER_WILDCARD:
     119           0 :         attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
     120           0 :         ret = sss_filter_sanitize_ex(state, name, &clean_name,
     121             :                                      LDAP_ALLOWED_WILDCARDS);
     122           0 :         if (ret != EOK) {
     123           0 :             goto done;
     124             :         }
     125           0 :         break;
     126             :     case BE_FILTER_NAME:
     127           0 :         if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) {
     128           0 :             attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name;
     129             :         } else {
     130           0 :             attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
     131             :         }
     132           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     133           0 :         if (ret != EOK) {
     134           0 :             goto done;
     135             :         }
     136           0 :         break;
     137             :     case BE_FILTER_IDNUM:
     138           0 :         if (state->use_id_mapping) {
     139             :             /* If we're ID-mapping, we need to use the objectSID
     140             :              * in the search filter.
     141             :              */
     142           0 :             uid = strtouint32(name, &endptr, 10);
     143           0 :             if (errno != EOK) {
     144           0 :                 ret = EINVAL;
     145           0 :                 goto done;
     146             :             }
     147             : 
     148             :             /* Convert the UID to its objectSID */
     149           0 :             err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map,
     150             :                                         uid, &sid);
     151           0 :             if (err == IDMAP_NO_DOMAIN) {
     152           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     153             :                       "[%s] did not match any configured ID mapping domain\n",
     154             :                        name);
     155             : 
     156           0 :                 ret = sysdb_delete_user(state->domain, NULL, uid);
     157           0 :                 if (ret == ENOENT) {
     158             :                     /* Ignore errors to remove users that were not cached previously */
     159           0 :                     ret = EOK;
     160             :                 }
     161             : 
     162           0 :                 goto done;
     163           0 :             } else if (err != IDMAP_SUCCESS) {
     164           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     165             :                       "Mapping ID [%s] to SID failed: [%s]\n",
     166             :                        name, idmap_error_string(err));
     167           0 :                 ret = EIO;
     168           0 :                 goto done;
     169             :             }
     170             : 
     171           0 :             attr_name = ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name;
     172           0 :             ret = sss_filter_sanitize(state, sid, &clean_name);
     173           0 :             sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid);
     174           0 :             if (ret != EOK) {
     175           0 :                 goto done;
     176             :             }
     177             : 
     178             :         } else {
     179           0 :             attr_name = ctx->opts->user_map[SDAP_AT_USER_UID].name;
     180           0 :             ret = sss_filter_sanitize(state, name, &clean_name);
     181           0 :             if (ret != EOK) {
     182           0 :                 goto done;
     183             :             }
     184             :         }
     185           0 :         break;
     186             :     case BE_FILTER_SECID:
     187           0 :         attr_name = ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name;
     188             : 
     189           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     190           0 :         if (ret != EOK) {
     191           0 :             goto done;
     192             :         }
     193           0 :         break;
     194             :     case BE_FILTER_UUID:
     195           0 :         attr_name = ctx->opts->user_map[SDAP_AT_USER_UUID].name;
     196           0 :         if (attr_name == NULL) {
     197           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     198             :                   "UUID search not configured for this backend.\n");
     199           0 :             ret = EINVAL;
     200           0 :             goto done;
     201             :         }
     202             : 
     203           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     204           0 :         if (ret != EOK) {
     205           0 :             goto done;
     206             :         }
     207           0 :         break;
     208             :     case BE_FILTER_CERT:
     209           0 :         attr_name = ctx->opts->user_map[SDAP_AT_USER_CERT].name;
     210           0 :         if (attr_name == NULL) {
     211           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     212             :                   "Certificate search not configured for this backend.\n");
     213           0 :             ret = EINVAL;
     214           0 :             goto done;
     215             :         }
     216             : 
     217           0 :         ret = sss_cert_derb64_to_ldap_filter(state, name, attr_name,
     218             :                                              &user_filter);
     219           0 :         if (ret != EOK) {
     220           0 :             DEBUG(SSSDBG_OP_FAILURE,
     221             :                   "sss_cert_derb64_to_ldap_filter failed.\n");
     222           0 :             goto done;
     223             :         }
     224           0 :         break;
     225             :     default:
     226           0 :         ret = EINVAL;
     227           0 :         goto done;
     228             :     }
     229             : 
     230           0 :     if (attr_name == NULL) {
     231           0 :         DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n");
     232           0 :         ret = EINVAL;
     233           0 :         goto done;
     234             :     }
     235             : 
     236           0 :     if (user_filter == NULL) {
     237           0 :         user_filter = talloc_asprintf(state, "(%s=%s)", attr_name, clean_name);
     238           0 :         talloc_free(clean_name);
     239           0 :         if (user_filter == NULL) {
     240           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
     241           0 :             ret = ENOMEM;
     242           0 :             goto done;
     243             :         }
     244             :     }
     245             : 
     246           0 :     if (state->use_id_mapping || filter_type == BE_FILTER_SECID) {
     247             :         /* When mapping IDs or looking for SIDs, we don't want to limit
     248             :          * ourselves to users with a UID value. But there must be a SID to map
     249             :          * from.
     250             :          */
     251           0 :         state->filter = talloc_asprintf(state,
     252             :                                         "(&%s(objectclass=%s)(%s=*)(%s=*))",
     253             :                                         user_filter,
     254           0 :                                         ctx->opts->user_map[SDAP_OC_USER].name,
     255           0 :                                         ctx->opts->user_map[SDAP_AT_USER_NAME].name,
     256           0 :                                         ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name);
     257             :     } else {
     258             :         /* When not ID-mapping, make sure there is a non-NULL UID */
     259           0 :         state->filter = talloc_asprintf(state,
     260             :                                         "(&%s(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))",
     261             :                                         user_filter,
     262           0 :                                         ctx->opts->user_map[SDAP_OC_USER].name,
     263           0 :                                         ctx->opts->user_map[SDAP_AT_USER_NAME].name,
     264           0 :                                         ctx->opts->user_map[SDAP_AT_USER_UID].name,
     265           0 :                                         ctx->opts->user_map[SDAP_AT_USER_UID].name);
     266             :     }
     267             : 
     268           0 :     talloc_zfree(user_filter);
     269           0 :     if (!state->filter) {
     270           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n");
     271           0 :         ret = ENOMEM;
     272           0 :         goto done;
     273             :     }
     274             : 
     275             :     /* TODO: handle attrs_type */
     276           0 :     ret = build_attrs_from_map(state, ctx->opts->user_map,
     277           0 :                                ctx->opts->user_map_cnt,
     278           0 :                                NULL, &state->attrs, NULL);
     279           0 :     if (ret != EOK) goto done;
     280             : 
     281           0 :     ret = users_get_retry(req);
     282           0 :     if (ret != EOK) {
     283           0 :         goto done;
     284             :     }
     285             : 
     286           0 :     return req;
     287             : 
     288             : done:
     289           0 :     if (ret != EOK) {
     290           0 :         tevent_req_error(req, ret);
     291             :     } else {
     292           0 :         tevent_req_done(req);
     293             :     }
     294           0 :     return tevent_req_post(req, ev);
     295             : }
     296             : 
     297           0 : static int users_get_retry(struct tevent_req *req)
     298             : {
     299           0 :     struct users_get_state *state = tevent_req_data(req,
     300             :                                                     struct users_get_state);
     301             :     struct tevent_req *subreq;
     302           0 :     int ret = EOK;
     303             : 
     304           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
     305           0 :     if (!subreq) {
     306           0 :         return ret;
     307             :     }
     308             : 
     309           0 :     tevent_req_set_callback(subreq, users_get_connect_done, req);
     310           0 :     return EOK;
     311             : }
     312             : 
     313           0 : static void users_get_connect_done(struct tevent_req *subreq)
     314             : {
     315           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     316             :                                                       struct tevent_req);
     317           0 :     struct users_get_state *state = tevent_req_data(req,
     318             :                                                      struct users_get_state);
     319           0 :     int dp_error = DP_ERR_FATAL;
     320             :     int ret;
     321             : 
     322           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     323           0 :     talloc_zfree(subreq);
     324             : 
     325           0 :     if (ret != EOK) {
     326           0 :         state->dp_error = dp_error;
     327           0 :         tevent_req_error(req, ret);
     328           0 :         return;
     329             :     }
     330             : 
     331             :     /* If POSIX attributes have been requested with an AD server and we
     332             :      * have no idea about POSIX attributes support, run a one-time check
     333             :      */
     334           0 :     if (state->use_id_mapping == false &&
     335           0 :             state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
     336           0 :             state->ctx->srv_opts &&
     337           0 :             state->ctx->srv_opts->posix_checked == false) {
     338           0 :         subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
     339             :                                        sdap_id_op_handle(state->op),
     340           0 :                                        state->sdom->user_search_bases,
     341           0 :                                        dp_opt_get_int(state->ctx->opts->basic,
     342             :                                                       SDAP_SEARCH_TIMEOUT));
     343           0 :         if (subreq == NULL) {
     344           0 :             tevent_req_error(req, ENOMEM);
     345           0 :             return;
     346             :         }
     347           0 :         tevent_req_set_callback(subreq, users_get_posix_check_done, req);
     348           0 :         return;
     349             :     }
     350             : 
     351           0 :     users_get_search(req);
     352             : }
     353             : 
     354           0 : static void users_get_posix_check_done(struct tevent_req *subreq)
     355             : {
     356             :     errno_t ret;
     357             :     errno_t ret2;
     358             :     bool has_posix;
     359             :     int dp_error;
     360           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     361             :                                                       struct tevent_req);
     362           0 :     struct users_get_state *state = tevent_req_data(req,
     363             :                                                     struct users_get_state);
     364             : 
     365           0 :     ret = sdap_posix_check_recv(subreq, &has_posix);
     366           0 :     talloc_zfree(subreq);
     367           0 :     if (ret != EOK) {
     368             :         /* We can only finish the id_op on error as the connection
     369             :          * is re-used by the user search
     370             :          */
     371           0 :         ret2 = sdap_id_op_done(state->op, ret, &dp_error);
     372           0 :         if (dp_error == DP_ERR_OK && ret2 != EOK) {
     373             :             /* retry */
     374           0 :             ret = users_get_retry(req);
     375           0 :             if (ret != EOK) {
     376           0 :                 tevent_req_error(req, ret);
     377             :             }
     378           0 :             return;
     379             :         }
     380             :     }
     381             : 
     382           0 :     state->ctx->srv_opts->posix_checked = true;
     383             : 
     384             :     /* If the check ran to completion, we know for certain about the attributes
     385             :      */
     386           0 :     if (ret == EOK && has_posix == false) {
     387           0 :         state->sdap_ret = ERR_NO_POSIX;
     388           0 :         tevent_req_done(req);
     389           0 :         return;
     390             :     }
     391             : 
     392           0 :     users_get_search(req);
     393             : }
     394             : 
     395           0 : static void users_get_search(struct tevent_req *req)
     396             : {
     397           0 :     struct users_get_state *state = tevent_req_data(req,
     398             :                                                      struct users_get_state);
     399             :     struct tevent_req *subreq;
     400             :     enum sdap_entry_lookup_type lookup_type;
     401             : 
     402           0 :     if (state->filter_type == BE_FILTER_WILDCARD) {
     403           0 :         lookup_type = SDAP_LOOKUP_WILDCARD;
     404             :     } else {
     405           0 :         lookup_type = SDAP_LOOKUP_SINGLE;
     406             :     }
     407             : 
     408           0 :     subreq = sdap_get_users_send(state, state->ev,
     409             :                                  state->domain, state->sysdb,
     410           0 :                                  state->ctx->opts,
     411           0 :                                  state->sdom->user_search_bases,
     412             :                                  sdap_id_op_handle(state->op),
     413           0 :                                  state->attrs, state->filter,
     414           0 :                                  dp_opt_get_int(state->ctx->opts->basic,
     415             :                                                 SDAP_SEARCH_TIMEOUT),
     416             :                                  lookup_type);
     417           0 :     if (!subreq) {
     418           0 :         tevent_req_error(req, ENOMEM);
     419           0 :         return;
     420             :     }
     421           0 :     tevent_req_set_callback(subreq, users_get_done, req);
     422             : }
     423             : 
     424           0 : static void users_get_done(struct tevent_req *subreq)
     425             : {
     426           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     427             :                                                       struct tevent_req);
     428           0 :     struct users_get_state *state = tevent_req_data(req,
     429             :                                                      struct users_get_state);
     430             :     char *endptr;
     431             :     uid_t uid;
     432           0 :     int dp_error = DP_ERR_FATAL;
     433             :     int ret;
     434             : 
     435           0 :     ret = sdap_get_users_recv(subreq, NULL, NULL);
     436           0 :     talloc_zfree(subreq);
     437             : 
     438           0 :     ret = sdap_id_op_done(state->op, ret, &dp_error);
     439           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     440             :         /* retry */
     441           0 :         ret = users_get_retry(req);
     442           0 :         if (ret != EOK) {
     443           0 :             tevent_req_error(req, ret);
     444           0 :             return;
     445             :         }
     446             : 
     447           0 :         return;
     448             :     }
     449             : 
     450           0 :     if ((ret == ENOENT) &&
     451           0 :         (state->ctx->opts->schema_type == SDAP_SCHEMA_RFC2307) &&
     452           0 :         (dp_opt_get_bool(state->ctx->opts->basic,
     453             :                          SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS) == true)) {
     454             :         struct sysdb_attrs **usr_attrs;
     455           0 :         const char *name = NULL;
     456             :         bool fallback;
     457             : 
     458           0 :         switch (state->filter_type) {
     459             :         case BE_FILTER_NAME:
     460           0 :             name = state->name;
     461           0 :             uid = -1;
     462           0 :             fallback = true;
     463           0 :             break;
     464             :         case BE_FILTER_IDNUM:
     465           0 :             uid = (uid_t) strtouint32(state->name, &endptr, 10);
     466           0 :             if (errno || *endptr || (state->name == endptr)) {
     467           0 :                 tevent_req_error(req, errno ? errno : EINVAL);
     468           0 :                 return;
     469             :             }
     470           0 :             fallback = true;
     471           0 :             break;
     472             :         default:
     473           0 :             fallback = false;
     474           0 :             break;
     475             :         }
     476             : 
     477           0 :         if (fallback) {
     478           0 :             ret = sdap_fallback_local_user(state, name, uid, &usr_attrs);
     479           0 :             if (ret == EOK) {
     480           0 :                 ret = sdap_save_user(state, state->ctx->opts, state->domain,
     481             :                                      usr_attrs[0], NULL, 0);
     482             :             }
     483             :         }
     484             :     }
     485           0 :     state->sdap_ret = ret;
     486             : 
     487           0 :     if (ret && ret != ENOENT) {
     488           0 :         state->dp_error = dp_error;
     489           0 :         tevent_req_error(req, ret);
     490           0 :         return;
     491             :     }
     492             : 
     493           0 :     if (ret == ENOENT && state->noexist_delete == true) {
     494           0 :         switch (state->filter_type) {
     495             :         case BE_FILTER_ENUM:
     496           0 :             tevent_req_error(req, ret);
     497           0 :             return;
     498             :         case BE_FILTER_NAME:
     499           0 :             ret = sysdb_delete_user(state->domain, state->name, 0);
     500           0 :             if (ret != EOK && ret != ENOENT) {
     501           0 :                 tevent_req_error(req, ret);
     502           0 :                 return;
     503             :             }
     504           0 :             break;
     505             : 
     506             :         case BE_FILTER_IDNUM:
     507           0 :             uid = (uid_t) strtouint32(state->name, &endptr, 10);
     508           0 :             if (errno || *endptr || (state->name == endptr)) {
     509           0 :                 tevent_req_error(req, errno ? errno : EINVAL);
     510           0 :                 return;
     511             :             }
     512             : 
     513           0 :             ret = sysdb_delete_user(state->domain, NULL, uid);
     514           0 :             if (ret != EOK && ret != ENOENT) {
     515           0 :                 tevent_req_error(req, ret);
     516           0 :                 return;
     517             :             }
     518           0 :             break;
     519             : 
     520             :         case BE_FILTER_SECID:
     521             :         case BE_FILTER_UUID:
     522             :             /* Since it is not clear if the SID/UUID belongs to a user or a
     523             :              * group we have nothing to do here. */
     524           0 :             break;
     525             : 
     526             :         case BE_FILTER_WILDCARD:
     527             :             /* We can't know if all users are up-to-date, especially in a large
     528             :              * environment. Do not delete any records, let the responder fetch
     529             :              * the entries they are requested in
     530             :              */
     531           0 :             break;
     532             : 
     533             :         case BE_FILTER_CERT:
     534           0 :             ret = sysdb_remove_cert(state->domain, state->name);
     535           0 :             if (ret != EOK) {
     536           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Unable to remove user certificate"
     537             :                       "[%d]: %s\n", ret, sss_strerror(ret));
     538           0 :                 tevent_req_error(req, ret);
     539           0 :                 return;
     540             :             }
     541           0 :             break;
     542             : 
     543             :         default:
     544           0 :             tevent_req_error(req, EINVAL);
     545           0 :             return;
     546             :         }
     547             :     }
     548             : 
     549           0 :     state->dp_error = DP_ERR_OK;
     550             :     /* FIXME - return sdap error so that we know the user was not found */
     551           0 :     tevent_req_done(req);
     552             : }
     553             : 
     554           0 : int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
     555             : {
     556           0 :     struct users_get_state *state = tevent_req_data(req,
     557             :                                                     struct users_get_state);
     558             : 
     559           0 :     if (dp_error_out) {
     560           0 :         *dp_error_out = state->dp_error;
     561             :     }
     562             : 
     563           0 :     if (sdap_ret) {
     564           0 :         *sdap_ret = state->sdap_ret;
     565             :     }
     566             : 
     567           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     568             : 
     569           0 :     return EOK;
     570             : }
     571             : 
     572             : /* =Groups-Related-Functions-(by-name,by-uid)============================= */
     573             : 
     574             : struct groups_get_state {
     575             :     struct tevent_context *ev;
     576             :     struct sdap_id_ctx *ctx;
     577             :     struct sdap_domain *sdom;
     578             :     struct sdap_id_conn_ctx *conn;
     579             :     struct sdap_id_op *op;
     580             :     struct sysdb_ctx *sysdb;
     581             :     struct sss_domain_info *domain;
     582             : 
     583             :     const char *name;
     584             :     int filter_type;
     585             : 
     586             :     char *filter;
     587             :     const char **attrs;
     588             :     bool use_id_mapping;
     589             : 
     590             :     int dp_error;
     591             :     int sdap_ret;
     592             :     bool noexist_delete;
     593             :     bool no_members;
     594             : };
     595             : 
     596             : static int groups_get_retry(struct tevent_req *req);
     597             : static void groups_get_connect_done(struct tevent_req *subreq);
     598             : static void groups_get_posix_check_done(struct tevent_req *subreq);
     599             : static void groups_get_search(struct tevent_req *req);
     600             : static void groups_get_done(struct tevent_req *subreq);
     601             : 
     602           0 : struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
     603             :                                    struct tevent_context *ev,
     604             :                                    struct sdap_id_ctx *ctx,
     605             :                                    struct sdap_domain *sdom,
     606             :                                    struct sdap_id_conn_ctx *conn,
     607             :                                    const char *name,
     608             :                                    int filter_type,
     609             :                                    int attrs_type,
     610             :                                    bool noexist_delete,
     611             :                                    bool no_members)
     612             : {
     613             :     struct tevent_req *req;
     614             :     struct groups_get_state *state;
     615           0 :     const char *attr_name = NULL;
     616             :     char *clean_name;
     617             :     char *endptr;
     618             :     int ret;
     619             :     gid_t gid;
     620             :     enum idmap_error_code err;
     621             :     char *sid;
     622             :     const char *member_filter[2];
     623             :     char *oc_list;
     624             : 
     625           0 :     req = tevent_req_create(memctx, &state, struct groups_get_state);
     626           0 :     if (!req) return NULL;
     627             : 
     628           0 :     state->ev = ev;
     629           0 :     state->ctx = ctx;
     630           0 :     state->sdom = sdom;
     631           0 :     state->conn = conn;
     632           0 :     state->dp_error = DP_ERR_FATAL;
     633           0 :     state->noexist_delete = noexist_delete;
     634           0 :     state->no_members = no_members;
     635             : 
     636           0 :     state->op = sdap_id_op_create(state, state->conn->conn_cache);
     637           0 :     if (!state->op) {
     638           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     639           0 :         ret = ENOMEM;
     640           0 :         goto done;
     641             :     }
     642             : 
     643           0 :     state->domain = sdom->dom;
     644           0 :     state->sysdb = sdom->dom->sysdb;
     645           0 :     state->name = name;
     646           0 :     state->filter_type = filter_type;
     647             : 
     648           0 :     state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
     649           0 :                                                           ctx->opts->idmap_ctx,
     650           0 :                                                           sdom->dom->name,
     651           0 :                                                           sdom->dom->domain_id);
     652             : 
     653           0 :     switch(filter_type) {
     654             :     case BE_FILTER_WILDCARD:
     655           0 :         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
     656           0 :         ret = sss_filter_sanitize_ex(state, name, &clean_name,
     657             :                                      LDAP_ALLOWED_WILDCARDS);
     658           0 :         if (ret != EOK) {
     659           0 :             goto done;
     660             :         }
     661           0 :         break;
     662             :     case BE_FILTER_NAME:
     663           0 :         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
     664             : 
     665           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     666           0 :         if (ret != EOK) {
     667           0 :             goto done;
     668             :         }
     669           0 :         break;
     670             :     case BE_FILTER_IDNUM:
     671           0 :         if (state->use_id_mapping) {
     672             :             /* If we're ID-mapping, we need to use the objectSID
     673             :              * in the search filter.
     674             :              */
     675           0 :             gid = strtouint32(name, &endptr, 10);
     676           0 :             if (errno != EOK) {
     677           0 :                 ret = EINVAL;
     678           0 :                 goto done;
     679             :             }
     680             : 
     681             :             /* Convert the GID to its objectSID */
     682           0 :             err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map,
     683             :                                         gid, &sid);
     684           0 :             if (err == IDMAP_NO_DOMAIN) {
     685           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     686             :                       "[%s] did not match any configured ID mapping domain\n",
     687             :                        name);
     688             : 
     689           0 :                 ret = sysdb_delete_group(state->domain, NULL, gid);
     690           0 :                 if (ret == ENOENT) {
     691             :                     /* Ignore errors to remove users that were not cached previously */
     692           0 :                     ret = EOK;
     693             :                 }
     694             : 
     695           0 :                 goto done;
     696           0 :             } else if (err != IDMAP_SUCCESS) {
     697           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     698             :                       "Mapping ID [%s] to SID failed: [%s]\n",
     699             :                        name, idmap_error_string(err));
     700           0 :                 ret = EIO;
     701           0 :                 goto done;
     702             :             }
     703             : 
     704           0 :             attr_name = ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name;
     705           0 :             ret = sss_filter_sanitize(state, sid, &clean_name);
     706           0 :             sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid);
     707           0 :             if (ret != EOK) {
     708           0 :                 goto done;
     709             :             }
     710             : 
     711             :         } else {
     712           0 :             attr_name = ctx->opts->group_map[SDAP_AT_GROUP_GID].name;
     713           0 :             ret = sss_filter_sanitize(state, name, &clean_name);
     714           0 :             if (ret != EOK) {
     715           0 :                 goto done;
     716             :             }
     717             :         }
     718           0 :         break;
     719             :     case BE_FILTER_SECID:
     720           0 :         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name;
     721             : 
     722           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     723           0 :         if (ret != EOK) {
     724           0 :             goto done;
     725             :         }
     726           0 :         break;
     727             :     case BE_FILTER_UUID:
     728           0 :         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_UUID].name;
     729           0 :         if (attr_name == NULL) {
     730           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     731             :                   "UUID search not configured for this backend.\n");
     732           0 :             ret = EINVAL;
     733           0 :             goto done;
     734             :         }
     735             : 
     736           0 :         ret = sss_filter_sanitize(state, name, &clean_name);
     737           0 :         if (ret != EOK) {
     738           0 :             goto done;
     739             :         }
     740           0 :         break;
     741             :     default:
     742           0 :         ret = EINVAL;
     743           0 :         goto done;
     744             :     }
     745             : 
     746           0 :     if (attr_name == NULL) {
     747           0 :         DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n");
     748           0 :         ret = EINVAL;
     749           0 :         goto done;
     750             :     }
     751             : 
     752           0 :     oc_list = sdap_make_oc_list(state, ctx->opts->group_map);
     753           0 :     if (oc_list == NULL) {
     754           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
     755           0 :         ret = ENOMEM;
     756           0 :         goto done;
     757             :     }
     758             : 
     759           0 :     if (state->use_id_mapping || filter_type == BE_FILTER_SECID) {
     760             :         /* When mapping IDs or looking for SIDs, we don't want to limit
     761             :          * ourselves to groups with a GID value
     762             :          */
     763             : 
     764           0 :         state->filter = talloc_asprintf(state,
     765             :                                         "(&(%s=%s)(%s)(%s=*))",
     766             :                                         attr_name, clean_name, oc_list,
     767           0 :                                         ctx->opts->group_map[SDAP_AT_GROUP_NAME].name);
     768             :     } else {
     769           0 :         state->filter = talloc_asprintf(state,
     770             :                                         "(&(%s=%s)(%s)(%s=*)(&(%s=*)(!(%s=0))))",
     771             :                                         attr_name, clean_name, oc_list,
     772           0 :                                         ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
     773           0 :                                         ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
     774           0 :                                         ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
     775             :     }
     776             : 
     777           0 :     talloc_zfree(clean_name);
     778           0 :     if (!state->filter) {
     779           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n");
     780           0 :         ret = ENOMEM;
     781           0 :         goto done;
     782             :     }
     783             : 
     784           0 :     member_filter[0] = (const char *)ctx->opts->group_map[SDAP_AT_GROUP_MEMBER].name;
     785           0 :     member_filter[1] = NULL;
     786             : 
     787             :     /* TODO: handle attrs_type */
     788           0 :     ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
     789           0 :                                (state->domain->ignore_group_members
     790           0 :                                     || state->no_members) ?
     791             :                                    (const char **)member_filter : NULL,
     792           0 :                                &state->attrs, NULL);
     793             : 
     794           0 :     if (ret != EOK) goto done;
     795             : 
     796           0 :     ret = groups_get_retry(req);
     797           0 :     if (ret != EOK) {
     798           0 :         goto done;
     799             :     }
     800             : 
     801           0 :     return req;
     802             : 
     803             : done:
     804           0 :     if (ret != EOK) {
     805           0 :         tevent_req_error(req, ret);
     806             :     } else {
     807           0 :         tevent_req_done(req);
     808             :     }
     809           0 :     return tevent_req_post(req, ev);
     810             : }
     811             : 
     812           0 : static int groups_get_retry(struct tevent_req *req)
     813             : {
     814           0 :     struct groups_get_state *state = tevent_req_data(req,
     815             :                                                     struct groups_get_state);
     816             :     struct tevent_req *subreq;
     817           0 :     int ret = EOK;
     818             : 
     819           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
     820           0 :     if (!subreq) {
     821           0 :         return ret;
     822             :     }
     823             : 
     824           0 :     tevent_req_set_callback(subreq, groups_get_connect_done, req);
     825           0 :     return EOK;
     826             : }
     827             : 
     828           0 : static void groups_get_connect_done(struct tevent_req *subreq)
     829             : {
     830           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     831             :                                                       struct tevent_req);
     832           0 :     struct groups_get_state *state = tevent_req_data(req,
     833             :                                                      struct groups_get_state);
     834           0 :     int dp_error = DP_ERR_FATAL;
     835             :     int ret;
     836             : 
     837           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     838           0 :     talloc_zfree(subreq);
     839             : 
     840           0 :     if (ret != EOK) {
     841           0 :         state->dp_error = dp_error;
     842           0 :         tevent_req_error(req, ret);
     843           0 :         return;
     844             :     }
     845             : 
     846             :     /* If POSIX attributes have been requested with an AD server and we
     847             :      * have no idea about POSIX attributes support, run a one-time check
     848             :      */
     849           0 :     if (state->use_id_mapping == false &&
     850           0 :             state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
     851           0 :             state->ctx->srv_opts &&
     852           0 :             state->ctx->srv_opts->posix_checked == false) {
     853           0 :         subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
     854             :                                        sdap_id_op_handle(state->op),
     855           0 :                                        state->sdom->user_search_bases,
     856           0 :                                        dp_opt_get_int(state->ctx->opts->basic,
     857             :                                                       SDAP_SEARCH_TIMEOUT));
     858           0 :         if (subreq == NULL) {
     859           0 :             tevent_req_error(req, ENOMEM);
     860           0 :             return;
     861             :         }
     862           0 :         tevent_req_set_callback(subreq, groups_get_posix_check_done, req);
     863           0 :         return;
     864             :     }
     865             : 
     866           0 :     groups_get_search(req);
     867             : }
     868             : 
     869           0 : static void groups_get_posix_check_done(struct tevent_req *subreq)
     870             : {
     871             :     errno_t ret;
     872             :     bool has_posix;
     873             :     int dp_error;
     874           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     875             :                                                       struct tevent_req);
     876           0 :     struct groups_get_state *state = tevent_req_data(req,
     877             :                                                      struct groups_get_state);
     878             : 
     879           0 :     ret = sdap_posix_check_recv(subreq, &has_posix);
     880           0 :     talloc_zfree(subreq);
     881           0 :     if (ret != EOK) {
     882             :         /* We can only finish the id_op on error as the connection
     883             :          * is re-used by the group search
     884             :          */
     885           0 :         ret = sdap_id_op_done(state->op, ret, &dp_error);
     886           0 :         if (dp_error == DP_ERR_OK && ret != EOK) {
     887             :             /* retry */
     888           0 :             ret = groups_get_retry(req);
     889           0 :             if (ret != EOK) {
     890           0 :                 tevent_req_error(req, ret);
     891             :             }
     892           0 :             return;
     893             :         }
     894             :     }
     895             : 
     896           0 :     state->ctx->srv_opts->posix_checked = true;
     897             : 
     898             :     /* If the check ran to completion, we know for certain about the attributes
     899             :      */
     900           0 :     if (has_posix == false) {
     901           0 :         state->sdap_ret = ERR_NO_POSIX;
     902           0 :         tevent_req_done(req);
     903           0 :         return;
     904             :     }
     905             : 
     906           0 :     groups_get_search(req);
     907             : }
     908             : 
     909           0 : static void groups_get_search(struct tevent_req *req)
     910             : {
     911           0 :     struct groups_get_state *state = tevent_req_data(req,
     912             :                                                      struct groups_get_state);
     913             :     struct tevent_req *subreq;
     914             :     enum sdap_entry_lookup_type lookup_type;
     915             : 
     916           0 :     if (state->filter_type == BE_FILTER_WILDCARD) {
     917           0 :         lookup_type = SDAP_LOOKUP_WILDCARD;
     918             :     } else {
     919           0 :         lookup_type = SDAP_LOOKUP_SINGLE;
     920             :     }
     921             : 
     922           0 :     subreq = sdap_get_groups_send(state, state->ev,
     923             :                                   state->sdom,
     924           0 :                                   state->ctx->opts,
     925             :                                   sdap_id_op_handle(state->op),
     926           0 :                                   state->attrs, state->filter,
     927           0 :                                   dp_opt_get_int(state->ctx->opts->basic,
     928             :                                                  SDAP_SEARCH_TIMEOUT),
     929             :                                   lookup_type,
     930           0 :                                   state->no_members);
     931           0 :     if (!subreq) {
     932           0 :         tevent_req_error(req, ENOMEM);
     933           0 :         return;
     934             :     }
     935           0 :     tevent_req_set_callback(subreq, groups_get_done, req);
     936             : }
     937             : 
     938           0 : static void groups_get_done(struct tevent_req *subreq)
     939             : {
     940           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     941             :                                                       struct tevent_req);
     942           0 :     struct groups_get_state *state = tevent_req_data(req,
     943             :                                                      struct groups_get_state);
     944             :     char *endptr;
     945             :     gid_t gid;
     946           0 :     int dp_error = DP_ERR_FATAL;
     947             :     int ret;
     948             : 
     949           0 :     ret = sdap_get_groups_recv(subreq, NULL, NULL);
     950           0 :     talloc_zfree(subreq);
     951           0 :     ret = sdap_id_op_done(state->op, ret, &dp_error);
     952             : 
     953           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     954             :         /* retry */
     955           0 :         ret = groups_get_retry(req);
     956           0 :         if (ret != EOK) {
     957           0 :             tevent_req_error(req, ret);
     958           0 :             return;
     959             :         }
     960             : 
     961           0 :         return;
     962             :     }
     963           0 :     state->sdap_ret = ret;
     964             : 
     965           0 :     if (ret && ret != ENOENT) {
     966           0 :         state->dp_error = dp_error;
     967           0 :         tevent_req_error(req, ret);
     968           0 :         return;
     969             :     }
     970             : 
     971           0 :     if (ret == ENOENT && state->noexist_delete == true) {
     972           0 :         switch (state->filter_type) {
     973             :         case BE_FILTER_ENUM:
     974           0 :             tevent_req_error(req, ret);
     975           0 :             return;
     976             :         case BE_FILTER_NAME:
     977           0 :             ret = sysdb_delete_group(state->domain, state->name, 0);
     978           0 :             if (ret != EOK && ret != ENOENT) {
     979           0 :                 tevent_req_error(req, ret);
     980           0 :                 return;
     981             :             }
     982           0 :             break;
     983             : 
     984             :         case BE_FILTER_IDNUM:
     985           0 :             gid = (gid_t) strtouint32(state->name, &endptr, 10);
     986           0 :             if (errno || *endptr || (state->name == endptr)) {
     987           0 :                 tevent_req_error(req, errno ? errno : EINVAL);
     988           0 :                 return;
     989             :             }
     990             : 
     991           0 :             ret = sysdb_delete_group(state->domain, NULL, gid);
     992           0 :             if (ret != EOK && ret != ENOENT) {
     993           0 :                 tevent_req_error(req, ret);
     994           0 :                 return;
     995             :             }
     996           0 :             break;
     997             : 
     998             :         case BE_FILTER_SECID:
     999             :         case BE_FILTER_UUID:
    1000             :             /* Since it is not clear if the SID/UUID belongs to a user or a
    1001             :              * group we have nothing to do here. */
    1002           0 :             break;
    1003             : 
    1004             :         case BE_FILTER_WILDCARD:
    1005             :             /* We can't know if all groups are up-to-date, especially in
    1006             :              * a large environment. Do not delete any records, let the
    1007             :              * responder fetch the entries they are requested in.
    1008             :              */
    1009           0 :             break;
    1010             : 
    1011             : 
    1012             :         default:
    1013           0 :             tevent_req_error(req, EINVAL);
    1014           0 :             return;
    1015             :         }
    1016             :     }
    1017             : 
    1018           0 :     state->dp_error = DP_ERR_OK;
    1019           0 :     tevent_req_done(req);
    1020             : }
    1021             : 
    1022           0 : int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
    1023             : {
    1024           0 :     struct groups_get_state *state = tevent_req_data(req,
    1025             :                                                      struct groups_get_state);
    1026             : 
    1027           0 :     if (dp_error_out) {
    1028           0 :         *dp_error_out = state->dp_error;
    1029             :     }
    1030             : 
    1031           0 :     if (sdap_ret) {
    1032           0 :         *sdap_ret = state->sdap_ret;
    1033             :     }
    1034             : 
    1035           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1036             : 
    1037           0 :     return EOK;
    1038             : }
    1039             : 
    1040             : 
    1041             : /* =Get-Groups-for-User================================================== */
    1042             : 
    1043             : struct groups_by_user_state {
    1044             :     struct tevent_context *ev;
    1045             :     struct sdap_id_ctx *ctx;
    1046             :     struct sdap_domain *sdom;
    1047             :     struct sdap_id_conn_ctx *conn;
    1048             :     struct sdap_id_op *op;
    1049             :     struct sysdb_ctx *sysdb;
    1050             :     struct sss_domain_info *domain;
    1051             : 
    1052             :     const char *name;
    1053             :     int name_type;
    1054             :     const char *extra_value;
    1055             :     const char **attrs;
    1056             : 
    1057             :     int dp_error;
    1058             :     int sdap_ret;
    1059             :     bool noexist_delete;
    1060             : };
    1061             : 
    1062             : static int groups_by_user_retry(struct tevent_req *req);
    1063             : static void groups_by_user_connect_done(struct tevent_req *subreq);
    1064             : static void groups_by_user_done(struct tevent_req *subreq);
    1065             : 
    1066           0 : static errno_t set_initgroups_expire_attribute(struct sss_domain_info *domain,
    1067             :                                                const char *name)
    1068             : {
    1069             :     errno_t ret;
    1070             :     time_t cache_timeout;
    1071             :     struct sysdb_attrs *attrs;
    1072             : 
    1073           0 :     attrs = sysdb_new_attrs(NULL);
    1074           0 :     if (attrs == NULL) {
    1075           0 :         return ENOMEM;
    1076             :     }
    1077             : 
    1078           0 :     cache_timeout = domain->user_timeout
    1079           0 :                         ? time(NULL) + domain->user_timeout
    1080           0 :                         : 0;
    1081             : 
    1082           0 :     ret = sysdb_attrs_add_time_t(attrs, SYSDB_INITGR_EXPIRE, cache_timeout);
    1083           0 :     if (ret != EOK) {
    1084           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up attrs\n");
    1085           0 :         goto done;
    1086             :     }
    1087             : 
    1088           0 :     ret = sysdb_set_user_attr(domain, name, attrs, SYSDB_MOD_REP);
    1089           0 :     if (ret != EOK) {
    1090           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1091             :               "Failed to set initgroups expire attribute\n");
    1092           0 :         goto done;
    1093             :     }
    1094             : 
    1095             : done:
    1096           0 :     talloc_zfree(attrs);
    1097           0 :     return ret;
    1098             : }
    1099             : 
    1100           0 : static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
    1101             :                                               struct tevent_context *ev,
    1102             :                                               struct sdap_id_ctx *ctx,
    1103             :                                               struct sdap_domain *sdom,
    1104             :                                               struct sdap_id_conn_ctx *conn,
    1105             :                                               const char *name,
    1106             :                                               int name_type,
    1107             :                                               const char *extra_value,
    1108             :                                               bool noexist_delete)
    1109             : {
    1110             :     struct tevent_req *req;
    1111             :     struct groups_by_user_state *state;
    1112             :     int ret;
    1113             : 
    1114           0 :     req = tevent_req_create(memctx, &state, struct groups_by_user_state);
    1115           0 :     if (!req) return NULL;
    1116             : 
    1117           0 :     state->ev = ev;
    1118           0 :     state->ctx = ctx;
    1119           0 :     state->dp_error = DP_ERR_FATAL;
    1120           0 :     state->conn = conn;
    1121           0 :     state->sdom = sdom;
    1122           0 :     state->noexist_delete = noexist_delete;
    1123             : 
    1124           0 :     state->op = sdap_id_op_create(state, state->conn->conn_cache);
    1125           0 :     if (!state->op) {
    1126           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
    1127           0 :         ret = ENOMEM;
    1128           0 :         goto fail;
    1129             :     }
    1130             : 
    1131           0 :     state->name = name;
    1132           0 :     state->name_type = name_type;
    1133           0 :     state->extra_value = extra_value;
    1134           0 :     state->domain = sdom->dom;
    1135           0 :     state->sysdb = sdom->dom->sysdb;
    1136             : 
    1137           0 :     ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
    1138           0 :                                NULL, &state->attrs, NULL);
    1139           0 :     if (ret != EOK) goto fail;
    1140             : 
    1141           0 :     ret = groups_by_user_retry(req);
    1142           0 :     if (ret != EOK) {
    1143           0 :         goto fail;
    1144             :     }
    1145             : 
    1146           0 :     return req;
    1147             : 
    1148             : fail:
    1149           0 :     tevent_req_error(req, ret);
    1150           0 :     tevent_req_post(req, ev);
    1151           0 :     return req;
    1152             : }
    1153             : 
    1154           0 : static int groups_by_user_retry(struct tevent_req *req)
    1155             : {
    1156           0 :     struct groups_by_user_state *state = tevent_req_data(req,
    1157             :                                                          struct groups_by_user_state);
    1158             :     struct tevent_req *subreq;
    1159           0 :     int ret = EOK;
    1160             : 
    1161           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
    1162           0 :     if (!subreq) {
    1163           0 :         return ret;
    1164             :     }
    1165             : 
    1166           0 :     tevent_req_set_callback(subreq, groups_by_user_connect_done, req);
    1167           0 :     return EOK;
    1168             : }
    1169             : 
    1170           0 : static void groups_by_user_connect_done(struct tevent_req *subreq)
    1171             : {
    1172           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1173             :                                                       struct tevent_req);
    1174           0 :     struct groups_by_user_state *state = tevent_req_data(req,
    1175             :                                                      struct groups_by_user_state);
    1176           0 :     int dp_error = DP_ERR_FATAL;
    1177             :     int ret;
    1178             : 
    1179           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
    1180           0 :     talloc_zfree(subreq);
    1181             : 
    1182           0 :     if (ret != EOK) {
    1183           0 :         state->dp_error = dp_error;
    1184           0 :         tevent_req_error(req, ret);
    1185           0 :         return;
    1186             :     }
    1187             : 
    1188           0 :     subreq = sdap_get_initgr_send(state,
    1189             :                                   state->ev,
    1190             :                                   state->sdom,
    1191             :                                   sdap_id_op_handle(state->op),
    1192             :                                   state->ctx,
    1193             :                                   state->conn,
    1194             :                                   state->name,
    1195             :                                   state->name_type,
    1196             :                                   state->extra_value,
    1197             :                                   state->attrs);
    1198           0 :     if (!subreq) {
    1199           0 :         tevent_req_error(req, ENOMEM);
    1200           0 :         return;
    1201             :     }
    1202           0 :     tevent_req_set_callback(subreq, groups_by_user_done, req);
    1203             : }
    1204             : 
    1205           0 : static void groups_by_user_done(struct tevent_req *subreq)
    1206             : {
    1207           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1208             :                                                       struct tevent_req);
    1209           0 :     struct groups_by_user_state *state = tevent_req_data(req,
    1210             :                                                      struct groups_by_user_state);
    1211           0 :     int dp_error = DP_ERR_FATAL;
    1212             :     int ret;
    1213             :     const char *cname;
    1214             : 
    1215           0 :     ret = sdap_get_initgr_recv(subreq);
    1216           0 :     talloc_zfree(subreq);
    1217           0 :     ret = sdap_id_op_done(state->op, ret, &dp_error);
    1218             : 
    1219           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
    1220             :         /* retry */
    1221           0 :         ret = groups_by_user_retry(req);
    1222           0 :         if (ret != EOK) {
    1223           0 :             tevent_req_error(req, ret);
    1224           0 :             return;
    1225             :         }
    1226             : 
    1227           0 :         return;
    1228             :     }
    1229           0 :     state->sdap_ret = ret;
    1230             : 
    1231           0 :     if (ret == EOK || ret == ENOENT) {
    1232             :         /* state->name is still the name used for the original req. The cached
    1233             :          * object might have a different name, e.g. a fully-qualified name. */
    1234           0 :         ret = sysdb_get_real_name(state, state->domain, state->name, &cname);
    1235           0 :         if (ret != EOK) {
    1236           0 :             cname = state->name;
    1237           0 :             DEBUG(SSSDBG_TRACE_INTERNAL,
    1238             :                   "Failed to canonicalize name, using [%s] [%d]: %s.\n",
    1239             :                   cname, ret, sss_strerror(ret));
    1240             :         }
    1241             :     }
    1242             : 
    1243           0 :     switch (state->sdap_ret) {
    1244             :     case ENOENT:
    1245           0 :         if (state->noexist_delete == true) {
    1246           0 :             ret = sysdb_delete_user(state->domain, cname, 0);
    1247           0 :             if (ret != EOK && ret != ENOENT) {
    1248           0 :                 tevent_req_error(req, ret);
    1249           0 :                 return;
    1250             :             }
    1251             :         }
    1252           0 :         break;
    1253             :     case EOK:
    1254           0 :         ret = set_initgroups_expire_attribute(state->domain, cname);
    1255           0 :         if (ret != EOK) {
    1256           0 :             state->dp_error = DP_ERR_FATAL;
    1257           0 :             tevent_req_error(req, ret);
    1258           0 :             return;
    1259             :         }
    1260           0 :         break;
    1261             :     default:
    1262           0 :         state->dp_error = dp_error;
    1263           0 :         tevent_req_error(req, ret);
    1264           0 :         return;
    1265             :     }
    1266             : 
    1267           0 :     state->dp_error = DP_ERR_OK;
    1268           0 :     tevent_req_done(req);
    1269             : }
    1270             : 
    1271           0 : int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
    1272             : {
    1273           0 :     struct groups_by_user_state *state = tevent_req_data(req,
    1274             :                                                              struct groups_by_user_state);
    1275             : 
    1276           0 :     if (dp_error_out) {
    1277           0 :         *dp_error_out = state->dp_error;
    1278             :     }
    1279             : 
    1280           0 :     if (sdap_ret) {
    1281           0 :         *sdap_ret = state->sdap_ret;
    1282             :     }
    1283             : 
    1284           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1285             : 
    1286           0 :     return EOK;
    1287             : }
    1288             : 
    1289             : /* =Get-Account-Info-Call================================================= */
    1290             : 
    1291             : /* FIXME: embed this function in sssd_be and only call out
    1292             :  * specific functions from modules ? */
    1293             : 
    1294             : static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
    1295             :                                                   struct tevent_context *ev,
    1296             :                                                   struct sdap_id_ctx *ctx,
    1297             :                                                   struct sdap_domain *sdom,
    1298             :                                                   struct sdap_id_conn_ctx *conn,
    1299             :                                                   const char *name,
    1300             :                                                   int filter_type,
    1301             :                                                   int attrs_type,
    1302             :                                                   bool noexist_delete);
    1303             : 
    1304             : errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
    1305             :                                      int *dp_error_out, int *sdap_ret);
    1306             : 
    1307           0 : bool sdap_is_enum_request(struct be_acct_req *ar)
    1308             : {
    1309           0 :     switch (ar->entry_type & BE_REQ_TYPE_MASK) {
    1310             :     case BE_REQ_USER:
    1311             :     case BE_REQ_GROUP:
    1312             :     case BE_REQ_SERVICES:
    1313           0 :         if (ar->filter_type == BE_FILTER_ENUM) {
    1314           0 :             return true;
    1315             :         }
    1316             :     }
    1317             : 
    1318           0 :     return false;
    1319             : }
    1320             : 
    1321             : /* A generic LDAP account info handler */
    1322             : struct sdap_handle_acct_req_state {
    1323             :     struct be_acct_req *ar;
    1324             :     const char *err;
    1325             :     int dp_error;
    1326             :     int sdap_ret;
    1327             : };
    1328             : 
    1329             : static void sdap_handle_acct_req_done(struct tevent_req *subreq);
    1330             : 
    1331             : struct tevent_req *
    1332           0 : sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
    1333             :                           struct be_ctx *be_ctx,
    1334             :                           struct be_acct_req *ar,
    1335             :                           struct sdap_id_ctx *id_ctx,
    1336             :                           struct sdap_domain *sdom,
    1337             :                           struct sdap_id_conn_ctx *conn,
    1338             :                           bool noexist_delete)
    1339             : {
    1340             :     struct tevent_req *req;
    1341             :     struct tevent_req *subreq;
    1342             :     struct sdap_handle_acct_req_state *state;
    1343             :     errno_t ret;
    1344             : 
    1345             : 
    1346           0 :     req = tevent_req_create(mem_ctx, &state,
    1347             :                             struct sdap_handle_acct_req_state);
    1348           0 :     if (!req) {
    1349           0 :         return NULL;
    1350             :     }
    1351           0 :     state->ar = ar;
    1352             : 
    1353           0 :     if (ar == NULL) {
    1354           0 :         ret = EINVAL;
    1355           0 :         goto done;
    1356             :     }
    1357             : 
    1358             :     PROBE(SDAP_ACCT_REQ_SEND,
    1359             :           state->ar->entry_type & BE_REQ_TYPE_MASK,
    1360             :           state->ar->filter_type, state->ar->filter_value,
    1361             :           PROBE_SAFE_STR(state->ar->extra_value));
    1362             : 
    1363           0 :     switch (ar->entry_type & BE_REQ_TYPE_MASK) {
    1364             :     case BE_REQ_USER: /* user */
    1365           0 :         subreq = users_get_send(state, be_ctx->ev, id_ctx,
    1366             :                                 sdom, conn,
    1367             :                                 ar->filter_value,
    1368           0 :                                 ar->filter_type,
    1369             :                                 ar->extra_value,
    1370           0 :                                 ar->attr_type,
    1371             :                                 noexist_delete);
    1372           0 :         break;
    1373             : 
    1374             :     case BE_REQ_GROUP: /* group */
    1375           0 :         subreq = groups_get_send(state, be_ctx->ev, id_ctx,
    1376             :                                  sdom, conn,
    1377             :                                  ar->filter_value,
    1378           0 :                                  ar->filter_type,
    1379           0 :                                  ar->attr_type,
    1380             :                                  noexist_delete, false);
    1381           0 :         break;
    1382             : 
    1383             :     case BE_REQ_INITGROUPS: /* init groups for user */
    1384           0 :         if (ar->filter_type != BE_FILTER_NAME
    1385           0 :                 && ar->filter_type != BE_FILTER_SECID
    1386           0 :                 && ar->filter_type != BE_FILTER_UUID) {
    1387           0 :             ret = EINVAL;
    1388           0 :             state->err = "Invalid filter type";
    1389           0 :             goto done;
    1390             :         }
    1391           0 :         if (ar->attr_type != BE_ATTR_CORE) {
    1392           0 :             ret = EINVAL;
    1393           0 :             state->err = "Invalid attr type";
    1394           0 :             goto done;
    1395             :         }
    1396             : 
    1397           0 :         subreq = groups_by_user_send(state, be_ctx->ev, id_ctx,
    1398             :                                      sdom, conn,
    1399             :                                      ar->filter_value,
    1400           0 :                                      ar->filter_type,
    1401             :                                      ar->extra_value,
    1402             :                                      noexist_delete);
    1403           0 :         break;
    1404             : 
    1405             :     case BE_REQ_NETGROUP:
    1406           0 :         if (ar->filter_type != BE_FILTER_NAME) {
    1407           0 :             ret = EINVAL;
    1408           0 :             state->err = "Invalid filter type";
    1409           0 :             goto done;
    1410             :         }
    1411             : 
    1412           0 :         subreq = ldap_netgroup_get_send(state, be_ctx->ev, id_ctx,
    1413             :                                         sdom, conn,
    1414             :                                         ar->filter_value,
    1415             :                                         noexist_delete);
    1416           0 :         break;
    1417             : 
    1418             :     case BE_REQ_SERVICES:
    1419           0 :         if (ar->filter_type == BE_FILTER_SECID
    1420           0 :                 || ar->filter_type == BE_FILTER_UUID) {
    1421           0 :             ret = EINVAL;
    1422           0 :             state->err = "Invalid filter type";
    1423           0 :             goto done;
    1424             :         }
    1425             : 
    1426           0 :         subreq = services_get_send(state, be_ctx->ev, id_ctx,
    1427             :                                    sdom, conn,
    1428             :                                    ar->filter_value,
    1429             :                                    ar->extra_value,
    1430           0 :                                    ar->filter_type,
    1431             :                                    noexist_delete);
    1432           0 :         break;
    1433             : 
    1434             :     case BE_REQ_BY_SECID:
    1435           0 :         if (ar->filter_type != BE_FILTER_SECID) {
    1436           0 :             ret = EINVAL;
    1437           0 :             state->err = "Invalid filter type";
    1438           0 :             goto done;
    1439             :         }
    1440             : 
    1441           0 :         subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
    1442             :                                          sdom, conn,
    1443             :                                          ar->filter_value,
    1444           0 :                                          ar->filter_type,
    1445           0 :                                          ar->attr_type,
    1446             :                                          noexist_delete);
    1447           0 :         break;
    1448             : 
    1449             :     case BE_REQ_BY_UUID:
    1450           0 :         if (ar->filter_type != BE_FILTER_UUID) {
    1451           0 :             ret = EINVAL;
    1452           0 :             state->err = "Invalid filter type";
    1453           0 :             goto done;
    1454             :         }
    1455             : 
    1456           0 :         subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
    1457             :                                          sdom, conn,
    1458             :                                          ar->filter_value,
    1459           0 :                                          ar->filter_type,
    1460           0 :                                          ar->attr_type,
    1461             :                                          noexist_delete);
    1462           0 :         break;
    1463             : 
    1464             :     case BE_REQ_USER_AND_GROUP:
    1465           0 :         if (!(ar->filter_type == BE_FILTER_NAME ||
    1466           0 :               ar->filter_type == BE_FILTER_IDNUM)) {
    1467           0 :             ret = EINVAL;
    1468           0 :             state->err = "Invalid filter type";
    1469           0 :             goto done;
    1470             :         }
    1471             : 
    1472           0 :         subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
    1473             :                                          sdom, conn,
    1474             :                                          ar->filter_value,
    1475           0 :                                          ar->filter_type,
    1476           0 :                                          ar->attr_type,
    1477             :                                          noexist_delete);
    1478           0 :         break;
    1479             : 
    1480             :     case BE_REQ_BY_CERT:
    1481           0 :         subreq = users_get_send(state, be_ctx->ev, id_ctx,
    1482             :                                 sdom, conn,
    1483             :                                 ar->filter_value,
    1484           0 :                                 ar->filter_type,
    1485             :                                 ar->extra_value,
    1486           0 :                                 ar->attr_type,
    1487             :                                 noexist_delete);
    1488           0 :         break;
    1489             : 
    1490             :     default: /*fail*/
    1491           0 :         ret = EINVAL;
    1492           0 :         state->err = "Invalid request type";
    1493           0 :         goto done;
    1494             :     }
    1495             : 
    1496           0 :     if (!subreq) {
    1497           0 :         ret = ENOMEM;
    1498           0 :         goto done;
    1499             :     }
    1500             : 
    1501           0 :     tevent_req_set_callback(subreq, sdap_handle_acct_req_done, req);
    1502           0 :     return req;
    1503             : 
    1504             : done:
    1505           0 :     if (ret == EOK) {
    1506           0 :         tevent_req_done(req);
    1507             :     } else {
    1508           0 :         tevent_req_error(req, ret);
    1509             :     }
    1510             : 
    1511           0 :     tevent_req_post(req, be_ctx->ev);
    1512           0 :     return req;
    1513             : }
    1514             : 
    1515             : static void
    1516           0 : sdap_handle_acct_req_done(struct tevent_req *subreq)
    1517             : {
    1518           0 :     struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
    1519             :     struct sdap_handle_acct_req_state *state;
    1520             :     errno_t ret;
    1521           0 :     const char *err = "Invalid request type";
    1522             : 
    1523           0 :     state = tevent_req_data(req, struct sdap_handle_acct_req_state);
    1524             : 
    1525           0 :     switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
    1526             :     case BE_REQ_USER: /* user */
    1527           0 :         err = "User lookup failed";
    1528           0 :         ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1529           0 :         break;
    1530             :     case BE_REQ_GROUP: /* group */
    1531           0 :         err = "Group lookup failed";
    1532           0 :         ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1533           0 :         break;
    1534             :     case BE_REQ_INITGROUPS: /* init groups for user */
    1535           0 :         err = "Init group lookup failed";
    1536           0 :         ret = groups_by_user_recv(subreq, &state->dp_error, &state->sdap_ret);
    1537           0 :         break;
    1538             :     case BE_REQ_NETGROUP:
    1539           0 :         err = "Netgroup lookup failed";
    1540           0 :         ret = ldap_netgroup_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1541           0 :         break;
    1542             :     case BE_REQ_SERVICES:
    1543           0 :         err = "Service lookup failed";
    1544           0 :         ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1545           0 :         break;
    1546             :     case BE_REQ_BY_SECID:
    1547             :         /* Fallthrough */
    1548             :     case BE_REQ_BY_UUID:
    1549             :         /* Fallthrough */
    1550             :     case BE_REQ_USER_AND_GROUP:
    1551           0 :         err = "Lookup by SID failed";
    1552           0 :         ret = sdap_get_user_and_group_recv(subreq, &state->dp_error,
    1553             :                                            &state->sdap_ret);
    1554           0 :         break;
    1555             :     case BE_REQ_BY_CERT:
    1556           0 :         err = "User lookup by certificate failed";
    1557           0 :         ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1558           0 :         break;
    1559             :     default: /*fail*/
    1560           0 :         ret = EINVAL;
    1561           0 :         break;
    1562             :     }
    1563           0 :     talloc_zfree(subreq);
    1564             : 
    1565           0 :     if (ret != EOK) {
    1566           0 :         state->err = err;
    1567           0 :         tevent_req_error(req, ret);
    1568           0 :         return;
    1569             :     }
    1570             : 
    1571           0 :     state->err = "Success";
    1572           0 :     tevent_req_done(req);
    1573             : }
    1574             : 
    1575             : errno_t
    1576           0 : sdap_handle_acct_req_recv(struct tevent_req *req,
    1577             :                           int *_dp_error, const char **_err,
    1578             :                           int *sdap_ret)
    1579             : {
    1580             :     struct sdap_handle_acct_req_state *state;
    1581             : 
    1582           0 :     state = tevent_req_data(req, struct sdap_handle_acct_req_state);
    1583             : 
    1584             :     PROBE(SDAP_ACCT_REQ_RECV,
    1585             :           state->ar->entry_type & BE_REQ_TYPE_MASK,
    1586             :           state->ar->filter_type, state->ar->filter_value,
    1587             :           PROBE_SAFE_STR(state->ar->extra_value));
    1588             : 
    1589           0 :     if (_dp_error) {
    1590           0 :         *_dp_error = state->dp_error;
    1591             :     }
    1592             : 
    1593           0 :     if (_err) {
    1594           0 :         *_err = state->err;
    1595             :     }
    1596             : 
    1597           0 :     if (sdap_ret) {
    1598           0 :         *sdap_ret = state->sdap_ret;
    1599             :     }
    1600             : 
    1601           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1602           0 :     return EOK;
    1603             : }
    1604             : 
    1605             : struct get_user_and_group_state {
    1606             :     struct tevent_context *ev;
    1607             :     struct sdap_id_ctx *id_ctx;
    1608             :     struct sdap_domain *sdom;
    1609             :     struct sdap_id_conn_ctx *conn;
    1610             :     struct sdap_id_op *op;
    1611             :     struct sysdb_ctx *sysdb;
    1612             :     struct sss_domain_info *domain;
    1613             : 
    1614             :     const char *filter_val;
    1615             :     int filter_type;
    1616             :     int attrs_type;
    1617             : 
    1618             :     char *filter;
    1619             :     const char **attrs;
    1620             : 
    1621             :     int dp_error;
    1622             :     int sdap_ret;
    1623             :     bool noexist_delete;
    1624             : };
    1625             : 
    1626             : static void get_user_and_group_users_done(struct tevent_req *subreq);
    1627             : static void get_user_and_group_groups_done(struct tevent_req *subreq);
    1628             : 
    1629           0 : static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
    1630             :                                                   struct tevent_context *ev,
    1631             :                                                   struct sdap_id_ctx *id_ctx,
    1632             :                                                   struct sdap_domain *sdom,
    1633             :                                                   struct sdap_id_conn_ctx *conn,
    1634             :                                                   const char *filter_val,
    1635             :                                                   int filter_type,
    1636             :                                                   int attrs_type,
    1637             :                                                   bool noexist_delete)
    1638             : {
    1639             :     struct tevent_req *req;
    1640             :     struct tevent_req *subreq;
    1641             :     struct get_user_and_group_state *state;
    1642             :     int ret;
    1643             : 
    1644           0 :     req = tevent_req_create(memctx, &state, struct get_user_and_group_state);
    1645           0 :     if (req == NULL) {
    1646           0 :         DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
    1647           0 :         return NULL;
    1648             :     }
    1649             : 
    1650           0 :     state->ev = ev;
    1651           0 :     state->id_ctx = id_ctx;
    1652           0 :     state->sdom = sdom;
    1653           0 :     state->conn = conn;
    1654           0 :     state->dp_error = DP_ERR_FATAL;
    1655           0 :     state->noexist_delete = noexist_delete;
    1656             : 
    1657           0 :     state->op = sdap_id_op_create(state, state->conn->conn_cache);
    1658           0 :     if (!state->op) {
    1659           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
    1660           0 :         ret = ENOMEM;
    1661           0 :         goto fail;
    1662             :     }
    1663             : 
    1664           0 :     state->domain = sdom->dom;
    1665           0 :     state->sysdb = sdom->dom->sysdb;
    1666           0 :     state->filter_val = filter_val;
    1667           0 :     state->filter_type = filter_type;
    1668           0 :     state->attrs_type = attrs_type;
    1669             : 
    1670           0 :     subreq = groups_get_send(req, state->ev, state->id_ctx,
    1671           0 :                              state->sdom, state->conn,
    1672           0 :                              state->filter_val, state->filter_type,
    1673           0 :                              state->attrs_type, state->noexist_delete, false);
    1674           0 :     if (subreq == NULL) {
    1675           0 :         DEBUG(SSSDBG_OP_FAILURE, "users_get_send failed.\n");
    1676           0 :         ret = ENOMEM;
    1677           0 :         goto fail;
    1678             :     }
    1679             : 
    1680           0 :     tevent_req_set_callback(subreq, get_user_and_group_groups_done, req);
    1681             : 
    1682           0 :     return req;
    1683             : 
    1684             : fail:
    1685           0 :     tevent_req_error(req, ret);
    1686           0 :     tevent_req_post(req, ev);
    1687           0 :     return req;
    1688             : }
    1689             : 
    1690           0 : static void get_user_and_group_groups_done(struct tevent_req *subreq)
    1691             : {
    1692           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1693             :                                                       struct tevent_req);
    1694           0 :     struct get_user_and_group_state *state = tevent_req_data(req,
    1695             :                                                struct get_user_and_group_state);
    1696             :     int ret;
    1697             :     struct ad_id_ctx *ad_id_ctx;
    1698             :     struct sdap_id_conn_ctx *user_conn;
    1699             : 
    1700           0 :     ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1701           0 :     talloc_zfree(subreq);
    1702             : 
    1703           0 :     if (ret != EOK) {           /* Fatal error while looking up group */
    1704           0 :         tevent_req_error(req, ret);
    1705           0 :         return;
    1706             :     }
    1707             : 
    1708           0 :     if (state->sdap_ret == EOK) {   /* Matching group found */
    1709           0 :         tevent_req_done(req);
    1710           0 :         return;
    1711           0 :     } else if (state->sdap_ret != ENOENT) {
    1712           0 :         tevent_req_error(req, EIO);
    1713           0 :         return;
    1714             :     }
    1715             : 
    1716             :     /* Now the search finished fine but did not find an entry.
    1717             :      * Retry with users. */
    1718             : 
    1719           0 :     user_conn = state->conn;
    1720             :     /* Prefer LDAP over GC for users */
    1721           0 :     if (state->id_ctx->opts->schema_type == SDAP_SCHEMA_AD
    1722           0 :             && state->sdom->pvt != NULL) {
    1723           0 :         ad_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx);
    1724           0 :         if (ad_id_ctx != NULL &&  ad_id_ctx->ldap_ctx != NULL
    1725           0 :                 && state->conn == ad_id_ctx->gc_ctx) {
    1726           0 :             DEBUG(SSSDBG_TRACE_ALL,
    1727             :                   "Switching to LDAP connection for user lookup.\n");
    1728           0 :             user_conn = ad_id_ctx->ldap_ctx;
    1729             :         }
    1730             :     }
    1731             : 
    1732           0 :     subreq = users_get_send(req, state->ev, state->id_ctx,
    1733             :                             state->sdom, user_conn,
    1734             :                             state->filter_val, state->filter_type, NULL,
    1735           0 :                             state->attrs_type, state->noexist_delete);
    1736           0 :     if (subreq == NULL) {
    1737           0 :         DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n");
    1738           0 :         tevent_req_error(req, ENOMEM);
    1739           0 :         return;
    1740             :     }
    1741             : 
    1742           0 :     tevent_req_set_callback(subreq, get_user_and_group_users_done, req);
    1743             : }
    1744             : 
    1745           0 : static void get_user_and_group_users_done(struct tevent_req *subreq)
    1746             : {
    1747           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1748             :                                                       struct tevent_req);
    1749           0 :     struct get_user_and_group_state *state = tevent_req_data(req,
    1750             :                                                struct get_user_and_group_state);
    1751             :     int ret;
    1752             : 
    1753           0 :     ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
    1754           0 :     talloc_zfree(subreq);
    1755             : 
    1756           0 :     if (ret != EOK) {
    1757           0 :         tevent_req_error(req, ret);
    1758           0 :         return;
    1759             :     }
    1760           0 :     if (state->sdap_ret == ENOENT) {
    1761           0 :         if (state->noexist_delete == true) {
    1762             :             /* The search ran to completion, but nothing was found.
    1763             :              * Delete the existing entry, if any. */
    1764           0 :             ret = sysdb_delete_by_sid(state->sysdb, state->domain,
    1765             :                                       state->filter_val);
    1766           0 :             if (ret != EOK) {
    1767           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Could not delete entry by SID!\n");
    1768           0 :                 tevent_req_error(req, ret);
    1769           0 :                 return;
    1770             :             }
    1771             :         }
    1772           0 :     } else if (state->sdap_ret != EOK) {
    1773           0 :         tevent_req_error(req, EIO);
    1774           0 :         return;
    1775             :     }
    1776             : 
    1777             :     /* Both ret and sdap->ret are EOK. Matching user found */
    1778           0 :     tevent_req_done(req);
    1779           0 :     return;
    1780             : }
    1781             : 
    1782           0 : errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
    1783             :                                      int *dp_error_out, int *sdap_ret)
    1784             : {
    1785           0 :     struct get_user_and_group_state *state = tevent_req_data(req,
    1786             :                                                struct get_user_and_group_state);
    1787             : 
    1788           0 :     if (dp_error_out) {
    1789           0 :         *dp_error_out = state->dp_error;
    1790             :     }
    1791             : 
    1792           0 :     if (sdap_ret) {
    1793           0 :         *sdap_ret = state->sdap_ret;
    1794             :     }
    1795             : 
    1796           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1797             : 
    1798           0 :     return EOK;
    1799             : }
    1800             : 
    1801             : struct sdap_account_info_handler_state {
    1802             :     struct dp_reply_std reply;
    1803             : };
    1804             : 
    1805             : static void sdap_account_info_handler_done(struct tevent_req *subreq);
    1806             : 
    1807             : struct tevent_req *
    1808           0 : sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
    1809             :                                struct sdap_id_ctx *id_ctx,
    1810             :                                struct be_acct_req *data,
    1811             :                                struct dp_req_params *params)
    1812             : {
    1813             :     struct sdap_account_info_handler_state *state;
    1814             :     struct tevent_req *subreq;
    1815             :     struct tevent_req *req;
    1816             :     errno_t ret;
    1817             : 
    1818           0 :     req = tevent_req_create(mem_ctx, &state,
    1819             :                             struct sdap_account_info_handler_state);
    1820           0 :     if (req == NULL) {
    1821           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
    1822           0 :         return NULL;
    1823             :     }
    1824             : 
    1825           0 :     if (sdap_is_enum_request(data)) {
    1826           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
    1827           0 :         ret = EOK;
    1828           0 :         goto immediately;
    1829             :     }
    1830             : 
    1831           0 :     subreq = sdap_handle_acct_req_send(state, params->be_ctx, data, id_ctx,
    1832           0 :                                        id_ctx->opts->sdom, id_ctx->conn, true);
    1833           0 :     if (subreq == NULL) {
    1834           0 :         ret = ENOMEM;
    1835           0 :         goto immediately;
    1836             :     }
    1837             : 
    1838           0 :     tevent_req_set_callback(subreq, sdap_account_info_handler_done, req);
    1839             : 
    1840           0 :     return req;
    1841             : 
    1842             : immediately:
    1843           0 :     dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
    1844             : 
    1845             :     /* TODO For backward compatibility we always return EOK to DP now. */
    1846           0 :     tevent_req_done(req);
    1847           0 :     tevent_req_post(req, params->ev);
    1848             : 
    1849           0 :     return req;
    1850             : }
    1851             : 
    1852           0 : static void sdap_account_info_handler_done(struct tevent_req *subreq)
    1853             : {
    1854             :     struct sdap_account_info_handler_state *state;
    1855             :     struct tevent_req *req;
    1856             :     const char *error_msg;
    1857             :     int dp_error;
    1858             :     errno_t ret;
    1859             : 
    1860           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1861           0 :     state = tevent_req_data(req, struct sdap_account_info_handler_state);
    1862             : 
    1863           0 :     ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL);
    1864           0 :     talloc_zfree(subreq);
    1865             : 
    1866             :     /* TODO For backward compatibility we always return EOK to DP now. */
    1867           0 :     dp_reply_std_set(&state->reply, dp_error, ret, error_msg);
    1868           0 :     tevent_req_done(req);
    1869           0 : }
    1870             : 
    1871           0 : errno_t sdap_account_info_handler_recv(TALLOC_CTX *mem_ctx,
    1872             :                                        struct tevent_req *req,
    1873             :                                        struct dp_reply_std *data)
    1874             : {
    1875           0 :     struct sdap_account_info_handler_state *state = NULL;
    1876             : 
    1877           0 :     state = tevent_req_data(req, struct sdap_account_info_handler_state);
    1878             : 
    1879           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1880             : 
    1881           0 :     *data = state->reply;
    1882             : 
    1883           0 :     return EOK;
    1884             : }

Generated by: LCOV version 1.10