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

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     IPA Helper routines - external users and groups with s2n plugin
       5             : 
       6             :     Copyright (C) Sumit Bose <sbose@redhat.com> - 2011
       7             : 
       8             :     This program is free software; you can redistribute it and/or modify
       9             :     it under the terms of the GNU General Public License as published by
      10             :     the Free Software Foundation; either version 3 of the License, or
      11             :     (at your option) any later version.
      12             : 
      13             :     This program is distributed in the hope that it will be useful,
      14             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :     GNU General Public License for more details.
      17             : 
      18             :     You should have received a copy of the GNU General Public License
      19             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "util/util.h"
      23             : #include "util/sss_nss.h"
      24             : #include "util/strtonum.h"
      25             : #include "util/crypto/sss_crypto.h"
      26             : #include "providers/ldap/sdap_async_private.h"
      27             : #include "providers/ldap/sdap_async_ad.h"
      28             : #include "providers/ldap/ldap_common.h"
      29             : #include "providers/ldap/sdap_idmap.h"
      30             : #include "providers/ipa/ipa_id.h"
      31             : #include "providers/ipa/ipa_subdomains.h"
      32             : #include "providers/ad/ad_pac.h"
      33             : #include "db/sysdb.h"
      34             : 
      35             : enum input_types {
      36             :     INP_SID = 1,
      37             :     INP_NAME,
      38             :     INP_POSIX_UID,
      39             :     INP_POSIX_GID,
      40             :     INP_CERT
      41             : };
      42             : 
      43             : enum request_types {
      44             :     REQ_SIMPLE = 1,
      45             :     REQ_FULL,
      46             :     REQ_FULL_WITH_MEMBERS
      47             : };
      48             : 
      49             : enum response_types {
      50             :     RESP_SID = 1,
      51             :     RESP_NAME,
      52             :     RESP_USER,
      53             :     RESP_GROUP,
      54             :     RESP_USER_GROUPLIST,
      55             :     RESP_GROUP_MEMBERS
      56             : };
      57             : 
      58             : /* ==Sid2Name Extended Operation============================================= */
      59             : struct ipa_s2n_exop_state {
      60             :     struct sdap_handle *sh;
      61             : 
      62             :     struct sdap_op *op;
      63             : 
      64             :     char *retoid;
      65             :     struct berval *retdata;
      66             : };
      67             : 
      68             : static void ipa_s2n_exop_done(struct sdap_op *op,
      69             :                            struct sdap_msg *reply,
      70             :                            int error, void *pvt);
      71             : 
      72           0 : static struct tevent_req *ipa_s2n_exop_send(TALLOC_CTX *mem_ctx,
      73             :                                             struct tevent_context *ev,
      74             :                                             struct sdap_handle *sh,
      75             :                                             bool is_v1,
      76             :                                             int timeout,
      77             :                                             struct berval *bv)
      78             : {
      79           0 :     struct tevent_req *req = NULL;
      80             :     struct ipa_s2n_exop_state *state;
      81             :     int ret;
      82             :     int msgid;
      83             : 
      84           0 :     req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_exop_state);
      85           0 :     if (!req) return NULL;
      86             : 
      87           0 :     state->sh = sh;
      88           0 :     state->retoid = NULL;
      89           0 :     state->retdata = NULL;
      90             : 
      91           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Executing extended operation\n");
      92             : 
      93           0 :     ret = ldap_extended_operation(state->sh->ldap,
      94             :                                is_v1 ? EXOP_SID2NAME_V1_OID : EXOP_SID2NAME_OID,
      95             :                                bv, NULL, NULL, &msgid);
      96           0 :     if (ret == -1 || msgid == -1) {
      97           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ldap_extended_operation failed\n");
      98           0 :         ret = ERR_NETWORK_IO;
      99           0 :         goto fail;
     100             :     }
     101           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "ldap_extended_operation sent, msgid = %d\n",
     102             :                                   msgid);
     103             : 
     104           0 :     ret = sdap_op_add(state, ev, state->sh, msgid, ipa_s2n_exop_done, req,
     105           0 :                       timeout, &state->op);
     106           0 :     if (ret) {
     107           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set up operation!\n");
     108           0 :         ret = ERR_INTERNAL;
     109           0 :         goto fail;
     110             :     }
     111             : 
     112           0 :     return req;
     113             : 
     114             : fail:
     115           0 :     tevent_req_error(req, ret);
     116           0 :     tevent_req_post(req, ev);
     117           0 :     return req;
     118             : }
     119             : 
     120           0 : static void ipa_s2n_exop_done(struct sdap_op *op,
     121             :                                struct sdap_msg *reply,
     122             :                                int error, void *pvt)
     123             : {
     124           0 :     struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
     125           0 :     struct ipa_s2n_exop_state *state = tevent_req_data(req,
     126             :                                                     struct ipa_s2n_exop_state);
     127             :     int ret;
     128           0 :     char *errmsg = NULL;
     129           0 :     char *retoid = NULL;
     130           0 :     struct berval *retdata = NULL;
     131             :     int result;
     132             : 
     133           0 :     if (error) {
     134           0 :         tevent_req_error(req, error);
     135           0 :         return;
     136             :     }
     137             : 
     138           0 :     ret = ldap_parse_result(state->sh->ldap, reply->msg,
     139             :                             &result, NULL, &errmsg, NULL,
     140             :                             NULL, 0);
     141           0 :     if (ret != LDAP_SUCCESS) {
     142           0 :         DEBUG(SSSDBG_OP_FAILURE, "ldap_parse_result failed (%d)\n",
     143             :                                  state->op->msgid);
     144           0 :         ret = ERR_NETWORK_IO;
     145           0 :         goto done;
     146             :     }
     147             : 
     148           0 :     DEBUG(result == LDAP_SUCCESS ? SSSDBG_TRACE_FUNC : SSSDBG_OP_FAILURE,
     149             :           "ldap_extended_operation result: %s(%d), %s.\n",
     150             :           sss_ldap_err2string(result), result, errmsg);
     151             : 
     152           0 :     if (result != LDAP_SUCCESS) {
     153           0 :         if (result == LDAP_NO_SUCH_OBJECT) {
     154           0 :             ret = ENOENT;
     155             :         } else {
     156           0 :             DEBUG(SSSDBG_OP_FAILURE, "ldap_extended_operation failed, server " \
     157             :                                      "logs might contain more details.\n");
     158           0 :             ret = ERR_NETWORK_IO;
     159             :         }
     160           0 :         goto done;
     161             :     }
     162             : 
     163           0 :     ret = ldap_parse_extended_result(state->sh->ldap, reply->msg,
     164             :                                       &retoid, &retdata, 0);
     165           0 :     if (ret != LDAP_SUCCESS) {
     166           0 :         DEBUG(SSSDBG_OP_FAILURE, "ldap_parse_extendend_result failed (%d)\n",
     167             :                                  ret);
     168           0 :         ret = ERR_NETWORK_IO;
     169           0 :         goto done;
     170             :     }
     171           0 :     if (retdata == NULL) {
     172           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing exop result data.\n");
     173           0 :         ret = EINVAL;
     174           0 :         goto done;
     175             :     }
     176             : 
     177           0 :     state->retoid = talloc_strdup(state, retoid);
     178           0 :     if (state->retoid == NULL) {
     179           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     180           0 :         ret = ENOMEM;
     181           0 :         goto done;
     182             :     }
     183             : 
     184           0 :     state->retdata = talloc(state, struct berval);
     185           0 :     if (state->retdata == NULL) {
     186           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n");
     187           0 :         ret = ENOMEM;
     188           0 :         goto done;
     189             :     }
     190           0 :     state->retdata->bv_len = retdata->bv_len;
     191           0 :     state->retdata->bv_val = talloc_memdup(state->retdata, retdata->bv_val,
     192             :                                            retdata->bv_len);
     193           0 :     if (state->retdata->bv_val == NULL) {
     194           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n");
     195           0 :         ret = ENOMEM;
     196           0 :         goto done;
     197             :     }
     198             : 
     199           0 :     ret = EOK;
     200             : 
     201             : done:
     202           0 :     ldap_memfree(errmsg);
     203           0 :     ldap_memfree(retoid);
     204           0 :     ber_bvfree(retdata);
     205           0 :     if (ret == EOK) {
     206           0 :         tevent_req_done(req);
     207             :     } else {
     208           0 :         tevent_req_error(req, ret);
     209             :     }
     210             : }
     211             : 
     212           0 : static int ipa_s2n_exop_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     213             :                              char **retoid, struct berval **retdata)
     214             : {
     215           0 :     struct ipa_s2n_exop_state *state = tevent_req_data(req,
     216             :                                                     struct ipa_s2n_exop_state);
     217             : 
     218           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     219             : 
     220           0 :     *retoid = talloc_steal(mem_ctx, state->retoid);
     221           0 :     *retdata = talloc_steal(mem_ctx, state->retdata);
     222             : 
     223           0 :     return EOK;
     224             : }
     225             : 
     226           0 : static errno_t talloc_ber_flatten(TALLOC_CTX *mem_ctx, BerElement *ber,
     227             :                                   struct berval **_bv)
     228             : {
     229             :     int ret;
     230           0 :     struct berval *bv = NULL;
     231           0 :     struct berval *tbv = NULL;
     232             : 
     233           0 :     ret = ber_flatten(ber, &bv);
     234           0 :     if (ret == -1) {
     235           0 :         ret = EFAULT;
     236           0 :         goto done;
     237             :     }
     238             : 
     239           0 :     tbv = talloc_zero(mem_ctx, struct berval);
     240           0 :     if (tbv == NULL) {
     241           0 :         ret = ENOMEM;
     242           0 :         goto done;
     243             :     }
     244             : 
     245           0 :     tbv->bv_len = bv->bv_len;
     246           0 :     tbv->bv_val = talloc_memdup(tbv, bv->bv_val, bv->bv_len);
     247           0 :     if (tbv->bv_val == NULL) {
     248           0 :         ret = ENOMEM;
     249           0 :         goto done;
     250             :     }
     251             : 
     252           0 :     ret = EOK;
     253             : 
     254             : done:
     255           0 :     ber_bvfree(bv);
     256           0 :     if (ret == EOK) {
     257           0 :         *_bv = tbv;
     258             :     } else  {
     259           0 :         talloc_free(tbv);
     260             :     }
     261             : 
     262           0 :     return ret;
     263             : }
     264             : 
     265             : /* The extended operation expect the following ASN.1 encoded request data:
     266             :  *
     267             :  * ExtdomRequestValue ::= SEQUENCE {
     268             :  *    inputType ENUMERATED {
     269             :  *        sid (1),
     270             :  *        name (2),
     271             :  *        posix uid (3),
     272             :  *        posix gid (3)
     273             :  *    },
     274             :  *    requestType ENUMERATED {
     275             :  *        simple (1),
     276             :  *        full (2)
     277             :  *        full_with_members (3)
     278             :  *    },
     279             :  *    data InputData
     280             :  * }
     281             :  *
     282             :  * InputData ::= CHOICE {
     283             :  *    sid OCTET STRING,
     284             :  *    name NameDomainData
     285             :  *    uid PosixUid,
     286             :  *    gid PosixGid
     287             :  * }
     288             :  *
     289             :  * NameDomainData ::= SEQUENCE {
     290             :  *    domain_name OCTET STRING,
     291             :  *    object_name OCTET STRING
     292             :  * }
     293             :  *
     294             :  * PosixUid ::= SEQUENCE {
     295             :  *    domain_name OCTET STRING,
     296             :  *    uid INTEGER
     297             :  * }
     298             :  *
     299             :  * PosixGid ::= SEQUENCE {
     300             :  *    domain_name OCTET STRING,
     301             :  *    gid INTEGER
     302             :  * }
     303             :  *
     304             :  */
     305             : 
     306           0 : static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
     307             :                                   const char *domain_name,
     308             :                                   int entry_type,
     309             :                                   enum request_types request_type,
     310             :                                   struct req_input *req_input,
     311             :                                   struct berval **_bv)
     312             : {
     313           0 :     BerElement *ber = NULL;
     314             :     int ret;
     315             : 
     316           0 :     ber = ber_alloc_t( LBER_USE_DER );
     317           0 :     if (ber == NULL) {
     318           0 :         return ENOMEM;
     319             :     }
     320             : 
     321           0 :     switch (entry_type) {
     322             :         case BE_REQ_USER:
     323             :         case BE_REQ_USER_AND_GROUP:  /* the extdom exop does not care if the
     324             :                                         ID belongs to a user or a group */
     325           0 :             if (req_input->type == REQ_INP_NAME) {
     326           0 :                 ret = ber_printf(ber, "{ee{ss}}", INP_NAME, request_type,
     327             :                                                   domain_name,
     328             :                                                   req_input->inp.name);
     329           0 :             } else if (req_input->type == REQ_INP_ID) {
     330           0 :                 ret = ber_printf(ber, "{ee{si}}", INP_POSIX_UID, request_type,
     331             :                                                   domain_name,
     332             :                                                   req_input->inp.id);
     333             :             } else {
     334           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
     335             :                                           req_input->type == REQ_INP_ID);
     336           0 :                 ret = EINVAL;
     337           0 :                 goto done;
     338             :             }
     339           0 :             break;
     340             :         case BE_REQ_GROUP:
     341           0 :             if (req_input->type == REQ_INP_NAME) {
     342           0 :                 ret = ber_printf(ber, "{ee{ss}}", INP_NAME, request_type,
     343             :                                                   domain_name,
     344             :                                                   req_input->inp.name);
     345           0 :             } else if (req_input->type == REQ_INP_ID) {
     346           0 :                 ret = ber_printf(ber, "{ee{si}}", INP_POSIX_GID, request_type,
     347             :                                                   domain_name,
     348             :                                                   req_input->inp.id);
     349             :             } else {
     350           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
     351             :                                           req_input->type == REQ_INP_ID);
     352           0 :                 ret = EINVAL;
     353           0 :                 goto done;
     354             :             }
     355           0 :             break;
     356             :         case BE_REQ_BY_SECID:
     357           0 :             if (req_input->type == REQ_INP_SECID) {
     358           0 :                 ret = ber_printf(ber, "{ees}", INP_SID, request_type,
     359             :                                                req_input->inp.secid);
     360             :             } else {
     361           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
     362             :                                          req_input->type == REQ_INP_ID);
     363           0 :                 ret = EINVAL;
     364           0 :                 goto done;
     365             :             }
     366           0 :             break;
     367             :         case BE_REQ_BY_CERT:
     368           0 :             if (req_input->type == REQ_INP_CERT) {
     369           0 :             ret = ber_printf(ber, "{ees}", INP_CERT, request_type,
     370             :                                            req_input->inp.cert);
     371             :             } else {
     372           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n",
     373             :                                           req_input->type);
     374           0 :                 ret = EINVAL;
     375           0 :                 goto done;
     376             :             }
     377           0 :             break;
     378             :         default:
     379           0 :             ret = EINVAL;
     380           0 :             goto done;
     381             :     }
     382           0 :     if (ret == -1) {
     383           0 :         ret = EFAULT;
     384           0 :         goto done;
     385             :     }
     386             : 
     387           0 :     ret = talloc_ber_flatten(mem_ctx, ber, _bv);
     388           0 :     if (ret != EOK) {
     389           0 :         goto done;
     390             :     }
     391             : 
     392           0 :     ret = EOK;
     393             : 
     394             : done:
     395           0 :     ber_free(ber, 1);
     396             : 
     397           0 :     return ret;
     398             : }
     399             : 
     400             : /* If the extendend operation is successful it returns the following ASN.1
     401             :  * encoded response:
     402             :  *
     403             :  * ExtdomResponseValue ::= SEQUENCE {
     404             :  *    responseType ENUMERATED {
     405             :  *        sid (1),
     406             :  *        name (2),
     407             :  *        posix_user (3),
     408             :  *        posix_group (4),
     409             :  *        posix_user_grouplist (5),
     410             :  *        posix_group_members (6)
     411             :  *    },
     412             :  *    data OutputData
     413             :  * }
     414             :  *
     415             :  * OutputData ::= CHOICE {
     416             :  *    sid OCTET STRING,
     417             :  *    name NameDomainData,
     418             :  *    user PosixUser,
     419             :  *    group PosixGroup,
     420             :  *    usergrouplist PosixUserGrouplist,
     421             :  *    groupmembers PosixGroupMembers
     422             :  *
     423             :  * }
     424             :  *
     425             :  * NameDomainData ::= SEQUENCE {
     426             :  *    domain_name OCTET STRING,
     427             :  *    object_name OCTET STRING
     428             :  * }
     429             :  *
     430             :  * PosixUser ::= SEQUENCE {
     431             :  *    domain_name OCTET STRING,
     432             :  *    user_name OCTET STRING,
     433             :  *    uid INTEGER
     434             :  *    gid INTEGER
     435             :  * }
     436             :  *
     437             :  * PosixGroup ::= SEQUENCE {
     438             :  *    domain_name OCTET STRING,
     439             :  *    group_name OCTET STRING,
     440             :  *    gid INTEGER
     441             :  * }
     442             :  *
     443             :  * PosixUserGrouplist ::= SEQUENCE {
     444             :  *    domain_name OCTET STRING,
     445             :  *    user_name OCTET STRING,
     446             :  *    uid INTEGER,
     447             :  *    gid INTEGER,
     448             :  *    gecos OCTET STRING,
     449             :  *    home_directory OCTET STRING,
     450             :  *    shell OCTET STRING,
     451             :  *    grouplist GroupNameList
     452             :  * }
     453             :  *
     454             :  * GroupNameList ::= SEQUENCE OF OCTET STRING
     455             :  *
     456             :  * PosixGroupMembers ::= SEQUENCE {
     457             :  *    domain_name OCTET STRING,
     458             :  *    group_name OCTET STRING,
     459             :  *    gid INTEGER,
     460             :  *    members GroupMemberList
     461             :  * }
     462             :  *
     463             :  * GroupMemberList ::= SEQUENCE OF OCTET STRING
     464             :  */
     465             : 
     466             : struct resp_attrs {
     467             :     enum response_types response_type;
     468             :     char *domain_name;
     469             :     union {
     470             :         struct passwd user;
     471             :         struct group group;
     472             :         char *sid_str;
     473             :         char *name;
     474             :     } a;
     475             :     size_t ngroups;
     476             :     char **groups;
     477             :     struct sysdb_attrs *sysdb_attrs;
     478             : };
     479             : 
     480           0 : static errno_t get_extra_attrs(BerElement *ber, struct resp_attrs *resp_attrs)
     481             : {
     482             :     ber_tag_t tag;
     483             :     ber_len_t ber_len;
     484             :     char *ber_cookie;
     485             :     char *name;
     486             :     struct berval **values;
     487             :     struct ldb_val v;
     488             :     int ret;
     489             :     size_t c;
     490             : 
     491           0 :     if (resp_attrs->sysdb_attrs == NULL) {
     492           0 :         resp_attrs->sysdb_attrs = sysdb_new_attrs(resp_attrs);
     493           0 :         if (resp_attrs->sysdb_attrs == NULL) {
     494           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
     495           0 :             return ENOMEM;
     496             :         }
     497             :     }
     498             : 
     499           0 :     DEBUG(SSSDBG_TRACE_ALL, "Found new sequence.\n");
     500           0 :     for (tag = ber_first_element(ber, &ber_len, &ber_cookie);
     501             :          tag != LBER_DEFAULT;
     502           0 :          tag = ber_next_element(ber, &ber_len, ber_cookie)) {
     503             : 
     504           0 :         tag = ber_scanf(ber, "{a{V}}", &name, &values);
     505           0 :         if (tag == LBER_ERROR) {
     506           0 :             DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     507           0 :             return EINVAL;
     508             :         }
     509           0 :         DEBUG(SSSDBG_TRACE_ALL, "Extra attribute [%s].\n", name);
     510             : 
     511           0 :         for (c = 0; values[c] != NULL; c++) {
     512             : 
     513           0 :             if (strcmp(name, SYSDB_USER_CERT) == 0) {
     514           0 :                 if (values[c]->bv_val[values[c]->bv_len] != '\0') {
     515           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     516             :                           "base64 encoded certificate not 0-terminated.\n");
     517           0 :                     return EINVAL;
     518             :                 }
     519             : 
     520           0 :                 v.data = sss_base64_decode(NULL, values[c]->bv_val, &v.length);
     521           0 :                 if (v.data == NULL) {
     522           0 :                     DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
     523           0 :                     return EINVAL;
     524             :                 }
     525             :             } else {
     526           0 :                 v.data = (uint8_t *)values[c]->bv_val;
     527           0 :                 v.length = values[c]->bv_len;
     528             :             }
     529             : 
     530           0 :             ret = sysdb_attrs_add_val(resp_attrs->sysdb_attrs, name, &v);
     531           0 :             if (ret != EOK) {
     532           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n");
     533           0 :                 ldap_memfree(name);
     534           0 :                 ber_bvecfree(values);
     535           0 :                 return ret;
     536             :             }
     537             :         }
     538             : 
     539           0 :         ldap_memfree(name);
     540           0 :         ber_bvecfree(values);
     541             :     }
     542             : 
     543           0 :     return EOK;
     544             : }
     545             : 
     546           0 : static errno_t add_v1_user_data(BerElement *ber, struct resp_attrs *attrs)
     547             : {
     548             :     ber_tag_t tag;
     549             :     ber_len_t ber_len;
     550             :     int ret;
     551           0 :     char *gecos = NULL;
     552           0 :     char *homedir = NULL;
     553           0 :     char *shell = NULL;
     554           0 :     char **list = NULL;
     555             :     size_t c;
     556             : 
     557           0 :     tag = ber_scanf(ber, "aaa", &gecos, &homedir, &shell);
     558           0 :     if (tag == LBER_ERROR) {
     559           0 :         DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     560           0 :         ret = EINVAL;
     561           0 :         goto done;
     562             :     }
     563             : 
     564           0 :     if (gecos == NULL || *gecos == '\0') {
     565           0 :         attrs->a.user.pw_gecos = NULL;
     566             :     } else {
     567           0 :         attrs->a.user.pw_gecos = talloc_strdup(attrs, gecos);
     568           0 :         if (attrs->a.user.pw_gecos == NULL) {
     569           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     570           0 :             ret = ENOMEM;
     571           0 :             goto done;
     572             :         }
     573             :     }
     574             : 
     575           0 :     if (homedir == NULL || *homedir == '\0') {
     576           0 :         attrs->a.user.pw_dir = NULL;
     577             :     } else {
     578           0 :         attrs->a.user.pw_dir = talloc_strdup(attrs, homedir);
     579           0 :         if (attrs->a.user.pw_dir == NULL) {
     580           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     581           0 :             ret = ENOMEM;
     582           0 :             goto done;
     583             :         }
     584             :     }
     585             : 
     586           0 :     if (shell == NULL || *shell == '\0') {
     587           0 :         attrs->a.user.pw_shell = NULL;
     588             :     } else {
     589           0 :         attrs->a.user.pw_shell = talloc_strdup(attrs, shell);
     590           0 :         if (attrs->a.user.pw_shell == NULL) {
     591           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     592           0 :             ret = ENOMEM;
     593           0 :             goto done;
     594             :         }
     595             :     }
     596             : 
     597           0 :     tag = ber_scanf(ber, "{v}", &list);
     598           0 :     if (tag == LBER_ERROR) {
     599           0 :         DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     600           0 :         ret = EINVAL;
     601           0 :         goto done;
     602             :     }
     603             : 
     604           0 :     for (attrs->ngroups = 0; list[attrs->ngroups] != NULL;
     605           0 :          attrs->ngroups++);
     606             : 
     607           0 :     if (attrs->ngroups > 0) {
     608           0 :         attrs->groups = talloc_zero_array(attrs, char *, attrs->ngroups + 1);
     609           0 :         if (attrs->groups == NULL) {
     610           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     611           0 :             ret = ENOMEM;
     612           0 :             goto done;
     613             :         }
     614             : 
     615           0 :         for (c = 0; c < attrs->ngroups; c++) {
     616           0 :             attrs->groups[c] = talloc_strdup(attrs->groups,
     617           0 :                                              list[c]);
     618           0 :             if (attrs->groups[c] == NULL) {
     619           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     620           0 :                 ret = ENOMEM;
     621           0 :                 goto done;
     622             :             }
     623             :         }
     624             :     }
     625             : 
     626           0 :     tag = ber_peek_tag(ber, &ber_len);
     627           0 :     DEBUG(SSSDBG_TRACE_ALL, "BER tag is [%d]\n", (int) tag);
     628           0 :     if (tag == LBER_SEQUENCE) {
     629           0 :         ret = get_extra_attrs(ber, attrs);
     630           0 :         if (ret != EOK) {
     631           0 :             DEBUG(SSSDBG_OP_FAILURE, "get_extra_attrs failed.\n");
     632           0 :             goto done;
     633             :         }
     634             :     }
     635             : 
     636             : 
     637           0 :     ret = EOK;
     638             : 
     639             : done:
     640           0 :     ber_memfree(gecos);
     641           0 :     ber_memfree(homedir);
     642           0 :     ber_memfree(shell);
     643           0 :     ber_memvfree((void **) list);
     644             : 
     645           0 :     return ret;
     646             : }
     647             : 
     648           0 : static errno_t add_v1_group_data(BerElement *ber, struct resp_attrs *attrs)
     649             : {
     650             :     ber_tag_t tag;
     651             :     ber_len_t ber_len;
     652             :     int ret;
     653           0 :     char **list = NULL;
     654             :     size_t c;
     655             : 
     656           0 :     tag = ber_scanf(ber, "{v}", &list);
     657           0 :     if (tag == LBER_ERROR) {
     658           0 :         DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     659           0 :         ret = EINVAL;
     660           0 :         goto done;
     661             :     }
     662             : 
     663           0 :     if (list != NULL) {
     664           0 :         for (attrs->ngroups = 0; list[attrs->ngroups] != NULL;
     665           0 :              attrs->ngroups++);
     666             : 
     667           0 :         if (attrs->ngroups > 0) {
     668           0 :             attrs->a.group.gr_mem = talloc_zero_array(attrs, char *,
     669             :                                                     attrs->ngroups + 1);
     670           0 :             if (attrs->a.group.gr_mem == NULL) {
     671           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     672           0 :                 ret = ENOMEM;
     673           0 :                 goto done;
     674             :             }
     675             : 
     676           0 :             for (c = 0; c < attrs->ngroups; c++) {
     677           0 :                 attrs->a.group.gr_mem[c] =
     678           0 :                                     talloc_strdup(attrs->a.group.gr_mem,
     679           0 :                                                   list[c]);
     680           0 :                 if (attrs->a.group.gr_mem[c] == NULL) {
     681           0 :                     DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     682           0 :                     ret = ENOMEM;
     683           0 :                     goto done;
     684             :                 }
     685             :             }
     686             :         }
     687             :     } else {
     688           0 :         attrs->a.group.gr_mem = talloc_zero_array(attrs, char *, 1);
     689           0 :         if (attrs->a.group.gr_mem == NULL) {
     690           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     691           0 :             ret = ENOMEM;
     692           0 :             goto done;
     693             :         }
     694             :     }
     695             : 
     696           0 :     tag = ber_peek_tag(ber, &ber_len);
     697           0 :     DEBUG(SSSDBG_TRACE_ALL, "BER tag is [%d]\n", (int) tag);
     698           0 :     if (tag == LBER_SEQUENCE) {
     699           0 :         ret = get_extra_attrs(ber, attrs);
     700           0 :         if (ret != EOK) {
     701           0 :             DEBUG(SSSDBG_OP_FAILURE, "get_extra_attrs failed.\n");
     702           0 :             goto done;
     703             :         }
     704             :     }
     705             : 
     706           0 :     ret = EOK;
     707             : 
     708             : done:
     709           0 :     ber_memvfree((void **) list);
     710             : 
     711           0 :     return ret;
     712             : }
     713             : 
     714             : static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
     715             :                                     struct req_input *req_input,
     716             :                                     struct resp_attrs *attrs,
     717             :                                     struct resp_attrs *simple_attrs,
     718             :                                     const char *view_name,
     719             :                                     struct sysdb_attrs *override_attrs,
     720             :                                     bool update_initgr_timeout);
     721             : 
     722           0 : static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
     723             :                                      char *retoid,
     724             :                                      struct berval *retdata,
     725             :                                      struct resp_attrs **resp_attrs)
     726             : {
     727           0 :     BerElement *ber = NULL;
     728             :     ber_tag_t tag;
     729             :     int ret;
     730             :     enum response_types type;
     731           0 :     char *domain_name = NULL;
     732           0 :     char *name = NULL;
     733             :     uid_t uid;
     734             :     gid_t gid;
     735           0 :     struct resp_attrs *attrs = NULL;
     736             :     char *sid_str;
     737           0 :     bool is_v1 = false;
     738             : 
     739           0 :     if (retoid == NULL || retdata == NULL) {
     740           0 :         DEBUG(SSSDBG_OP_FAILURE, "Missing OID or data.\n");
     741           0 :         return EINVAL;
     742             :     }
     743             : 
     744           0 :     if (strcmp(retoid, EXOP_SID2NAME_V1_OID) == 0) {
     745           0 :         is_v1 = true;
     746           0 :     } else if (strcmp(retoid, EXOP_SID2NAME_OID) == 0) {
     747           0 :         is_v1 = false;
     748             :     } else {
     749           0 :         DEBUG(SSSDBG_OP_FAILURE,
     750             :               "Result has wrong OID, expected [%s] or [%s], got [%s].\n",
     751             :               EXOP_SID2NAME_OID, EXOP_SID2NAME_V1_OID, retoid);
     752           0 :         return EINVAL;
     753             :     }
     754             : 
     755           0 :     ber = ber_init(retdata);
     756           0 :     if (ber == NULL) {
     757           0 :         DEBUG(SSSDBG_OP_FAILURE, "ber_init failed.\n");
     758           0 :         return EINVAL;
     759             :     }
     760             : 
     761           0 :     tag = ber_scanf(ber, "{e", &type);
     762           0 :     if (tag == LBER_ERROR) {
     763           0 :         DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     764           0 :         ret = EINVAL;
     765           0 :         goto done;
     766             :     }
     767             : 
     768           0 :     attrs = talloc_zero(mem_ctx, struct resp_attrs);
     769           0 :     if (attrs == NULL) {
     770           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
     771           0 :         ret = ENOMEM;
     772           0 :         goto done;
     773             :     }
     774             : 
     775           0 :     switch (type) {
     776             :         case RESP_USER:
     777             :         case RESP_USER_GROUPLIST:
     778           0 :             tag = ber_scanf(ber, "{aaii", &domain_name, &name, &uid, &gid);
     779           0 :             if (tag == LBER_ERROR) {
     780           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     781           0 :                 ret = EINVAL;
     782           0 :                 goto done;
     783             :             }
     784             : 
     785             :             /* Winbind is not consistent with the case of the returned user
     786             :              * name. In general all names should be lower case but there are
     787             :              * bug in some version of winbind which might lead to upper case
     788             :              * letters in the name. To be on the safe side we explicitly
     789             :              * lowercase the name. */
     790           0 :             attrs->a.user.pw_name = sss_tc_utf8_str_tolower(attrs, name);
     791           0 :             if (attrs->a.user.pw_name == NULL) {
     792           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     793           0 :                 ret = ENOMEM;
     794           0 :                 goto done;
     795             :             }
     796             : 
     797           0 :             attrs->a.user.pw_uid = uid;
     798           0 :             attrs->a.user.pw_gid = gid;
     799             : 
     800           0 :             if (is_v1 && type == RESP_USER_GROUPLIST) {
     801           0 :                 ret = add_v1_user_data(ber, attrs);
     802           0 :                 if (ret != EOK) {
     803           0 :                     DEBUG(SSSDBG_OP_FAILURE, "add_v1_user_data failed.\n");
     804           0 :                     goto done;
     805             :                 }
     806             :             }
     807             : 
     808           0 :             tag = ber_scanf(ber, "}}");
     809           0 :             if (tag == LBER_ERROR) {
     810           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     811           0 :                 ret = EINVAL;
     812           0 :                 goto done;
     813             :             }
     814             : 
     815           0 :             break;
     816             :         case RESP_GROUP:
     817             :         case RESP_GROUP_MEMBERS:
     818           0 :             tag = ber_scanf(ber, "{aai", &domain_name, &name, &gid);
     819           0 :             if (tag == LBER_ERROR) {
     820           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     821           0 :                 ret = EINVAL;
     822           0 :                 goto done;
     823             :             }
     824             : 
     825             :             /* Winbind is not consistent with the case of the returned user
     826             :              * name. In general all names should be lower case but there are
     827             :              * bug in some version of winbind which might lead to upper case
     828             :              * letters in the name. To be on the safe side we explicitly
     829             :              * lowercase the name. */
     830           0 :             attrs->a.group.gr_name = sss_tc_utf8_str_tolower(attrs, name);
     831           0 :             if (attrs->a.group.gr_name == NULL) {
     832           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     833           0 :                 ret = ENOMEM;
     834           0 :                 goto done;
     835             :             }
     836             : 
     837           0 :             attrs->a.group.gr_gid = gid;
     838             : 
     839           0 :             if (is_v1 && type == RESP_GROUP_MEMBERS) {
     840           0 :                 ret = add_v1_group_data(ber, attrs);
     841           0 :                 if (ret != EOK) {
     842           0 :                     DEBUG(SSSDBG_OP_FAILURE, "add_v1_group_data failed.\n");
     843           0 :                     goto done;
     844             :                 }
     845             :             }
     846             : 
     847           0 :             tag = ber_scanf(ber, "}}");
     848           0 :             if (tag == LBER_ERROR) {
     849           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     850           0 :                 ret = EINVAL;
     851           0 :                 goto done;
     852             :             }
     853             : 
     854           0 :             break;
     855             :         case RESP_SID:
     856           0 :             tag = ber_scanf(ber, "a}", &sid_str);
     857           0 :             if (tag == LBER_ERROR) {
     858           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     859           0 :                 ret = EINVAL;
     860           0 :                 goto done;
     861             :             }
     862             : 
     863           0 :             attrs->a.sid_str = talloc_strdup(attrs, sid_str);
     864           0 :             if (attrs->a.sid_str == NULL) {
     865           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     866           0 :                 ret = ENOMEM;
     867           0 :                 goto done;
     868             :             }
     869           0 :             break;
     870             :         case RESP_NAME:
     871           0 :             tag = ber_scanf(ber, "{aa}", &domain_name, &name);
     872           0 :             if (tag == LBER_ERROR) {
     873           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n");
     874           0 :                 ret = EINVAL;
     875           0 :                 goto done;
     876             :             }
     877             : 
     878           0 :             attrs->a.name = sss_tc_utf8_str_tolower(attrs, name);
     879           0 :             if (attrs->a.name == NULL) {
     880           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sss_tc_utf8_str_tolower failed.\n");
     881           0 :                 ret = ENOMEM;
     882           0 :                 goto done;
     883             :             }
     884           0 :             break;
     885             :         default:
     886           0 :             DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
     887             :                                       type);
     888           0 :             ret = EINVAL;
     889           0 :             goto done;
     890             :     }
     891             : 
     892           0 :     attrs->response_type = type;
     893           0 :     if (type != RESP_SID) {
     894           0 :         attrs->domain_name = talloc_strdup(attrs, domain_name);
     895           0 :         if (attrs->domain_name == NULL) {
     896           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     897           0 :             ret = ENOMEM;
     898           0 :             goto done;
     899             :         }
     900             :     }
     901             : 
     902           0 :     ret = EOK;
     903             : 
     904             : done:
     905           0 :     ber_memfree(domain_name);
     906           0 :     ber_memfree(name);
     907           0 :     ber_free(ber, 1);
     908             : 
     909           0 :     if (ret == EOK) {
     910           0 :         *resp_attrs = attrs;
     911             :     } else {
     912           0 :         talloc_free(attrs);
     913             :     }
     914             : 
     915           0 :     return ret;
     916             : }
     917             : 
     918             : struct ipa_s2n_get_list_state {
     919             :     struct tevent_context *ev;
     920             :     struct ipa_id_ctx *ipa_ctx;
     921             :     struct sss_domain_info *dom;
     922             :     struct sdap_handle *sh;
     923             :     struct req_input req_input;
     924             :     char **list;
     925             :     size_t list_idx;
     926             :     int exop_timeout;
     927             :     int entry_type;
     928             :     enum request_types request_type;
     929             :     struct resp_attrs *attrs;
     930             :     struct sss_domain_info *obj_domain;
     931             :     struct sysdb_attrs *override_attrs;
     932             : };
     933             : 
     934             : static errno_t ipa_s2n_get_list_step(struct tevent_req *req);
     935             : static void ipa_s2n_get_list_get_override_done(struct tevent_req *subreq);
     936             : static void ipa_s2n_get_list_next(struct tevent_req *subreq);
     937             : static errno_t ipa_s2n_get_list_save_step(struct tevent_req *req);
     938             : 
     939           0 : static struct tevent_req *ipa_s2n_get_list_send(TALLOC_CTX *mem_ctx,
     940             :                                                 struct tevent_context *ev,
     941             :                                                 struct ipa_id_ctx *ipa_ctx,
     942             :                                                 struct sss_domain_info *dom,
     943             :                                                 struct sdap_handle *sh,
     944             :                                                 int exop_timeout,
     945             :                                                 int entry_type,
     946             :                                                 enum request_types request_type,
     947             :                                                 enum req_input_type list_type,
     948             :                                                 char **list)
     949             : {
     950             :     int ret;
     951             :     struct ipa_s2n_get_list_state *state;
     952             :     struct tevent_req *req;
     953             : 
     954           0 :     req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_get_list_state);
     955           0 :     if (req == NULL) {
     956           0 :         return NULL;
     957             :     }
     958             : 
     959           0 :     if ((entry_type == BE_REQ_BY_SECID && list_type != REQ_INP_SECID)
     960           0 :            || (entry_type != BE_REQ_BY_SECID && list_type == REQ_INP_SECID)) {
     961           0 :         DEBUG(SSSDBG_OP_FAILURE, "Invalid parameter combination [%d][%d].\n",
     962             :                                  request_type, list_type);
     963           0 :         ret = EINVAL;
     964           0 :         goto done;
     965             :     }
     966             : 
     967           0 :     state->ev = ev;
     968           0 :     state->ipa_ctx = ipa_ctx;
     969           0 :     state->dom = dom;
     970           0 :     state->sh = sh;
     971           0 :     state->list = list;
     972           0 :     state->list_idx = 0;
     973           0 :     state->req_input.type = list_type;
     974           0 :     state->req_input.inp.name = NULL;
     975           0 :     state->exop_timeout = exop_timeout;
     976           0 :     state->entry_type = entry_type;
     977           0 :     state->request_type = request_type;
     978           0 :     state->attrs = NULL;
     979           0 :     state->override_attrs = NULL;
     980             : 
     981           0 :     ret = ipa_s2n_get_list_step(req);
     982           0 :     if (ret != EOK) {
     983           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_step failed.\n");
     984           0 :         goto done;
     985             :     }
     986             : 
     987             : done:
     988           0 :     if (ret != EOK) {
     989           0 :         tevent_req_error(req, ret);
     990           0 :         tevent_req_post(req, ev);
     991             :     }
     992             : 
     993           0 :     return req;
     994             : }
     995             : 
     996           0 : static errno_t ipa_s2n_get_list_step(struct tevent_req *req)
     997             : {
     998             :     int ret;
     999           0 :     struct ipa_s2n_get_list_state *state = tevent_req_data(req,
    1000             :                                                struct ipa_s2n_get_list_state);
    1001             :     struct berval *bv_req;
    1002             :     struct tevent_req *subreq;
    1003             :     struct sss_domain_info *parent_domain;
    1004           0 :     char *short_name = NULL;
    1005           0 :     char *domain_name = NULL;
    1006             :     uint32_t id;
    1007             :     char *endptr;
    1008           0 :     bool need_v1 = false;
    1009             : 
    1010           0 :     parent_domain = get_domains_head(state->dom);
    1011           0 :     switch (state->req_input.type) {
    1012             :     case REQ_INP_NAME:
    1013             : 
    1014           0 :         ret = sss_parse_name(state, parent_domain->names,
    1015           0 :                              state->list[state->list_idx],
    1016             :                              &domain_name, &short_name);
    1017           0 :         if (ret != EOK) {
    1018           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
    1019             :                                         state->list[state->list_idx],
    1020             :                                         ret, sss_strerror(ret));
    1021           0 :             return ret;
    1022             :         }
    1023             : 
    1024           0 :         if (domain_name) {
    1025           0 :             state->obj_domain = find_domain_by_name(parent_domain,
    1026             :                                                     domain_name, true);
    1027           0 :             if (state->obj_domain == NULL) {
    1028           0 :                 DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
    1029           0 :                 return ENOMEM;
    1030             :             }
    1031             :         } else {
    1032           0 :             state->obj_domain = parent_domain;
    1033             :         }
    1034             : 
    1035           0 :         state->req_input.inp.name = short_name;
    1036             : 
    1037           0 :         break;
    1038             :     case REQ_INP_ID:
    1039           0 :         errno = 0;
    1040           0 :         id = strtouint32(state->list[state->list_idx], &endptr, 10);
    1041           0 :         if (errno != 0 || *endptr != '\0'
    1042           0 :                 || (state->list[state->list_idx] == endptr)) {
    1043           0 :             DEBUG(SSSDBG_OP_FAILURE, "strtouint32 failed.\n");
    1044           0 :             return EINVAL;
    1045             :         }
    1046           0 :         state->req_input.inp.id = id;
    1047           0 :         state->obj_domain = state->dom;
    1048             : 
    1049           0 :         break;
    1050             :     case REQ_INP_SECID:
    1051           0 :         state->req_input.inp.secid = state->list[state->list_idx];
    1052           0 :         state->obj_domain = find_domain_by_sid(parent_domain,
    1053             :                                                state->req_input.inp.secid);
    1054           0 :         if (state->obj_domain == NULL) {
    1055           0 :             DEBUG(SSSDBG_OP_FAILURE,
    1056             :                   "find_domain_by_sid failed for SID [%s].\n",
    1057             :                   state->req_input.inp.secid);
    1058           0 :             return EINVAL;
    1059             :         }
    1060             : 
    1061           0 :         break;
    1062             :     default:
    1063           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unexpected inoput type [%d].\n",
    1064             :                                  state->req_input.type);
    1065           0 :         return EINVAL;
    1066             :     }
    1067             : 
    1068           0 :     ret = s2n_encode_request(state, state->obj_domain->name, state->entry_type,
    1069             :                              state->request_type,
    1070             :                              &state->req_input, &bv_req);
    1071           0 :     if (ret != EOK) {
    1072           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n_encode_request failed.\n");
    1073           0 :         return ret;
    1074             :     }
    1075             : 
    1076           0 :     if (state->request_type == REQ_FULL_WITH_MEMBERS) {
    1077           0 :         need_v1 = true;
    1078             :     }
    1079             : 
    1080           0 :     subreq = ipa_s2n_exop_send(state, state->ev, state->sh, need_v1,
    1081             :                                state->exop_timeout, bv_req);
    1082           0 :     if (subreq == NULL) {
    1083           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_exop_send failed.\n");
    1084           0 :         return ENOMEM;
    1085             :     }
    1086           0 :     tevent_req_set_callback(subreq, ipa_s2n_get_list_next, req);
    1087             : 
    1088           0 :     return EOK;
    1089             : }
    1090             : 
    1091           0 : static void ipa_s2n_get_list_next(struct tevent_req *subreq)
    1092             : {
    1093             :     int ret;
    1094           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1095             :                                                       struct tevent_req);
    1096           0 :     struct ipa_s2n_get_list_state *state = tevent_req_data(req,
    1097             :                                                struct ipa_s2n_get_list_state);
    1098           0 :     char *retoid = NULL;
    1099           0 :     struct berval *retdata = NULL;
    1100             :     const char *sid_str;
    1101             :     struct be_acct_req *ar;
    1102             : 
    1103           0 :     ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata);
    1104           0 :     talloc_zfree(subreq);
    1105           0 :     if (ret != EOK) {
    1106           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n exop request failed.\n");
    1107           0 :         goto fail;
    1108             :     }
    1109             : 
    1110           0 :     talloc_zfree(state->attrs);
    1111           0 :     ret = s2n_response_to_attrs(state, retoid, retdata, &state->attrs);
    1112           0 :     if (ret != EOK) {
    1113           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n_response_to_attrs failed.\n");
    1114           0 :         goto fail;
    1115             :     }
    1116             : 
    1117           0 :     if (is_default_view(state->ipa_ctx->view_name)) {
    1118           0 :         ret = ipa_s2n_get_list_save_step(req);
    1119           0 :         if (ret == EOK) {
    1120           0 :             tevent_req_done(req);
    1121           0 :         } else if (ret != EAGAIN) {
    1122           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_save_step failed.\n");
    1123           0 :             goto fail;
    1124             :         }
    1125             : 
    1126           0 :         return;
    1127             :     }
    1128             : 
    1129           0 :     ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
    1130             :                                  &sid_str);
    1131           0 :     if (ret != EOK) {
    1132           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    1133           0 :         goto fail;
    1134             :     }
    1135             : 
    1136           0 :     ret = get_be_acct_req_for_sid(state, sid_str, state->obj_domain->name, &ar);
    1137           0 :     if (ret != EOK) {
    1138           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
    1139           0 :         goto fail;
    1140             :     }
    1141             : 
    1142           0 :     subreq = ipa_get_ad_override_send(state, state->ev,
    1143           0 :                            state->ipa_ctx->sdap_id_ctx,
    1144           0 :                            state->ipa_ctx->ipa_options,
    1145           0 :                            dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
    1146             :                                              IPA_KRB5_REALM),
    1147           0 :                            state->ipa_ctx->view_name,
    1148             :                            ar);
    1149           0 :     if (subreq == NULL) {
    1150           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
    1151           0 :         ret = ENOMEM;
    1152           0 :         goto fail;
    1153             :     }
    1154           0 :     tevent_req_set_callback(subreq, ipa_s2n_get_list_get_override_done, req);
    1155             : 
    1156           0 :     return;
    1157             : 
    1158             : fail:
    1159           0 :     tevent_req_error(req,ret);
    1160           0 :     return;
    1161             : }
    1162             : 
    1163           0 : static void ipa_s2n_get_list_get_override_done(struct tevent_req *subreq)
    1164             : {
    1165             :     int ret;
    1166           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1167             :                                                       struct tevent_req);
    1168           0 :     struct ipa_s2n_get_list_state *state = tevent_req_data(req,
    1169             :                                                struct ipa_s2n_get_list_state);
    1170             : 
    1171           0 :     ret = ipa_get_ad_override_recv(subreq, NULL, state, &state->override_attrs);
    1172           0 :     talloc_zfree(subreq);
    1173           0 :     if (ret != EOK) {
    1174           0 :         DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
    1175           0 :         goto fail;
    1176             :     }
    1177             : 
    1178           0 :     ret = ipa_s2n_get_list_save_step(req);
    1179           0 :     if (ret == EOK) {
    1180           0 :         tevent_req_done(req);
    1181           0 :     } else if (ret != EAGAIN) {
    1182           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_save_step failed.\n");
    1183           0 :         goto fail;
    1184             :     }
    1185             : 
    1186           0 :     return;
    1187             : 
    1188             : fail:
    1189           0 :     tevent_req_error(req,ret);
    1190           0 :     return;
    1191             : }
    1192             : 
    1193           0 : static errno_t ipa_s2n_get_list_save_step(struct tevent_req *req)
    1194             : {
    1195             :     int ret;
    1196           0 :     struct ipa_s2n_get_list_state *state = tevent_req_data(req,
    1197             :                                                struct ipa_s2n_get_list_state);
    1198             : 
    1199           0 :     ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
    1200           0 :                                NULL, state->ipa_ctx->view_name,
    1201             :                                state->override_attrs, false);
    1202           0 :     if (ret != EOK) {
    1203           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
    1204           0 :         return ret;
    1205             :     }
    1206             : 
    1207           0 :     state->list_idx++;
    1208           0 :     if (state->list[state->list_idx] == NULL) {
    1209           0 :         return EOK;
    1210             :     }
    1211             : 
    1212           0 :     ret = ipa_s2n_get_list_step(req);
    1213           0 :     if (ret != EOK) {
    1214           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_step failed.\n");
    1215           0 :         return ret;
    1216             :     }
    1217             : 
    1218           0 :     return EAGAIN;
    1219             : }
    1220             : 
    1221           0 : static int ipa_s2n_get_list_recv(struct tevent_req *req)
    1222             : {
    1223           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1224             : 
    1225           0 :     return EOK;
    1226             : }
    1227             : 
    1228             : struct ipa_s2n_get_user_state {
    1229             :     struct tevent_context *ev;
    1230             :     struct ipa_id_ctx *ipa_ctx;
    1231             :     struct sdap_options *opts;
    1232             :     struct sss_domain_info *dom;
    1233             :     struct sdap_handle *sh;
    1234             :     struct req_input *req_input;
    1235             :     int entry_type;
    1236             :     enum request_types request_type;
    1237             :     struct resp_attrs *attrs;
    1238             :     struct resp_attrs *simple_attrs;
    1239             :     struct sysdb_attrs *override_attrs;
    1240             :     int exop_timeout;
    1241             : };
    1242             : 
    1243             : static void ipa_s2n_get_user_done(struct tevent_req *subreq);
    1244             : 
    1245           0 : struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
    1246             :                                              struct tevent_context *ev,
    1247             :                                              struct ipa_id_ctx *ipa_ctx,
    1248             :                                              struct sdap_options *opts,
    1249             :                                              struct sss_domain_info *dom,
    1250             :                                              struct sysdb_attrs *override_attrs,
    1251             :                                              struct sdap_handle *sh,
    1252             :                                              int entry_type,
    1253             :                                              struct req_input *req_input)
    1254             : {
    1255             :     struct ipa_s2n_get_user_state *state;
    1256             :     struct tevent_req *req;
    1257             :     struct tevent_req *subreq;
    1258           0 :     struct berval *bv_req = NULL;
    1259           0 :     int ret = EFAULT;
    1260           0 :     bool is_v1 = false;
    1261             : 
    1262           0 :     req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_get_user_state);
    1263           0 :     if (req == NULL) {
    1264           0 :         return NULL;
    1265             :     }
    1266             : 
    1267           0 :     state->ev = ev;
    1268           0 :     state->ipa_ctx = ipa_ctx;
    1269           0 :     state->opts = opts;
    1270           0 :     state->dom = dom;
    1271           0 :     state->sh = sh;
    1272           0 :     state->req_input = req_input;
    1273           0 :     state->entry_type = entry_type;
    1274           0 :     state->attrs = NULL;
    1275           0 :     state->simple_attrs = NULL;
    1276           0 :     state->exop_timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT);
    1277           0 :     state->override_attrs = override_attrs;
    1278             : 
    1279           0 :     if (sdap_is_extension_supported(sh, EXOP_SID2NAME_V1_OID)) {
    1280           0 :         state->request_type = REQ_FULL_WITH_MEMBERS;
    1281           0 :         is_v1 = true;
    1282           0 :     } else if (sdap_is_extension_supported(sh, EXOP_SID2NAME_OID)) {
    1283           0 :         state->request_type = REQ_FULL;
    1284           0 :         is_v1 = false;
    1285             :     } else {
    1286           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Extdom not supported on the server, "
    1287             :                               "cannot resolve objects from trusted domains.\n");
    1288           0 :         ret = EIO;
    1289           0 :         goto fail;
    1290             :     }
    1291             : 
    1292           0 :     ret = s2n_encode_request(state, dom->name, entry_type, state->request_type,
    1293             :                              req_input, &bv_req);
    1294           0 :     if (ret != EOK) {
    1295           0 :         goto fail;
    1296             :     }
    1297             : 
    1298           0 :     subreq = ipa_s2n_exop_send(state, state->ev, state->sh, is_v1,
    1299           0 :                                state->exop_timeout, bv_req);
    1300           0 :     if (subreq == NULL) {
    1301           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_exop_send failed.\n");
    1302           0 :         ret = ENOMEM;
    1303           0 :         goto fail;
    1304             :     }
    1305           0 :     tevent_req_set_callback(subreq, ipa_s2n_get_user_done, req);
    1306             : 
    1307           0 :     return req;
    1308             : 
    1309             : fail:
    1310           0 :     tevent_req_error(req, ret);
    1311           0 :     tevent_req_post(req, ev);
    1312             : 
    1313           0 :     return req;
    1314             : }
    1315             : 
    1316           0 : static errno_t process_members(struct sss_domain_info *domain,
    1317             :                                struct sysdb_attrs *group_attrs,
    1318             :                                char **members,
    1319             :                                TALLOC_CTX *mem_ctx, char ***_missing_members)
    1320             : {
    1321             :     int ret;
    1322             :     size_t c;
    1323             :     TALLOC_CTX *tmp_ctx;
    1324             :     struct ldb_message *msg;
    1325             :     const char *dn_str;
    1326             :     struct sss_domain_info *obj_domain;
    1327             :     struct sss_domain_info *parent_domain;
    1328           0 :     char **missing_members = NULL;
    1329           0 :     size_t miss_count = 0;
    1330             : 
    1331           0 :     if (members == NULL) {
    1332           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "No members\n");
    1333           0 :         if (_missing_members != NULL) {
    1334           0 :             *_missing_members = NULL;
    1335             :         }
    1336           0 :         return EOK;
    1337             :     }
    1338             : 
    1339           0 :     tmp_ctx = talloc_new(NULL);
    1340           0 :     if (tmp_ctx == NULL) {
    1341           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
    1342           0 :         return ENOMEM;
    1343             :     }
    1344             : 
    1345           0 :     if (_missing_members != NULL && mem_ctx != NULL) {
    1346             :         /* count members */
    1347           0 :         for (c = 0; members[c] != NULL; c++);
    1348           0 :         missing_members = talloc_zero_array(tmp_ctx, char *, c + 1);
    1349           0 :         if (missing_members == NULL) {
    1350           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_array_zero failed.\n");
    1351           0 :             ret = ENOMEM;
    1352           0 :             goto done;
    1353             :         }
    1354             :     }
    1355             : 
    1356           0 :     parent_domain = get_domains_head(domain);
    1357             : 
    1358           0 :     for (c = 0; members[c] != NULL; c++) {
    1359           0 :         obj_domain = find_domain_by_object_name(parent_domain, members[c]);
    1360           0 :         if (obj_domain == NULL) {
    1361           0 :             DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_object_name failed.\n");
    1362           0 :             ret = ENOMEM;
    1363           0 :             goto done;
    1364             :         }
    1365             : 
    1366           0 :         ret = sysdb_search_user_by_name(tmp_ctx, obj_domain, members[c], NULL,
    1367             :                                         &msg);
    1368           0 :         if (ret == EOK) {
    1369           0 :             if (group_attrs != NULL) {
    1370           0 :                 dn_str = ldb_dn_get_linearized(msg->dn);
    1371           0 :                 if (dn_str == NULL) {
    1372           0 :                     DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
    1373           0 :                     ret = EINVAL;
    1374           0 :                     goto done;
    1375             :                 }
    1376             : 
    1377           0 :                 DEBUG(SSSDBG_TRACE_ALL, "Adding member [%s][%s]\n",
    1378             :                                         members[c], dn_str);
    1379             : 
    1380           0 :                 ret = sysdb_attrs_add_string_safe(group_attrs, SYSDB_MEMBER,
    1381             :                                                   dn_str);
    1382           0 :                 if (ret != EOK) {
    1383           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    1384             :                           "sysdb_attrs_add_string_safe failed.\n");
    1385           0 :                     goto done;
    1386             :                 }
    1387             :             }
    1388           0 :         } else if (ret == ENOENT) {
    1389           0 :             if (group_attrs != NULL) {
    1390           0 :                 DEBUG(SSSDBG_TRACE_ALL, "Adding ghost member [%s]\n",
    1391             :                                         members[c]);
    1392             : 
    1393             :                 /* There were cases where the server returned the same user
    1394             :                  * multiple times */
    1395           0 :                 ret = sysdb_attrs_add_string_safe(group_attrs, SYSDB_GHOST,
    1396           0 :                                                   members[c]);
    1397           0 :                 if (ret != EOK) {
    1398           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    1399             :                           "sysdb_attrs_add_string failed.\n");
    1400           0 :                     goto done;
    1401             :                 }
    1402             :             }
    1403             : 
    1404           0 :             if (missing_members != NULL) {
    1405           0 :                 missing_members[miss_count] = talloc_strdup(missing_members,
    1406           0 :                                                             members[c]);
    1407           0 :                 if (missing_members[miss_count] == NULL) {
    1408           0 :                     DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
    1409           0 :                     ret = ENOMEM;
    1410           0 :                     goto done;
    1411             :                 }
    1412           0 :                 miss_count++;
    1413             :             }
    1414             :         } else {
    1415           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_name failed.\n");
    1416           0 :             goto done;
    1417             :         }
    1418             :     }
    1419             : 
    1420           0 :     if (_missing_members != NULL)  {
    1421           0 :         if (miss_count == 0) {
    1422           0 :             *_missing_members = NULL;
    1423             :         } else {
    1424           0 :             if (mem_ctx != NULL) {
    1425           0 :                 *_missing_members = talloc_steal(mem_ctx, missing_members);
    1426             :             } else {
    1427           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
    1428             :                       "Missing memory context for missing members list.\n");
    1429           0 :                 ret = EINVAL;
    1430           0 :                 goto done;
    1431             :             }
    1432             :         }
    1433             :     }
    1434             : 
    1435           0 :     ret = EOK;
    1436             : done:
    1437           0 :     talloc_free(tmp_ctx);
    1438             : 
    1439           0 :     return ret;
    1440             : }
    1441             : 
    1442           0 : static errno_t get_group_dn_list(TALLOC_CTX *mem_ctx,
    1443             :                                  struct sss_domain_info *dom,
    1444             :                                  size_t ngroups, char **groups,
    1445             :                                  struct ldb_dn ***_dn_list,
    1446             :                                  char ***_missing_groups)
    1447             : {
    1448             :     int ret;
    1449             :     size_t c;
    1450             :     TALLOC_CTX *tmp_ctx;
    1451           0 :     struct ldb_dn **dn_list = NULL;
    1452           0 :     char **missing_groups = NULL;
    1453           0 :     struct ldb_message *msg = NULL;
    1454           0 :     size_t n_dns = 0;
    1455           0 :     size_t n_missing = 0;
    1456             :     struct sss_domain_info *obj_domain;
    1457             :     struct sss_domain_info *parent_domain;
    1458             : 
    1459           0 :     tmp_ctx = talloc_new(NULL);
    1460           0 :     if (tmp_ctx == NULL) {
    1461           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
    1462           0 :         return ENOMEM;
    1463             :     }
    1464             : 
    1465           0 :     dn_list = talloc_zero_array(tmp_ctx, struct ldb_dn *, ngroups + 1);
    1466           0 :     missing_groups = talloc_zero_array(tmp_ctx, char *, ngroups + 1);
    1467           0 :     if (dn_list == NULL || missing_groups == NULL) {
    1468           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_array_zero failed.\n");
    1469           0 :         ret = ENOMEM;
    1470           0 :         goto done;
    1471             :     }
    1472             : 
    1473           0 :     parent_domain = (dom->parent == NULL) ? dom : dom->parent;
    1474             : 
    1475           0 :     for (c = 0; c < ngroups; c++) {
    1476           0 :         obj_domain = find_domain_by_object_name(parent_domain, groups[c]);
    1477           0 :         if (obj_domain == NULL) {
    1478           0 :             DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_object_name failed.\n");
    1479           0 :             ret = ENOMEM;
    1480           0 :             goto done;
    1481             :         }
    1482             : 
    1483           0 :         ret = sysdb_search_group_by_name(tmp_ctx, obj_domain, groups[c], NULL,
    1484             :                                          &msg);
    1485           0 :         if (ret == EOK) {
    1486           0 :             dn_list[n_dns] = ldb_dn_copy(dn_list, msg->dn);
    1487           0 :             if (dn_list[n_dns] == NULL) {
    1488           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_copy failed.\n");
    1489           0 :                 ret = ENOMEM;
    1490           0 :                 goto done;
    1491             :             }
    1492           0 :             n_dns++;
    1493           0 :         } else if (ret == ENOENT) {
    1494           0 :             missing_groups[n_missing] = talloc_strdup(missing_groups,
    1495           0 :                                                       groups[c]);
    1496           0 :             if (missing_groups[n_missing] == NULL) {
    1497           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
    1498           0 :                 ret = ENOMEM;
    1499           0 :                 goto done;
    1500             :             }
    1501           0 :             n_missing++;
    1502             :         } else {
    1503           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_group_by_name failed.\n");
    1504           0 :             goto done;
    1505             :         }
    1506             :     }
    1507             : 
    1508           0 :     if (n_missing != 0) {
    1509           0 :         *_missing_groups = talloc_steal(mem_ctx, missing_groups);
    1510             :     } else {
    1511           0 :         *_missing_groups = NULL;
    1512             :     }
    1513             : 
    1514           0 :     if (n_dns != 0) {
    1515           0 :         *_dn_list = talloc_steal(mem_ctx, dn_list);
    1516             :     } else {
    1517           0 :         *dn_list = NULL;
    1518             :     }
    1519             : 
    1520           0 :     ret = EOK;
    1521             : 
    1522             : done:
    1523           0 :     talloc_free(tmp_ctx);
    1524             : 
    1525           0 :     return ret;
    1526             : }
    1527             : 
    1528             : static void ipa_s2n_get_list_done(struct tevent_req  *subreq);
    1529             : static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq);
    1530           0 : static void ipa_s2n_get_user_done(struct tevent_req *subreq)
    1531             : {
    1532           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1533             :                                                       struct tevent_req);
    1534           0 :     struct ipa_s2n_get_user_state *state = tevent_req_data(req,
    1535             :                                                 struct ipa_s2n_get_user_state);
    1536             :     int ret;
    1537           0 :     char *retoid = NULL;
    1538           0 :     struct berval *retdata = NULL;
    1539           0 :     struct resp_attrs *attrs = NULL;
    1540           0 :     struct berval *bv_req = NULL;
    1541           0 :     char **missing_list = NULL;
    1542           0 :     struct ldb_dn **group_dn_list = NULL;
    1543             :     const char *sid_str;
    1544             :     struct be_acct_req *ar;
    1545             : 
    1546           0 :     ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata);
    1547           0 :     talloc_zfree(subreq);
    1548           0 :     if (ret != EOK) {
    1549           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n exop request failed.\n");
    1550           0 :         if (state->req_input->type == REQ_INP_CERT) {
    1551           0 :             DEBUG(SSSDBG_OP_FAILURE,
    1552             :                   "Maybe the server does not support lookups by "
    1553             :                   "certificates.\n");
    1554             :         }
    1555           0 :         goto done;
    1556             :     }
    1557             : 
    1558           0 :     switch (state->request_type) {
    1559             :     case REQ_FULL_WITH_MEMBERS:
    1560             :     case REQ_FULL:
    1561           0 :         ret = s2n_response_to_attrs(state, retoid, retdata, &attrs);
    1562           0 :         if (ret != EOK) {
    1563           0 :             DEBUG(SSSDBG_OP_FAILURE, "s2n_response_to_attrs failed.\n");
    1564           0 :             goto done;
    1565             :         }
    1566             : 
    1567           0 :         if (!(strcasecmp(state->dom->name, attrs->domain_name) == 0 ||
    1568           0 :               (state->dom->flat_name != NULL &&
    1569           0 :                strcasecmp(state->dom->flat_name, attrs->domain_name) == 0))) {
    1570           0 :             DEBUG(SSSDBG_OP_FAILURE, "Unexpected domain name returned, "
    1571             :                                       "expected [%s] or [%s], got [%s].\n",
    1572             :                          state->dom->name,
    1573             :                          state->dom->flat_name == NULL ? "" :
    1574             :                                                          state->dom->flat_name,
    1575             :                          attrs->domain_name);
    1576           0 :             ret = EINVAL;
    1577           0 :             goto done;
    1578             :         }
    1579             : 
    1580           0 :         state->attrs = attrs;
    1581             : 
    1582           0 :         if (attrs->response_type == RESP_USER_GROUPLIST) {
    1583           0 :             ret = get_group_dn_list(state, state->dom,
    1584           0 :                                     attrs->ngroups, attrs->groups,
    1585             :                                     &group_dn_list, &missing_list);
    1586           0 :             if (ret != EOK) {
    1587           0 :                 DEBUG(SSSDBG_OP_FAILURE, "get_group_dn_list failed.\n");
    1588           0 :                 goto done;
    1589             :             }
    1590             : 
    1591           0 :             if (missing_list != NULL) {
    1592           0 :                 subreq = ipa_s2n_get_list_send(state, state->ev,
    1593             :                                                  state->ipa_ctx, state->dom,
    1594             :                                                  state->sh, state->exop_timeout,
    1595             :                                                  BE_REQ_GROUP,
    1596             :                                                  REQ_FULL_WITH_MEMBERS,
    1597             :                                                  REQ_INP_NAME,
    1598             :                                                  missing_list);
    1599           0 :                 if (subreq == NULL) {
    1600           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    1601             :                           "ipa_s2n_get_list_send failed.\n");
    1602           0 :                     ret = ENOMEM;
    1603           0 :                     goto done;
    1604             :                 }
    1605           0 :                 tevent_req_set_callback(subreq, ipa_s2n_get_list_done,
    1606             :                                         req);
    1607             : 
    1608           0 :                 return;
    1609             :             }
    1610           0 :             break;
    1611           0 :         } else if (attrs->response_type == RESP_GROUP_MEMBERS) {
    1612           0 :             ret = process_members(state->dom, NULL, attrs->a.group.gr_mem,
    1613             :                                   state, &missing_list);
    1614           0 :             if (ret != EOK) {
    1615           0 :                 DEBUG(SSSDBG_OP_FAILURE, "process_members failed.\n");
    1616           0 :                 goto done;
    1617             :             }
    1618             : 
    1619           0 :             if (missing_list != NULL) {
    1620           0 :                 subreq = ipa_s2n_get_list_send(state, state->ev,
    1621             :                                                  state->ipa_ctx, state->dom,
    1622             :                                                  state->sh, state->exop_timeout,
    1623             :                                                  BE_REQ_USER,
    1624             :                                                  REQ_FULL_WITH_MEMBERS,
    1625             :                                                  REQ_INP_NAME,
    1626             :                                                  missing_list);
    1627           0 :                 if (subreq == NULL) {
    1628           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    1629             :                           "ipa_s2n_get_list_send failed.\n");
    1630           0 :                     ret = ENOMEM;
    1631           0 :                     goto done;
    1632             :                 }
    1633           0 :                 tevent_req_set_callback(subreq, ipa_s2n_get_list_done,
    1634             :                                         req);
    1635             : 
    1636           0 :                 return;
    1637             :             }
    1638           0 :             break;
    1639             :         }
    1640             : 
    1641           0 :         if (state->req_input->type == REQ_INP_SECID) {
    1642             :             /* We already know the SID, we do not have to read it. */
    1643           0 :             break;
    1644             :         }
    1645             : 
    1646           0 :         state->request_type = REQ_SIMPLE;
    1647             : 
    1648           0 :         ret = s2n_encode_request(state, state->dom->name, state->entry_type,
    1649             :                                  state->request_type, state->req_input,
    1650             :                                  &bv_req);
    1651           0 :         if (ret != EOK) {
    1652           0 :             goto done;
    1653             :         }
    1654             : 
    1655           0 :         subreq = ipa_s2n_exop_send(state, state->ev, state->sh, false,
    1656             :                                    state->exop_timeout, bv_req);
    1657           0 :         if (subreq == NULL) {
    1658           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_exop_send failed.\n");
    1659           0 :             ret = ENOMEM;
    1660           0 :             goto done;
    1661             :         }
    1662           0 :         tevent_req_set_callback(subreq, ipa_s2n_get_user_done, req);
    1663             : 
    1664           0 :         return;
    1665             : 
    1666             :     case REQ_SIMPLE:
    1667           0 :         ret = s2n_response_to_attrs(state, retoid, retdata,
    1668             :                                     &state->simple_attrs);
    1669           0 :         if (ret != EOK) {
    1670           0 :             DEBUG(SSSDBG_OP_FAILURE, "s2n_response_to_attrs failed.\n");
    1671           0 :             goto done;
    1672             :         }
    1673             : 
    1674           0 :         break;
    1675             :     default:
    1676           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n");
    1677           0 :         ret = EINVAL;
    1678           0 :         goto done;
    1679             :     }
    1680             : 
    1681           0 :     if (state->attrs == NULL) {
    1682           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing data of full request.\n");
    1683           0 :         ret = EINVAL;
    1684           0 :         goto done;
    1685             :     }
    1686             : 
    1687           0 :     if (state->simple_attrs != NULL
    1688           0 :             && state->simple_attrs->response_type == RESP_SID) {
    1689           0 :         sid_str = state->simple_attrs->a.sid_str;
    1690           0 :         ret = EOK;
    1691           0 :     } else if (state->attrs->sysdb_attrs != NULL) {
    1692           0 :         ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
    1693             :                                      &sid_str);
    1694           0 :     } else if (state->req_input->type == REQ_INP_SECID) {
    1695           0 :         sid_str = state->req_input->inp.secid;
    1696           0 :         ret = EOK;
    1697             :     } else {
    1698           0 :         DEBUG(SSSDBG_TRACE_FUNC, "No SID available.\n");
    1699           0 :         ret = ENOENT;
    1700             :     }
    1701             : 
    1702           0 :     if (ret == ENOENT || is_default_view(state->ipa_ctx->view_name)) {
    1703           0 :         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
    1704             :                                    state->simple_attrs, NULL, NULL, true);
    1705           0 :         if (ret != EOK) {
    1706           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
    1707           0 :             goto done;
    1708             :         }
    1709           0 :     } else if (ret == EOK) {
    1710           0 :         ret = get_be_acct_req_for_sid(state, sid_str, state->dom->name, &ar);
    1711           0 :         if (ret != EOK) {
    1712           0 :             DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
    1713           0 :             goto done;
    1714             :         }
    1715             : 
    1716           0 :         subreq = ipa_get_ad_override_send(state, state->ev,
    1717           0 :                            state->ipa_ctx->sdap_id_ctx,
    1718           0 :                            state->ipa_ctx->ipa_options,
    1719           0 :                            dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
    1720             :                                              IPA_KRB5_REALM),
    1721           0 :                            state->ipa_ctx->view_name,
    1722             :                            ar);
    1723           0 :         if (subreq == NULL) {
    1724           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
    1725           0 :             ret = ENOMEM;
    1726           0 :             goto done;
    1727             :         }
    1728           0 :         tevent_req_set_callback(subreq, ipa_s2n_get_user_get_override_done,
    1729             :                                 req);
    1730             : 
    1731           0 :         return;
    1732             :     } else {
    1733           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    1734           0 :         goto done;
    1735             :     }
    1736             : 
    1737             : done:
    1738           0 :     if (ret == EOK) {
    1739           0 :         tevent_req_done(req);
    1740             :     } else {
    1741           0 :         tevent_req_error(req, ret);
    1742             :     }
    1743           0 :     return;
    1744             : }
    1745             : 
    1746           0 : static errno_t get_groups_dns(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
    1747             :                               char **name_list, char ***_dn_list)
    1748             : {
    1749             :     int ret;
    1750             :     TALLOC_CTX *tmp_ctx;
    1751             :     int c;
    1752             :     struct sss_domain_info *root_domain;
    1753             :     char **dn_list;
    1754             : 
    1755           0 :     if (name_list == NULL) {
    1756           0 :         *_dn_list = NULL;
    1757           0 :         return EOK;
    1758             :     }
    1759             : 
    1760             :     /* To handle cross-domain memberships we have to check the domain for
    1761             :      * each group the member should be added or deleted. Since sub-domains
    1762             :      * use fully-qualified names by default any short name can only belong
    1763             :      * to the root/head domain. find_domain_by_object_name() will return
    1764             :      * the domain given in the first argument if the second argument is a
    1765             :      * a short name hence we always use root_domain as first argument. */
    1766           0 :     root_domain = get_domains_head(dom);
    1767           0 :     if (root_domain->fqnames) {
    1768           0 :         DEBUG(SSSDBG_TRACE_FUNC,
    1769             :               "Root domain uses fully-qualified names, " \
    1770             :               "objects might not be correctly added to groups with " \
    1771             :               "short names.\n");
    1772             :     }
    1773             : 
    1774           0 :     tmp_ctx = talloc_new(NULL);
    1775           0 :     if (tmp_ctx == NULL) {
    1776           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
    1777           0 :         return ENOMEM;
    1778             :     }
    1779             : 
    1780           0 :     for (c = 0; name_list[c] != NULL; c++);
    1781             : 
    1782           0 :     dn_list = talloc_zero_array(tmp_ctx, char *, c + 1);
    1783           0 :     if (dn_list == NULL) {
    1784           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n");
    1785           0 :         ret = ENOMEM;
    1786           0 :         goto done;
    1787             :     }
    1788             : 
    1789           0 :     for (c = 0; name_list[c] != NULL; c++) {
    1790           0 :         dom = find_domain_by_object_name(root_domain, name_list[c]);
    1791           0 :         if (dom == NULL) {
    1792           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    1793             :                   "Cannot find domain for [%s].\n", name_list[c]);
    1794           0 :             ret = ENOENT;
    1795           0 :             goto done;
    1796             :         }
    1797             : 
    1798             :         /* This might fail if some unexpected cases are used. But current
    1799             :          * sysdb code which handles group membership constructs DNs this way
    1800             :          * as well, IPA names are lowercased and AD names by default will be
    1801             :          * lowercased as well. If there are really use-cases which cause an
    1802             :          * issue here, sysdb_group_strdn() has to be replaced by a proper
    1803             :          * search. */
    1804           0 :         dn_list[c] = sysdb_group_strdn(dn_list, dom->name, name_list[c]);
    1805           0 :         if (dn_list[c] == NULL) {
    1806           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_group_strdn failed.\n");
    1807           0 :             ret = ENOMEM;
    1808           0 :             goto done;
    1809             :         }
    1810             : 
    1811           0 :         DEBUG(SSSDBG_TRACE_ALL, "Added [%s][%s].\n", name_list[c], dn_list[c]);
    1812             :     }
    1813             : 
    1814           0 :     *_dn_list = talloc_steal(mem_ctx, dn_list);
    1815           0 :     ret = EOK;
    1816             : 
    1817             : done:
    1818           0 :     talloc_free(tmp_ctx);
    1819             : 
    1820           0 :     return ret;
    1821             : }
    1822             : 
    1823           0 : static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
    1824             :                                     struct req_input *req_input,
    1825             :                                     struct resp_attrs *attrs,
    1826             :                                     struct resp_attrs *simple_attrs,
    1827             :                                     const char *view_name,
    1828             :                                     struct sysdb_attrs *override_attrs,
    1829             :                                     bool update_initgr_timeout)
    1830             : {
    1831             :     int ret;
    1832             :     time_t now;
    1833             :     struct sss_nss_homedir_ctx homedir_ctx;
    1834           0 :     char *name = NULL;
    1835             :     char *realm;
    1836           0 :     char *upn = NULL;
    1837             :     gid_t gid;
    1838           0 :     gid_t orig_gid = 0;
    1839             :     TALLOC_CTX *tmp_ctx;
    1840             :     const char *sid_str;
    1841             :     const char *tmp_str;
    1842             :     struct ldb_result *res;
    1843             :     enum sysdb_member_type type;
    1844             :     char **sysdb_grouplist;
    1845             :     char **add_groups;
    1846             :     char **add_groups_dns;
    1847             :     char **del_groups;
    1848             :     char **del_groups_dns;
    1849           0 :     bool in_transaction = false;
    1850             :     int tret;
    1851           0 :     struct sysdb_attrs *gid_override_attrs = NULL;
    1852             :     char ** exop_grouplist;
    1853             :     struct ldb_message *msg;
    1854           0 :     struct ldb_message_element *el = NULL;
    1855           0 :     const char *missing[] = {NULL, NULL};
    1856             : 
    1857           0 :     tmp_ctx = talloc_new(NULL);
    1858           0 :     if (tmp_ctx == NULL) {
    1859           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
    1860           0 :         return ENOMEM;
    1861             :     }
    1862             : 
    1863           0 :     now = time(NULL);
    1864             : 
    1865           0 :     if (attrs->sysdb_attrs == NULL) {
    1866           0 :         attrs->sysdb_attrs = sysdb_new_attrs(attrs);
    1867           0 :         if (attrs->sysdb_attrs == NULL) {
    1868           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
    1869           0 :             ret = ENOMEM;
    1870           0 :             goto done;
    1871             :         }
    1872             :     }
    1873             : 
    1874           0 :     if (attrs->sysdb_attrs != NULL) {
    1875           0 :         ret = sysdb_attrs_get_string(attrs->sysdb_attrs,
    1876             :                                      ORIGINALAD_PREFIX SYSDB_NAME, &tmp_str);
    1877           0 :         if (ret == EOK) {
    1878           0 :             name = talloc_strdup(tmp_ctx, tmp_str);
    1879           0 :             if (name == NULL) {
    1880           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
    1881           0 :                 ret = ENOMEM;
    1882           0 :                 goto done;
    1883             :             }
    1884           0 :             DEBUG(SSSDBG_TRACE_ALL, "Found original AD name [%s].\n", name);
    1885           0 :         } else if (ret == ENOENT) {
    1886           0 :             name = NULL;
    1887             :         } else {
    1888           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    1889           0 :             goto done;
    1890             :         }
    1891             : 
    1892           0 :         ret = sysdb_attrs_get_string(attrs->sysdb_attrs,
    1893             :                                      SYSDB_DEFAULT_OVERRIDE_NAME, &tmp_str);
    1894           0 :         if (ret == EOK) {
    1895           0 :             ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs,
    1896             :                                                      tmp_str);
    1897           0 :             if (ret != EOK) {
    1898           0 :                 DEBUG(SSSDBG_OP_FAILURE,
    1899             :                       "sysdb_attrs_add_lc_name_alias_safe failed.\n");
    1900           0 :                 goto done;
    1901             :             }
    1902           0 :         } else if (ret != ENOENT) {
    1903           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    1904           0 :             goto done;
    1905             :         }
    1906             : 
    1907           0 :         ret = sysdb_attrs_get_string(attrs->sysdb_attrs, SYSDB_UPN, &tmp_str);
    1908           0 :         if (ret == EOK) {
    1909           0 :             upn = talloc_strdup(tmp_ctx, tmp_str);
    1910           0 :             if (upn == NULL) {
    1911           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
    1912           0 :                 ret = ENOMEM;
    1913           0 :                 goto done;
    1914             :             }
    1915           0 :             DEBUG(SSSDBG_TRACE_ALL, "Found original AD upn [%s].\n", upn);
    1916           0 :         } else if (ret == ENOENT) {
    1917           0 :             upn = NULL;
    1918             :         } else {
    1919           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    1920           0 :             goto done;
    1921             :         }
    1922             :     }
    1923             : 
    1924           0 :     if (strcmp(dom->name, attrs->domain_name) != 0) {
    1925           0 :         dom = find_domain_by_name(get_domains_head(dom),
    1926           0 :                                   attrs->domain_name, true);
    1927           0 :         if (dom == NULL) {
    1928           0 :             DEBUG(SSSDBG_OP_FAILURE,
    1929             :                     "Cannot find domain: [%s]\n", attrs->domain_name);
    1930           0 :             ret = EINVAL;
    1931           0 :             goto done;
    1932             :         }
    1933             :     }
    1934             : 
    1935           0 :     switch (attrs->response_type) {
    1936             :         case RESP_USER:
    1937             :         case RESP_USER_GROUPLIST:
    1938           0 :             type = SYSDB_MEMBER_USER;
    1939           0 :             if (dom->subdomain_homedir
    1940           0 :                     && attrs->a.user.pw_dir == NULL) {
    1941           0 :                 ZERO_STRUCT(homedir_ctx);
    1942           0 :                 homedir_ctx.username = attrs->a.user.pw_name;
    1943           0 :                 homedir_ctx.uid = attrs->a.user.pw_uid;
    1944           0 :                 homedir_ctx.domain = dom->name;
    1945           0 :                 homedir_ctx.flatname = dom->flat_name;
    1946           0 :                 homedir_ctx.config_homedir_substr = dom->homedir_substr;
    1947             : 
    1948           0 :                 attrs->a.user.pw_dir = expand_homedir_template(attrs,
    1949             :                                                   dom->subdomain_homedir,
    1950             :                                                   &homedir_ctx);
    1951           0 :                 if (attrs->a.user.pw_dir == NULL) {
    1952           0 :                     ret = ENOMEM;
    1953           0 :                     goto done;
    1954             :                 }
    1955             :             }
    1956             : 
    1957           0 :             if (name == NULL) {
    1958             :                 /* we always use the fully qualified name for subdomain users */
    1959           0 :                 name = sss_tc_fqname(tmp_ctx, dom->names, dom,
    1960           0 :                                      attrs->a.user.pw_name);
    1961           0 :                 if (!name) {
    1962           0 :                     DEBUG(SSSDBG_OP_FAILURE, "failed to format user name.\n");
    1963           0 :                     ret = ENOMEM;
    1964           0 :                     goto done;
    1965             :                 }
    1966             :             }
    1967             : 
    1968           0 :             ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs, name);
    1969           0 :             if (ret != EOK) {
    1970           0 :                 DEBUG(SSSDBG_OP_FAILURE,
    1971             :                       "sysdb_attrs_add_lc_name_alias_safe failed.\n");
    1972           0 :                 goto done;
    1973             :             }
    1974             : 
    1975           0 :             if (upn == NULL) {
    1976             :                 /* We also have to store a fake UPN here, because otherwise the
    1977             :                  * krb5 child later won't be able to properly construct one as
    1978             :                  * the username is fully qualified but the child doesn't have
    1979             :                  * access to the regex to deconstruct it */
    1980             :                 /* FIXME: The real UPN is available from the PAC, we should get
    1981             :                  * it from there. */
    1982           0 :                 realm = get_uppercase_realm(tmp_ctx, dom->name);
    1983           0 :                 if (!realm) {
    1984           0 :                     DEBUG(SSSDBG_OP_FAILURE, "failed to get realm.\n");
    1985           0 :                     ret = ENOMEM;
    1986           0 :                     goto done;
    1987             :                 }
    1988           0 :                 upn = talloc_asprintf(tmp_ctx, "%s@%s",
    1989             :                                       attrs->a.user.pw_name, realm);
    1990           0 :                 if (!upn) {
    1991           0 :                     DEBUG(SSSDBG_OP_FAILURE, "failed to format UPN.\n");
    1992           0 :                     ret = ENOMEM;
    1993           0 :                     goto done;
    1994             :                 }
    1995             : 
    1996             :                 /* We might already have the SID or the UPN from other sources
    1997             :                  * hence sysdb_attrs_add_string_safe is used to avoid double
    1998             :                  * entries. */
    1999           0 :                 ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs, SYSDB_UPN,
    2000             :                                                   upn);
    2001           0 :                 if (ret != EOK) {
    2002           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2003             :                           "sysdb_attrs_add_string failed.\n");
    2004           0 :                     goto done;
    2005             :                 }
    2006             :             }
    2007             : 
    2008           0 :             if (req_input->type == REQ_INP_SECID) {
    2009           0 :                 ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
    2010             :                                                   SYSDB_SID_STR,
    2011             :                                                   req_input->inp.secid);
    2012           0 :                 if (ret != EOK) {
    2013           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2014             :                           "sysdb_attrs_add_string failed.\n");
    2015           0 :                     goto done;
    2016             :                 }
    2017             :             }
    2018             : 
    2019           0 :             if (simple_attrs != NULL
    2020           0 :                     && simple_attrs->response_type == RESP_SID) {
    2021           0 :                 ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
    2022             :                                                   SYSDB_SID_STR,
    2023           0 :                                                   simple_attrs->a.sid_str);
    2024           0 :                 if (ret != EOK) {
    2025           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2026             :                           "sysdb_attrs_add_string failed.\n");
    2027           0 :                     goto done;
    2028             :                 }
    2029             :             }
    2030             : 
    2031           0 :             if (attrs->response_type == RESP_USER_GROUPLIST
    2032           0 :                     && update_initgr_timeout) {
    2033             :                 /* Since RESP_USER_GROUPLIST contains all group memberships it
    2034             :                  * is effectively an initgroups request hence
    2035             :                  * SYSDB_INITGR_EXPIRE will be set.*/
    2036           0 :                 ret = sysdb_attrs_add_time_t(attrs->sysdb_attrs,
    2037             :                                              SYSDB_INITGR_EXPIRE,
    2038           0 :                                              time(NULL) + dom->user_timeout);
    2039           0 :                 if (ret != EOK) {
    2040           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2041             :                           "sysdb_attrs_add_time_t failed.\n");
    2042           0 :                     goto done;
    2043             :                 }
    2044             :             }
    2045             : 
    2046           0 :             gid = 0;
    2047           0 :             if (dom->mpg == false) {
    2048           0 :                 gid = attrs->a.user.pw_gid;
    2049             :             } else {
    2050             :                 /* The extdom plugin always returns the objects with the
    2051             :                  * default view applied. Since the GID is handled specially
    2052             :                  * for MPG domains we have add any overridden GID separately.
    2053             :                  */
    2054           0 :                 ret = sysdb_attrs_get_uint32_t(attrs->sysdb_attrs,
    2055             :                                                ORIGINALAD_PREFIX SYSDB_GIDNUM,
    2056             :                                                &orig_gid);
    2057           0 :                 if (ret == EOK || ret == ENOENT) {
    2058           0 :                     if ((orig_gid != 0 && orig_gid != attrs->a.user.pw_gid)
    2059           0 :                             || attrs->a.user.pw_uid != attrs->a.user.pw_gid) {
    2060             : 
    2061           0 :                         gid_override_attrs = sysdb_new_attrs(tmp_ctx);
    2062           0 :                         if (gid_override_attrs == NULL) {
    2063           0 :                             DEBUG(SSSDBG_OP_FAILURE,
    2064             :                                   "sysdb_new_attrs failed.\n");
    2065           0 :                             ret = ENOMEM;
    2066           0 :                             goto done;
    2067             :                         }
    2068             : 
    2069           0 :                         ret = sysdb_attrs_add_uint32(gid_override_attrs,
    2070             :                                                      SYSDB_GIDNUM,
    2071             :                                                      attrs->a.user.pw_gid);
    2072           0 :                         if (ret != EOK) {
    2073           0 :                             DEBUG(SSSDBG_OP_FAILURE,
    2074             :                                   "sysdb_attrs_add_uint32 failed.\n");
    2075           0 :                             goto done;
    2076             :                         }
    2077             :                     }
    2078             :                 } else {
    2079           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2080             :                           "sysdb_attrs_get_uint32_t failed.\n");
    2081           0 :                     goto done;
    2082             :                 }
    2083             :             }
    2084             : 
    2085           0 :             ret = sysdb_attrs_get_el_ext(attrs->sysdb_attrs,
    2086             :                                          SYSDB_ORIG_MEMBEROF, false, &el);
    2087           0 :             if (ret == ENOENT) {
    2088           0 :                 missing[0] = SYSDB_ORIG_MEMBEROF;
    2089             :             }
    2090             : 
    2091           0 :             ret = sysdb_transaction_start(dom->sysdb);
    2092           0 :             if (ret != EOK) {
    2093           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
    2094           0 :                 goto done;
    2095             :             }
    2096           0 :             in_transaction = true;
    2097             : 
    2098           0 :             ret = sysdb_store_user(dom, name, NULL,
    2099             :                                    attrs->a.user.pw_uid,
    2100           0 :                                    gid, attrs->a.user.pw_gecos,
    2101           0 :                                    attrs->a.user.pw_dir, attrs->a.user.pw_shell,
    2102             :                                    NULL, attrs->sysdb_attrs,
    2103           0 :                                    missing[0] == NULL ? NULL
    2104             :                                                       : discard_const(missing),
    2105           0 :                                    dom->user_timeout, now);
    2106           0 :             if (ret == EEXIST && dom->mpg == true) {
    2107             :                 /* This handles the case where getgrgid() was called for
    2108             :                  * this user, so a group was created in the cache
    2109             :                  */
    2110           0 :                 ret = sysdb_search_group_by_name(tmp_ctx, dom, name, NULL, &msg);
    2111           0 :                 if (ret != EOK) {
    2112             :                     /* Fail even on ENOENT, the group must be around */
    2113           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2114             :                           "Could not delete MPG group [%d]: %s\n",
    2115             :                           ret, sss_strerror(ret));
    2116           0 :                     goto done;
    2117             :                 }
    2118             : 
    2119           0 :                 ret = sysdb_delete_group(dom, NULL, attrs->a.user.pw_uid);
    2120           0 :                 if (ret != EOK) {
    2121           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2122             :                           "sysdb_delete_group failed for MPG group [%d]: %s\n",
    2123             :                           ret, sss_strerror(ret));
    2124           0 :                     goto done;
    2125             :                 }
    2126             : 
    2127           0 :                 ret = sysdb_store_user(dom, name, NULL,
    2128             :                                        attrs->a.user.pw_uid,
    2129           0 :                                        gid, attrs->a.user.pw_gecos,
    2130           0 :                                        attrs->a.user.pw_dir,
    2131           0 :                                        attrs->a.user.pw_shell,
    2132             :                                        NULL, attrs->sysdb_attrs, NULL,
    2133           0 :                                        dom->user_timeout, now);
    2134           0 :                 if (ret != EOK) {
    2135           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2136             :                           "sysdb_store_user failed for MPG user [%d]: %s\n",
    2137             :                           ret, sss_strerror(ret));
    2138           0 :                     goto done;
    2139             :                 }
    2140           0 :             } else if (ret != EOK) {
    2141           0 :                 DEBUG(SSSDBG_OP_FAILURE,
    2142             :                       "sysdb_store_user failed [%d]: %s\n",
    2143             :                       ret, sss_strerror(ret));
    2144           0 :                 goto done;
    2145             :             }
    2146             : 
    2147           0 :             if (gid_override_attrs != NULL) {
    2148           0 :                 ret = sysdb_set_user_attr(dom, name, gid_override_attrs,
    2149             :                                           SYSDB_MOD_REP);
    2150           0 :                 if (ret != EOK) {
    2151           0 :                     DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_user_attr failed.\n");
    2152           0 :                     goto done;
    2153             :                 }
    2154             :             }
    2155             : 
    2156           0 :             if (attrs->response_type == RESP_USER_GROUPLIST) {
    2157           0 :                 ret = get_sysdb_grouplist(tmp_ctx, dom->sysdb, dom, name,
    2158             :                                           &sysdb_grouplist);
    2159           0 :                 if (ret != EOK) {
    2160           0 :                     DEBUG(SSSDBG_OP_FAILURE, "get_sysdb_grouplist failed.\n");
    2161           0 :                     goto done;
    2162             :                 }
    2163             : 
    2164             :                 /* names returned by extdom exop will be all lower case, since
    2165             :                  * we handle domain names case sensitve in the cache we have
    2166             :                  * to make sure we use the right case. */
    2167           0 :                 ret = fix_domain_in_name_list(tmp_ctx, dom, attrs->groups,
    2168             :                                               &exop_grouplist);
    2169           0 :                 if (ret != EOK) {
    2170           0 :                     DEBUG(SSSDBG_OP_FAILURE, "fix_domain_name failed.\n");
    2171           0 :                     goto done;
    2172             :                 }
    2173             : 
    2174           0 :                 ret = diff_string_lists(tmp_ctx, exop_grouplist,
    2175             :                                         sysdb_grouplist, &add_groups,
    2176             :                                         &del_groups, NULL);
    2177           0 :                 if (ret != EOK) {
    2178           0 :                     DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n");
    2179           0 :                     goto done;
    2180             :                 }
    2181             : 
    2182           0 :                 ret = get_groups_dns(tmp_ctx, dom, add_groups, &add_groups_dns);
    2183           0 :                 if (ret != EOK) {
    2184           0 :                     DEBUG(SSSDBG_OP_FAILURE, "get_groups_dns failed.\n");
    2185           0 :                     goto done;
    2186             :                 }
    2187             : 
    2188           0 :                 ret = get_groups_dns(tmp_ctx, dom, del_groups, &del_groups_dns);
    2189           0 :                 if (ret != EOK) {
    2190           0 :                     DEBUG(SSSDBG_OP_FAILURE, "get_groups_dns failed.\n");
    2191           0 :                     goto done;
    2192             :                 }
    2193             : 
    2194           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL, "Updating memberships for %s\n",
    2195             :                                              name);
    2196           0 :                 ret = sysdb_update_members_dn(dom, name, SYSDB_MEMBER_USER,
    2197             :                                           (const char *const *) add_groups_dns,
    2198             :                                           (const char *const *) del_groups_dns);
    2199           0 :                 if (ret != EOK) {
    2200           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Membership update failed [%d]: %s\n",
    2201             :                                                ret, sss_strerror(ret));
    2202           0 :                     goto done;
    2203             :                 }
    2204             :             }
    2205             : 
    2206           0 :             ret = sysdb_transaction_commit(dom->sysdb);
    2207           0 :             if (ret != EOK) {
    2208           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
    2209           0 :                 goto done;
    2210             :             }
    2211           0 :             in_transaction = false;
    2212             : 
    2213           0 :             break;
    2214             :         case RESP_GROUP:
    2215             :         case RESP_GROUP_MEMBERS:
    2216           0 :             type = SYSDB_MEMBER_GROUP;
    2217             : 
    2218           0 :             if (name == NULL) {
    2219           0 :                 name = attrs->a.group.gr_name;
    2220             :             }
    2221             : 
    2222           0 :             if (IS_SUBDOMAIN(dom)) {
    2223             :                 /* we always use the fully qualified name for subdomain users */
    2224           0 :                 name = sss_get_domain_name(tmp_ctx, name, dom);
    2225           0 :                 if (!name) {
    2226           0 :                     DEBUG(SSSDBG_OP_FAILURE, "failed to format user name,\n");
    2227           0 :                     ret = ENOMEM;
    2228           0 :                     goto done;
    2229             :                 }
    2230             :             }
    2231           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Processing group %s\n", name);
    2232             : 
    2233           0 :             ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs, name);
    2234           0 :             if (ret != EOK) {
    2235           0 :                 DEBUG(SSSDBG_OP_FAILURE,
    2236             :                       "sysdb_attrs_add_lc_name_alias_safe failed.\n");
    2237           0 :                 goto done;
    2238             :             }
    2239             : 
    2240             :             /* We might already have the SID from other sources hence
    2241             :              * sysdb_attrs_add_string_safe is used to avoid double entries. */
    2242           0 :             if (req_input->type == REQ_INP_SECID) {
    2243           0 :                 ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
    2244             :                                                   SYSDB_SID_STR,
    2245             :                                                   req_input->inp.secid);
    2246           0 :                 if (ret != EOK) {
    2247           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2248             :                           "sysdb_attrs_add_string failed.\n");
    2249           0 :                     goto done;
    2250             :                 }
    2251             :             }
    2252             : 
    2253           0 :             if (simple_attrs != NULL
    2254           0 :                 && simple_attrs->response_type == RESP_SID) {
    2255           0 :                 ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
    2256             :                                                   SYSDB_SID_STR,
    2257           0 :                                                   simple_attrs->a.sid_str);
    2258           0 :                 if (ret != EOK) {
    2259           0 :                     DEBUG(SSSDBG_OP_FAILURE,
    2260             :                           "sysdb_attrs_add_string failed.\n");
    2261           0 :                     goto done;
    2262             :                 }
    2263             :             }
    2264             : 
    2265           0 :             ret = process_members(dom, attrs->sysdb_attrs,
    2266             :                                   attrs->a.group.gr_mem, NULL, NULL);
    2267           0 :             if (ret != EOK) {
    2268           0 :                 DEBUG(SSSDBG_OP_FAILURE, "process_members failed.\n");
    2269           0 :                 goto done;
    2270             :             }
    2271             : 
    2272           0 :             ret = sysdb_store_group(dom, name, attrs->a.group.gr_gid,
    2273           0 :                                     attrs->sysdb_attrs, dom->group_timeout,
    2274             :                                     now);
    2275           0 :             if (ret != EOK) {
    2276           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_group failed.\n");
    2277           0 :                 goto done;
    2278             :             }
    2279           0 :             break;
    2280             :         default:
    2281           0 :             DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
    2282             :                                       attrs->response_type);
    2283           0 :             ret = EINVAL;
    2284           0 :             goto done;
    2285             :     }
    2286             : 
    2287           0 :     ret = sysdb_attrs_get_string(attrs->sysdb_attrs, SYSDB_SID_STR, &sid_str);
    2288           0 :     if (ret != EOK) {
    2289           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    2290             :               "Cannot find SID of object with override.\n");
    2291           0 :         goto done;
    2292             :     }
    2293             : 
    2294           0 :     ret = sysdb_search_object_by_sid(tmp_ctx, dom, sid_str, NULL, &res);
    2295           0 :     if (ret != EOK) {
    2296           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    2297             :               "Cannot find object with override with SID [%s].\n", sid_str);
    2298           0 :         goto done;
    2299             :     }
    2300             : 
    2301           0 :     if (!is_default_view(view_name)) {
    2302             :         /* For the default view the data return by the extdom plugin already
    2303             :          * contains all needed data and it is not expected to have a separate
    2304             :          * override object. */
    2305           0 :         ret = sysdb_store_override(dom, view_name, type, override_attrs,
    2306           0 :                                    res->msgs[0]->dn);
    2307           0 :         if (ret != EOK) {
    2308           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
    2309           0 :             goto done;
    2310             :         }
    2311             :     }
    2312             : 
    2313             : done:
    2314           0 :     if (in_transaction) {
    2315           0 :         tret = sysdb_transaction_cancel(dom->sysdb);
    2316           0 :         if (tret != EOK) {
    2317           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
    2318             :         }
    2319             :     }
    2320             : 
    2321           0 :     talloc_free(tmp_ctx);
    2322             : 
    2323           0 :     return ret;
    2324             : }
    2325             : 
    2326           0 : static void ipa_s2n_get_list_done(struct tevent_req  *subreq)
    2327             : {
    2328             :     int ret;
    2329           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    2330             :                                                       struct tevent_req);
    2331           0 :     struct ipa_s2n_get_user_state *state = tevent_req_data(req,
    2332             :                                                 struct ipa_s2n_get_user_state);
    2333             :     const char *sid_str;
    2334             :     struct be_acct_req *ar;
    2335             : 
    2336           0 :     ret = ipa_s2n_get_list_recv(subreq);
    2337           0 :     talloc_zfree(subreq);
    2338           0 :     if (ret != EOK) {
    2339           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n get_fqlist request failed.\n");
    2340           0 :         tevent_req_error(req, ret);
    2341           0 :         return;
    2342             :     }
    2343             : 
    2344           0 :     ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
    2345             :                                  &sid_str);
    2346           0 :     if (ret == ENOENT) {
    2347           0 :         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
    2348             :                                    state->simple_attrs, NULL, NULL, true);
    2349           0 :         if (ret != EOK) {
    2350           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
    2351           0 :             goto fail;
    2352             :         }
    2353           0 :         tevent_req_done(req);
    2354           0 :         return;
    2355           0 :     } else if (ret != EOK) {
    2356           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
    2357           0 :         goto fail;
    2358             :     }
    2359             : 
    2360           0 :     ret = get_be_acct_req_for_sid(state, sid_str, state->dom->name, &ar);
    2361           0 :     if (ret != EOK) {
    2362           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
    2363           0 :         goto fail;
    2364             :     }
    2365             : 
    2366           0 :     if (state->override_attrs == NULL
    2367           0 :             && !is_default_view(state->ipa_ctx->view_name)) {
    2368           0 :         subreq = ipa_get_ad_override_send(state, state->ev,
    2369           0 :                            state->ipa_ctx->sdap_id_ctx,
    2370           0 :                            state->ipa_ctx->ipa_options,
    2371           0 :                            dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
    2372             :                                              IPA_KRB5_REALM),
    2373           0 :                            state->ipa_ctx->view_name,
    2374             :                            ar);
    2375           0 :         if (subreq == NULL) {
    2376           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
    2377           0 :             ret = ENOMEM;
    2378           0 :             goto fail;
    2379             :         }
    2380           0 :         tevent_req_set_callback(subreq, ipa_s2n_get_user_get_override_done,
    2381             :                                 req);
    2382             :     } else {
    2383           0 :         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
    2384             :                                    state->simple_attrs,
    2385           0 :                                    state->ipa_ctx->view_name,
    2386             :                                    state->override_attrs, true);
    2387           0 :         if (ret != EOK) {
    2388           0 :             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
    2389           0 :             tevent_req_error(req, ret);
    2390           0 :             return;
    2391             :         }
    2392             : 
    2393           0 :         tevent_req_done(req);
    2394             :     }
    2395             : 
    2396           0 :     return;
    2397             : 
    2398             : fail:
    2399           0 :     tevent_req_error(req, ret);
    2400           0 :     return;
    2401             : }
    2402             : 
    2403           0 : static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq)
    2404             : {
    2405             :     int ret;
    2406           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    2407             :                                                       struct tevent_req);
    2408           0 :     struct ipa_s2n_get_user_state *state = tevent_req_data(req,
    2409             :                                                 struct ipa_s2n_get_user_state);
    2410           0 :     struct sysdb_attrs *override_attrs = NULL;
    2411             : 
    2412           0 :     ret = ipa_get_ad_override_recv(subreq, NULL, state, &override_attrs);
    2413           0 :     talloc_zfree(subreq);
    2414           0 :     if (ret != EOK) {
    2415           0 :         DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
    2416           0 :         tevent_req_error(req, ret);
    2417           0 :         return;
    2418             :     }
    2419             : 
    2420           0 :     ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
    2421           0 :                                state->simple_attrs, state->ipa_ctx->view_name,
    2422             :                                override_attrs, true);
    2423           0 :     if (ret != EOK) {
    2424           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
    2425           0 :         tevent_req_error(req, ret);
    2426           0 :         return;
    2427             :     }
    2428             : 
    2429           0 :     tevent_req_done(req);
    2430           0 :     return;
    2431             : }
    2432             : 
    2433           0 : int ipa_s2n_get_acct_info_recv(struct tevent_req *req)
    2434             : {
    2435           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    2436             : 
    2437           0 :     return EOK;
    2438             : }
    2439             : 
    2440             : struct ipa_get_subdom_acct_process_pac_state {
    2441             :     struct tevent_context *ev;
    2442             :     struct sdap_handle *sh;
    2443             :     struct sss_domain_info *dom;
    2444             :     char *username;
    2445             : 
    2446             :     size_t num_missing_sids;
    2447             :     char **missing_sids;
    2448             :     size_t num_cached_groups;
    2449             :     char **cached_groups;
    2450             : };
    2451             : 
    2452             : static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq);
    2453             : 
    2454           0 : struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
    2455             :                                                    struct tevent_context *ev,
    2456             :                                                    struct sdap_handle *sh,
    2457             :                                                    struct ipa_id_ctx *ipa_ctx,
    2458             :                                                    struct sss_domain_info *dom,
    2459             :                                                    struct ldb_message *user_msg)
    2460             : {
    2461             :     int ret;
    2462             :     struct ipa_get_subdom_acct_process_pac_state *state;
    2463             :     struct tevent_req *req;
    2464             :     struct tevent_req *subreq;
    2465             :     char *user_sid;
    2466             :     char *primary_group_sid;
    2467             :     size_t num_sids;
    2468             :     char **group_sids;
    2469             : 
    2470           0 :     req = tevent_req_create(mem_ctx, &state,
    2471             :                             struct ipa_get_subdom_acct_process_pac_state);
    2472           0 :     if (req == NULL) {
    2473           0 :         DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
    2474           0 :         return NULL;
    2475             :     }
    2476             : 
    2477           0 :     state->ev = ev;
    2478           0 :     state->sh = sh;
    2479           0 :     state->dom = dom;
    2480             : 
    2481           0 :     ret = ad_get_pac_data_from_user_entry(state, user_msg,
    2482           0 :                                      ipa_ctx->sdap_id_ctx->opts->idmap_ctx->map,
    2483           0 :                                      &state->username,
    2484             :                                      &user_sid, &primary_group_sid,
    2485             :                                      &num_sids, &group_sids);
    2486           0 :     if (ret != EOK) {
    2487           0 :         DEBUG(SSSDBG_OP_FAILURE, "ad_get_pac_data_from_user_entry failed.\n");
    2488           0 :         goto done;
    2489             :     }
    2490             : 
    2491           0 :     ret = sdap_ad_tokengroups_get_posix_members(state, state->dom,
    2492             :                                                 num_sids, group_sids,
    2493           0 :                                                 &state->num_missing_sids,
    2494           0 :                                                 &state->missing_sids,
    2495           0 :                                                 &state->num_cached_groups,
    2496           0 :                                                 &state->cached_groups);
    2497           0 :     if (ret != EOK) {
    2498           0 :         DEBUG(SSSDBG_OP_FAILURE,
    2499             :               "sdap_ad_tokengroups_get_posix_members failed.\n");
    2500           0 :         goto done;
    2501             :     }
    2502             : 
    2503             : 
    2504           0 :     if (state->num_missing_sids == 0) {
    2505           0 :         ret = sdap_ad_tokengroups_update_members(state->username,
    2506           0 :                                                  state->dom->sysdb,
    2507           0 :                                                  state->dom,
    2508           0 :                                                  state->cached_groups);
    2509           0 :         if (ret != EOK) {
    2510           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
    2511             :                                          ret, strerror(ret));
    2512             :         }
    2513             : 
    2514           0 :         goto done;
    2515             :     }
    2516             : 
    2517             : 
    2518           0 :     subreq = ipa_s2n_get_list_send(state, state->ev, ipa_ctx, state->dom,
    2519           0 :                                state->sh,
    2520           0 :                                dp_opt_get_int(ipa_ctx->sdap_id_ctx->opts->basic,
    2521             :                                               SDAP_SEARCH_TIMEOUT),
    2522             :                                BE_REQ_BY_SECID, REQ_FULL, REQ_INP_SECID,
    2523           0 :                                state->missing_sids);
    2524           0 :     if (subreq == NULL) {
    2525           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_send failed.\n");
    2526           0 :         ret = ENOMEM;
    2527           0 :         goto done;
    2528             :     }
    2529           0 :     tevent_req_set_callback(subreq, ipa_get_subdom_acct_process_pac_done, req);
    2530             : 
    2531           0 :     return req;
    2532             : 
    2533             : done:
    2534           0 :     if (ret == EOK) {
    2535           0 :         tevent_req_done(req);
    2536             :     } else {
    2537           0 :         tevent_req_error(req, ret);
    2538             :     }
    2539           0 :     tevent_req_post(req, ev);
    2540             : 
    2541           0 :     return req;
    2542             : }
    2543             : 
    2544           0 : static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq)
    2545             : {
    2546             :     int ret;
    2547           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    2548             :                                                       struct tevent_req);
    2549           0 :     struct ipa_get_subdom_acct_process_pac_state *state = tevent_req_data(req,
    2550             :                                   struct ipa_get_subdom_acct_process_pac_state);
    2551             :     char **cached_groups;
    2552             :     size_t num_cached_groups;
    2553             : 
    2554           0 :     ret = ipa_s2n_get_list_recv(subreq);
    2555           0 :     talloc_zfree(subreq);
    2556           0 :     if (ret != EOK) {
    2557           0 :         DEBUG(SSSDBG_OP_FAILURE, "s2n get_fqlist request failed.\n");
    2558           0 :         tevent_req_error(req, ret);
    2559           0 :         return;
    2560             :     }
    2561             : 
    2562             :     /* from ad_pac.c */
    2563           0 :     ret = sdap_ad_tokengroups_get_posix_members(state, state->dom,
    2564             :                                                 state->num_missing_sids,
    2565             :                                                 state->missing_sids,
    2566             :                                                 NULL, NULL,
    2567             :                                                 &num_cached_groups,
    2568             :                                                 &cached_groups);
    2569           0 :     if (ret != EOK){
    2570           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2571             :               "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n",
    2572             :               ret, strerror(ret));
    2573           0 :         goto done;
    2574             :     }
    2575             : 
    2576           0 :     state->cached_groups = concatenate_string_array(state,
    2577             :                                                     state->cached_groups,
    2578             :                                                     state->num_cached_groups,
    2579             :                                                     cached_groups,
    2580             :                                                     num_cached_groups);
    2581           0 :     if (state->cached_groups == NULL) {
    2582           0 :         ret = ENOMEM;
    2583           0 :         goto done;
    2584             :     }
    2585             : 
    2586             :     /* update membership of existing groups */
    2587           0 :     ret = sdap_ad_tokengroups_update_members(state->username,
    2588           0 :                                              state->dom->sysdb,
    2589             :                                              state->dom,
    2590             :                                              state->cached_groups);
    2591           0 :     if (ret != EOK) {
    2592           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
    2593             :                                      ret, strerror(ret));
    2594           0 :         goto done;
    2595             :     }
    2596             : 
    2597           0 :     ret = EOK;
    2598             : 
    2599             : done:
    2600           0 :     if (ret == EOK) {
    2601           0 :         tevent_req_done(req);
    2602             :     } else {
    2603           0 :         tevent_req_error(req, ret);
    2604             :     }
    2605             : 
    2606           0 :     return;
    2607             : }
    2608             : 
    2609           0 : errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req)
    2610             : {
    2611           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    2612             : 
    2613           0 :     return EOK;
    2614             : }

Generated by: LCOV version 1.10