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

Generated by: LCOV version 1.10