LCOV - code coverage report
Current view: top level - providers/ldap - sdap_async_users.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 467 0.0 %
Date: 2015-10-19 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Async LDAP Helper routines - retrieving users
       5             : 
       6             :     Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
       7             :     Copyright (C) 2010, Ralf Haferkamp <rhafer@suse.de>, Novell Inc.
       8             :     Copyright (C) Jan Zeleny <jzeleny@redhat.com> - 2011
       9             : 
      10             :     This program is free software; you can redistribute it and/or modify
      11             :     it under the terms of the GNU General Public License as published by
      12             :     the Free Software Foundation; either version 3 of the License, or
      13             :     (at your option) any later version.
      14             : 
      15             :     This program is distributed in the hope that it will be useful,
      16             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :     GNU General Public License for more details.
      19             : 
      20             :     You should have received a copy of the GNU General Public License
      21             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "util/util.h"
      25             : #include "db/sysdb.h"
      26             : #include "providers/ldap/sdap_async_private.h"
      27             : #include "providers/ldap/ldap_common.h"
      28             : #include "providers/ldap/sdap_idmap.h"
      29             : #include "providers/ldap/sdap_users.h"
      30             : 
      31             : #define REALM_SEPARATOR '@'
      32             : 
      33           0 : static void make_realm_upper_case(const char *upn)
      34             : {
      35             :     char *c;
      36             : 
      37           0 :     c = strchr(upn, REALM_SEPARATOR);
      38           0 :     if (c == NULL) {
      39           0 :         DEBUG(SSSDBG_TRACE_ALL, "No realm delimiter found in upn [%s].\n", upn);
      40           0 :         return;
      41             :     }
      42             : 
      43           0 :     while(*(++c) != '\0') {
      44           0 :         c[0] = toupper(*c);
      45             :     }
      46             : 
      47           0 :     return;
      48             : }
      49             : 
      50             : /* ==Save-User-Entry====================================================== */
      51             : 
      52             : static errno_t
      53           0 : sdap_get_idmap_primary_gid(struct sdap_options *opts,
      54             :                            struct sysdb_attrs *attrs,
      55             :                            char *sid_str,
      56             :                            char *dom_sid_str,
      57             :                            gid_t *_gid)
      58             : {
      59             :     errno_t ret;
      60           0 :     TALLOC_CTX *tmpctx = NULL;
      61             :     gid_t gid, primary_gid;
      62             :     char *group_sid_str;
      63             : 
      64           0 :     tmpctx = talloc_new(NULL);
      65           0 :     if (!tmpctx) {
      66           0 :         ret = ENOMEM;
      67           0 :         goto done;
      68             :     }
      69             : 
      70           0 :     ret = sysdb_attrs_get_uint32_t(attrs,
      71           0 :                 opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name,
      72             :                 &primary_gid);
      73           0 :     if (ret != EOK) {
      74           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "no primary group ID provided\n");
      75           0 :         ret = EINVAL;
      76           0 :         goto done;
      77             :     }
      78             : 
      79             :     /* The primary group ID is just the RID part of the objectSID
      80             :      * of the group. Generate the GID by adding this to the domain
      81             :      * SID value.
      82             :      */
      83             : 
      84             :     /* First, get the domain SID if we didn't do so above */
      85           0 :     if (!dom_sid_str) {
      86           0 :         ret = sdap_idmap_get_dom_sid_from_object(tmpctx, sid_str,
      87             :                                                  &dom_sid_str);
      88           0 :         if (ret != EOK) {
      89           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
      90             :                   "Could not parse domain SID from [%s]\n", sid_str);
      91           0 :             goto done;
      92             :         }
      93             :     }
      94             : 
      95             :     /* Add the RID to the end */
      96           0 :     group_sid_str = talloc_asprintf(tmpctx, "%s-%lu", dom_sid_str,
      97             :                                    (unsigned long) primary_gid);
      98           0 :     if (!group_sid_str) {
      99           0 :         ret = ENOMEM;
     100           0 :         goto done;
     101             :     }
     102             : 
     103             :     /* Convert the SID into a UNIX group ID */
     104           0 :     ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, group_sid_str, &gid);
     105           0 :     if (ret != EOK) goto done;
     106             : 
     107           0 :     ret = EOK;
     108           0 :     *_gid = gid;
     109             : done:
     110           0 :     talloc_free(tmpctx);
     111           0 :     return ret;
     112             : }
     113             : 
     114             : /* FIXME: support storing additional attributes */
     115           0 : int sdap_save_user(TALLOC_CTX *memctx,
     116             :                    struct sdap_options *opts,
     117             :                    struct sss_domain_info *dom,
     118             :                    struct sysdb_attrs *attrs,
     119             :                    char **_usn_value,
     120             :                    time_t now)
     121             : {
     122             :     struct ldb_message_element *el;
     123             :     int ret;
     124           0 :     const char *user_name = NULL;
     125           0 :     const char *fullname = NULL;
     126             :     const char *pwd;
     127             :     const char *gecos;
     128             :     const char *homedir;
     129             :     const char *shell;
     130           0 :     const char *orig_dn = NULL;
     131             :     uid_t uid;
     132             :     gid_t gid;
     133             :     struct sysdb_attrs *user_attrs;
     134           0 :     char *upn = NULL;
     135             :     size_t i;
     136             :     int cache_timeout;
     137           0 :     char *usn_value = NULL;
     138           0 :     char **missing = NULL;
     139           0 :     TALLOC_CTX *tmpctx = NULL;
     140             :     bool use_id_mapping;
     141             :     char *sid_str;
     142           0 :     char *dom_sid_str = NULL;
     143             :     struct sss_domain_info *subdomain;
     144             : 
     145           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Save user\n");
     146             : 
     147           0 :     tmpctx = talloc_new(NULL);
     148           0 :     if (!tmpctx) {
     149           0 :         ret = ENOMEM;
     150           0 :         goto done;
     151             :     }
     152             : 
     153           0 :     user_attrs = sysdb_new_attrs(tmpctx);
     154           0 :     if (user_attrs == NULL) {
     155           0 :         ret = ENOMEM;
     156           0 :         goto done;
     157             :     }
     158             : 
     159             :     /* Always store SID string if available */
     160           0 :     ret = sdap_attrs_get_sid_str(tmpctx, opts->idmap_ctx, attrs,
     161           0 :                                 opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name,
     162             :                                 &sid_str);
     163           0 :     if (ret == EOK) {
     164           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str);
     165           0 :         if (ret != EOK) {
     166           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n",
     167             :                                          sss_strerror(ret));
     168           0 :             goto done;
     169             :         }
     170           0 :     } else if (ret == ENOENT) {
     171           0 :         DEBUG(SSSDBG_TRACE_ALL, "objectSID: not available for user\n");
     172           0 :         sid_str = NULL;
     173             :     } else {
     174           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n",
     175             :                                      sss_strerror(ret));
     176           0 :         sid_str = NULL;
     177             :     }
     178             : 
     179             :     /* Always store UUID if available */
     180           0 :     ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name,
     181             :                                      attrs,
     182           0 :                                      opts->user_map[SDAP_AT_USER_UUID].sys_name,
     183             :                                      user_attrs, SYSDB_UUID);
     184           0 :     if (ret != EOK) {
     185           0 :         DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE,
     186             :               "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret));
     187             :     }
     188             : 
     189             :     /* If this object has a SID available, we will determine the correct
     190             :      * domain by its SID. */
     191           0 :     if (sid_str != NULL) {
     192           0 :         subdomain = find_domain_by_sid(get_domains_head(dom), sid_str);
     193           0 :         if (subdomain) {
     194           0 :             dom = subdomain;
     195             :         } else {
     196           0 :             DEBUG(SSSDBG_TRACE_FUNC, "SID %s does not belong to any known "
     197             :                                       "domain\n", sid_str);
     198             :         }
     199             :     }
     200             : 
     201           0 :     ret = sdap_get_user_primary_name(memctx, opts, attrs, dom, &user_name);
     202           0 :     if (ret != EOK) {
     203           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to get user name\n");
     204           0 :         goto done;
     205             :     }
     206           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Processing user %s\n", user_name);
     207             : 
     208           0 :     if (opts->schema_type == SDAP_SCHEMA_AD) {
     209           0 :         ret = sysdb_attrs_get_string(attrs,
     210           0 :                     opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname);
     211           0 :         if (ret == EOK) {
     212           0 :             ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname);
     213           0 :             if (ret != EOK) {
     214           0 :                 goto done;
     215             :             }
     216           0 :         } else if (ret != ENOENT) {
     217           0 :             goto done;
     218             :         }
     219             :     }
     220             : 
     221           0 :     ret = sysdb_attrs_get_el(attrs,
     222           0 :                              opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
     223           0 :     if (ret) goto done;
     224           0 :     if (el->num_values == 0) pwd = NULL;
     225           0 :     else pwd = (const char *)el->values[0].data;
     226             : 
     227           0 :     ret = sysdb_attrs_get_el(attrs,
     228           0 :                              opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el);
     229           0 :     if (ret) goto done;
     230           0 :     if (el->num_values == 0) gecos = NULL;
     231           0 :     else gecos = (const char *)el->values[0].data;
     232             : 
     233           0 :     if (!gecos) {
     234             :         /* Fall back to the user's full name */
     235           0 :         ret = sysdb_attrs_get_el(
     236             :                 attrs,
     237           0 :                 opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el);
     238           0 :         if (ret) goto done;
     239           0 :         if (el->num_values > 0) gecos = (const char *)el->values[0].data;
     240             :     }
     241             : 
     242           0 :     ret = sysdb_attrs_get_el(attrs,
     243           0 :                              opts->user_map[SDAP_AT_USER_HOME].sys_name, &el);
     244           0 :     if (ret) goto done;
     245           0 :     if (el->num_values == 0) homedir = NULL;
     246           0 :     else homedir = (const char *)el->values[0].data;
     247             : 
     248           0 :     ret = sysdb_attrs_get_el(attrs,
     249           0 :                              opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el);
     250           0 :     if (ret) goto done;
     251           0 :     if (el->num_values == 0) shell = NULL;
     252           0 :     else shell = (const char *)el->values[0].data;
     253             : 
     254           0 :     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
     255           0 :                                                                dom->name,
     256             :                                                                sid_str);
     257             : 
     258             :     /* Retrieve or map the UID as appropriate */
     259           0 :     if (use_id_mapping) {
     260             : 
     261           0 :         if (sid_str == NULL) {
     262           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "SID not available, cannot map a " \
     263             :                                          "unix ID to user [%s].\n", user_name);
     264           0 :             ret = ENOENT;
     265           0 :             goto done;
     266             :         }
     267             : 
     268           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     269             :               "Mapping user [%s] objectSID [%s] to unix ID\n", user_name, sid_str);
     270             : 
     271             :         /* Convert the SID into a UNIX user ID */
     272           0 :         ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid);
     273           0 :         if (ret == ENOTSUP) {
     274           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
     275           0 :             ret = EOK;
     276           0 :             goto done;
     277           0 :         } else if (ret != EOK) {
     278           0 :             goto done;
     279             :         }
     280             : 
     281             :         /* Store the UID in the ldap_attrs so it doesn't get
     282             :          * treated as a missing attribute from LDAP and removed.
     283             :          */
     284           0 :         ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid);
     285           0 :         if (ret) {
     286           0 :             DEBUG(SSSDBG_OP_FAILURE, "Cannot set the id-mapped UID\n");
     287           0 :             goto done;
     288             :         }
     289             :     } else {
     290           0 :         ret = sysdb_attrs_get_uint32_t(attrs,
     291           0 :                                        opts->user_map[SDAP_AT_USER_UID].sys_name,
     292             :                                        &uid);
     293           0 :         if (ret != EOK) {
     294           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     295             :                   "no uid provided for [%s] in domain [%s].\n",
     296             :                    user_name, dom->name);
     297           0 :             ret = EINVAL;
     298           0 :             goto done;
     299             :         }
     300             :     }
     301             :     /* check that the uid is valid for this domain */
     302           0 :     if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
     303           0 :             DEBUG(SSSDBG_OP_FAILURE,
     304             :                   "User [%s] filtered out! (uid out of range)\n",
     305             :                       user_name);
     306           0 :         ret = EINVAL;
     307           0 :         goto done;
     308             :     }
     309             : 
     310           0 :     if (use_id_mapping) {
     311           0 :         ret = sdap_get_idmap_primary_gid(opts, attrs, sid_str, dom_sid_str,
     312             :                                          &gid);
     313           0 :         if (ret) {
     314           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     315             :                   "Cannot get the GID for [%s] in domain [%s].\n",
     316             :                    user_name, dom->name);
     317           0 :             goto done;
     318             :         }
     319             : 
     320           0 :         if (IS_SUBDOMAIN(dom)) {
     321             :             /* For subdomain users, only create the private group as
     322             :              * the subdomain is an MPG domain.
     323             :              * But we have to save the GID of the original primary group
     324             :              * becasuse otherwise this information might be lost because
     325             :              * typically (Unix and AD) the user is not listed in his primary
     326             :              * group as a member.
     327             :              */
     328           0 :             ret = sysdb_attrs_add_uint32(user_attrs, SYSDB_PRIMARY_GROUP_GIDNUM,
     329             :                                          (uint32_t) gid);
     330           0 :             if (ret != EOK) {
     331           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_uint32 failed.\n");
     332           0 :                 goto done;
     333             :             }
     334             : 
     335           0 :             gid = 0;
     336             :         }
     337             : 
     338             :         /* Store the GID in the ldap_attrs so it doesn't get
     339             :         * treated as a missing attribute from LDAP and removed.
     340             :         */
     341           0 :         ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
     342           0 :         if (ret != EOK) goto done;
     343             :     } else {
     344           0 :         ret = sysdb_attrs_get_uint32_t(attrs,
     345           0 :                                        opts->user_map[SDAP_AT_USER_GID].sys_name,
     346             :                                        &gid);
     347           0 :         if (ret != EOK) {
     348           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     349             :                   "no gid provided for [%s] in domain [%s].\n",
     350             :                   user_name, dom->name);
     351           0 :             ret = EINVAL;
     352           0 :             goto done;
     353             :         }
     354             :     }
     355             : 
     356             :     /* check that the gid is valid for this domain */
     357           0 :     if (IS_SUBDOMAIN(dom) == false &&
     358           0 :             OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
     359           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     360             :               "User [%s] filtered out! (primary gid out of range)\n",
     361             :                user_name);
     362           0 :         ret = EINVAL;
     363           0 :         goto done;
     364             :     }
     365             : 
     366           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
     367           0 :     if (ret) {
     368           0 :         goto done;
     369             :     }
     370           0 :     if (!el || el->num_values == 0) {
     371           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     372             :               "originalDN is not available for [%s].\n", user_name);
     373             :     } else {
     374           0 :         orig_dn = (const char *) el->values[0].data;
     375           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Adding originalDN [%s] to attributes "
     376             :                 "of [%s].\n", orig_dn, user_name);
     377             : 
     378           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn);
     379           0 :         if (ret) {
     380           0 :             goto done;
     381             :         }
     382             :     }
     383             : 
     384           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el);
     385           0 :     if (ret) {
     386           0 :         goto done;
     387             :     }
     388           0 :     if (el->num_values == 0) {
     389           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     390             :               "Original memberOf is not available for [%s].\n", user_name);
     391             :     } else {
     392           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     393             :               "Adding original memberOf attributes to [%s].\n", user_name);
     394           0 :         for (i = 0; i < el->num_values; i++) {
     395           0 :             ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
     396           0 :                     (const char *) el->values[i].data);
     397           0 :             if (ret) {
     398           0 :                 goto done;
     399             :             }
     400             :         }
     401             :     }
     402             : 
     403           0 :     ret = sdap_attrs_add_string(attrs,
     404             :                             opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name,
     405             :                             "original mod-Timestamp",
     406             :                             user_name, user_attrs);
     407           0 :     if (ret != EOK) {
     408           0 :         goto done;
     409             :     }
     410             : 
     411           0 :     ret = sysdb_attrs_get_el(attrs,
     412           0 :                       opts->user_map[SDAP_AT_USER_USN].sys_name, &el);
     413           0 :     if (ret) {
     414           0 :         goto done;
     415             :     }
     416           0 :     if (el->num_values == 0) {
     417           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     418             :               "Original USN value is not available for [%s].\n", user_name);
     419             :     } else {
     420           0 :         ret = sysdb_attrs_add_string(user_attrs,
     421           0 :                           opts->user_map[SDAP_AT_USER_USN].sys_name,
     422           0 :                           (const char*)el->values[0].data);
     423           0 :         if (ret) {
     424           0 :             goto done;
     425             :         }
     426           0 :         usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
     427           0 :         if (!usn_value) {
     428           0 :             ret = ENOMEM;
     429           0 :             goto done;
     430             :         }
     431             :     }
     432             : 
     433           0 :     ret = sysdb_attrs_get_el(attrs,
     434           0 :                              opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el);
     435           0 :     if (ret) {
     436           0 :         goto done;
     437             :     }
     438           0 :     if (el->num_values == 0) {
     439           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     440             :               "User principal is not available for [%s].\n", user_name);
     441             :     } else {
     442           0 :         upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
     443           0 :         if (!upn) {
     444           0 :             ret = ENOMEM;
     445           0 :             goto done;
     446             :         }
     447           0 :         if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
     448           0 :             make_realm_upper_case(upn);
     449             :         }
     450           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     451             :               "Adding user principal [%s] to attributes of [%s].\n",
     452             :                upn, user_name);
     453           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
     454           0 :         if (ret) {
     455           0 :             goto done;
     456             :         }
     457             :     }
     458             : 
     459           0 :     for (i = SDAP_FIRST_EXTRA_USER_AT; i < opts->user_map_cnt; i++) {
     460           0 :         ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name,
     461             :                                   NULL, user_name, user_attrs);
     462           0 :         if (ret) {
     463           0 :             goto done;
     464             :         }
     465             :     }
     466             : 
     467           0 :     cache_timeout = dom->user_timeout;
     468             : 
     469           0 :     ret = sdap_save_all_names(user_name, attrs, dom, user_attrs);
     470           0 :     if (ret != EOK) {
     471           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save user names\n");
     472           0 :         goto done;
     473             :     }
     474             : 
     475             :     /* Make sure that any attributes we requested from LDAP that we
     476             :      * did not receive are also removed from the sysdb
     477             :      */
     478           0 :     ret = list_missing_attrs(user_attrs, opts->user_map, opts->user_map_cnt,
     479             :                              attrs, &missing);
     480           0 :     if (ret != EOK) {
     481           0 :         goto done;
     482             :     }
     483             : 
     484           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Storing info for user %s\n", user_name);
     485             : 
     486           0 :     ret = sysdb_store_user(dom, user_name, pwd, uid, gid,
     487             :                            gecos, homedir, shell, orig_dn,
     488             :                            user_attrs, missing, cache_timeout, now);
     489           0 :     if (ret) goto done;
     490             : 
     491           0 :     if (_usn_value) {
     492           0 :         *_usn_value = talloc_steal(memctx, usn_value);
     493             :     }
     494             : 
     495           0 :     talloc_steal(memctx, user_attrs);
     496           0 :     ret = EOK;
     497             : 
     498             : done:
     499           0 :     if (ret) {
     500           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     501             :               "Failed to save user [%s]\n",
     502             :                user_name ? user_name : "Unknown");
     503             :     }
     504           0 :     talloc_free(tmpctx);
     505           0 :     return ret;
     506             : }
     507             : 
     508             : 
     509             : /* ==Generic-Function-to-save-multiple-users============================= */
     510             : 
     511           0 : int sdap_save_users(TALLOC_CTX *memctx,
     512             :                     struct sysdb_ctx *sysdb,
     513             :                     struct sss_domain_info *dom,
     514             :                     struct sdap_options *opts,
     515             :                     struct sysdb_attrs **users,
     516             :                     int num_users,
     517             :                     char **_usn_value)
     518             : {
     519             :     TALLOC_CTX *tmpctx;
     520           0 :     char *higher_usn = NULL;
     521             :     char *usn_value;
     522             :     int ret;
     523             :     errno_t sret;
     524             :     int i;
     525             :     time_t now;
     526           0 :     bool in_transaction = false;
     527             : 
     528           0 :     if (num_users == 0) {
     529             :         /* Nothing to do if there are no users */
     530           0 :         return EOK;
     531             :     }
     532             : 
     533           0 :     tmpctx = talloc_new(memctx);
     534           0 :     if (!tmpctx) {
     535           0 :         return ENOMEM;
     536             :     }
     537             : 
     538           0 :     ret = sysdb_transaction_start(sysdb);
     539           0 :     if (ret) {
     540           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     541           0 :         goto done;
     542             :     }
     543           0 :     in_transaction = true;
     544             : 
     545           0 :     now = time(NULL);
     546           0 :     for (i = 0; i < num_users; i++) {
     547           0 :         usn_value = NULL;
     548             : 
     549           0 :         ret = sdap_save_user(tmpctx, opts, dom, users[i], &usn_value, now);
     550             : 
     551             :         /* Do not fail completely on errors.
     552             :          * Just report the failure to save and go on */
     553           0 :         if (ret) {
     554           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store user %d. Ignoring.\n", i);
     555             :         } else {
     556           0 :             DEBUG(SSSDBG_TRACE_ALL, "User %d processed!\n", i);
     557             :         }
     558             : 
     559           0 :         if (usn_value) {
     560           0 :             if (higher_usn) {
     561           0 :                 if ((strlen(usn_value) > strlen(higher_usn)) ||
     562           0 :                     (strcmp(usn_value, higher_usn) > 0)) {
     563           0 :                     talloc_zfree(higher_usn);
     564           0 :                     higher_usn = usn_value;
     565             :                 } else {
     566           0 :                     talloc_zfree(usn_value);
     567             :                 }
     568             :             } else {
     569           0 :                 higher_usn = usn_value;
     570             :             }
     571             :         }
     572             :     }
     573             : 
     574           0 :     ret = sysdb_transaction_commit(sysdb);
     575           0 :     if (ret) {
     576           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction!\n");
     577           0 :         goto done;
     578             :     }
     579           0 :     in_transaction = false;
     580             : 
     581           0 :     if (_usn_value) {
     582           0 :         *_usn_value = talloc_steal(memctx, higher_usn);
     583             :     }
     584             : 
     585             : done:
     586           0 :     if (in_transaction) {
     587           0 :         sret = sysdb_transaction_cancel(sysdb);
     588           0 :         if (sret != EOK) {
     589           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
     590             :         }
     591             :     }
     592           0 :     talloc_zfree(tmpctx);
     593           0 :     return ret;
     594             : }
     595             : 
     596             : 
     597             : /* ==Search-Users-with-filter============================================= */
     598             : 
     599             : struct sdap_search_user_state {
     600             :     struct tevent_context *ev;
     601             :     struct sdap_options *opts;
     602             :     struct sdap_handle *sh;
     603             :     struct sss_domain_info *dom;
     604             : 
     605             :     const char **attrs;
     606             :     const char *base_filter;
     607             :     const char *filter;
     608             :     int timeout;
     609             :     enum sdap_entry_lookup_type lookup_type;
     610             : 
     611             :     char *higher_usn;
     612             :     struct sysdb_attrs **users;
     613             :     size_t count;
     614             : 
     615             :     size_t base_iter;
     616             :     struct sdap_search_base **search_bases;
     617             : };
     618             : 
     619             : static errno_t sdap_search_user_next_base(struct tevent_req *req);
     620             : static void sdap_search_user_copy_batch(struct sdap_search_user_state *state,
     621             :                                         struct sysdb_attrs **users,
     622             :                                         size_t count);
     623             : static void sdap_search_user_process(struct tevent_req *subreq);
     624             : 
     625           0 : struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
     626             :                                          struct tevent_context *ev,
     627             :                                          struct sss_domain_info *dom,
     628             :                                          struct sdap_options *opts,
     629             :                                          struct sdap_search_base **search_bases,
     630             :                                          struct sdap_handle *sh,
     631             :                                          const char **attrs,
     632             :                                          const char *filter,
     633             :                                          int timeout,
     634             :                                          enum sdap_entry_lookup_type lookup_type)
     635             : {
     636             :     errno_t ret;
     637             :     struct tevent_req *req;
     638             :     struct sdap_search_user_state *state;
     639             : 
     640           0 :     req = tevent_req_create(memctx, &state, struct sdap_search_user_state);
     641           0 :     if (req == NULL) return NULL;
     642             : 
     643           0 :     state->ev = ev;
     644           0 :     state->opts = opts;
     645           0 :     state->dom = dom;
     646           0 :     state->sh = sh;
     647           0 :     state->attrs = attrs;
     648           0 :     state->higher_usn = NULL;
     649           0 :     state->users =  NULL;
     650           0 :     state->count = 0;
     651           0 :     state->timeout = timeout;
     652           0 :     state->base_filter = filter;
     653           0 :     state->base_iter = 0;
     654           0 :     state->search_bases = search_bases;
     655           0 :     state->lookup_type = lookup_type;
     656             : 
     657           0 :     if (!state->search_bases) {
     658           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     659             :               "User lookup request without a search base\n");
     660           0 :         ret = EINVAL;
     661           0 :         goto done;
     662             :     }
     663             : 
     664           0 :     ret = sdap_search_user_next_base(req);
     665             : 
     666             : done:
     667           0 :     if (ret != EOK) {
     668           0 :         tevent_req_error(req, ret);
     669           0 :         tevent_req_post(req, state->ev);
     670             :     }
     671             : 
     672           0 :     return req;
     673             : }
     674             : 
     675           0 : static errno_t sdap_search_user_next_base(struct tevent_req *req)
     676             : {
     677             :     struct tevent_req *subreq;
     678             :     struct sdap_search_user_state *state;
     679           0 :     bool need_paging = false;
     680           0 :     int sizelimit = 0;
     681             : 
     682           0 :     state = tevent_req_data(req, struct sdap_search_user_state);
     683             : 
     684           0 :     talloc_zfree(state->filter);
     685           0 :     state->filter = sdap_get_id_specific_filter(state,
     686             :                         state->base_filter,
     687           0 :                         state->search_bases[state->base_iter]->filter);
     688           0 :     if (state->filter == NULL) {
     689           0 :         return ENOMEM;
     690             :     }
     691             : 
     692           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     693             :           "Searching for users with base [%s]\n",
     694             :            state->search_bases[state->base_iter]->basedn);
     695             : 
     696           0 :     switch (state->lookup_type) {
     697             :     case SDAP_LOOKUP_SINGLE:
     698           0 :         break;
     699             :     /* Only requests that can return multiple entries should require
     700             :      * the paging control
     701             :      */
     702             :     case SDAP_LOOKUP_WILDCARD:
     703           0 :         sizelimit = dp_opt_get_int(state->opts->basic, SDAP_WILDCARD_LIMIT);
     704           0 :         need_paging = true;
     705           0 :         break;
     706             :     case SDAP_LOOKUP_ENUMERATE:
     707           0 :         need_paging = true;
     708           0 :         break;
     709             :     }
     710             : 
     711           0 :     subreq = sdap_get_and_parse_generic_send(
     712             :             state, state->ev, state->opts, state->sh,
     713           0 :             state->search_bases[state->base_iter]->basedn,
     714           0 :             state->search_bases[state->base_iter]->scope,
     715             :             state->filter, state->attrs,
     716           0 :             state->opts->user_map, state->opts->user_map_cnt,
     717             :             0, NULL, NULL, sizelimit, state->timeout,
     718             :             need_paging);
     719           0 :     if (subreq == NULL) {
     720           0 :         return ENOMEM;
     721             :     }
     722           0 :     tevent_req_set_callback(subreq, sdap_search_user_process, req);
     723             : 
     724           0 :     return EOK;
     725             : }
     726             : 
     727           0 : static void sdap_search_user_process(struct tevent_req *subreq)
     728             : {
     729           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     730             :                                                       struct tevent_req);
     731           0 :     struct sdap_search_user_state *state = tevent_req_data(req,
     732             :                                             struct sdap_search_user_state);
     733             :     int ret;
     734             :     size_t count;
     735             :     struct sysdb_attrs **users;
     736           0 :     bool next_base = false;
     737             : 
     738           0 :     ret = sdap_get_and_parse_generic_recv(subreq, state,
     739             :                                           &count, &users);
     740           0 :     talloc_zfree(subreq);
     741           0 :     if (ret) {
     742           0 :         tevent_req_error(req, ret);
     743           0 :         return;
     744             :     }
     745             : 
     746           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     747             :           "Search for users, returned %zu results.\n", count);
     748             : 
     749           0 :     if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \
     750           0 :             state->lookup_type == SDAP_LOOKUP_ENUMERATE || \
     751           0 :         count == 0) {
     752             :         /* No users found in this search or looking up multiple entries */
     753           0 :         next_base = true;
     754             :     }
     755             : 
     756             :     /* Add this batch of users to the list */
     757           0 :     if (count > 0) {
     758           0 :         state->users =
     759           0 :                 talloc_realloc(state,
     760             :                                state->users,
     761             :                                struct sysdb_attrs *,
     762             :                                state->count + count + 1);
     763           0 :         if (!state->users) {
     764           0 :             tevent_req_error(req, ENOMEM);
     765           0 :             return;
     766             :         }
     767             : 
     768           0 :         sdap_search_user_copy_batch(state, users, count);
     769             :     }
     770             : 
     771           0 :     if (next_base) {
     772           0 :         state->base_iter++;
     773           0 :         if (state->search_bases[state->base_iter]) {
     774             :             /* There are more search bases to try */
     775           0 :             ret = sdap_search_user_next_base(req);
     776           0 :             if (ret != EOK) {
     777           0 :                 tevent_req_error(req, ret);
     778             :             }
     779           0 :             return;
     780             :         }
     781             :     }
     782             : 
     783             :     /* No more search bases
     784             :      * Return ENOENT if no users were found
     785             :      */
     786           0 :     if (state->count == 0) {
     787           0 :         tevent_req_error(req, ENOENT);
     788           0 :         return;
     789             :     }
     790             : 
     791           0 :     DEBUG(SSSDBG_TRACE_ALL, "Retrieved total %zu users\n", state->count);
     792           0 :     tevent_req_done(req);
     793             : }
     794             : 
     795           0 : static void sdap_search_user_copy_batch(struct sdap_search_user_state *state,
     796             :                                         struct sysdb_attrs **users,
     797             :                                         size_t count)
     798             : {
     799             :     size_t copied;
     800             :     bool filter;
     801             : 
     802             :     /* Always copy all objects for wildcard lookups. */
     803           0 :     filter = state->lookup_type == SDAP_LOOKUP_SINGLE ? true : false;
     804             : 
     805           0 :     copied = sdap_steal_objects_in_dom(state->opts,
     806             :                                        state->users,
     807             :                                        state->count,
     808             :                                        state->dom,
     809             :                                        users, count, filter);
     810             : 
     811           0 :     state->count += copied;
     812           0 :     state->users[state->count] = NULL;
     813           0 : }
     814             : 
     815           0 : int sdap_search_user_recv(TALLOC_CTX *memctx, struct tevent_req *req,
     816             :                           char **higher_usn, struct sysdb_attrs ***users,
     817             :                           size_t *count)
     818             : {
     819           0 :     struct sdap_search_user_state *state = tevent_req_data(req,
     820             :                                             struct sdap_search_user_state);
     821             : 
     822           0 :     if (higher_usn) {
     823           0 :         *higher_usn = talloc_steal(memctx, state->higher_usn);
     824             :     }
     825             : 
     826           0 :     if (users) {
     827           0 :         *users = talloc_steal(memctx, state->users);
     828             :     }
     829             : 
     830           0 :     if (count) {
     831           0 :         *count = state->count;
     832             :     }
     833             : 
     834           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     835             : 
     836           0 :     return EOK;
     837             : }
     838             : 
     839             : /* ==Search-And-Save-Users-with-filter============================================= */
     840             : struct sdap_get_users_state {
     841             :     struct sysdb_ctx *sysdb;
     842             :     struct sdap_options *opts;
     843             :     struct sss_domain_info *dom;
     844             : 
     845             :     char *higher_usn;
     846             :     struct sysdb_attrs **users;
     847             :     size_t count;
     848             : };
     849             : 
     850             : static void sdap_get_users_done(struct tevent_req *subreq);
     851             : 
     852           0 : struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
     853             :                                        struct tevent_context *ev,
     854             :                                        struct sss_domain_info *dom,
     855             :                                        struct sysdb_ctx *sysdb,
     856             :                                        struct sdap_options *opts,
     857             :                                        struct sdap_search_base **search_bases,
     858             :                                        struct sdap_handle *sh,
     859             :                                        const char **attrs,
     860             :                                        const char *filter,
     861             :                                        int timeout,
     862             :                                        enum sdap_entry_lookup_type lookup_type)
     863             : {
     864             :     errno_t ret;
     865             :     struct tevent_req *req;
     866             :     struct tevent_req *subreq;
     867             :     struct sdap_get_users_state *state;
     868             : 
     869           0 :     req = tevent_req_create(memctx, &state, struct sdap_get_users_state);
     870           0 :     if (!req) return NULL;
     871             : 
     872           0 :     state->sysdb = sysdb;
     873           0 :     state->opts = opts;
     874           0 :     state->dom = dom;
     875             : 
     876           0 :     subreq = sdap_search_user_send(state, ev, dom, opts, search_bases,
     877             :                                    sh, attrs, filter, timeout, lookup_type);
     878           0 :     if (subreq == NULL) {
     879           0 :         ret = ENOMEM;
     880           0 :         goto done;
     881             :     }
     882           0 :     tevent_req_set_callback(subreq, sdap_get_users_done, req);
     883             : 
     884           0 :     ret = EOK;
     885             : done:
     886           0 :     if (ret != EOK) {
     887           0 :         tevent_req_error(req, ret);
     888           0 :         tevent_req_post(req, ev);
     889             :     }
     890             : 
     891           0 :     return req;
     892             : }
     893             : 
     894           0 : static void sdap_get_users_done(struct tevent_req *subreq)
     895             : {
     896           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     897             :                                                       struct tevent_req);
     898           0 :     struct sdap_get_users_state *state = tevent_req_data(req,
     899             :                                             struct sdap_get_users_state);
     900             :     int ret;
     901             : 
     902           0 :     ret = sdap_search_user_recv(state, subreq, &state->higher_usn,
     903             :                                 &state->users, &state->count);
     904           0 :     if (ret) {
     905           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve users\n");
     906           0 :         tevent_req_error(req, ret);
     907           0 :         return;
     908             :     }
     909             : 
     910           0 :     ret = sdap_save_users(state, state->sysdb,
     911             :                           state->dom, state->opts,
     912           0 :                           state->users, state->count,
     913             :                           &state->higher_usn);
     914           0 :     if (ret) {
     915           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to store users.\n");
     916           0 :         tevent_req_error(req, ret);
     917           0 :         return;
     918             :     }
     919             : 
     920           0 :     DEBUG(SSSDBG_TRACE_ALL, "Saving %zu Users - Done\n", state->count);
     921             : 
     922           0 :     tevent_req_done(req);
     923             : }
     924             : 
     925           0 : int sdap_get_users_recv(struct tevent_req *req,
     926             :                         TALLOC_CTX *mem_ctx, char **usn_value)
     927             : {
     928           0 :     struct sdap_get_users_state *state = tevent_req_data(req,
     929             :                                             struct sdap_get_users_state);
     930             : 
     931           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     932             : 
     933           0 :     if (usn_value) {
     934           0 :         *usn_value = talloc_steal(mem_ctx, state->higher_usn);
     935             :     }
     936             : 
     937           0 :     return EOK;
     938             : }
     939             : 
     940             : /* ==Fetch-Fallback-local-user============================================ */
     941             : 
     942           0 : errno_t sdap_fallback_local_user(TALLOC_CTX *memctx,
     943             :                                  const char *name, uid_t uid,
     944             :                                  struct sysdb_attrs ***reply)
     945             : {
     946             :     struct sysdb_attrs **ua;
     947             :     struct sysdb_attrs *user;
     948             :     struct passwd *pwd;
     949             :     int ret;
     950             : 
     951           0 :     if (name) {
     952           0 :         pwd = getpwnam(name);
     953             :     } else {
     954           0 :         pwd = getpwuid(uid);
     955             :     }
     956             : 
     957           0 :     if (!pwd) {
     958           0 :         return errno ? errno : ENOENT;
     959             :     }
     960             : 
     961           0 :     ua = talloc_array(memctx, struct sysdb_attrs *, 2);
     962           0 :     if (!ua) {
     963           0 :         ret = ENOMEM;
     964           0 :         goto done;
     965             :     }
     966           0 :     ua[1] = NULL;
     967             : 
     968           0 :     user = sysdb_new_attrs(ua);
     969           0 :     if (!user) {
     970           0 :         ret = ENOMEM;
     971           0 :         goto done;
     972             :     }
     973           0 :     ua[0] = user;
     974             : 
     975           0 :     ret = sysdb_attrs_add_string(user, SYSDB_NAME, pwd->pw_name);
     976           0 :     if (ret != EOK) {
     977           0 :         goto done;
     978             :     }
     979             : 
     980           0 :     if (pwd->pw_passwd) {
     981           0 :         ret = sysdb_attrs_add_string(user, SYSDB_PWD, pwd->pw_passwd);
     982           0 :         if (ret != EOK) {
     983           0 :             goto done;
     984             :         }
     985             :     }
     986             : 
     987           0 :     ret = sysdb_attrs_add_long(user, SYSDB_UIDNUM, (long)pwd->pw_uid);
     988           0 :     if (ret != EOK) {
     989           0 :         goto done;
     990             :     }
     991             : 
     992           0 :     ret = sysdb_attrs_add_long(user, SYSDB_GIDNUM, (long)pwd->pw_gid);
     993           0 :     if (ret != EOK) {
     994           0 :         goto done;
     995             :     }
     996             : 
     997           0 :     if (pwd->pw_gecos) {
     998           0 :         ret = sysdb_attrs_add_string(user, SYSDB_GECOS, pwd->pw_gecos);
     999           0 :         if (ret != EOK) {
    1000           0 :             goto done;
    1001             :         }
    1002             :     }
    1003             : 
    1004           0 :     if (pwd->pw_dir) {
    1005           0 :         ret = sysdb_attrs_add_string(user, SYSDB_HOMEDIR, pwd->pw_dir);
    1006           0 :         if (ret != EOK) {
    1007           0 :             goto done;
    1008             :         }
    1009             :     }
    1010             : 
    1011           0 :     if (pwd->pw_shell) {
    1012           0 :         ret = sysdb_attrs_add_string(user, SYSDB_SHELL, pwd->pw_shell);
    1013           0 :         if (ret != EOK) {
    1014           0 :             goto done;
    1015             :         }
    1016             :     }
    1017             : 
    1018             : done:
    1019           0 :     if (ret != EOK) {
    1020           0 :         talloc_free(ua);
    1021             :     } else {
    1022           0 :         *reply = ua;
    1023             :     }
    1024             : 
    1025           0 :     return ret;
    1026             : }

Generated by: LCOV version 1.10