LCOV - code coverage report
Current view: top level - responder/pac - pacsrv_cmd.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 541 0.0 %
Date: 2015-10-19 Functions: 0 21 0.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    PAC Responder
       5             : 
       6             :    Copyright (C) Sumit Bose <sbose@redhat.com> 2012
       7             :                  Jan Zeleny <jzeleny@redhat.com> 2012
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "util/util.h"
      24             : #include "responder/pac/pacsrv.h"
      25             : #include "confdb/confdb.h"
      26             : 
      27           0 : static errno_t pac_cmd_done(struct cli_ctx *cctx, int cmd_ret)
      28             : {
      29             :     int ret;
      30             : 
      31           0 :     if (cmd_ret == EAGAIN) {
      32             :         /* async processing, just return here */
      33           0 :         return EOK;
      34             :     }
      35             : 
      36           0 :     ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
      37           0 :                          &cctx->creq->out);
      38           0 :     if (ret != EOK) {
      39           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_packet_new failed [%d][%s].\n",
      40             :                                   ret, strerror(ret));
      41           0 :         return ret;
      42             :     }
      43             : 
      44           0 :     sss_packet_set_error(cctx->creq->out, cmd_ret);
      45             : 
      46           0 :     sss_cmd_done(cctx, NULL);
      47             : 
      48           0 :     return EOK;
      49             : }
      50             : 
      51             : struct pac_req_ctx {
      52             :     struct cli_ctx *cctx;
      53             :     struct pac_ctx *pac_ctx;
      54             :     const char *domain_name;
      55             :     const char *user_name;
      56             :     struct sss_domain_info *dom;
      57             : 
      58             :     struct PAC_LOGON_INFO *logon_info;
      59             :     struct dom_sid2 *domain_sid;
      60             : 
      61             :     size_t del_grp_count;
      62             :     struct grp_info *del_grp_list;
      63             : 
      64             :     size_t add_sid_count;
      65             :     char **add_sids;
      66             : 
      67             :     hash_table_t *sid_table;
      68             :     char *user_sid_str;
      69             :     char *user_dom_sid_str;
      70             :     char *primary_group_sid_str;
      71             : };
      72             : 
      73             : static errno_t pac_resolve_sids_next(struct pac_req_ctx *pr_ctx);
      74             : static void pac_lookup_sids_done(struct tevent_req *req);
      75             : static struct tevent_req *pac_lookup_sids_send(TALLOC_CTX *mem_ctx,
      76             :                                                struct tevent_context *ev,
      77             :                                                struct pac_req_ctx *pr_ctx,
      78             :                                                struct pac_ctx *pac_ctx,
      79             :                                                hash_table_t *sid_table);
      80             : static errno_t pac_lookup_sids_recv(struct tevent_req *req);
      81             : static void pac_add_user_next(struct pac_req_ctx *pr_ctx);
      82             : static void pac_get_domains_done(struct tevent_req *req);
      83             : static errno_t pac_user_get_grp_info(TALLOC_CTX *mem_ctx,
      84             :                                      struct pac_req_ctx *pr_ctx,
      85             :                                      size_t *_del_grp_count,
      86             :                                      struct grp_info **_del_grp_list,
      87             :                                      size_t *_add_sid_count,
      88             :                                      char ***_add_sids);
      89             : static errno_t save_pac_user(struct pac_req_ctx *pr_ctx);
      90             : static void pac_get_group_done(struct tevent_req *subreq);
      91             : static errno_t pac_save_memberships_next(struct tevent_req *req);
      92             : static errno_t pac_store_membership(struct pac_req_ctx *pr_ctx,
      93             :                                     struct ldb_dn *user_dn,
      94             :                                     const char *grp_sid_str,
      95             :                                     struct sss_domain_info *grp_dom);
      96             : struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx);
      97             : static void pac_save_memberships_done(struct tevent_req *req);
      98             : 
      99             : 
     100           0 : static errno_t pac_add_pac_user(struct cli_ctx *cctx)
     101             : {
     102             :     int ret;
     103             :     uint8_t *body;
     104             :     size_t blen;
     105             :     struct pac_req_ctx *pr_ctx;
     106             :     struct tevent_req *req;
     107             :     enum idmap_error_code err;
     108             : 
     109           0 :     sss_packet_get_body(cctx->creq->in, &body, &blen);
     110             : 
     111           0 :     pr_ctx = talloc_zero(cctx, struct pac_req_ctx);
     112           0 :     if (pr_ctx == NULL) {
     113           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
     114           0 :         return ENOMEM;
     115             :     }
     116             : 
     117           0 :     pr_ctx->cctx = cctx;
     118             : 
     119           0 :     pr_ctx->pac_ctx = talloc_get_type(cctx->rctx->pvt_ctx,  struct pac_ctx);
     120           0 :     if (pr_ctx->pac_ctx == NULL) {
     121           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Cannot find pac responder context.\n");
     122           0 :         return EINVAL;
     123             :     }
     124             : 
     125           0 :     ret = get_data_from_pac(pr_ctx, body, blen,
     126             :                             &pr_ctx->logon_info);
     127           0 :     if (ret != EOK) {
     128           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_data_from_pac failed.\n");
     129           0 :         goto done;
     130             :     }
     131             : 
     132           0 :     pr_ctx->domain_name = pr_ctx->logon_info->info3.base.logon_domain.string;
     133           0 :     if (pr_ctx->domain_name == NULL) {
     134           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "No domain name in PAC\n");
     135           0 :         ret = EINVAL;
     136           0 :         goto done;
     137             :     }
     138             : 
     139           0 :     if (pr_ctx->logon_info->info3.base.account_name.string == NULL) {
     140           0 :         ret = EINVAL;
     141           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Missing account name in PAC.\n");
     142           0 :         goto done;
     143             :     }
     144             : 
     145             :     /* To be compatible with winbind based lookups we have to use lower case
     146             :      * names only, effectively making the domain case-insenvitive. */
     147           0 :     pr_ctx->user_name = sss_tc_utf8_str_tolower(pr_ctx,
     148           0 :                             pr_ctx->logon_info->info3.base.account_name.string);
     149           0 :     if (pr_ctx->user_name == NULL) {
     150           0 :         ret = ENOMEM;
     151           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "sss_tc_utf8_str_tolower failed.\n");
     152           0 :         goto done;
     153             :     }
     154             : 
     155           0 :     err = sss_idmap_smb_sid_to_sid(pr_ctx->pac_ctx->idmap_ctx,
     156           0 :                                    pr_ctx->logon_info->info3.base.domain_sid,
     157             :                                    &pr_ctx->user_dom_sid_str);
     158           0 :     if (err != IDMAP_SUCCESS) {
     159           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_idmap_smb_sid_to_sid failed.\n");
     160           0 :         ret = EFAULT;
     161           0 :         goto done;
     162             :     }
     163             : 
     164           0 :     talloc_steal(pr_ctx, pr_ctx->user_dom_sid_str);
     165             : 
     166           0 :     ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str,
     167             :                                      &pr_ctx->dom);
     168           0 :     if (ret == EAGAIN || ret == ENOENT) {
     169           0 :         req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true,
     170             :                                       pr_ctx->domain_name);
     171           0 :         if (req == NULL) {
     172           0 :             ret = ENOMEM;
     173             :         } else {
     174           0 :             tevent_req_set_callback(req, pac_get_domains_done, pr_ctx);
     175           0 :             ret = EAGAIN;
     176             :         }
     177           0 :         goto done;
     178           0 :     } else if (ret != EOK) {
     179           0 :         DEBUG(SSSDBG_OP_FAILURE, "responder_get_domain_by_id failed.\n");
     180           0 :         goto done;
     181             :     }
     182             : 
     183           0 :     ret = pac_resolve_sids_next(pr_ctx);
     184             : 
     185             : done:
     186           0 :     if (ret != EAGAIN) {
     187           0 :         talloc_free(pr_ctx);
     188             :     }
     189           0 :     return pac_cmd_done(cctx, ret);
     190             : }
     191             : 
     192           0 : static void pac_get_domains_done(struct tevent_req *req)
     193             : {
     194           0 :     struct pac_req_ctx *pr_ctx = tevent_req_callback_data(req,
     195             :                                                           struct pac_req_ctx);
     196           0 :     struct cli_ctx *cctx = pr_ctx->cctx;
     197             :     int ret;
     198             : 
     199           0 :     ret = sss_dp_get_domains_recv(req);
     200           0 :     talloc_free(req);
     201           0 :     if (ret != EOK) {
     202           0 :         goto done;
     203             :     }
     204             : 
     205           0 :     ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str,
     206             :                                      &pr_ctx->dom);
     207           0 :     if (ret != EOK) {
     208           0 :         DEBUG(SSSDBG_OP_FAILURE, "Corresponding domain [%s] has not been "
     209             :                                   "found\n", pr_ctx->user_dom_sid_str);
     210           0 :         ret = ENOENT;
     211           0 :         goto done;
     212             :     }
     213             : 
     214           0 :     ret = pac_resolve_sids_next(pr_ctx);
     215             : 
     216             : done:
     217           0 :     if (ret != EAGAIN) {
     218           0 :         talloc_free(pr_ctx);
     219             :     }
     220           0 :     pac_cmd_done(cctx, ret);
     221           0 : }
     222             : 
     223           0 : static errno_t pac_resolve_sids_next(struct pac_req_ctx *pr_ctx)
     224             : {
     225             :     int ret;
     226             :     struct tevent_req *req;
     227             : 
     228           0 :     ret = get_sids_from_pac(pr_ctx, pr_ctx->pac_ctx, pr_ctx->logon_info,
     229             :                             &pr_ctx->user_sid_str,
     230             :                             &pr_ctx->primary_group_sid_str,
     231             :                             &pr_ctx->sid_table);
     232           0 :     if (ret != 0) {
     233           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_sids_from_pac failed.\n");
     234           0 :         return ret;
     235             :     }
     236             : 
     237           0 :     req = pac_lookup_sids_send(pr_ctx, pr_ctx->cctx->ev, pr_ctx,
     238             :                                pr_ctx->pac_ctx, pr_ctx->sid_table);
     239           0 :     if (req == NULL) {
     240           0 :         DEBUG(SSSDBG_OP_FAILURE, "pac_lookup_sids_send failed.\n");
     241           0 :         return ENOMEM;
     242             :     }
     243             : 
     244           0 :     tevent_req_set_callback(req, pac_lookup_sids_done, pr_ctx);
     245             : 
     246           0 :     ret = EAGAIN;
     247             : 
     248             : 
     249           0 :     return ret;
     250             : }
     251             : 
     252           0 : static void pac_lookup_sids_done(struct tevent_req *req)
     253             : {
     254           0 :     struct pac_req_ctx *pr_ctx = tevent_req_callback_data(req, struct pac_req_ctx);
     255           0 :     struct cli_ctx *cctx = pr_ctx->cctx;
     256             :     errno_t ret;
     257             :     unsigned long count;
     258             :     hash_entry_t *entries;
     259             :     hash_key_t key;
     260             :     hash_value_t value;
     261             :     size_t c;
     262             :     struct sss_domain_info *dom;
     263             :     uint64_t id;
     264             :     struct ldb_result *msg;
     265             : 
     266           0 :     ret = pac_lookup_sids_recv(req);
     267           0 :     talloc_zfree(req);
     268             : 
     269           0 :     if (ret != EOK) {
     270           0 :         talloc_free(pr_ctx);
     271           0 :         pac_cmd_done(cctx, ret);
     272           0 :         return;
     273             :     }
     274             : 
     275           0 :     key.type = HASH_KEY_STRING;
     276           0 :     value.type = HASH_VALUE_ULONG;
     277             : 
     278           0 :     ret = hash_entries(pr_ctx->sid_table, &count, &entries);
     279           0 :     if (ret != HASH_SUCCESS) {
     280           0 :         DEBUG(SSSDBG_OP_FAILURE, "hash_entries failed [%d][%s].\n",
     281             :                                  ret, hash_error_string(ret));
     282           0 :         talloc_free(pr_ctx);
     283           0 :         pac_cmd_done(cctx, ret);
     284           0 :         return;
     285             :     }
     286             : 
     287           0 :     for (c = 0; c < count; c++) {
     288           0 :         if (entries[c].value.ul == 0) {
     289           0 :             ret =responder_get_domain_by_id(cctx->rctx,
     290           0 :                                             entries[c].key.str, &dom);
     291           0 :             if (ret != EOK) {
     292           0 :                 DEBUG(SSSDBG_OP_FAILURE, "No domain found for SID [%s].\n",
     293             :                                           entries[c].key.str);
     294           0 :                 continue;
     295             :             }
     296             : 
     297           0 :             msg = NULL;
     298           0 :             ret = sysdb_search_object_by_sid(pr_ctx, dom, entries[c].key.str,
     299             :                                              NULL, &msg);
     300           0 :             if (ret == ENOENT) {
     301           0 :                 DEBUG(SSSDBG_OP_FAILURE, "No entry found for SID [%s].\n",
     302             :                       entries[c].key.str);
     303           0 :                 continue;
     304           0 :             } else if (ret != EOK) {
     305           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     306             :                       "sysdb_search_object_by_sid failed.\n");
     307           0 :                 continue;
     308             :             }
     309             : 
     310           0 :             if (msg->count > 1) {
     311           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "More then one result returned " \
     312             :                                             "for SID [%s].\n",
     313             :                                             entries[c].key.str);
     314           0 :                 talloc_free(msg);
     315           0 :                 pac_cmd_done(cctx, EINVAL);
     316           0 :                 return;
     317             :             }
     318             : 
     319           0 :             id = ldb_msg_find_attr_as_uint64(msg->msgs[0],
     320             :                                              SYSDB_UIDNUM, 0);
     321           0 :             if (id == 0) {
     322           0 :                 id = ldb_msg_find_attr_as_uint64(msg->msgs[0],
     323             :                                                  SYSDB_GIDNUM, 0);
     324             :             }
     325             : 
     326           0 :             if (id == 0) {
     327           0 :                 DEBUG(SSSDBG_OP_FAILURE, "No ID found in entry.\n");
     328           0 :                 talloc_free(msg);
     329           0 :                 continue;
     330             :             }
     331             : 
     332           0 :             key.str = entries[c].key.str;
     333           0 :             value.ul = id;
     334             : 
     335           0 :             ret = hash_enter(pr_ctx->sid_table, &key, &value);
     336           0 :             if (ret != HASH_SUCCESS) {
     337           0 :                 DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed [%d][%s].\n",
     338             :                                           ret, hash_error_string(ret));
     339           0 :                 continue;
     340             :             }
     341           0 :             talloc_free(msg);
     342             :         }
     343             :     }
     344             : 
     345           0 :     pac_add_user_next(pr_ctx);
     346             : }
     347             : 
     348           0 : static void pac_add_user_next(struct pac_req_ctx *pr_ctx)
     349             : {
     350             :     int ret;
     351             :     struct tevent_req *req;
     352           0 :     struct cli_ctx *cctx = pr_ctx->cctx;
     353             : 
     354           0 :     ret = save_pac_user(pr_ctx);
     355           0 :     if (ret != EOK) {
     356           0 :         DEBUG(SSSDBG_OP_FAILURE, "save_pac_user failed.\n");
     357           0 :         goto done;
     358             :     }
     359             : 
     360           0 :     ret = pac_user_get_grp_info(pr_ctx, pr_ctx, &pr_ctx->del_grp_count,
     361             :                                 &pr_ctx->del_grp_list,
     362             :                                 &pr_ctx->add_sid_count, &pr_ctx->add_sids);
     363           0 :     if (ret != EOK) {
     364           0 :         DEBUG(SSSDBG_OP_FAILURE, "pac_user_get_grp_info failed.\n");
     365           0 :         goto done;
     366             :     }
     367             : 
     368           0 :     req = pac_save_memberships_send(pr_ctx);
     369           0 :     if (req == NULL) {
     370           0 :         ret = ENOMEM;
     371           0 :         goto done;
     372             :     }
     373             : 
     374           0 :     tevent_req_set_callback(req, pac_save_memberships_done, pr_ctx);
     375             : 
     376           0 :     ret = EAGAIN;
     377             : 
     378             : done:
     379           0 :     if (ret != EAGAIN) {
     380           0 :         talloc_free(pr_ctx);
     381             :     }
     382           0 :     pac_cmd_done(cctx, ret);
     383           0 : }
     384             : 
     385           0 : static errno_t pac_user_get_grp_info(TALLOC_CTX *mem_ctx,
     386             :                                      struct pac_req_ctx *pr_ctx,
     387             :                                      size_t *_del_grp_count,
     388             :                                      struct grp_info **_del_grp_list,
     389             :                                      size_t *_add_sid_count,
     390             :                                      char ***_add_sids)
     391             : {
     392             :     struct sysdb_ctx *sysdb;
     393             :     int ret;
     394           0 :     TALLOC_CTX *tmp_ctx = NULL;
     395           0 :     struct ldb_result *res = NULL;
     396             :     size_t c;
     397             :     const char *tmp_str;
     398             : 
     399           0 :     size_t add_sid_count = 0;
     400           0 :     char **add_sids = NULL;
     401             : 
     402             :     size_t del_idx;
     403           0 :     size_t del_grp_count = 0;
     404           0 :     struct grp_info *del_grp_list = NULL;
     405             : 
     406             :     const char *cur_sid;
     407             :     hash_key_t key;
     408             :     hash_value_t value;
     409             : 
     410           0 :     struct hash_iter_context_t *iter = NULL;
     411             :     hash_entry_t *entry;
     412             : 
     413           0 :     sysdb = pr_ctx->dom->sysdb;
     414           0 :     if (sysdb == NULL) {
     415           0 :         ret = EINVAL;
     416           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal: Sysdb CTX not found for this domain!\n");
     417           0 :         goto done;
     418             :     }
     419             : 
     420           0 :     tmp_ctx = talloc_new(NULL);
     421           0 :     if (tmp_ctx == NULL) {
     422           0 :         ret = ENOMEM;
     423           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
     424           0 :         goto done;
     425             :     }
     426             : 
     427           0 :     ret = sysdb_initgroups(tmp_ctx, pr_ctx->dom, pr_ctx->user_name, &res);
     428           0 :     if (ret != EOK) {
     429           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_initgroups failed.\n");
     430           0 :         goto done;
     431             :     }
     432             : 
     433           0 :     if (res->count == 0) {
     434           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_initgroups did not found [%s].\n",
     435             :                                   pr_ctx->user_name);
     436           0 :         ret = ENOENT;
     437           0 :         goto done;
     438             :     }
     439             : 
     440             :     /* First result is the user entry then the groups follow */
     441           0 :     if (res->count > 1) {
     442           0 :         del_grp_count = res->count - 1;
     443           0 :         del_grp_list = talloc_zero_array(tmp_ctx, struct grp_info,
     444             :                                          del_grp_count);
     445           0 :         if (del_grp_list == NULL) {
     446           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     447           0 :             ret = ENOMEM;
     448           0 :             goto done;
     449             :         }
     450           0 :         del_idx = 0;
     451             : 
     452           0 :         key.type = HASH_KEY_STRING;
     453             : 
     454           0 :         for (c = 0; c < (res->count - 1); c++) {
     455           0 :             cur_sid = ldb_msg_find_attr_as_string(res->msgs[c + 1],
     456             :                                                   SYSDB_SID_STR, NULL);
     457           0 :             if (cur_sid == NULL) {
     458           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Missing SID in group entry.\n");
     459           0 :                 ret = EINVAL;
     460           0 :                 goto done;
     461             :             }
     462             : 
     463           0 :             key.str = discard_const(cur_sid);
     464           0 :             ret = hash_lookup(pr_ctx->sid_table, &key, &value);
     465           0 :             if (ret == HASH_SUCCESS) {
     466           0 :                 DEBUG(SSSDBG_TRACE_ALL, "User [%s] already member of group " \
     467             :                                          "with SID [%s].\n",
     468             :                                          pr_ctx->user_name, cur_sid);
     469             : 
     470           0 :                 ret = hash_delete(pr_ctx->sid_table, &key);
     471           0 :                 if (ret != HASH_SUCCESS) {
     472           0 :                     DEBUG(SSSDBG_OP_FAILURE, "Failed to remove hash entry.\n");
     473           0 :                     ret = EIO;
     474           0 :                     goto done;
     475             :                 }
     476           0 :             } else if (ret == HASH_ERROR_KEY_NOT_FOUND) {
     477           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL, "Group with SID [%s] is not in " \
     478             :                                               "the PAC anymore, membership " \
     479             :                                               "must be removed.\n", cur_sid);
     480             : 
     481           0 :                 tmp_str = ldb_msg_find_attr_as_string(res->msgs[c + 1],
     482             :                                                       SYSDB_ORIG_DN, NULL);
     483           0 :                 if (tmp_str != NULL) {
     484           0 :                     del_grp_list[del_idx].orig_dn = talloc_strdup(del_grp_list,
     485             :                                                                   tmp_str);
     486           0 :                     if (del_grp_list[del_idx].orig_dn == NULL) {
     487           0 :                         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     488           0 :                         ret = ENOMEM;
     489           0 :                         goto done;
     490             :                     }
     491             :                 }
     492             : 
     493           0 :                 del_grp_list[del_idx].dn = ldb_dn_copy(del_grp_list,
     494           0 :                                                        res->msgs[c + 1]->dn);
     495           0 :                 if (del_grp_list[del_idx].dn == NULL) {
     496           0 :                     DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_copy failed.\n");
     497           0 :                     ret = ENOMEM;
     498           0 :                     goto done;
     499             :                 }
     500             : 
     501           0 :                 del_idx++;
     502             :             }
     503             :         }
     504           0 :         del_grp_count = del_idx;
     505             :     }
     506             : 
     507           0 :     add_sid_count = hash_count(pr_ctx->sid_table);
     508           0 :     if (add_sid_count > 0) {
     509           0 :         add_sids = talloc_array(tmp_ctx, char *, add_sid_count);
     510           0 :         if (add_sids == NULL) {
     511           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     512           0 :             ret = ENOMEM;
     513           0 :             goto done;
     514             :         }
     515             : 
     516           0 :         iter = new_hash_iter_context(pr_ctx->sid_table);
     517           0 :         c = 0;
     518           0 :         while ((entry = iter->next(iter)) != NULL) {
     519           0 :             if (strcmp(entry->key.str, pr_ctx->user_sid_str) != 0) {
     520           0 :                 add_sids[c] = talloc_strdup(add_sids, entry->key.str);
     521           0 :                 if (add_sids[c] == NULL) {
     522           0 :                     DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     523           0 :                     ret = ENOMEM;
     524           0 :                     goto done;
     525             :                 }
     526           0 :                 DEBUG(SSSDBG_TRACE_ALL, "SID [%s] added to add_sids " \
     527             :                                          "list.\n", entry->key.str);
     528           0 :                 c++;
     529             :             }
     530             :         }
     531           0 :         add_sid_count = c;
     532             :     }
     533             : 
     534             : 
     535           0 :     *_del_grp_count = del_grp_count;
     536           0 :     *_del_grp_list = talloc_steal(mem_ctx, del_grp_list);
     537           0 :     *_add_sid_count = add_sid_count;
     538           0 :     *_add_sids = talloc_steal(mem_ctx, add_sids);
     539             : 
     540           0 :     ret = EOK;
     541             : 
     542             : done:
     543           0 :     talloc_free(iter);
     544           0 :     talloc_free(tmp_ctx);
     545             : 
     546           0 :     return ret;
     547             : }
     548             : 
     549           0 : static errno_t save_pac_user(struct pac_req_ctx *pr_ctx)
     550             : {
     551             :     struct sysdb_ctx *sysdb;
     552             :     int ret;
     553           0 :     const char *attrs[] = {SYSDB_NAME, SYSDB_NAME_ALIAS, SYSDB_UIDNUM,
     554             :                            SYSDB_GIDNUM, SYSDB_GECOS, SYSDB_HOMEDIR,
     555             :                            SYSDB_SHELL, SYSDB_ORIG_DN, SYSDB_CACHEDPWD, NULL};
     556             :     struct ldb_message *msg;
     557           0 :     struct passwd *pwd = NULL;
     558           0 :     TALLOC_CTX *tmp_ctx = NULL;
     559           0 :     struct sysdb_attrs *user_attrs = NULL;
     560             : 
     561           0 :     sysdb = pr_ctx->dom->sysdb;
     562           0 :     if (sysdb == NULL) {
     563           0 :         ret = EINVAL;
     564           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal: Sysdb CTX not found for this domain!\n");
     565           0 :         goto done;
     566             :     }
     567             : 
     568           0 :     tmp_ctx = talloc_new(NULL);
     569           0 :     if (tmp_ctx == NULL) {
     570           0 :         ret = ENOMEM;
     571           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
     572           0 :         goto done;
     573             :     }
     574             : 
     575           0 :     ret = get_pwd_from_pac(tmp_ctx, pr_ctx->dom, pr_ctx->user_sid_str,
     576             :                            pr_ctx->primary_group_sid_str, pr_ctx->sid_table,
     577             :                            pr_ctx->logon_info, &pwd, &user_attrs);
     578           0 :     if (ret != EOK) {
     579           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_pwd_from_pac failed.\n");
     580           0 :         goto done;
     581             :     }
     582             : 
     583           0 :     ret = sysdb_search_user_by_uid(tmp_ctx, pr_ctx->dom, pwd->pw_uid, attrs,
     584             :                                    &msg);
     585           0 :     if (ret == ENOENT) {
     586           0 :         if (pwd->pw_gid == 0 && !pr_ctx->dom->mpg) {
     587           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Primary group RID from the PAC "
     588             :                                        "cannot be translated into a GID for "
     589             :                                        "user [%s]. Typically this happens "
     590             :                                        "when UIDs and GIDs are read from AD "
     591             :                                        "and the primary AD group does not "
     592             :                                        "have a GID assigned. Make sure the "
     593             :                                        "user is created by the ID provider "
     594             :                                        "before GSSAPI based authentication "
     595             :                                        "is used in this case.\n",
     596             :                   pwd->pw_name);
     597           0 :             ret = EINVAL;
     598           0 :             goto done;
     599             :         }
     600             : 
     601           0 :         ret = sysdb_store_user(pr_ctx->dom, pwd->pw_name, NULL,
     602           0 :                                pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos,
     603           0 :                                pwd->pw_dir,
     604           0 :                                pwd->pw_shell, NULL, user_attrs, NULL,
     605           0 :                                pr_ctx->dom->user_timeout, 0);
     606           0 :         if (ret != EOK) {
     607           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed [%d][%s].\n",
     608             :                                       ret, strerror(ret));
     609           0 :             goto done;
     610             :         }
     611           0 :     } else if (ret != EOK && ret != ENOENT) {
     612           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_id failed.\n");
     613           0 :         goto done;
     614             :     }
     615             : 
     616           0 :     ret = EOK;
     617             : 
     618             : done:
     619           0 :     talloc_free(tmp_ctx);
     620           0 :     return ret;
     621             : }
     622             : 
     623             : struct pac_save_memberships_state {
     624             :     size_t sid_iter;
     625             :     struct ldb_dn *user_dn;
     626             : 
     627             :     struct pac_req_ctx *pr_ctx;
     628             : };
     629             : 
     630             : static errno_t
     631             : pac_save_memberships_delete(struct pac_save_memberships_state *state);
     632             : 
     633           0 : struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx)
     634             : {
     635             :     struct pac_save_memberships_state *state;
     636           0 :     struct sss_domain_info *dom = pr_ctx->dom;
     637             :     struct tevent_req *req;
     638             :     errno_t ret;
     639           0 :     char *dom_name = NULL;
     640             :     struct ldb_message *msg;
     641             : 
     642           0 :     req = tevent_req_create(pr_ctx, &state, struct pac_save_memberships_state);
     643           0 :     if (req == NULL) {
     644           0 :         return NULL;
     645             :     }
     646             : 
     647           0 :     state->sid_iter = 0;
     648             : 
     649           0 :     dom_name = sss_get_domain_name(state, pr_ctx->user_name, dom);
     650           0 :     if (dom_name == NULL) {
     651           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_sprintf failed.\n");
     652           0 :         ret = ENOMEM;
     653           0 :         goto done;
     654             :     }
     655             : 
     656           0 :     ret = sysdb_search_user_by_name(state, dom, dom_name, NULL, &msg);
     657           0 :     if (ret != EOK) {
     658           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_name failed " \
     659             :                                   "[%d][%s].\n", ret, strerror(ret));
     660           0 :         goto done;
     661             :     }
     662             : 
     663           0 :     state->user_dn = msg->dn;
     664           0 :     state->pr_ctx = pr_ctx;
     665             : 
     666           0 :     ret = pac_save_memberships_delete(state);
     667           0 :     if (ret != EOK) {
     668           0 :         DEBUG(SSSDBG_OP_FAILURE, "pac_save_memberships_delete failed.\n");
     669           0 :         goto done;
     670             :     }
     671             : 
     672           0 :     ret = pac_save_memberships_next(req);
     673           0 :     if (ret == EOK) {
     674           0 :         tevent_req_done(req);
     675           0 :         tevent_req_post(req, pr_ctx->cctx->ev);
     676             :     }
     677             : 
     678             : done:
     679           0 :     talloc_free(dom_name);
     680           0 :     if (ret != EOK && ret != EAGAIN) {
     681           0 :         tevent_req_error(req, ret);
     682           0 :         tevent_req_post(req, pr_ctx->cctx->ev);
     683             :     }
     684             : 
     685           0 :     return req;
     686             : }
     687             : 
     688             : static errno_t
     689           0 : pac_save_memberships_delete(struct pac_save_memberships_state *state)
     690             : {
     691             :     int ret;
     692             :     int sret;
     693             :     size_t c;
     694             :     struct pac_req_ctx *pr_ctx;
     695           0 :     bool in_transaction = false;
     696             :     TALLOC_CTX *tmp_ctx;
     697           0 :     struct sysdb_attrs *user_attrs = NULL;
     698             : 
     699           0 :     pr_ctx = state->pr_ctx;
     700             : 
     701           0 :     if (pr_ctx->del_grp_count == 0) {
     702           0 :         return EOK;
     703             :     }
     704             : 
     705           0 :     if (pr_ctx->del_grp_list == NULL) {
     706           0 :         DEBUG(SSSDBG_OP_FAILURE, "Missing group list.\n");
     707           0 :         return EINVAL;
     708             :     }
     709             : 
     710           0 :     tmp_ctx = talloc_new(NULL);
     711           0 :     if (tmp_ctx == NULL) {
     712           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
     713           0 :         return ENOMEM;
     714             :     }
     715             : 
     716           0 :     ret = sysdb_transaction_start(pr_ctx->dom->sysdb);
     717           0 :     if (ret != EOK) {
     718           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
     719           0 :         goto done;
     720             :     }
     721           0 :     in_transaction = true;
     722             : 
     723           0 :     for (c = 0; c < pr_ctx->del_grp_count; c++) {
     724             :         /* If there is a failure for one group we still try to remove the
     725             :          * remaining groups. */
     726           0 :         ret = sysdb_mod_group_member(pr_ctx->dom, state->user_dn,
     727           0 :                                      pr_ctx->del_grp_list[c].dn,
     728             :                                      LDB_FLAG_MOD_DELETE);
     729           0 :         if (ret != EOK) {
     730           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_mod_group_member failed for " \
     731             :                                       "user [%s] and group[%s].\n",
     732             :                                       ldb_dn_get_linearized(state->user_dn),
     733             :                                       ldb_dn_get_linearized(
     734             :                                                   pr_ctx->del_grp_list[c].dn));
     735           0 :             continue;
     736             :         }
     737             : 
     738           0 :         if (pr_ctx->del_grp_list[c].orig_dn != NULL) {
     739           0 :             user_attrs = sysdb_new_attrs(tmp_ctx);
     740           0 :             if (user_attrs == NULL) {
     741           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
     742           0 :                 continue;
     743             :             }
     744             : 
     745           0 :             ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
     746           0 :                                          pr_ctx->del_grp_list[c].orig_dn);
     747           0 :             if (ret != EOK) {
     748           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
     749           0 :                 continue;
     750             :             }
     751             : 
     752           0 :             ret = sysdb_set_entry_attr(pr_ctx->dom->sysdb, state->user_dn, user_attrs,
     753             :                                        LDB_FLAG_MOD_DELETE);
     754           0 :             if (ret != EOK) {
     755           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
     756           0 :                 continue;
     757             :             }
     758           0 :             talloc_free(user_attrs);
     759             :         }
     760             :     }
     761             : 
     762           0 :     ret = sysdb_transaction_commit(pr_ctx->dom->sysdb);
     763           0 :     if (ret != EOK) {
     764           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed.\n");
     765           0 :         goto done;
     766             :     }
     767           0 :     in_transaction = false;
     768             : 
     769           0 :     ret = EOK;
     770             : done:
     771           0 :     if (in_transaction) {
     772           0 :         sret = sysdb_transaction_cancel(pr_ctx->dom->sysdb);
     773           0 :         if (sret != EOK) {
     774           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed.\n");
     775             :         }
     776             :     }
     777             : 
     778           0 :     talloc_free(tmp_ctx);
     779             : 
     780           0 :     return ret;
     781             : }
     782             : 
     783           0 : static errno_t pac_save_memberships_next(struct tevent_req *req)
     784             : {
     785             :     errno_t ret;
     786             :     char *sid;
     787             :     struct sss_domain_info *grp_dom;
     788             :     struct tevent_req *subreq;
     789             :     struct pac_save_memberships_state *state;
     790             :     struct pac_req_ctx *pr_ctx;
     791             : 
     792           0 :     state = tevent_req_data(req, struct pac_save_memberships_state);
     793           0 :     pr_ctx = state->pr_ctx;
     794             : 
     795           0 :     if (pr_ctx->add_sid_count == 0) {
     796           0 :         return EOK;
     797             :     }
     798             : 
     799           0 :     if (pr_ctx->add_sids == NULL) {
     800           0 :         DEBUG(SSSDBG_OP_FAILURE, "Missing list of SIDs.\n");
     801           0 :         return EINVAL;
     802             :     }
     803             : 
     804           0 :     while (state->sid_iter < pr_ctx->add_sid_count) {
     805           0 :         sid = pr_ctx->add_sids[state->sid_iter];
     806           0 :         ret = responder_get_domain_by_id(pr_ctx->pac_ctx->rctx, sid, &grp_dom);
     807           0 :         if (ret != EOK) {
     808           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "responder_get_domain_by_id failed, " \
     809             :                                          "will try next group\n");
     810           0 :             state->sid_iter++;
     811           0 :             continue;
     812             :         }
     813             : 
     814           0 :         ret = pac_store_membership(state->pr_ctx, state->user_dn, sid, grp_dom);
     815           0 :         if (ret == EOK) {
     816           0 :             state->sid_iter++;
     817           0 :             continue;
     818           0 :         } else if (ret == ENOENT) {
     819           0 :             subreq = sss_dp_get_account_send(state, pr_ctx->cctx->rctx,
     820             :                                              grp_dom, true,
     821             :                                              SSS_DP_SECID, sid, 0, NULL);
     822           0 :             if (subreq == NULL) {
     823           0 :                 ret = ENOMEM;
     824           0 :                 goto done;
     825             :             }
     826           0 :             tevent_req_set_callback(subreq, pac_get_group_done, req);
     827             : 
     828           0 :             return EAGAIN;
     829             :         } else  {
     830           0 :             DEBUG(SSSDBG_OP_FAILURE, "pac_store_membership failed, "
     831             :                                       "trying next group.\n");
     832           0 :             state->sid_iter++;
     833           0 :             continue;
     834             :         }
     835             :     }
     836             : 
     837           0 :     ret = EOK;
     838             : done:
     839           0 :     return ret;
     840             : }
     841             : 
     842           0 : static void pac_get_group_done(struct tevent_req *subreq)
     843             : {
     844             :     struct tevent_req *req;
     845             :     struct pac_save_memberships_state *state;
     846             : 
     847           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     848           0 :     state = tevent_req_data(req, struct pac_save_memberships_state);
     849             : 
     850             :     errno_t ret;
     851             :     dbus_uint16_t err_maj;
     852             :     dbus_uint32_t err_min;
     853             :     char *err_msg;
     854             :     char *sid;
     855             :     struct sss_domain_info *grp_dom;
     856           0 :     struct pac_req_ctx *pr_ctx = state->pr_ctx;
     857             : 
     858           0 :     ret = sss_dp_get_account_recv(req, subreq,
     859             :                                   &err_maj, &err_min,
     860             :                                   &err_msg);
     861           0 :     talloc_zfree(subreq);
     862           0 :     talloc_zfree(err_msg);
     863           0 :     if (ret != EOK) {
     864           0 :         goto error;
     865             :     }
     866             : 
     867           0 :     sid = pr_ctx->add_sids[state->sid_iter];
     868           0 :     ret = responder_get_domain_by_id(pr_ctx->pac_ctx->rctx,sid, &grp_dom);
     869           0 :     if (ret != EOK) {
     870           0 :         DEBUG(SSSDBG_OP_FAILURE, "responder_get_domain_by_id failed.\n");
     871           0 :         goto error;
     872             :     }
     873             : 
     874           0 :     ret = pac_store_membership(state->pr_ctx, state->user_dn, sid, grp_dom);
     875           0 :     if (ret != EOK) {
     876           0 :         DEBUG(SSSDBG_OP_FAILURE, "pac_store_membership failed, "
     877             :                                   "trying next group.\n");
     878             :     }
     879           0 :     state->sid_iter++;
     880             : 
     881           0 :     ret = pac_save_memberships_next(req);
     882           0 :     if (ret == EOK) {
     883           0 :         tevent_req_done(req);
     884           0 :     } else if (ret != EAGAIN) {
     885           0 :         goto error;
     886             :     }
     887             : 
     888           0 :     return;
     889             : 
     890             : error:
     891           0 :     tevent_req_error(req, ret);
     892             : }
     893             : 
     894             : static errno_t
     895           0 : pac_store_membership(struct pac_req_ctx *pr_ctx,
     896             :                      struct ldb_dn *user_dn,
     897             :                      const char *grp_sid_str,
     898             :                      struct sss_domain_info *grp_dom)
     899             : {
     900             :     TALLOC_CTX *tmp_ctx;
     901             :     struct sysdb_attrs *user_attrs;
     902             :     struct ldb_result *group;
     903             :     errno_t ret;
     904             :     const char *orig_group_dn;
     905           0 :     const char *group_attrs[] = { SYSDB_ORIG_DN, SYSDB_OBJECTCLASS, NULL };
     906             :     const char *oc;
     907             : 
     908           0 :     tmp_ctx = talloc_new(NULL);
     909           0 :     if (tmp_ctx == NULL) {
     910           0 :         return ENOMEM;
     911             :     }
     912             : 
     913           0 :     ret = sysdb_search_object_by_sid(tmp_ctx, grp_dom, grp_sid_str,
     914             :                                      group_attrs, &group);
     915           0 :     if (ret == ENOENT) {
     916           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unexpected number of groups returned.\n");
     917           0 :         goto done;
     918           0 :     } else if (ret != EOK) {
     919           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
     920             :               "sysdb_search_object_by_sid for SID [%s] failed [%d][%s].\n",
     921             :               grp_sid_str, ret, strerror(ret));
     922           0 :         goto done;
     923             :     }
     924             : 
     925           0 :     if (group->count != 1) {
     926           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unexpected number of groups returned.\n");
     927           0 :         ret = EINVAL;
     928           0 :         goto done;
     929             :     }
     930             : 
     931           0 :     oc = ldb_msg_find_attr_as_string(group->msgs[0], SYSDB_OBJECTCLASS, NULL);
     932           0 :     if (oc == NULL || strcmp(oc, SYSDB_GROUP_CLASS) != 0) {
     933           0 :         DEBUG(SSSDBG_OP_FAILURE, "Return object does not have group " \
     934             :                                   "objectclass.\n");
     935           0 :         ret = EINVAL;
     936           0 :         goto done;
     937             :     }
     938             : 
     939           0 :     DEBUG(SSSDBG_TRACE_ALL, "Adding user [%s] to group [%s][%s].\n",
     940             :                              ldb_dn_get_linearized(user_dn), grp_sid_str,
     941             :                              ldb_dn_get_linearized(group->msgs[0]->dn));
     942           0 :     ret = sysdb_mod_group_member(grp_dom, user_dn, group->msgs[0]->dn,
     943             :                                  LDB_FLAG_MOD_ADD);
     944           0 :     if (ret != EOK) {
     945           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_mod_group_member failed user [%s] " \
     946             :                                   "group [%s].\n",
     947             :                                   ldb_dn_get_linearized(user_dn),
     948             :                                   ldb_dn_get_linearized(group->msgs[0]->dn));
     949           0 :         goto done;
     950             :     }
     951             : 
     952           0 :     orig_group_dn = ldb_msg_find_attr_as_string(group->msgs[0], SYSDB_ORIG_DN,
     953             :                                                 NULL);
     954           0 :     if (orig_group_dn != NULL) {
     955           0 :         DEBUG(SSSDBG_TRACE_ALL, "Adding original group DN [%s] to user [%s].\n",
     956             :                                  orig_group_dn,
     957             :                                  ldb_dn_get_linearized(user_dn));
     958           0 :         user_attrs = sysdb_new_attrs(tmp_ctx);
     959           0 :         if (user_attrs == NULL) {
     960           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
     961           0 :             ret = ENOMEM;
     962           0 :             goto done;
     963             :         }
     964             : 
     965           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
     966             :                                      orig_group_dn);
     967           0 :         if (ret != EOK) {
     968           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
     969           0 :             goto done;
     970             :         }
     971             : 
     972           0 :         ret = sysdb_set_entry_attr(pr_ctx->dom->sysdb, user_dn, user_attrs,
     973             :                                    LDB_FLAG_MOD_ADD);
     974           0 :         if (ret != EOK) {
     975           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
     976           0 :             goto done;
     977             :         }
     978             :     } else {
     979           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Original DN not available for group " \
     980             :                                      "[%s][%s].\n", grp_sid_str,
     981             :                                      ldb_dn_get_linearized(group->msgs[0]->dn));
     982             :     }
     983             : 
     984             : done:
     985           0 :     talloc_free(tmp_ctx);
     986           0 :     return ret;
     987             : }
     988             : 
     989           0 : static errno_t pac_save_memberships_recv(struct tevent_req *subreq)
     990             : {
     991           0 :     TEVENT_REQ_RETURN_ON_ERROR(subreq);
     992             : 
     993           0 :     return EOK;
     994             : }
     995             : 
     996           0 : static void pac_save_memberships_done(struct tevent_req *req)
     997             : {
     998           0 :     struct pac_req_ctx *pr_ctx = tevent_req_callback_data(req, struct pac_req_ctx);
     999           0 :     struct cli_ctx *cctx = pr_ctx->cctx;
    1000             :     errno_t ret;
    1001             : 
    1002           0 :     ret = pac_save_memberships_recv(req);
    1003           0 :     talloc_zfree(req);
    1004             : 
    1005           0 :     talloc_free(pr_ctx);
    1006           0 :     pac_cmd_done(cctx, ret);
    1007           0 : }
    1008             : 
    1009             : struct pac_lookup_sids_state {
    1010             :     struct pac_ctx *pac_ctx;
    1011             :     struct pac_req_ctx *pr_ctx;
    1012             :     hash_table_t *sid_table;
    1013             :     struct hash_iter_context_t *iter;
    1014             : };
    1015             : 
    1016             : static errno_t pac_lookup_sids_next(struct tevent_req *req);
    1017             : static void pac_lookup_sids_next_done(struct tevent_req *subreq);
    1018             : 
    1019           0 : static struct tevent_req *pac_lookup_sids_send(TALLOC_CTX *mem_ctx,
    1020             :                                                struct tevent_context *ev,
    1021             :                                                struct pac_req_ctx *pr_ctx,
    1022             :                                                struct pac_ctx *pac_ctx,
    1023             :                                                hash_table_t *sid_table)
    1024             : {
    1025             :     struct tevent_req *req;
    1026             :     struct pac_lookup_sids_state *state;
    1027             :     int ret;
    1028             : 
    1029           0 :     req = tevent_req_create(mem_ctx, &state, struct pac_lookup_sids_state);
    1030           0 :     if (req == NULL) {
    1031           0 :         return NULL;
    1032             :     }
    1033             : 
    1034           0 :     state->pac_ctx = pac_ctx;
    1035           0 :     state->pr_ctx = pr_ctx;
    1036           0 :     state->sid_table = sid_table;
    1037           0 :     state->iter = talloc_steal(state, new_hash_iter_context(state->sid_table));
    1038             : 
    1039           0 :     ret = pac_lookup_sids_next(req);
    1040             : 
    1041           0 :     if (ret != EAGAIN) {
    1042           0 :         if (ret == EOK) {
    1043           0 :             tevent_req_done(req);
    1044             :         } else {
    1045           0 :             tevent_req_error(req, ret);
    1046             :         }
    1047           0 :         tevent_req_post(req, ev);
    1048             :     }
    1049             : 
    1050           0 :     return req;
    1051             : }
    1052             : 
    1053             : 
    1054           0 : static errno_t pac_lookup_sids_next(struct tevent_req *req)
    1055             : {
    1056             :     struct pac_lookup_sids_state *state;
    1057           0 :     state = tevent_req_data(req, struct pac_lookup_sids_state);
    1058             :     hash_entry_t *entry;
    1059             :     struct tevent_req *subreq;
    1060             :     struct sss_domain_info *dom;
    1061             :     int ret;
    1062             : 
    1063           0 :     while ((entry = state->iter->next(state->iter)) != NULL) {
    1064           0 :         if (entry->value.ul == 0) {
    1065           0 :             ret = responder_get_domain_by_id(state->pac_ctx->rctx,
    1066           0 :                                              entry->key.str, &dom);
    1067           0 :             if (ret == EOK && dom != NULL) {
    1068           0 :                 subreq = sss_dp_get_account_send(state,
    1069           0 :                                                  state->pr_ctx->cctx->rctx,
    1070             :                                                  dom, true,
    1071           0 :                                                  SSS_DP_SECID, entry->key.str,
    1072             :                                                  0, NULL);
    1073           0 :                 if (subreq == NULL) {
    1074           0 :                     return ENOMEM;
    1075             :                 }
    1076           0 :                 tevent_req_set_callback(subreq, pac_lookup_sids_next_done, req);
    1077           0 :                 return EAGAIN;
    1078             :             }
    1079             :         }
    1080             :     }
    1081             : 
    1082           0 :     return EOK;
    1083             : }
    1084             : 
    1085           0 : static void pac_lookup_sids_next_done(struct tevent_req *subreq)
    1086             : {
    1087             :     struct tevent_req *req;
    1088             : 
    1089           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1090             : 
    1091             :     errno_t ret;
    1092             :     dbus_uint16_t err_maj;
    1093             :     dbus_uint32_t err_min;
    1094             :     char *err_msg;
    1095             : 
    1096           0 :     ret = sss_dp_get_account_recv(req, subreq,
    1097             :                                   &err_maj, &err_min,
    1098             :                                   &err_msg);
    1099           0 :     if (ret != EOK) {
    1100           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1101             :               "Unable to get information from Data Provider\n"
    1102             :               "dp_error: [%u], errno: [%u], error_msg: [%s]\n",
    1103             :               (unsigned int)err_maj, (unsigned int)err_min,
    1104             :               err_msg ? err_msg : "none");
    1105             :     }
    1106             : 
    1107           0 :     talloc_zfree(subreq);
    1108           0 :     talloc_zfree(err_msg);
    1109             :     /* Errors during individual lookups are ignored. */
    1110             : 
    1111           0 :     ret = pac_lookup_sids_next(req);
    1112           0 :     if (ret == EOK) {
    1113           0 :         tevent_req_done(req);
    1114           0 :     } else if (ret != EAGAIN) {
    1115           0 :         tevent_req_error(req, ret);
    1116             :     }
    1117             : 
    1118           0 :     return;
    1119             : }
    1120             : 
    1121           0 : static errno_t pac_lookup_sids_recv(struct tevent_req *req)
    1122             : {
    1123           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1124             : 
    1125           0 :     return EOK;
    1126             : }
    1127             : 
    1128           0 : struct cli_protocol_version *register_cli_protocol_version(void)
    1129             : {
    1130             :     static struct cli_protocol_version pac_cli_protocol_version[] = {
    1131             :         {1, "2011-04-12", "initial version"},
    1132             :         {0, NULL, NULL}
    1133             :     };
    1134             : 
    1135           0 :     return pac_cli_protocol_version;
    1136             : }
    1137             : 
    1138             : static struct sss_cmd_table pac_cmds[] = {
    1139             :     {SSS_GET_VERSION, sss_cmd_get_version},
    1140             :     {SSS_PAC_ADD_PAC_USER, pac_add_pac_user},
    1141             :     {SSS_CLI_NULL, NULL}
    1142             : };
    1143             : 
    1144           0 : struct sss_cmd_table *get_pac_cmds(void) {
    1145           0 :     return pac_cmds;
    1146             : }

Generated by: LCOV version 1.10