LCOV - code coverage report
Current view: top level - providers/ldap - sdap_async_users.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 468 0.0 %
Date: 2016-06-29 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 "util/probes.h"
      26             : #include "db/sysdb.h"
      27             : #include "providers/ldap/sdap_async_private.h"
      28             : #include "providers/ldap/ldap_common.h"
      29             : #include "providers/ldap/sdap_idmap.h"
      30             : #include "providers/ldap/sdap_users.h"
      31             : 
      32             : #define REALM_SEPARATOR '@'
      33             : 
      34           0 : static void make_realm_upper_case(const char *upn)
      35             : {
      36             :     char *c;
      37             : 
      38           0 :     c = strchr(upn, REALM_SEPARATOR);
      39           0 :     if (c == NULL) {
      40           0 :         DEBUG(SSSDBG_TRACE_ALL, "No realm delimiter found in upn [%s].\n", upn);
      41           0 :         return;
      42             :     }
      43             : 
      44           0 :     while(*(++c) != '\0') {
      45           0 :         c[0] = toupper(*c);
      46             :     }
      47             : 
      48           0 :     return;
      49             : }
      50             : 
      51             : /* ==Save-User-Entry====================================================== */
      52             : 
      53             : static errno_t
      54           0 : sdap_get_idmap_primary_gid(struct sdap_options *opts,
      55             :                            struct sysdb_attrs *attrs,
      56             :                            char *sid_str,
      57             :                            char *dom_sid_str,
      58             :                            gid_t *_gid)
      59             : {
      60             :     errno_t ret;
      61           0 :     TALLOC_CTX *tmpctx = NULL;
      62             :     gid_t gid, primary_gid;
      63             :     char *group_sid_str;
      64             : 
      65           0 :     tmpctx = talloc_new(NULL);
      66           0 :     if (!tmpctx) {
      67           0 :         ret = ENOMEM;
      68           0 :         goto done;
      69             :     }
      70             : 
      71           0 :     ret = sysdb_attrs_get_uint32_t(attrs,
      72           0 :                 opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name,
      73             :                 &primary_gid);
      74           0 :     if (ret != EOK) {
      75           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "no primary group ID provided\n");
      76           0 :         ret = EINVAL;
      77           0 :         goto done;
      78             :     }
      79             : 
      80             :     /* The primary group ID is just the RID part of the objectSID
      81             :      * of the group. Generate the GID by adding this to the domain
      82             :      * SID value.
      83             :      */
      84             : 
      85             :     /* First, get the domain SID if we didn't do so above */
      86           0 :     if (!dom_sid_str) {
      87           0 :         ret = sdap_idmap_get_dom_sid_from_object(tmpctx, sid_str,
      88             :                                                  &dom_sid_str);
      89           0 :         if (ret != EOK) {
      90           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
      91             :                   "Could not parse domain SID from [%s]\n", sid_str);
      92           0 :             goto done;
      93             :         }
      94             :     }
      95             : 
      96             :     /* Add the RID to the end */
      97           0 :     group_sid_str = talloc_asprintf(tmpctx, "%s-%lu", dom_sid_str,
      98             :                                    (unsigned long) primary_gid);
      99           0 :     if (!group_sid_str) {
     100           0 :         ret = ENOMEM;
     101           0 :         goto done;
     102             :     }
     103             : 
     104             :     /* Convert the SID into a UNIX group ID */
     105           0 :     ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, group_sid_str, &gid);
     106           0 :     if (ret != EOK) goto done;
     107             : 
     108           0 :     ret = EOK;
     109           0 :     *_gid = gid;
     110             : done:
     111           0 :     talloc_free(tmpctx);
     112           0 :     return ret;
     113             : }
     114             : 
     115             : /* FIXME: support storing additional attributes */
     116           0 : int sdap_save_user(TALLOC_CTX *memctx,
     117             :                    struct sdap_options *opts,
     118             :                    struct sss_domain_info *dom,
     119             :                    struct sysdb_attrs *attrs,
     120             :                    char **_usn_value,
     121             :                    time_t now)
     122             : {
     123             :     struct ldb_message_element *el;
     124             :     int ret;
     125           0 :     const char *user_name = NULL;
     126           0 :     const char *fullname = NULL;
     127             :     const char *pwd;
     128             :     const char *gecos;
     129             :     const char *homedir;
     130             :     const char *shell;
     131           0 :     const char *orig_dn = NULL;
     132             :     uid_t uid;
     133             :     gid_t gid;
     134             :     struct sysdb_attrs *user_attrs;
     135           0 :     char *upn = NULL;
     136             :     size_t i;
     137             :     int cache_timeout;
     138           0 :     char *usn_value = NULL;
     139           0 :     char **missing = NULL;
     140           0 :     TALLOC_CTX *tmpctx = NULL;
     141             :     bool use_id_mapping;
     142             :     char *sid_str;
     143           0 :     char *dom_sid_str = NULL;
     144             :     struct sss_domain_info *subdomain;
     145             : 
     146           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Save user\n");
     147             : 
     148           0 :     tmpctx = talloc_new(NULL);
     149           0 :     if (!tmpctx) {
     150           0 :         ret = ENOMEM;
     151           0 :         goto done;
     152             :     }
     153             : 
     154           0 :     user_attrs = sysdb_new_attrs(tmpctx);
     155           0 :     if (user_attrs == NULL) {
     156           0 :         ret = ENOMEM;
     157           0 :         goto done;
     158             :     }
     159             : 
     160             :     /* Always store SID string if available */
     161           0 :     ret = sdap_attrs_get_sid_str(tmpctx, opts->idmap_ctx, attrs,
     162           0 :                                 opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name,
     163             :                                 &sid_str);
     164           0 :     if (ret == EOK) {
     165           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str);
     166           0 :         if (ret != EOK) {
     167           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n",
     168             :                                          sss_strerror(ret));
     169           0 :             goto done;
     170             :         }
     171           0 :     } else if (ret == ENOENT) {
     172           0 :         DEBUG(SSSDBG_TRACE_ALL, "objectSID: not available for user\n");
     173           0 :         sid_str = NULL;
     174             :     } else {
     175           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n",
     176             :                                      sss_strerror(ret));
     177           0 :         sid_str = NULL;
     178             :     }
     179             : 
     180             :     /* Always store UUID if available */
     181           0 :     ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name,
     182             :                                      attrs,
     183           0 :                                      opts->user_map[SDAP_AT_USER_UUID].sys_name,
     184             :                                      user_attrs, SYSDB_UUID);
     185           0 :     if (ret != EOK) {
     186           0 :         DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE,
     187             :               "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret));
     188             :     }
     189             : 
     190             :     /* If this object has a SID available, we will determine the correct
     191             :      * domain by its SID. */
     192           0 :     if (sid_str != NULL) {
     193           0 :         subdomain = find_domain_by_sid(get_domains_head(dom), sid_str);
     194           0 :         if (subdomain) {
     195           0 :             dom = subdomain;
     196             :         } else {
     197           0 :             DEBUG(SSSDBG_TRACE_FUNC, "SID %s does not belong to any known "
     198             :                                       "domain\n", sid_str);
     199             :         }
     200             :     }
     201             : 
     202           0 :     ret = sdap_get_user_primary_name(memctx, opts, attrs, dom, &user_name);
     203           0 :     if (ret != EOK) {
     204           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to get user name\n");
     205           0 :         goto done;
     206             :     }
     207           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Processing user %s\n", user_name);
     208             : 
     209           0 :     if (opts->schema_type == SDAP_SCHEMA_AD) {
     210           0 :         ret = sysdb_attrs_get_string(attrs,
     211           0 :                     opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname);
     212           0 :         if (ret == EOK) {
     213           0 :             ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname);
     214           0 :             if (ret != EOK) {
     215           0 :                 goto done;
     216             :             }
     217           0 :         } else if (ret != ENOENT) {
     218           0 :             goto done;
     219             :         }
     220             :     }
     221             : 
     222           0 :     ret = sysdb_attrs_get_el(attrs,
     223           0 :                              opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
     224           0 :     if (ret) goto done;
     225           0 :     if (el->num_values == 0) pwd = NULL;
     226           0 :     else pwd = (const char *)el->values[0].data;
     227             : 
     228           0 :     ret = sysdb_attrs_get_el(attrs,
     229           0 :                              opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el);
     230           0 :     if (ret) goto done;
     231           0 :     if (el->num_values == 0) gecos = NULL;
     232           0 :     else gecos = (const char *)el->values[0].data;
     233             : 
     234           0 :     if (!gecos) {
     235             :         /* Fall back to the user's full name */
     236           0 :         ret = sysdb_attrs_get_el(
     237             :                 attrs,
     238           0 :                 opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el);
     239           0 :         if (ret) goto done;
     240           0 :         if (el->num_values > 0) gecos = (const char *)el->values[0].data;
     241             :     }
     242             : 
     243           0 :     ret = sysdb_attrs_get_el(attrs,
     244           0 :                              opts->user_map[SDAP_AT_USER_HOME].sys_name, &el);
     245           0 :     if (ret) goto done;
     246           0 :     if (el->num_values == 0) homedir = NULL;
     247           0 :     else homedir = (const char *)el->values[0].data;
     248             : 
     249           0 :     ret = sysdb_attrs_get_el(attrs,
     250           0 :                              opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el);
     251           0 :     if (ret) goto done;
     252           0 :     if (el->num_values == 0) shell = NULL;
     253           0 :     else shell = (const char *)el->values[0].data;
     254             : 
     255           0 :     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
     256           0 :                                                                dom->name,
     257             :                                                                sid_str);
     258             : 
     259             :     /* Retrieve or map the UID as appropriate */
     260           0 :     if (use_id_mapping) {
     261             : 
     262           0 :         if (sid_str == NULL) {
     263           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "SID not available, cannot map a " \
     264             :                                          "unix ID to user [%s].\n", user_name);
     265           0 :             ret = ENOENT;
     266           0 :             goto done;
     267             :         }
     268             : 
     269           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     270             :               "Mapping user [%s] objectSID [%s] to unix ID\n", user_name, sid_str);
     271             : 
     272             :         /* Convert the SID into a UNIX user ID */
     273           0 :         ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid);
     274           0 :         if (ret == ENOTSUP) {
     275           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
     276           0 :             ret = EOK;
     277           0 :             goto done;
     278           0 :         } else if (ret != EOK) {
     279           0 :             goto done;
     280             :         }
     281             : 
     282             :         /* Store the UID in the ldap_attrs so it doesn't get
     283             :          * treated as a missing attribute from LDAP and removed.
     284             :          */
     285           0 :         ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid);
     286           0 :         if (ret) {
     287           0 :             DEBUG(SSSDBG_OP_FAILURE, "Cannot set the id-mapped UID\n");
     288           0 :             goto done;
     289             :         }
     290             :     } else {
     291           0 :         ret = sysdb_attrs_get_uint32_t(attrs,
     292           0 :                                        opts->user_map[SDAP_AT_USER_UID].sys_name,
     293             :                                        &uid);
     294           0 :         if (ret != EOK) {
     295           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     296             :                   "no uid provided for [%s] in domain [%s].\n",
     297             :                    user_name, dom->name);
     298           0 :             ret = EINVAL;
     299           0 :             goto done;
     300             :         }
     301             :     }
     302             :     /* check that the uid is valid for this domain */
     303           0 :     if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
     304           0 :             DEBUG(SSSDBG_OP_FAILURE,
     305             :                   "User [%s] filtered out! (uid out of range)\n",
     306             :                       user_name);
     307           0 :         ret = EINVAL;
     308           0 :         goto done;
     309             :     }
     310             : 
     311           0 :     if (use_id_mapping) {
     312           0 :         ret = sdap_get_idmap_primary_gid(opts, attrs, sid_str, dom_sid_str,
     313             :                                          &gid);
     314           0 :         if (ret) {
     315           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     316             :                   "Cannot get the GID for [%s] in domain [%s].\n",
     317             :                    user_name, dom->name);
     318           0 :             goto done;
     319             :         }
     320             : 
     321           0 :         if (IS_SUBDOMAIN(dom)) {
     322             :             /* For subdomain users, only create the private group as
     323             :              * the subdomain is an MPG domain.
     324             :              * But we have to save the GID of the original primary group
     325             :              * becasuse otherwise this information might be lost because
     326             :              * typically (Unix and AD) the user is not listed in his primary
     327             :              * group as a member.
     328             :              */
     329           0 :             ret = sysdb_attrs_add_uint32(user_attrs, SYSDB_PRIMARY_GROUP_GIDNUM,
     330             :                                          (uint32_t) gid);
     331           0 :             if (ret != EOK) {
     332           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_uint32 failed.\n");
     333           0 :                 goto done;
     334             :             }
     335             : 
     336           0 :             gid = 0;
     337             :         }
     338             : 
     339             :         /* Store the GID in the ldap_attrs so it doesn't get
     340             :         * treated as a missing attribute from LDAP and removed.
     341             :         */
     342           0 :         ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
     343           0 :         if (ret != EOK) goto done;
     344             :     } else {
     345           0 :         ret = sysdb_attrs_get_uint32_t(attrs,
     346           0 :                                        opts->user_map[SDAP_AT_USER_GID].sys_name,
     347             :                                        &gid);
     348           0 :         if (ret != EOK) {
     349           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     350             :                   "no gid provided for [%s] in domain [%s].\n",
     351             :                   user_name, dom->name);
     352           0 :             ret = EINVAL;
     353           0 :             goto done;
     354             :         }
     355             :     }
     356             : 
     357             :     /* check that the gid is valid for this domain */
     358           0 :     if (IS_SUBDOMAIN(dom) == false &&
     359           0 :             OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
     360           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     361             :               "User [%s] filtered out! (primary gid out of range)\n",
     362             :                user_name);
     363           0 :         ret = EINVAL;
     364           0 :         goto done;
     365             :     }
     366             : 
     367           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
     368           0 :     if (ret) {
     369           0 :         goto done;
     370             :     }
     371           0 :     if (!el || el->num_values == 0) {
     372           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     373             :               "originalDN is not available for [%s].\n", user_name);
     374             :     } else {
     375           0 :         orig_dn = (const char *) el->values[0].data;
     376           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Adding originalDN [%s] to attributes "
     377             :                 "of [%s].\n", orig_dn, user_name);
     378             : 
     379           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn);
     380           0 :         if (ret) {
     381           0 :             goto done;
     382             :         }
     383             :     }
     384             : 
     385           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el);
     386           0 :     if (ret) {
     387           0 :         goto done;
     388             :     }
     389           0 :     if (el->num_values == 0) {
     390           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     391             :               "Original memberOf is not available for [%s].\n", user_name);
     392             :     } else {
     393           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     394             :               "Adding original memberOf attributes to [%s].\n", user_name);
     395           0 :         for (i = 0; i < el->num_values; i++) {
     396           0 :             ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
     397           0 :                     (const char *) el->values[i].data);
     398           0 :             if (ret) {
     399           0 :                 goto done;
     400             :             }
     401             :         }
     402             :     }
     403             : 
     404           0 :     ret = sdap_attrs_add_string(attrs,
     405             :                             opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name,
     406             :                             "original mod-Timestamp",
     407             :                             user_name, user_attrs);
     408           0 :     if (ret != EOK) {
     409           0 :         goto done;
     410             :     }
     411             : 
     412           0 :     ret = sysdb_attrs_get_el(attrs,
     413           0 :                       opts->user_map[SDAP_AT_USER_USN].sys_name, &el);
     414           0 :     if (ret) {
     415           0 :         goto done;
     416             :     }
     417           0 :     if (el->num_values == 0) {
     418           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     419             :               "Original USN value is not available for [%s].\n", user_name);
     420             :     } else {
     421           0 :         ret = sysdb_attrs_add_string(user_attrs,
     422           0 :                           opts->user_map[SDAP_AT_USER_USN].sys_name,
     423           0 :                           (const char*)el->values[0].data);
     424           0 :         if (ret) {
     425           0 :             goto done;
     426             :         }
     427           0 :         usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
     428           0 :         if (!usn_value) {
     429           0 :             ret = ENOMEM;
     430           0 :             goto done;
     431             :         }
     432             :     }
     433             : 
     434           0 :     ret = sysdb_attrs_get_el(attrs,
     435           0 :                              opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el);
     436           0 :     if (ret) {
     437           0 :         goto done;
     438             :     }
     439           0 :     if (el->num_values == 0) {
     440           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     441             :               "User principal is not available for [%s].\n", user_name);
     442             :     } else {
     443           0 :         upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
     444           0 :         if (!upn) {
     445           0 :             ret = ENOMEM;
     446           0 :             goto done;
     447             :         }
     448           0 :         if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
     449           0 :             make_realm_upper_case(upn);
     450             :         }
     451           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     452             :               "Adding user principal [%s] to attributes of [%s].\n",
     453             :                upn, user_name);
     454           0 :         ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
     455           0 :         if (ret) {
     456           0 :             goto done;
     457             :         }
     458             :     }
     459             : 
     460           0 :     for (i = SDAP_FIRST_EXTRA_USER_AT; i < opts->user_map_cnt; i++) {
     461           0 :         ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name,
     462             :                                   NULL, user_name, user_attrs);
     463           0 :         if (ret) {
     464           0 :             goto done;
     465             :         }
     466             :     }
     467             : 
     468           0 :     cache_timeout = dom->user_timeout;
     469             : 
     470           0 :     ret = sdap_save_all_names(user_name, attrs, dom, user_attrs);
     471           0 :     if (ret != EOK) {
     472           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save user names\n");
     473           0 :         goto done;
     474             :     }
     475             : 
     476             :     /* Make sure that any attributes we requested from LDAP that we
     477             :      * did not receive are also removed from the sysdb
     478             :      */
     479           0 :     ret = list_missing_attrs(user_attrs, opts->user_map, opts->user_map_cnt,
     480             :                              attrs, &missing);
     481           0 :     if (ret != EOK) {
     482           0 :         goto done;
     483             :     }
     484             : 
     485           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Storing info for user %s\n", user_name);
     486             : 
     487           0 :     ret = sysdb_store_user(dom, user_name, pwd, uid, gid,
     488             :                            gecos, homedir, shell, orig_dn,
     489             :                            user_attrs, missing, cache_timeout, now);
     490           0 :     if (ret) goto done;
     491             : 
     492           0 :     if (_usn_value) {
     493           0 :         *_usn_value = talloc_steal(memctx, usn_value);
     494             :     }
     495             : 
     496           0 :     talloc_steal(memctx, user_attrs);
     497           0 :     ret = EOK;
     498             : 
     499             : done:
     500           0 :     if (ret) {
     501           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     502             :               "Failed to save user [%s]\n",
     503             :                user_name ? user_name : "Unknown");
     504             :     }
     505           0 :     talloc_free(tmpctx);
     506           0 :     return ret;
     507             : }
     508             : 
     509             : 
     510             : /* ==Generic-Function-to-save-multiple-users============================= */
     511             : 
     512           0 : int sdap_save_users(TALLOC_CTX *memctx,
     513             :                     struct sysdb_ctx *sysdb,
     514             :                     struct sss_domain_info *dom,
     515             :                     struct sdap_options *opts,
     516             :                     struct sysdb_attrs **users,
     517             :                     int num_users,
     518             :                     char **_usn_value)
     519             : {
     520             :     TALLOC_CTX *tmpctx;
     521           0 :     char *higher_usn = NULL;
     522             :     char *usn_value;
     523             :     int ret;
     524             :     errno_t sret;
     525             :     int i;
     526             :     time_t now;
     527           0 :     bool in_transaction = false;
     528             : 
     529           0 :     if (num_users == 0) {
     530             :         /* Nothing to do if there are no users */
     531           0 :         return EOK;
     532             :     }
     533             : 
     534           0 :     tmpctx = talloc_new(memctx);
     535           0 :     if (!tmpctx) {
     536           0 :         return ENOMEM;
     537             :     }
     538             : 
     539           0 :     ret = sysdb_transaction_start(sysdb);
     540           0 :     if (ret) {
     541           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     542           0 :         goto done;
     543             :     }
     544           0 :     in_transaction = true;
     545             : 
     546           0 :     now = time(NULL);
     547           0 :     for (i = 0; i < num_users; i++) {
     548           0 :         usn_value = NULL;
     549             : 
     550           0 :         ret = sdap_save_user(tmpctx, opts, dom, users[i], &usn_value, now);
     551             : 
     552             :         /* Do not fail completely on errors.
     553             :          * Just report the failure to save and go on */
     554           0 :         if (ret) {
     555           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store user %d. Ignoring.\n", i);
     556             :         } else {
     557           0 :             DEBUG(SSSDBG_TRACE_ALL, "User %d processed!\n", i);
     558             :         }
     559             : 
     560           0 :         if (usn_value) {
     561           0 :             if (higher_usn) {
     562           0 :                 if ((strlen(usn_value) > strlen(higher_usn)) ||
     563           0 :                     (strcmp(usn_value, higher_usn) > 0)) {
     564           0 :                     talloc_zfree(higher_usn);
     565           0 :                     higher_usn = usn_value;
     566             :                 } else {
     567           0 :                     talloc_zfree(usn_value);
     568             :                 }
     569             :             } else {
     570           0 :                 higher_usn = usn_value;
     571             :             }
     572             :         }
     573             :     }
     574             : 
     575           0 :     ret = sysdb_transaction_commit(sysdb);
     576           0 :     if (ret) {
     577           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction!\n");
     578           0 :         goto done;
     579             :     }
     580           0 :     in_transaction = false;
     581             : 
     582           0 :     if (_usn_value) {
     583           0 :         *_usn_value = talloc_steal(memctx, higher_usn);
     584             :     }
     585             : 
     586             : done:
     587           0 :     if (in_transaction) {
     588           0 :         sret = sysdb_transaction_cancel(sysdb);
     589           0 :         if (sret != EOK) {
     590           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
     591             :         }
     592             :     }
     593           0 :     talloc_zfree(tmpctx);
     594           0 :     return ret;
     595             : }
     596             : 
     597             : 
     598             : /* ==Search-Users-with-filter============================================= */
     599             : 
     600             : struct sdap_search_user_state {
     601             :     struct tevent_context *ev;
     602             :     struct sdap_options *opts;
     603             :     struct sdap_handle *sh;
     604             :     struct sss_domain_info *dom;
     605             : 
     606             :     const char **attrs;
     607             :     const char *base_filter;
     608             :     const char *filter;
     609             :     int timeout;
     610             :     enum sdap_entry_lookup_type lookup_type;
     611             : 
     612             :     char *higher_usn;
     613             :     struct sysdb_attrs **users;
     614             :     size_t count;
     615             : 
     616             :     size_t base_iter;
     617             :     struct sdap_search_base **search_bases;
     618             : };
     619             : 
     620             : static errno_t sdap_search_user_next_base(struct tevent_req *req);
     621             : static void sdap_search_user_copy_batch(struct sdap_search_user_state *state,
     622             :                                         struct sysdb_attrs **users,
     623             :                                         size_t count);
     624             : static void sdap_search_user_process(struct tevent_req *subreq);
     625             : 
     626           0 : struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
     627             :                                          struct tevent_context *ev,
     628             :                                          struct sss_domain_info *dom,
     629             :                                          struct sdap_options *opts,
     630             :                                          struct sdap_search_base **search_bases,
     631             :                                          struct sdap_handle *sh,
     632             :                                          const char **attrs,
     633             :                                          const char *filter,
     634             :                                          int timeout,
     635             :                                          enum sdap_entry_lookup_type lookup_type)
     636             : {
     637             :     errno_t ret;
     638             :     struct tevent_req *req;
     639             :     struct sdap_search_user_state *state;
     640             : 
     641           0 :     req = tevent_req_create(memctx, &state, struct sdap_search_user_state);
     642           0 :     if (req == NULL) return NULL;
     643             : 
     644           0 :     state->ev = ev;
     645           0 :     state->opts = opts;
     646           0 :     state->dom = dom;
     647           0 :     state->sh = sh;
     648           0 :     state->attrs = attrs;
     649           0 :     state->higher_usn = NULL;
     650           0 :     state->users =  NULL;
     651           0 :     state->count = 0;
     652           0 :     state->timeout = timeout;
     653           0 :     state->base_filter = filter;
     654           0 :     state->base_iter = 0;
     655           0 :     state->search_bases = search_bases;
     656           0 :     state->lookup_type = lookup_type;
     657             : 
     658           0 :     if (!state->search_bases) {
     659           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     660             :               "User lookup request without a search base\n");
     661           0 :         ret = EINVAL;
     662           0 :         goto done;
     663             :     }
     664             : 
     665           0 :     ret = sdap_search_user_next_base(req);
     666             : 
     667             : done:
     668           0 :     if (ret != EOK) {
     669           0 :         tevent_req_error(req, ret);
     670           0 :         tevent_req_post(req, state->ev);
     671             :     }
     672             : 
     673           0 :     return req;
     674             : }
     675             : 
     676           0 : static errno_t sdap_search_user_next_base(struct tevent_req *req)
     677             : {
     678             :     struct tevent_req *subreq;
     679             :     struct sdap_search_user_state *state;
     680           0 :     bool need_paging = false;
     681           0 :     int sizelimit = 0;
     682             : 
     683           0 :     state = tevent_req_data(req, struct sdap_search_user_state);
     684             : 
     685           0 :     talloc_zfree(state->filter);
     686           0 :     state->filter = sdap_combine_filters(state, 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             :     const char *filter;
     845             : 
     846             :     char *higher_usn;
     847             :     struct sysdb_attrs **users;
     848             :     size_t count;
     849             : };
     850             : 
     851             : static void sdap_get_users_done(struct tevent_req *subreq);
     852             : 
     853           0 : struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
     854             :                                        struct tevent_context *ev,
     855             :                                        struct sss_domain_info *dom,
     856             :                                        struct sysdb_ctx *sysdb,
     857             :                                        struct sdap_options *opts,
     858             :                                        struct sdap_search_base **search_bases,
     859             :                                        struct sdap_handle *sh,
     860             :                                        const char **attrs,
     861             :                                        const char *filter,
     862             :                                        int timeout,
     863             :                                        enum sdap_entry_lookup_type lookup_type)
     864             : {
     865             :     errno_t ret;
     866             :     struct tevent_req *req;
     867             :     struct tevent_req *subreq;
     868             :     struct sdap_get_users_state *state;
     869             : 
     870           0 :     req = tevent_req_create(memctx, &state, struct sdap_get_users_state);
     871           0 :     if (!req) return NULL;
     872             : 
     873           0 :     state->sysdb = sysdb;
     874           0 :     state->opts = opts;
     875           0 :     state->dom = dom;
     876             : 
     877           0 :     state->filter = filter;
     878             :     PROBE(SDAP_SEARCH_USER_SEND, state->filter);
     879             : 
     880           0 :     subreq = sdap_search_user_send(state, ev, dom, opts, search_bases,
     881             :                                    sh, attrs, filter, timeout, lookup_type);
     882           0 :     if (subreq == NULL) {
     883           0 :         ret = ENOMEM;
     884           0 :         goto done;
     885             :     }
     886           0 :     tevent_req_set_callback(subreq, sdap_get_users_done, req);
     887             : 
     888           0 :     ret = EOK;
     889             : done:
     890           0 :     if (ret != EOK) {
     891           0 :         tevent_req_error(req, ret);
     892           0 :         tevent_req_post(req, ev);
     893             :     }
     894             : 
     895           0 :     return req;
     896             : }
     897             : 
     898           0 : static void sdap_get_users_done(struct tevent_req *subreq)
     899             : {
     900           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     901             :                                                       struct tevent_req);
     902           0 :     struct sdap_get_users_state *state = tevent_req_data(req,
     903             :                                             struct sdap_get_users_state);
     904             :     int ret;
     905             : 
     906           0 :     ret = sdap_search_user_recv(state, subreq, &state->higher_usn,
     907             :                                 &state->users, &state->count);
     908           0 :     if (ret) {
     909           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve users [%d][%s].\n",
     910             :               ret, sss_strerror(ret));
     911           0 :         tevent_req_error(req, ret);
     912           0 :         return;
     913             :     }
     914             : 
     915             :     PROBE(SDAP_SEARCH_USER_SAVE_BEGIN, state->filter);
     916           0 :     ret = sdap_save_users(state, state->sysdb,
     917             :                           state->dom, state->opts,
     918           0 :                           state->users, state->count,
     919             :                           &state->higher_usn);
     920             :     PROBE(SDAP_SEARCH_USER_SAVE_END, state->filter);
     921           0 :     if (ret) {
     922           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to store users [%d][%s].\n",
     923             :               ret, sss_strerror(ret));
     924           0 :         tevent_req_error(req, ret);
     925           0 :         return;
     926             :     }
     927             : 
     928           0 :     DEBUG(SSSDBG_TRACE_ALL, "Saving %zu Users - Done\n", state->count);
     929             : 
     930           0 :     tevent_req_done(req);
     931             : }
     932             : 
     933           0 : int sdap_get_users_recv(struct tevent_req *req,
     934             :                         TALLOC_CTX *mem_ctx, char **usn_value)
     935             : {
     936           0 :     struct sdap_get_users_state *state = tevent_req_data(req,
     937             :                                             struct sdap_get_users_state);
     938             : 
     939             :     PROBE(SDAP_SEARCH_USER_RECV, state->filter);
     940           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     941             : 
     942           0 :     if (usn_value) {
     943           0 :         *usn_value = talloc_steal(mem_ctx, state->higher_usn);
     944             :     }
     945             : 
     946           0 :     return EOK;
     947             : }
     948             : 
     949             : /* ==Fetch-Fallback-local-user============================================ */
     950             : 
     951           0 : errno_t sdap_fallback_local_user(TALLOC_CTX *memctx,
     952             :                                  const char *name, uid_t uid,
     953             :                                  struct sysdb_attrs ***reply)
     954             : {
     955             :     struct sysdb_attrs **ua;
     956             :     struct sysdb_attrs *user;
     957             :     struct passwd *pwd;
     958             :     int ret;
     959             : 
     960           0 :     if (name) {
     961           0 :         pwd = getpwnam(name);
     962             :     } else {
     963           0 :         pwd = getpwuid(uid);
     964             :     }
     965             : 
     966           0 :     if (!pwd) {
     967           0 :         return errno ? errno : ENOENT;
     968             :     }
     969             : 
     970           0 :     ua = talloc_array(memctx, struct sysdb_attrs *, 2);
     971           0 :     if (!ua) {
     972           0 :         ret = ENOMEM;
     973           0 :         goto done;
     974             :     }
     975           0 :     ua[1] = NULL;
     976             : 
     977           0 :     user = sysdb_new_attrs(ua);
     978           0 :     if (!user) {
     979           0 :         ret = ENOMEM;
     980           0 :         goto done;
     981             :     }
     982           0 :     ua[0] = user;
     983             : 
     984           0 :     ret = sysdb_attrs_add_string(user, SYSDB_NAME, pwd->pw_name);
     985           0 :     if (ret != EOK) {
     986           0 :         goto done;
     987             :     }
     988             : 
     989           0 :     if (pwd->pw_passwd) {
     990           0 :         ret = sysdb_attrs_add_string(user, SYSDB_PWD, pwd->pw_passwd);
     991           0 :         if (ret != EOK) {
     992           0 :             goto done;
     993             :         }
     994             :     }
     995             : 
     996           0 :     ret = sysdb_attrs_add_long(user, SYSDB_UIDNUM, (long)pwd->pw_uid);
     997           0 :     if (ret != EOK) {
     998           0 :         goto done;
     999             :     }
    1000             : 
    1001           0 :     ret = sysdb_attrs_add_long(user, SYSDB_GIDNUM, (long)pwd->pw_gid);
    1002           0 :     if (ret != EOK) {
    1003           0 :         goto done;
    1004             :     }
    1005             : 
    1006           0 :     if (pwd->pw_gecos) {
    1007           0 :         ret = sysdb_attrs_add_string(user, SYSDB_GECOS, pwd->pw_gecos);
    1008           0 :         if (ret != EOK) {
    1009           0 :             goto done;
    1010             :         }
    1011             :     }
    1012             : 
    1013           0 :     if (pwd->pw_dir) {
    1014           0 :         ret = sysdb_attrs_add_string(user, SYSDB_HOMEDIR, pwd->pw_dir);
    1015           0 :         if (ret != EOK) {
    1016           0 :             goto done;
    1017             :         }
    1018             :     }
    1019             : 
    1020           0 :     if (pwd->pw_shell) {
    1021           0 :         ret = sysdb_attrs_add_string(user, SYSDB_SHELL, pwd->pw_shell);
    1022           0 :         if (ret != EOK) {
    1023           0 :             goto done;
    1024             :         }
    1025             :     }
    1026             : 
    1027             : done:
    1028           0 :     if (ret != EOK) {
    1029           0 :         talloc_free(ua);
    1030             :     } else {
    1031           0 :         *reply = ua;
    1032             :     }
    1033             : 
    1034           0 :     return ret;
    1035             : }

Generated by: LCOV version 1.10