Example #1
0
errno_t
sdap_save_all_names(const char *name,
                    struct sysdb_attrs *ldap_attrs,
                    struct sss_domain_info *dom,
                    struct sysdb_attrs *attrs)
{
    const char **aliases = NULL;
    const char *domname;
    errno_t ret;
    TALLOC_CTX *tmp_ctx;
    int i;
    bool lowercase = !dom->case_sensitive;

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_get_aliases(tmp_ctx, ldap_attrs, name,
                                  lowercase, &aliases);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to get the alias list");
        goto done;
    }

    for (i = 0; aliases[i]; i++) {
        domname = sss_get_domain_name(tmp_ctx, aliases[i], dom);
        if (domname == NULL) {
            ret = ENOMEM;
            goto done;
        }

        if (lowercase) {
            ret = sysdb_attrs_add_lc_name_alias(attrs, domname);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Failed to add lower-cased version "
                                          "of alias [%s] into the "
                                          "attribute list\n", aliases[i]);
                goto done;
            }
        } else {
            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, domname);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Failed to add alias [%s] into the "
                                          "attribute list\n", aliases[i]);
                goto done;
            }
        }

    }

    ret = EOK;
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #2
0
static void do_pam_chauthtok(struct LOCAL_request *lreq)
{
    int ret;
    char *newauthtok;
    char *salt;
    char *new_hash;
    struct pam_data *pd;

    pd = lreq->preq->pd;

    newauthtok = talloc_strndup(lreq, (char *) pd->newauthtok,
                                pd->newauthtok_size);
    NULL_CHECK_OR_JUMP(newauthtok, ("talloc_strndup failed.\n"), lreq->error,
                       ENOMEM, done);
    memset(pd->newauthtok, 0, pd->newauthtok_size);

    if (strlen(newauthtok) == 0) {
        /* TODO: should we allow null passwords via a config option ? */
        DEBUG(1, ("Empty passwords are not allowed!\n"));
        lreq->error = EINVAL;
        goto done;
    }

    ret = s3crypt_gen_salt(lreq, &salt);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("Salt generation failed.\n"),
                      lreq->error, ret, done);
    DEBUG(4, ("Using salt [%s]\n", salt));

    ret = s3crypt_sha512(lreq, newauthtok, salt, &new_hash);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
                      lreq->error, ret, done);
    DEBUG(4, ("New hash [%s]\n", new_hash));
    memset(newauthtok, 0, pd->newauthtok_size);

    lreq->mod_attrs = sysdb_new_attrs(lreq);
    NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
                       lreq->error, ENOMEM, done);

    ret = sysdb_attrs_add_string(lreq->mod_attrs, SYSDB_PWD, new_hash);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_string failed.\n"),
                      lreq->error, ret, done);

    ret = sysdb_attrs_add_long(lreq->mod_attrs,
                               "lastPasswordChange", (long)time(NULL));
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
                      lreq->error, ret, done);

    ret = sysdb_set_user_attr(lreq->dbctx, lreq->preq->pd->user,
                              lreq->mod_attrs, SYSDB_MOD_REP);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_set_user_attr failed.\n"),
                      lreq->error, ret, done);

done:
    return;
}
Example #3
0
static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
        struct sss_domain_info *domain,
        struct sysdb_attrs *group_attrs,
        struct group *grp,
        time_t now)
{
    errno_t ret;
    size_t i;
    TALLOC_CTX *tmp_ctx = NULL;
    struct ldb_message *msg;

    if (!sysdb || !grp) return EINVAL;

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) return ENOMEM;

    for (i = 0; grp->gr_mem[i]; i++) {
        ret = sysdb_search_user_by_name(tmp_ctx, domain, grp->gr_mem[i],
                                        NULL, &msg);
        if (ret == EOK) {
            /* Member already exists in the cache */
            DEBUG(SSSDBG_TRACE_INTERNAL,
                  "Member [%s] already cached\n", grp->gr_mem[i]);
            /* clean up */
            talloc_zfree(msg);
            continue;
        } else if (ret == ENOENT) {
            /* No entry for this user. Create a ghost user */
            DEBUG(SSSDBG_TRACE_LIBS,
                  "Member [%s] not cached, creating ghost user entry\n",
                  grp->gr_mem[i]);

            ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST, grp->gr_mem[i]);
            if (ret != EOK) {
                DEBUG(SSSDBG_MINOR_FAILURE,
                      "Cannot store ghost user entry: [%d]: %s\n",
                      ret, strerror(ret));
                goto done;
            }
        } else {
            /* Unexpected error */
            DEBUG(SSSDBG_MINOR_FAILURE,
                  "Error searching cache for user [%s]: [%s]\n",
                  grp->gr_mem[i], strerror(ret));
            goto done;
        }
    }

    ret = EOK;
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #4
0
static void do_pam_chauthtok(struct LOCAL_request *lreq)
{
    int ret;
    const char *password;
    char *salt;
    char *new_hash;
    struct pam_data *pd;

    pd = lreq->preq->pd;

    ret = sss_authtok_get_password(pd->newauthtok, &password, NULL);
    if (ret) {
        /* TODO: should we allow null passwords via a config option ? */
        if (ret == ENOENT) {
            DEBUG(1, ("Empty passwords are not allowed!\n"));
        }
        lreq->error = EINVAL;
        goto done;
    }

    ret = s3crypt_gen_salt(lreq, &salt);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("Salt generation failed.\n"),
                      lreq->error, ret, done);
    DEBUG(4, ("Using salt [%s]\n", salt));

    ret = s3crypt_sha512(lreq, password, salt, &new_hash);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
                      lreq->error, ret, done);
    DEBUG(4, ("New hash [%s]\n", new_hash));

    lreq->mod_attrs = sysdb_new_attrs(lreq);
    NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
                       lreq->error, ENOMEM, done);

    ret = sysdb_attrs_add_string(lreq->mod_attrs, SYSDB_PWD, new_hash);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_string failed.\n"),
                      lreq->error, ret, done);

    ret = sysdb_attrs_add_long(lreq->mod_attrs,
                               "lastPasswordChange", (long)time(NULL));
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
                      lreq->error, ret, done);

    ret = sysdb_set_user_attr(lreq->dbctx, lreq->domain,
                              lreq->preq->pd->user,
                              lreq->mod_attrs, SYSDB_MOD_REP);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_set_user_attr failed.\n"),
                      lreq->error, ret, done);

done:
    sss_authtok_set_empty(pd->newauthtok);
}
Example #5
0
static int attr_op(struct ops_ctx *octx, const char *nameval, int op)
{
    TALLOC_CTX *tmp_ctx;
    errno_t ret;
    struct sysdb_attrs *attrs;
    char *name;
    char **vals;
    int nvals;
    int i;

    switch(op) {
    case SYSDB_MOD_ADD:
    case SYSDB_MOD_DEL:
    case SYSDB_MOD_REP:
        break;
    default:
        return EINVAL;
    }

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) return ENOMEM;

    attrs = sysdb_new_attrs(tmp_ctx);
    if (attrs == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = attr_name_val_split(tmp_ctx, nameval, &name, &vals, &nvals);
    if (ret != EOK) {
        goto done;
    }

    for (i=0; i < nvals; i++) {
        ret = sysdb_attrs_add_string(attrs, name, vals[i]);
        if (ret != EOK) {
            DEBUG(SSSDBG_MINOR_FAILURE,
                  "Could not add %s to %s\n", vals[i], name);
            continue;
        }
    }

    ret = sysdb_set_user_attr(octx->domain, octx->name, attrs, op);
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #6
0
static int krb5_mod_ccname(TALLOC_CTX *mem_ctx,
                           struct sysdb_ctx *sysdb,
                           const char *name,
                           const char *ccname,
                           int mod_op)
{
    TALLOC_CTX *tmpctx;
    struct sysdb_attrs *attrs;
    int ret;

    if (name == NULL || ccname == NULL) {
        DEBUG(1, ("Missing user or ccache name.\n"));
        return EINVAL;
    }

    if (mod_op != SYSDB_MOD_REP && mod_op != SYSDB_MOD_DEL) {
        DEBUG(1, ("Unsupported operation [%d].\n", mod_op));
        return EINVAL;
    }

    DEBUG(9, ("%s ccname [%s] for user [%s].\n",
              mod_op == SYSDB_MOD_REP ? "Save" : "Delete", ccname, name));

    tmpctx = talloc_new(mem_ctx);
    if (!tmpctx) {
        return ENOMEM;
    }

    attrs = sysdb_new_attrs(mem_ctx);
    if (!attrs) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_CCACHE_FILE, ccname);
    if (ret != EOK) {
        DEBUG(1, ("sysdb_attrs_add_string failed.\n"));
        goto done;
    }

    ret = sysdb_transaction_start(sysdb);
    if (ret != EOK) {
        DEBUG(6, ("Error %d starting transaction (%s)\n", ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_set_user_attr(sysdb, name, attrs, mod_op);
    if (ret != EOK) {
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
        sysdb_transaction_cancel(sysdb);
        goto done;
    }

    ret = sysdb_transaction_commit(sysdb);
    if (ret != EOK) {
        DEBUG(1, ("Failed to commit transaction!\n"));
    }

done:
    talloc_zfree(tmpctx);
    return ret;
}
Example #7
0
errno_t
sysdb_save_autofsmap(struct sysdb_ctx *sysdb_ctx,
                     struct sss_domain_info *domain,
                     const char *name,
                     const char *autofsmapname,
                     struct sysdb_attrs *attrs,
                     int cache_timeout,
                     time_t now)
{
    errno_t ret;
    TALLOC_CTX *tmp_ctx;

    DEBUG(SSSDBG_TRACE_FUNC, ("Adding autofs map %s\n", autofsmapname));

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    if (!attrs) {
        attrs = sysdb_new_attrs(tmp_ctx);
        if (!attrs) {
            ret = ENOMEM;
            goto done;
        }
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
                                 SYSDB_AUTOFS_MAP_OC);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set map object class [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_AUTOFS_MAP_NAME, autofsmapname);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set map name [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set name attribute [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set sysdb lastUpdate [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
                                 ((cache_timeout) ?
                                  (now + cache_timeout) : 0));
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set sysdb cache expire [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_store_custom(sysdb_ctx, domain, name, AUTOFS_MAP_SUBDIR, attrs);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("sysdb_store_custom failed [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = EOK;
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #8
0
/* FIXME: support storing additional attributes */
int sdap_save_user(TALLOC_CTX *memctx,
                   struct sdap_options *opts,
                   struct sss_domain_info *dom,
                   struct sysdb_attrs *attrs,
                   char **_usn_value,
                   time_t now)
{
    struct ldb_message_element *el;
    int ret;
    const char *user_name = NULL;
    const char *fullname = NULL;
    const char *pwd;
    const char *gecos;
    const char *homedir;
    const char *shell;
    const char *orig_dn = NULL;
    uid_t uid;
    gid_t gid;
    struct sysdb_attrs *user_attrs;
    char *upn = NULL;
    size_t i;
    int cache_timeout;
    char *usn_value = NULL;
    char **missing = NULL;
    TALLOC_CTX *tmpctx = NULL;
    bool use_id_mapping;
    char *sid_str;
    char *dom_sid_str = NULL;
    struct sss_domain_info *subdomain;

    DEBUG(SSSDBG_TRACE_FUNC, "Save user\n");

    tmpctx = talloc_new(NULL);
    if (!tmpctx) {
        ret = ENOMEM;
        goto done;
    }

    user_attrs = sysdb_new_attrs(tmpctx);
    if (user_attrs == NULL) {
        ret = ENOMEM;
        goto done;
    }

    /* Always store SID string if available */
    ret = sdap_attrs_get_sid_str(tmpctx, opts->idmap_ctx, attrs,
                                opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name,
                                &sid_str);
    if (ret == EOK) {
        ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str);
        if (ret != EOK) {
            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n",
                                         sss_strerror(ret));
            goto done;
        }
    } else if (ret == ENOENT) {
        DEBUG(SSSDBG_TRACE_ALL, "objectSID: not available for user\n");
        sid_str = NULL;
    } else {
        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n",
                                     sss_strerror(ret));
        sid_str = NULL;
    }

    /* Always store UUID if available */
    ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name,
                                     attrs,
                                     opts->user_map[SDAP_AT_USER_UUID].sys_name,
                                     user_attrs, SYSDB_UUID);
    if (ret != EOK) {
        DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE,
              "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret));
    }

    /* If this object has a SID available, we will determine the correct
     * domain by its SID. */
    if (sid_str != NULL) {
        subdomain = find_domain_by_sid(get_domains_head(dom), sid_str);
        if (subdomain) {
            dom = subdomain;
        } else {
            DEBUG(SSSDBG_TRACE_FUNC, "SID %s does not belong to any known "
                                      "domain\n", sid_str);
        }
    }

    ret = sdap_get_user_primary_name(memctx, opts, attrs, dom, &user_name);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to get user name\n");
        goto done;
    }
    DEBUG(SSSDBG_TRACE_FUNC, "Processing user %s\n", user_name);

    if (opts->schema_type == SDAP_SCHEMA_AD) {
        ret = sysdb_attrs_get_string(attrs,
                    opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname);
        if (ret == EOK) {
            ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname);
            if (ret != EOK) {
                goto done;
            }
        } else if (ret != ENOENT) {
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) pwd = NULL;
    else pwd = (const char *)el->values[0].data;

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) gecos = NULL;
    else gecos = (const char *)el->values[0].data;

    if (!gecos) {
        /* Fall back to the user's full name */
        ret = sysdb_attrs_get_el(
                attrs,
                opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el);
        if (ret) goto done;
        if (el->num_values > 0) gecos = (const char *)el->values[0].data;
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_HOME].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) homedir = NULL;
    else homedir = (const char *)el->values[0].data;

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) shell = NULL;
    else shell = (const char *)el->values[0].data;

    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
                                                               dom->name,
                                                               sid_str);

    /* Retrieve or map the UID as appropriate */
    if (use_id_mapping) {

        if (sid_str == NULL) {
            DEBUG(SSSDBG_MINOR_FAILURE, "SID not available, cannot map a " \
                                         "unix ID to user [%s].\n", user_name);
            ret = ENOENT;
            goto done;
        }

        DEBUG(SSSDBG_TRACE_LIBS,
              "Mapping user [%s] objectSID [%s] to unix ID\n", user_name, sid_str);

        /* Convert the SID into a UNIX user ID */
        ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid);
        if (ret == ENOTSUP) {
            DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
            ret = EOK;
            goto done;
        } else if (ret != EOK) {
            goto done;
        }

        /* Store the UID in the ldap_attrs so it doesn't get
         * treated as a missing attribute from LDAP and removed.
         */
        ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, "Cannot set the id-mapped UID\n");
            goto done;
        }
    } else {
        ret = sysdb_attrs_get_uint32_t(attrs,
                                       opts->user_map[SDAP_AT_USER_UID].sys_name,
                                       &uid);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "no uid provided for [%s] in domain [%s].\n",
                   user_name, dom->name);
            ret = EINVAL;
            goto done;
        }
    }
    /* check that the uid is valid for this domain */
    if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "User [%s] filtered out! (uid out of range)\n",
                      user_name);
        ret = EINVAL;
        goto done;
    }

    if (use_id_mapping) {
        ret = sdap_get_idmap_primary_gid(opts, attrs, sid_str, dom_sid_str,
                                         &gid);
        if (ret) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Cannot get the GID for [%s] in domain [%s].\n",
                   user_name, dom->name);
            goto done;
        }

        if (IS_SUBDOMAIN(dom)) {
            /* For subdomain users, only create the private group as
             * the subdomain is an MPG domain.
             * But we have to save the GID of the original primary group
             * becasuse otherwise this information might be lost because
             * typically (Unix and AD) the user is not listed in his primary
             * group as a member.
             */
            ret = sysdb_attrs_add_uint32(user_attrs, SYSDB_PRIMARY_GROUP_GIDNUM,
                                         (uint32_t) gid);
            if (ret != EOK) {
                DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_uint32 failed.\n");
                goto done;
            }

            gid = 0;
        }

        /* Store the GID in the ldap_attrs so it doesn't get
        * treated as a missing attribute from LDAP and removed.
        */
        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
        if (ret != EOK) goto done;
    } else {
        ret = sysdb_attrs_get_uint32_t(attrs,
                                       opts->user_map[SDAP_AT_USER_GID].sys_name,
                                       &gid);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "no gid provided for [%s] in domain [%s].\n",
                  user_name, dom->name);
            ret = EINVAL;
            goto done;
        }
    }

    /* check that the gid is valid for this domain */
    if (IS_SUBDOMAIN(dom) == false &&
            OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "User [%s] filtered out! (primary gid out of range)\n",
               user_name);
        ret = EINVAL;
        goto done;
    }

    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
    if (ret) {
        goto done;
    }
    if (!el || el->num_values == 0) {
        DEBUG(SSSDBG_MINOR_FAILURE,
              "originalDN is not available for [%s].\n", user_name);
    } else {
        orig_dn = (const char *) el->values[0].data;
        DEBUG(SSSDBG_TRACE_INTERNAL, "Adding originalDN [%s] to attributes "
                "of [%s].\n", orig_dn, user_name);

        ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn);
        if (ret) {
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Original memberOf is not available for [%s].\n", user_name);
    } else {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Adding original memberOf attributes to [%s].\n", user_name);
        for (i = 0; i < el->num_values; i++) {
            ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
                    (const char *) el->values[i].data);
            if (ret) {
                goto done;
            }
        }
    }

    ret = sdap_attrs_add_string(attrs,
                            opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name,
                            "original mod-Timestamp",
                            user_name, user_attrs);
    if (ret != EOK) {
        goto done;
    }

    ret = sysdb_attrs_get_el(attrs,
                      opts->user_map[SDAP_AT_USER_USN].sys_name, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Original USN value is not available for [%s].\n", user_name);
    } else {
        ret = sysdb_attrs_add_string(user_attrs,
                          opts->user_map[SDAP_AT_USER_USN].sys_name,
                          (const char*)el->values[0].data);
        if (ret) {
            goto done;
        }
        usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
        if (!usn_value) {
            ret = ENOMEM;
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "User principal is not available for [%s].\n", user_name);
    } else {
        upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
        if (!upn) {
            ret = ENOMEM;
            goto done;
        }
        if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
            make_realm_upper_case(upn);
        }
        DEBUG(SSSDBG_TRACE_FUNC,
              "Adding user principal [%s] to attributes of [%s].\n",
               upn, user_name);
        ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
        if (ret) {
            goto done;
        }
    }

    for (i = SDAP_FIRST_EXTRA_USER_AT; i < opts->user_map_cnt; i++) {
        ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name,
                                  NULL, user_name, user_attrs);
        if (ret) {
            goto done;
        }
    }

    cache_timeout = dom->user_timeout;

    ret = sdap_save_all_names(user_name, attrs, dom, user_attrs);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save user names\n");
        goto done;
    }

    /* Make sure that any attributes we requested from LDAP that we
     * did not receive are also removed from the sysdb
     */
    ret = list_missing_attrs(user_attrs, opts->user_map, opts->user_map_cnt,
                             attrs, &missing);
    if (ret != EOK) {
        goto done;
    }

    DEBUG(SSSDBG_TRACE_FUNC, "Storing info for user %s\n", user_name);

    ret = sysdb_store_user(dom, user_name, pwd, uid, gid,
                           gecos, homedir, shell, orig_dn,
                           user_attrs, missing, cache_timeout, now);
    if (ret) goto done;

    if (_usn_value) {
        *_usn_value = talloc_steal(memctx, usn_value);
    }

    talloc_steal(memctx, user_attrs);
    ret = EOK;

done:
    if (ret) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Failed to save user [%s]\n",
               user_name ? user_name : "Unknown");
    }
    talloc_free(tmpctx);
    return ret;
}
Example #9
0
/* FIXME: support storing additional attributes */
int sdap_save_user(TALLOC_CTX *memctx,
                   struct sysdb_ctx *ctx,
                   struct sdap_options *opts,
                   struct sss_domain_info *dom,
                   struct sysdb_attrs *attrs,
                   bool is_initgr,
                   char **_usn_value,
                   time_t now)
{
    struct ldb_message_element *el;
    int ret;
    const char *name = NULL;
    const char *fullname = NULL;
    const char *pwd;
    const char *gecos;
    const char *homedir;
    const char *shell;
    const char *orig_dn = NULL;
    uid_t uid;
    gid_t gid, primary_gid;
    struct sysdb_attrs *user_attrs;
    char *upn = NULL;
    size_t i;
    int cache_timeout;
    char *usn_value = NULL;
    char **missing = NULL;
    TALLOC_CTX *tmpctx = NULL;
    bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
    char *sid_str;
    char *dom_sid_str = NULL;
    char *group_sid_str;

    DEBUG(9, ("Save user\n"));

    tmpctx = talloc_new(NULL);
    if (!tmpctx) {
        ret = ENOMEM;
        goto done;
    }

    user_attrs = sysdb_new_attrs(tmpctx);
    if (user_attrs == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_primary_name(ctx, attrs,
                                   opts->user_map[SDAP_AT_USER_NAME].name,
                                   &name);
    if (ret != EOK) {
        DEBUG(1, ("Failed to save the user - entry has no name attribute\n"));
        goto done;
    }

    if (opts->schema_type == SDAP_SCHEMA_AD) {
        ret = sysdb_attrs_get_string(attrs,
                    opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname);
        if (ret == EOK) {
            ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname);
            if (ret != EOK) {
                goto done;
            }
        } else if (ret != ENOENT) {
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) pwd = NULL;
    else pwd = (const char *)el->values[0].data;

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) gecos = NULL;
    else gecos = (const char *)el->values[0].data;

    if (!gecos) {
        /* Fall back to the user's full name */
        ret = sysdb_attrs_get_el(
                attrs,
                opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el);
        if (ret) goto done;
        if (el->num_values > 0) gecos = (const char *)el->values[0].data;
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_HOME].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) homedir = NULL;
    else homedir = (const char *)el->values[0].data;

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el);
    if (ret) goto done;
    if (el->num_values == 0) shell = NULL;
    else shell = (const char *)el->values[0].data;

    /* Retrieve or map the UID as appropriate */
    if (use_id_mapping) {
        DEBUG(SSSDBG_TRACE_LIBS,
              ("Mapping user [%s] objectSID to unix ID\n", name));

        ret = sdap_attrs_get_sid_str(
                tmpctx, opts->idmap_ctx, attrs,
                opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name,
                &sid_str);
        if (ret != EOK) goto done;

        /* Add string representation to the cache for easier
         * debugging
         */
        ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str);
        if (ret != EOK) goto done;

        /* Convert the SID into a UNIX user ID */
        ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid);
        if (ret == ENOTSUP) {
            DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n"));
            ret = EOK;
            goto done;
        } else if (ret != EOK) {
            goto done;
        }

        /* Store the UID in the ldap_attrs so it doesn't get
         * treated as a missing attribute from LDAP and removed.
         */
        ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped UID\n"));
            goto done;
        }
    } else {
        ret = sysdb_attrs_get_uint32_t(attrs,
                                       opts->user_map[SDAP_AT_USER_UID].sys_name,
                                       &uid);
        if (ret != EOK) {
            DEBUG(1, ("no uid provided for [%s] in domain [%s].\n",
                      name, dom->name));
            ret = EINVAL;
            goto done;
        }
    }
    /* check that the uid is valid for this domain */
    if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
            DEBUG(2, ("User [%s] filtered out! (uid out of range)\n",
                      name));
        ret = EINVAL;
        goto done;
    }

    if (use_id_mapping) {
        ret = sysdb_attrs_get_uint32_t(
                attrs,
                opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name,
                &primary_gid);
        if (ret != EOK) {
            DEBUG(SSSDBG_MINOR_FAILURE,
                  ("no primary group ID provided for [%s] in domain [%s].\n",
                   name, dom->name));
            ret = EINVAL;
            goto done;
        }

        /* The primary group ID is just the RID part of the objectSID
         * of the group. Generate the GID by adding this to the domain
         * SID value.
         */

        /* First, get the domain SID if we didn't do so above */
        if (!dom_sid_str) {
            ret = sdap_idmap_get_dom_sid_from_object(tmpctx, sid_str,
                                                     &dom_sid_str);
            if (ret != EOK) {
                DEBUG(SSSDBG_MINOR_FAILURE,
                      ("Could not parse domain SID from [%s]\n", sid_str));
                goto done;
            }
        }

        /* Add the RID to the end */
        group_sid_str = talloc_asprintf(tmpctx, "%s-%lu",
                                        dom_sid_str,
                                        (unsigned long)primary_gid);
        if (!group_sid_str) {
            ret = ENOMEM;
            goto done;
        }

        /* Convert the SID into a UNIX group ID */
        ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, group_sid_str, &gid);
        if (ret != EOK) goto done;

        /* Store the GID in the ldap_attrs so it doesn't get
         * treated as a missing attribute from LDAP and removed.
         */
        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
        if (ret != EOK) goto done;
    } else {
        ret = sysdb_attrs_get_uint32_t(attrs,
                                       opts->user_map[SDAP_AT_USER_GID].sys_name,
                                       &gid);
        if (ret != EOK) {
            DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
                      name, dom->name));
            ret = EINVAL;
            goto done;
        }
    }

    /* check that the gid is valid for this domain */
    if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
            DEBUG(2, ("User [%s] filtered out! (primary gid out of range)\n",
                      name));
        ret = EINVAL;
        goto done;
    }

    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
    if (ret) {
        goto done;
    }
    if (!el || el->num_values == 0) {
        DEBUG(SSSDBG_MINOR_FAILURE,
              ("originalDN is not available for [%s].\n", name));
    } else {
        orig_dn = (const char *) el->values[0].data;
        DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding originalDN [%s] to attributes "
                "of [%s].\n", orig_dn, name));

        ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn);
        if (ret) {
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("Original memberOf is not available for [%s].\n",
                    name));
    } else {
        DEBUG(7, ("Adding original memberOf attributes to [%s].\n",
                    name));
        for (i = 0; i < el->num_values; i++) {
            ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
                    (const char *) el->values[i].data);
            if (ret) {
                goto done;
            }
        }
    }

    ret = sdap_attrs_add_string(attrs,
                            opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name,
                            "original mod-Timestamp",
                            name, user_attrs);
    if (ret != EOK) {
        goto done;
    }

    ret = sysdb_attrs_get_el(attrs,
                      opts->user_map[SDAP_AT_USER_USN].sys_name, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("Original USN value is not available for [%s].\n",
                  name));
    } else {
        ret = sysdb_attrs_add_string(user_attrs,
                          opts->user_map[SDAP_AT_USER_USN].sys_name,
                          (const char*)el->values[0].data);
        if (ret) {
            goto done;
        }
        usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
        if (!usn_value) {
            ret = ENOMEM;
            goto done;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                             opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el);
    if (ret) {
        goto done;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("User principal is not available for [%s].\n", name));
    } else {
        upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
        if (!upn) {
            ret = ENOMEM;
            goto done;
        }
        if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
            make_realm_upper_case(upn);
        }
        DEBUG(7, ("Adding user principal [%s] to attributes of [%s].\n",
                  upn, name));
        ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
        if (ret) {
            goto done;
        }
    }

    for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) {
        ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name,
                                  NULL, name, user_attrs);
        if (ret) {
            goto done;
        }
    }

    cache_timeout = dom->user_timeout;

    if (is_initgr) {
        ret = sysdb_attrs_add_time_t(user_attrs, SYSDB_INITGR_EXPIRE,
                                     (cache_timeout ?
                                      (time(NULL) + cache_timeout) : 0));
        if (ret) {
            goto done;
        }
    }

    ret = sdap_save_all_names(name, attrs, !dom->case_sensitive, user_attrs);
    if (ret != EOK) {
        DEBUG(1, ("Failed to save user names\n"));
        goto done;
    }

    /* Make sure that any attributes we requested from LDAP that we
     * did not receive are also removed from the sysdb
     */
    ret = list_missing_attrs(user_attrs, opts->user_map, SDAP_OPTS_USER,
                             attrs, &missing);
    if (ret != EOK) {
        goto done;
    }

    DEBUG(6, ("Storing info for user %s\n", name));

    ret = sysdb_store_user(ctx, dom, name, pwd, uid, gid,
                           gecos, homedir, shell, orig_dn,
                           user_attrs, missing, cache_timeout, now);
    if (ret) goto done;

    if (_usn_value) {
        *_usn_value = talloc_steal(memctx, usn_value);
    }

    talloc_steal(memctx, user_attrs);
    ret = EOK;

done:
    if (ret) {
        DEBUG(2, ("Failed to save user [%s]\n",
                  name ? name : "Unknown"));
    }
    talloc_free(tmpctx);
    return ret;
}
Example #10
0
static void test_sysdb_handle_original_uuid(void **state)
{
    int ret;
    struct sysdb_attrs *src_attrs;
    struct sysdb_attrs *dest_attrs;
    const char *guid;
    uint8_t bin_guid[] = AD_GUID_BIN;
    struct ldb_val guid_val = {bin_guid, 16};

    ret = sysdb_handle_original_uuid(NULL, NULL, NULL, NULL, NULL);
    assert_int_equal(ret, ENOENT);

    src_attrs = sysdb_new_attrs(NULL);
    assert_non_null(src_attrs);

    dest_attrs = sysdb_new_attrs(NULL);
    assert_non_null(dest_attrs);

    ret = sysdb_handle_original_uuid("xyz", src_attrs, "abc", dest_attrs,
                                     "def");
    assert_int_equal(ret, ENOENT);

    ret = sysdb_attrs_add_val(src_attrs, "GUID", &guid_val);
    assert_int_equal(ret, EOK);

    ret = sysdb_attrs_add_string(src_attrs, "UUID", IPA_UUID);
    assert_int_equal(ret, EOK);

    ret = sysdb_handle_original_uuid(NULL, src_attrs, "GUID",
                                     dest_attrs, "def");
    assert_int_equal(ret, ENOENT);

    ret = sysdb_handle_original_uuid("objectGUID", NULL, "GUID",
                                     dest_attrs, "def");
    assert_int_equal(ret, EINVAL);

    ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID",
                                     dest_attrs, "def");
    assert_int_equal(ret, EOK);
    ret = sysdb_attrs_get_string(dest_attrs, "def", &guid);
    assert_int_equal(ret, EOK);
    assert_string_equal(guid, AD_GUID);

    ret = sysdb_handle_original_uuid("ipaUniqueID", src_attrs, "UUID",
                                     dest_attrs, "ghi");
    assert_int_equal(ret, EOK);
    ret = sysdb_attrs_get_string(dest_attrs, "ghi", &guid);
    assert_int_equal(ret, EOK);
    assert_string_equal(guid, IPA_UUID);

    talloc_free(src_attrs);
    src_attrs = sysdb_new_attrs(NULL);
    assert_non_null(src_attrs);

    /* check objectGUID with length other than 16 */
    ret = sysdb_attrs_add_string(src_attrs, "GUID", IPA_UUID);
    assert_int_equal(ret, EOK);
    ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID",
                                     dest_attrs, "jkl");
    assert_int_equal(ret, EOK);
    ret = sysdb_attrs_get_string(dest_attrs, "jkl", &guid);
    assert_int_equal(ret, EOK);
    assert_string_equal(guid, IPA_UUID);

    talloc_free(src_attrs);
    talloc_free(dest_attrs);
}
static errno_t add_ad_user_to_cached_groups(struct ldb_dn *user_dn,
                                            struct sss_domain_info *user_dom,
                                            struct sss_domain_info *group_dom,
                                            char **groups,
                                            bool *missing_groups)
{
    size_t c;
    struct sysdb_attrs *user_attrs;
    size_t msgs_count;
    struct ldb_message **msgs;
    char *subfilter;
    TALLOC_CTX *tmp_ctx;
    int ret;

    *missing_groups = false;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
        return ENOMEM;
    }

    for (c = 0; groups[c] != NULL; c++) {
        if (groups[c][0] == '\0') {
            continue;
        }

        subfilter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_ORIG_DN, groups[c]);
        if (subfilter == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_search_groups(tmp_ctx, group_dom, subfilter, NULL,
                                  &msgs_count, &msgs);
        if (ret != EOK) {
            if (ret == ENOENT) {
                DEBUG(SSSDBG_TRACE_ALL, "Group [%s] not in the cache.\n",
                                         groups[c]);
                *missing_groups = true;
                continue;
            } else {
                DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
                goto done;
            }
        }

/* TODO? Do we have to remove members as well? I think not because the AD
 * query before removes all memberships. */

        ret = sysdb_mod_group_member(group_dom, user_dn, msgs[0]->dn,
                                     LDB_FLAG_MOD_ADD);
        if (ret != EOK && ret != EEXIST) {
            DEBUG(SSSDBG_OP_FAILURE, "sysdb_mod_group_member failed.\n");
            goto done;
        }

        user_attrs = sysdb_new_attrs(tmp_ctx);
        if (user_attrs == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
                                     groups[c]);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
            goto done;
        }

        ret = sysdb_set_entry_attr(user_dom->sysdb, user_dn, user_attrs,
                                   LDB_FLAG_MOD_ADD);
        if (ret != EOK && ret != EEXIST) {
            DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
            goto done;
        }

        /* mark group as already processed */
        groups[c][0] = '\0';
    }

    ret = EOK;
done:
    talloc_free(tmp_ctx);

    return ret;
}
Example #12
0
int sdap_parse_entry(TALLOC_CTX *memctx,
                     struct sdap_handle *sh, struct sdap_msg *sm,
                     struct sdap_attr_map *map, int attrs_num,
                     struct sysdb_attrs **_attrs, char **_dn,
                     bool disable_range_retrieval)
{
    struct sysdb_attrs *attrs;
    BerElement *ber = NULL;
    struct berval **vals;
    struct ldb_val v;
    char *str;
    int lerrno;
    int a, i, ret;
    const char *name;
    bool store;
    bool base64;
    char *base_attr;
    char *dn = NULL;
    uint32_t range_offset;
    TALLOC_CTX *tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) return ENOMEM;

    lerrno = 0;
    ret = ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
    if (ret != LDAP_OPT_SUCCESS) {
        DEBUG(1, ("ldap_set_option failed [%s], ignored.\n",
                  sss_ldap_err2string(ret)));
    }

    attrs = sysdb_new_attrs(tmp_ctx);
    if (!attrs) {
        ret = ENOMEM;
        goto done;
    }

    str = ldap_get_dn(sh->ldap, sm->msg);
    if (!str) {
        ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
        DEBUG(1, ("ldap_get_dn failed: %d(%s)\n",
                  lerrno, sss_ldap_err2string(lerrno)));
        ret = EIO;
        goto done;
    }

    DEBUG(9, ("OriginalDN: [%s].\n", str));
    ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str);
    if (ret) goto done;
    if (_dn) {
        dn = talloc_strdup(tmp_ctx, str);
        if (!dn) {
            ret = ENOMEM;
            ldap_memfree(str);
            goto done;
        }
    }
    ldap_memfree(str);

    if (map) {
        vals = ldap_get_values_len(sh->ldap, sm->msg, "objectClass");
        if (!vals) {
            DEBUG(1, ("Unknown entry type, no objectClasses found!\n"));
            ret = EINVAL;
            goto done;
        }

        for (i = 0; vals[i]; i++) {
            /* the objectclass is always the first name in the map */
            if (strncasecmp(map[0].name,
                            vals[i]->bv_val, vals[i]->bv_len) == 0) {
                /* ok it's an entry of the right type */
                break;
            }
        }
        if (!vals[i]) {
            DEBUG(1, ("objectClass not matching: %s\n",
                      map[0].name));
            ldap_value_free_len(vals);
            ret = EINVAL;
            goto done;
        }
        ldap_value_free_len(vals);
    }

    str = ldap_first_attribute(sh->ldap, sm->msg, &ber);
    if (!str) {
        ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
        DEBUG(lerrno == LDAP_SUCCESS
              ? SSSDBG_TRACE_INTERNAL
              : SSSDBG_MINOR_FAILURE,
              ("Entry has no attributes [%d(%s)]!?\n",
               lerrno, sss_ldap_err2string(lerrno)));
        if (map) {
            ret = EINVAL;
            goto done;
        }
    }
    while (str) {
        base64 = false;

        ret = sdap_parse_range(tmp_ctx, str, &base_attr, &range_offset,
                               disable_range_retrieval);
        switch(ret) {
        case EAGAIN:
            /* This attribute contained range values and needs more to
             * be retrieved
             */
            /* TODO: return the set of attributes that need additional retrieval
             * For now, we'll continue below and treat it as regular values.
             */
            /* FALLTHROUGH */
        case ECANCELED:
            /* FALLTHROUGH */
        case EOK:
            break;
        default:
            DEBUG(SSSDBG_MINOR_FAILURE,
                  ("Could not determine if attribute [%s] was ranged\n", str));
            goto done;
        }

        if (map) {
            for (a = 1; a < attrs_num; a++) {
                /* check if this attr is valid with the chosen schema */
                if (!map[a].name) continue;
                /* check if it is an attr we are interested in */
                if (strcasecmp(base_attr, map[a].name) == 0) break;
            }
            /* interesting attr */
            if (a < attrs_num) {
                store = true;
                name = map[a].sys_name;
                if (strcmp(name, SYSDB_SSH_PUBKEY) == 0) {
                    base64 = true;
                }
            } else {
                store = false;
                name = NULL;
            }
        } else {
            name = base_attr;
            store = true;
        }

        if (ret == ECANCELED) {
            ret = EOK;
            store = false;
        }

        if (store) {
            vals = ldap_get_values_len(sh->ldap, sm->msg, str);
            if (!vals) {
                ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
                if (lerrno != LDAP_SUCCESS) {
                    DEBUG(1, ("LDAP Library error: %d(%s)",
                              lerrno, sss_ldap_err2string(lerrno)));
                    ret = EIO;
                    goto done;
                }

                DEBUG(5, ("Attribute [%s] has no values, skipping.\n", str));

            } else {
                if (!vals[0]) {
                    DEBUG(1, ("Missing value after ldap_get_values() ??\n"));
                    ret = EINVAL;
                    goto done;
                }
                for (i = 0; vals[i]; i++) {
                    if (vals[i]->bv_len == 0) {
                        DEBUG(SSSDBG_MINOR_FAILURE,
                              ("Value of attribute [%s] is empty. "
                               "Skipping this value.\n", str));
                        continue;
                    }
                    if (base64) {
                        v.data = (uint8_t *)sss_base64_encode(attrs,
                                (uint8_t *)vals[i]->bv_val, vals[i]->bv_len);
                        if (!v.data) {
                            ret = ENOMEM;
                            goto done;
                        }
                        v.length = strlen((const char *)v.data);
                    } else {
                        v.data = (uint8_t *)vals[i]->bv_val;
                        v.length = vals[i]->bv_len;
                    }

                    ret = sysdb_attrs_add_val(attrs, name, &v);
                    if (ret) goto done;
                }
                ldap_value_free_len(vals);
            }
        }

        ldap_memfree(str);
        str = ldap_next_attribute(sh->ldap, sm->msg, ber);
    }
    ber_free(ber, 0);
    ber = NULL;

    ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
    if (lerrno) {
        DEBUG(1, ("LDAP Library error: %d(%s)",
                  lerrno, sss_ldap_err2string(lerrno)));
        ret = EIO;
        goto done;
    }

    *_attrs = talloc_steal(memctx, attrs);
    if (_dn) *_dn = talloc_steal(memctx, dn);
    ret = EOK;

done:
    if (ber) ber_free(ber, 0);
    talloc_free(tmp_ctx);
    return ret;
}
Example #13
0
/* Parses an LDAPDerefRes into sdap_deref_attrs structure */
errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx,
                         struct sdap_attr_map_info *minfo,
                         size_t num_maps,
                         LDAPDerefRes *dref,
                         struct sdap_deref_attrs ***_res)
{
    TALLOC_CTX *tmp_ctx;
    LDAPDerefVal *dval;
    const char *orig_dn;
    const char **ocs;
    struct sdap_attr_map *map;
    int num_attrs;
    int ret, i, a, mi;
    const char *name;
    size_t len;
    struct sdap_deref_attrs **res;

    if (!dref || !minfo) return EINVAL;

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) return ENOMEM;

    res = talloc_array(tmp_ctx, struct sdap_deref_attrs *, num_maps);
    if (!res) {
        ret = ENOMEM;
        goto done;
    }

    for (i=0; i < num_maps; i++) {
        res[i] = talloc_zero(res, struct sdap_deref_attrs);
        if (!res[i]) {
            ret = ENOMEM;
            goto done;
        }

        res[i]->map = minfo[i].map;
    }

    if (!dref->derefVal.bv_val) {
        DEBUG(2, ("Entry has no DN?\n"));
        ret = EINVAL;
        goto done;
    }

    orig_dn = dref->derefVal.bv_val;
    DEBUG(SSSDBG_TRACE_LIBS,
          ("Dereferenced DN: %s\n", orig_dn));

    if (!dref->attrVals) {
        DEBUG(SSSDBG_MINOR_FAILURE,
              ("Dereferenced entry [%s] has no attributes\n",
              orig_dn));
        ret = EINVAL;
        goto done;
    }

    ocs = NULL;
    for (dval = dref->attrVals; dval != NULL; dval = dval->next) {
        if (strcasecmp("objectClass", dval->type) == 0) {
            if (dval->vals == NULL) {
                DEBUG(4, ("No value for objectClass, skipping\n"));
                continue;
            }

            for(len=0; dval->vals[len].bv_val; len++);

            ocs = talloc_array(tmp_ctx, const char *, len+1);
            if (!ocs) {
                ret = ENOMEM;
                goto done;
            }

            for (i=0; i<len; i++) {
                DEBUG(9, ("Dereferenced objectClass value: %s\n",
                          dval->vals[i].bv_val));
                ocs[i] = talloc_strdup(ocs, dval->vals[i].bv_val);
                if (!ocs[i]) {
                    ret = ENOMEM;
                    goto done;
                }
            }
            ocs[i] = NULL;
            break;
        }
    }
    if (!ocs) {
        DEBUG(1, ("Unknown entry type, no objectClasses found!\n"));
        ret = EINVAL;
        goto done;
    }

    for (mi = 0; mi < num_maps; mi++) {
        map = NULL;

        for (i=0; ocs[i]; i++) {
            /* the objectclass is always the first name in the map */
            if (strcasecmp(minfo[mi].map[0].name, ocs[i]) == 0) {
                DEBUG(9, ("Found map for objectclass '%s'\n", ocs[i]));
                map = minfo[mi].map;
                num_attrs = minfo[mi].num_attrs;
                break;
            }
        }
        if (!map) continue;

        res[mi]->attrs = sysdb_new_attrs(res[mi]);
        if (!res[mi]->attrs) {
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_add_string(res[mi]->attrs, SYSDB_ORIG_DN,
                                     orig_dn);
        if (ret) {
            goto done;
        }

        for (dval = dref->attrVals; dval != NULL; dval = dval->next) {
            DEBUG(8, ("Dereferenced attribute: %s\n", dval->type));

            for (a = 1; a < num_attrs; a++) {
                /* check if this attr is valid with the chosen schema */
                if (!map[a].name) continue;
                /* check if it is an attr we are interested in */
                if (strcasecmp(dval->type, map[a].name) == 0) break;
            }

            /* interesting attr */
            if (a < num_attrs) {
                name = map[a].sys_name;
            } else {
                continue;
            }

            if (dval->vals == NULL) {
                DEBUG(4, ("No value for attribute %s, skipping\n", name));
                continue;
            }

            for (i=0; dval->vals[i].bv_val; i++) {
                DEBUG(9, ("Dereferenced attribute value: %s\n",
                          dval->vals[i].bv_val));
                ret = sysdb_attrs_add_mem(res[mi]->attrs, name,
                                          dval->vals[i].bv_val,
                                          dval->vals[i].bv_len);
                if (ret) goto done;
            }
        }
    }


    *_res = talloc_steal(mem_ctx, res);
    ret = EOK;
done:
    talloc_zfree(tmp_ctx);
    return ret;
}
Example #14
0
static int usermod_build_attrs(TALLOC_CTX *mem_ctx,
                               const char *gecos,
                               const char *home,
                               const char *shell,
                               uid_t uid,
                               gid_t gid,
                               int lock,
                               struct sysdb_attrs **_attrs)
{
    int ret = EOK;
    struct sysdb_attrs *attrs;
    const char *attr_name = NULL;

    attrs = sysdb_new_attrs(mem_ctx);
    if (attrs == NULL) {
        return ENOMEM;
    }

    if (shell) {
        attr_name = SYSDB_SHELL;
        ret = sysdb_attrs_add_string(attrs,
                                     attr_name,
                                     shell);
    }

    if (ret == EOK && home) {
        attr_name = SYSDB_HOMEDIR;
        ret = sysdb_attrs_add_string(attrs,
                                     attr_name,
                                     home);
    }

    if (ret == EOK && gecos) {
        attr_name = SYSDB_GECOS;
        ret = sysdb_attrs_add_string(attrs,
                                     attr_name,
                                     gecos);
    }

    if (ret == EOK && uid) {
        attr_name = SYSDB_UIDNUM;
        ret = sysdb_attrs_add_long(attrs,
                                   attr_name,
                                   uid);
    }

    if (ret == EOK && gid) {
        attr_name = SYSDB_GIDNUM;
        ret = sysdb_attrs_add_long(attrs,
                                   attr_name,
                                   gid);
    }

    if (ret == EOK && lock == DO_LOCK) {
        attr_name = SYSDB_DISABLED;
        ret = sysdb_attrs_add_string(attrs,
                                     attr_name,
                                     "true");
    }

    if (ret == EOK && lock == DO_UNLOCK) {
        attr_name = SYSDB_DISABLED;
        /* PAM code checks for 'false' value in SYSDB_DISABLED attribute */
        ret = sysdb_attrs_add_string(attrs,
                                     attr_name,
                                     "false");
    }

    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Could not add attribute [%s] to changeset.\n", attr_name);
        return ret;
    }

    *_attrs = attrs;
    return EOK;
}
Example #15
0
static int save_user(struct sysdb_ctx *sysdb, struct sss_domain_info *domain,
                     bool lowercase, struct passwd *pwd, const char *real_name,
                     const char *alias, uint64_t cache_timeout)
{
    const char *shell;
    char *lower;
    struct sysdb_attrs *attrs = NULL;
    errno_t ret;
    const char *cased_alias;

    if (pwd->pw_shell && pwd->pw_shell[0] != '\0') {
        shell = pwd->pw_shell;
    } else {
        shell = NULL;
    }

    if (lowercase || alias) {
        attrs = sysdb_new_attrs(NULL);
        if (!attrs) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation error ?!\n"));
            return ENOMEM;
        }
    }

    if (lowercase) {
        lower = sss_tc_utf8_str_tolower(attrs, pwd->pw_name);
        if (!lower) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
            talloc_zfree(attrs);
            return ENOMEM;
        }

        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
            talloc_zfree(attrs);
            return ret;
        }
    }

    if (alias) {
        cased_alias = sss_get_cased_name(attrs, alias, !lowercase);
        if (!cased_alias) {
            talloc_zfree(attrs);
            return ENOMEM;
        }

        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
            talloc_zfree(attrs);
            return ret;
        }
    }

    ret = sysdb_store_user(sysdb, domain,
                           real_name,
                           pwd->pw_passwd,
                           pwd->pw_uid,
                           pwd->pw_gid,
                           pwd->pw_gecos,
                           pwd->pw_dir,
                           shell,
                           NULL,
                           attrs,
                           NULL,
                           cache_timeout,
                           0);
    talloc_zfree(attrs);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not add user to cache\n"));
        return ret;
    }

    return EOK;
}
Example #16
0
static int usermod_build_attrs(TALLOC_CTX *mem_ctx,
                               const char *gecos,
                               const char *home,
                               const char *shell,
                               uid_t uid,
                               gid_t gid,
                               int lock,
                               struct sysdb_attrs **_attrs)
{
    int ret;
    struct sysdb_attrs *attrs;

    attrs = sysdb_new_attrs(mem_ctx);
    if (attrs == NULL) {
        return ENOMEM;
    }

    if (shell) {
        ret = sysdb_attrs_add_string(attrs,
                                     SYSDB_SHELL,
                                     shell);
        VAR_CHECK(ret, EOK, SYSDB_SHELL,
                  "Could not add attribute to changeset\n");
    }

    if (home) {
        ret = sysdb_attrs_add_string(attrs,
                                     SYSDB_HOMEDIR,
                                     home);
        VAR_CHECK(ret, EOK, SYSDB_HOMEDIR,
                  "Could not add attribute to changeset\n");
    }

    if (gecos) {
        ret = sysdb_attrs_add_string(attrs,
                                     SYSDB_GECOS,
                                     gecos);
        VAR_CHECK(ret, EOK, SYSDB_GECOS,
                  "Could not add attribute to changeset\n");
    }

    if (uid) {
        ret = sysdb_attrs_add_long(attrs,
                                   SYSDB_UIDNUM,
                                   uid);
        VAR_CHECK(ret, EOK, SYSDB_UIDNUM,
                  "Could not add attribute to changeset\n");
    }

    if (gid) {
        ret = sysdb_attrs_add_long(attrs,
                                   SYSDB_GIDNUM,
                                   gid);
        VAR_CHECK(ret, EOK, SYSDB_GIDNUM,
                  "Could not add attribute to changeset\n");
    }

    if (lock == DO_LOCK) {
        ret = sysdb_attrs_add_string(attrs,
                                     SYSDB_DISABLED,
                                     "true");
        VAR_CHECK(ret, EOK, SYSDB_DISABLED,
                  "Could not add attribute to changeset\n");
    }

    if (lock == DO_UNLOCK) {
        /* PAM code checks for 'false' value in SYSDB_DISABLED attribute */
        ret = sysdb_attrs_add_string(attrs,
                                     SYSDB_DISABLED,
                                     "false");
        VAR_CHECK(ret, EOK, SYSDB_DISABLED,
                  "Could not add attribute to changeset\n");
    }

    *_attrs = attrs;
    return EOK;
}
Example #17
0
static errno_t sdap_save_netgroup(TALLOC_CTX *memctx,
                                  struct sysdb_ctx *ctx,
                                  struct sdap_options *opts,
                                  struct sss_domain_info *dom,
                                  struct sysdb_attrs *attrs,
                                  char **_timestamp)
{
    struct ldb_message_element *el;
    struct sysdb_attrs *netgroup_attrs;
    const char *name = NULL;
    int ret;
    char *timestamp = NULL;
    size_t c;

    ret = sysdb_attrs_get_el(attrs,
                             opts->netgroup_map[SDAP_AT_NETGROUP_NAME].sys_name,
                             &el);
    if (ret) goto fail;
    if (el->num_values == 0) {
        ret = EINVAL;
        goto fail;
    }
    name = (const char *)el->values[0].data;

    netgroup_attrs = sysdb_new_attrs(memctx);
    if (!netgroup_attrs) {
        ret = ENOMEM;
        goto fail;
    }

    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
    if (ret) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("Original DN is not available for [%s].\n", name));
    } else {
        DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n",
                  el->values[0].data, name));
        ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_ORIG_DN,
                                     (const char *)el->values[0].data);
        if (ret) {
            goto fail;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                         opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
                         &el);
    if (ret) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n",
                  name));
    } else {
        ret = sysdb_attrs_add_string(netgroup_attrs,
                         opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
                         (const char*)el->values[0].data);
        if (ret) {
            goto fail;
        }
        timestamp = talloc_strdup(memctx, (const char*)el->values[0].data);
        if (!timestamp) {
            ret = ENOMEM;
            goto fail;
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                           opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name,
                           &el);
    if (ret) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("No netgroup triples for netgroup [%s].\n", name));
    } else {
        for(c = 0; c < el->num_values; c++) {
            ret = sysdb_attrs_add_string(netgroup_attrs,
                           opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name,
                            (const char*)el->values[c].data);
            if (ret) {
                goto fail;
            }
        }
    }

    ret = sysdb_attrs_get_el(attrs,
                       opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name,
                       &el);
    if (ret != EOK) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("No original members for netgroup [%s]\n", name));

    } else {
        DEBUG(7, ("Adding original members to netgroup [%s]\n", name));
        for(c = 0; c < el->num_values; c++) {
            ret = sysdb_attrs_add_string(netgroup_attrs,
                       opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name,
                       (const char*)el->values[c].data);
            if (ret) {
                goto fail;
            }
        }
    }


    ret = sysdb_attrs_get_el(attrs, SYSDB_NETGROUP_MEMBER, &el);
    if (ret != EOK) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("No members for netgroup [%s]\n", name));

    } else {
        DEBUG(7, ("Adding members to netgroup [%s]\n", name));
        for(c = 0; c < el->num_values; c++) {
            ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_NETGROUP_MEMBER,
                                         (const char*)el->values[c].data);
            if (ret) {
                goto fail;
            }
        }
    }

    DEBUG(6, ("Storing info for netgroup %s\n", name));

    ret = sysdb_add_netgroup(ctx, name, NULL, netgroup_attrs,
                             dp_opt_get_int(opts->basic,
                                            SDAP_ENTRY_CACHE_TIMEOUT));
    if (ret) goto fail;

    if (_timestamp) {
        *_timestamp = timestamp;
    }

    return EOK;

fail:
    DEBUG(2, ("Failed to save netgroup %s\n", name));
    return ret;
}
Example #18
0
errno_t
sdap_save_all_names(const char *name,
                    struct sysdb_attrs *ldap_attrs,
                    struct sss_domain_info *dom,
                    enum sysdb_member_type entry_type,
                    struct sysdb_attrs *attrs)
{
    const char **aliases = NULL;
    const char *sysdb_alias;
    errno_t ret;
    TALLOC_CTX *tmp_ctx;
    int i;
    bool lowercase = !dom->case_sensitive;
    bool store_as_fqdn;

    switch (entry_type) {
    case SYSDB_MEMBER_USER:
    case SYSDB_MEMBER_GROUP:
        store_as_fqdn = true;
        break;
    default:
        store_as_fqdn = false;
        break;
    }

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_get_aliases(tmp_ctx, ldap_attrs, name,
                                  lowercase, &aliases);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to get the alias list\n");
        goto done;
    }

    for (i = 0; aliases[i]; i++) {
        if (store_as_fqdn) {
            sysdb_alias = sss_create_internal_fqname(tmp_ctx, aliases[i],
                                                 dom->name);
        } else {
            sysdb_alias = aliases[i];
        }

        if (sysdb_alias == NULL) {
            ret = ENOMEM;
            goto done;
        }

        if (lowercase) {
            ret = sysdb_attrs_add_lc_name_alias(attrs, sysdb_alias);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Failed to add lower-cased version "
                                          "of alias [%s] into the "
                                          "attribute list\n", aliases[i]);
                goto done;
            }
        } else {
            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, sysdb_alias);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Failed to add alias [%s] into the "
                                          "attribute list\n", aliases[i]);
                goto done;
            }
        }

    }

    ret = EOK;
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #19
0
errno_t
sysdb_store_ssh_host(struct sysdb_ctx *sysdb,
                     struct sss_domain_info *domain,
                     const char *name,
                     const char *alias,
                     time_t now,
                     struct sysdb_attrs *attrs)
{
    TALLOC_CTX *tmp_ctx;
    errno_t ret, sret;
    bool in_transaction = false;
    const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL };
    bool new_alias;
    struct ldb_message *host = NULL;
    struct ldb_message_element *el;
    unsigned int i;

    DEBUG(SSSDBG_TRACE_FUNC, ("Storing host %s\n", name));

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    ret = sysdb_transaction_start(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
        goto done;
    }

    in_transaction = true;

    ret = sysdb_get_ssh_host(tmp_ctx, sysdb, domain, name, search_attrs, &host);
    if (ret != EOK && ret != ENOENT) {
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SSH_HOST_OC);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              ("Could not set object class [%d]: %s\n", ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              ("Could not set name attribute [%d]: %s\n", ret, strerror(ret)));
        goto done;
    }

    if (alias) {
        new_alias = true;

        /* copy aliases from the existing entry */
        if (host) {
            el = ldb_msg_find_element(host, SYSDB_NAME_ALIAS);

            if (el) {
                for (i = 0; i < el->num_values; i++) {
                    if (strcmp((char *)el->values[i].data, alias) == 0) {
                        new_alias = false;
                    }

                    ret = sysdb_attrs_add_val(attrs,
                                              SYSDB_NAME_ALIAS, &el->values[i]);
                    if (ret != EOK) {
                        DEBUG(SSSDBG_OP_FAILURE,
                              ("Could not add name alias %s [%d]: %s\n",
                               el->values[i].data, ret, strerror(ret)));
                        goto done;
                    }
                }
            }
        }

        /* add alias only if it is not already present */
        if (new_alias) {
            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias);
            if (ret != EOK) {
                DEBUG(SSSDBG_OP_FAILURE,
                      ("Could not add name alias %s [%d]: %s\n",
                       alias, ret, strerror(ret)));
                goto done;
            }
        }
    }

    /* make sure sshPublicKey is present when modifying an existing host */
    if (host) {
        ret = sysdb_attrs_get_el(attrs, SYSDB_SSH_PUBKEY, &el);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  ("Could not get sysdb sshPublicKey [%d]: %s\n",
                   ret, strerror(ret)));
            goto done;
        }
    }

    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              ("Could not set sysdb lastUpdate [%d]: %s\n",
               ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_update_ssh_host(sysdb, domain, name, attrs);
    if (ret != EOK) {
        goto done;
    }

    ret = sysdb_transaction_commit(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
        goto done;
    }

    in_transaction = false;

    ret = EOK;

done:
    if (in_transaction) {
        sret = sysdb_transaction_cancel(sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
        }
    }

    talloc_free(tmp_ctx);

    return ret;
}
Example #20
0
static int krb5_mod_ccname(TALLOC_CTX *mem_ctx,
                           struct sysdb_ctx *sysdb,
                           struct sss_domain_info *domain,
                           const char *name,
                           const char *ccname,
                           int mod_op)
{
    TALLOC_CTX *tmpctx;
    struct sysdb_attrs *attrs;
    int ret;
    errno_t sret;
    bool in_transaction = false;

    if (name == NULL || ccname == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Missing user or ccache name.\n");
        return EINVAL;
    }

    if (mod_op != SYSDB_MOD_REP && mod_op != SYSDB_MOD_DEL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported operation [%d].\n", mod_op);
        return EINVAL;
    }

    DEBUG(SSSDBG_TRACE_ALL, "%s ccname [%s] for user [%s].\n",
              mod_op == SYSDB_MOD_REP ? "Save" : "Delete", ccname, name);

    tmpctx = talloc_new(mem_ctx);
    if (!tmpctx) {
        return ENOMEM;
    }

    attrs = sysdb_new_attrs(tmpctx);
    if (!attrs) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_CCACHE_FILE, ccname);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_add_string failed.\n");
        goto done;
    }

    ret = sysdb_transaction_start(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Error %d starting transaction (%s)\n", ret, strerror(ret));
        goto done;
    }
    in_transaction = true;

    ret = sysdb_set_user_attr(domain, name, attrs, mod_op);
    if (ret != EOK) {
        DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret));
        goto done;
    }

    ret = sysdb_transaction_commit(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction!\n");
        goto done;
    }
    in_transaction = false;

done:
    if (in_transaction) {
        sret = sysdb_transaction_cancel(sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
        }
    }
    talloc_zfree(tmpctx);
    return ret;
}
Example #21
0
errno_t
sysdb_save_autofsentry(struct sysdb_ctx *sysdb_ctx,
                       struct sss_domain_info *domain,
                       const char *map,
                       const char *key,
                       const char *value,
                       struct sysdb_attrs *attrs)
{
    errno_t ret;
    TALLOC_CTX *tmp_ctx;
    struct ldb_message *msg;
    struct ldb_dn *dn;
    const char *name;

    DEBUG(SSSDBG_TRACE_FUNC,
          ("Adding autofs entry [%s] - [%s]\n", key, value));

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    if (!attrs) {
        attrs = sysdb_new_attrs(tmp_ctx);
        if (!attrs) {
            ret = ENOMEM;
            goto done;
        }
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
                                 SYSDB_AUTOFS_ENTRY_OC);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set entry object class [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_AUTOFS_ENTRY_KEY, key);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set entry key [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_AUTOFS_ENTRY_VALUE, value);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set entry key [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    name = talloc_asprintf(tmp_ctx, "%s%s", key, value);
    if (!name) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, ("Could not set name attribute [%d]: %s\n",
              ret, strerror(ret)));
        goto done;
    }

    dn = sysdb_autofsentry_dn(tmp_ctx, sysdb_ctx, domain, map, key, value);
    if (!dn) {
        ret = ENOMEM;
        goto done;
    }

    msg = ldb_msg_new(tmp_ctx);
    if (!msg) {
        ret = ENOMEM;
        goto done;
    }

    msg->dn = dn;
    msg->elements = attrs->a;
    msg->num_elements = attrs->num;

    ret = ldb_add(sysdb_ctx->ldb, msg);
    ret = sysdb_error_to_errno(ret);
done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #22
0
static int
prepare_attrs_for_saving_ops(TALLOC_CTX *mem_ctx,
                             bool case_sensitive,
                             const char *real_name, /* already_qualified */
                             const char *alias, /* already qualified */
                             struct sysdb_attrs **attrs)
{
    const char *lc_name = NULL;
    const char *cased_alias = NULL;
    errno_t ret;

    if (!case_sensitive || alias != NULL) {
        if (*attrs == NULL) {
            *attrs = sysdb_new_attrs(mem_ctx);
            if (*attrs == NULL) {
                DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n");
                ret = ENOMEM;
                goto done;
            }
        }
    }

    if (!case_sensitive) {
        lc_name = sss_tc_utf8_str_tolower(*attrs, real_name);
        if (lc_name == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_add_string(*attrs, SYSDB_NAME_ALIAS, lc_name);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
            ret = ENOMEM;
            goto done;
        }

    }

    if (alias != NULL) {
        cased_alias = sss_get_cased_name(*attrs, alias, case_sensitive);
        if (cased_alias == NULL) {
            ret = ENOMEM;
            goto done;
        }

        /* Add the alias only if it differs from lowercased pw_name */
        if (lc_name == NULL || strcmp(cased_alias, lc_name) != 0) {
            ret = sysdb_attrs_add_string(*attrs, SYSDB_NAME_ALIAS,
                                         cased_alias);
            if (ret != EOK) {
                DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
                goto done;
            }
        }
    }

    ret = EOK;
done:
    return ret;
}
Example #23
0
static int save_user(struct sss_domain_info *domain,
                     bool lowercase, struct passwd *pwd, const char *real_name,
                     const char *alias, uint64_t cache_timeout)
{
    const char *shell;
    const char *gecos;
    struct sysdb_attrs *attrs = NULL;
    errno_t ret;
    const char *cased_alias;
    const char *lc_pw_name = NULL;

    if (pwd->pw_shell && pwd->pw_shell[0] != '\0') {
        shell = pwd->pw_shell;
    } else {
        shell = NULL;
    }

    if (pwd->pw_gecos && pwd->pw_gecos[0] != '\0') {
        gecos = pwd->pw_gecos;
    } else {
        gecos = NULL;
    }

    if (lowercase || alias) {
        attrs = sysdb_new_attrs(NULL);
        if (!attrs) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n");
            ret = ENOMEM;
            goto done;
        }
    }

    if (lowercase) {
        lc_pw_name = sss_tc_utf8_str_tolower(attrs, pwd->pw_name);
        if (lc_pw_name == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_pw_name);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
            ret = ENOMEM;
            goto done;
        }

    }

    if (alias) {
        cased_alias = sss_get_cased_name(attrs, alias, !lowercase);
        if (!cased_alias) {
            ret = ENOMEM;
            goto done;
        }

        /* Add the alias only if it differs from lowercased pw_name */
        if (lc_pw_name == NULL || strcmp(cased_alias, lc_pw_name) != 0) {
            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
                goto done;
            }
        }
    }

    ret = sysdb_store_user(domain,
                           real_name,
                           pwd->pw_passwd,
                           pwd->pw_uid,
                           pwd->pw_gid,
                           gecos,
                           pwd->pw_dir,
                           shell,
                           NULL,
                           attrs,
                           NULL,
                           cache_timeout,
                           0);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, "Could not add user to cache\n");
        goto done;
    }

done:
    talloc_zfree(attrs);
    return ret;
}
Example #24
0
errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
                                         struct sss_domain_info *domain,
                                         const char *user,
                                         const char *upn)
{
    TALLOC_CTX *tmp_ctx;
    int ret;
    int sret;
    const char *attrs[] = {SYSDB_UPN, SYSDB_CANONICAL_UPN, NULL};
    struct sysdb_attrs *new_attrs;
    struct ldb_result *res;
    bool in_transaction = false;
    const char *cached_upn;
    const char *cached_canonical_upn;

    if (sysdb == NULL || user == NULL || upn == NULL) {
        return EINVAL;
    }

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
        return ENOMEM;
    }

    ret = sysdb_get_user_attr(tmp_ctx, domain, user, attrs, &res);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_user_attr failed.\n");
        goto done;
    }

    if (res->count != 1) {
        DEBUG(SSSDBG_OP_FAILURE, "[%d] user objects for name [%s] found, " \
                                  "expected 1.\n", res->count, user);
        ret = EINVAL;
        goto done;
    }

    cached_upn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_UPN, NULL);

    if (cached_upn != NULL && strcmp(cached_upn, upn) == 0) {
        DEBUG(SSSDBG_TRACE_ALL, "Cached UPN and new one match, "
                                 "nothing to do.\n");
        ret = EOK;
        goto done;
    }

    cached_canonical_upn = ldb_msg_find_attr_as_string(res->msgs[0],
                                                       SYSDB_CANONICAL_UPN,
                                                       NULL);

    if (cached_canonical_upn != NULL
            && strcmp(cached_canonical_upn, upn) == 0) {
        DEBUG(SSSDBG_TRACE_ALL, "Cached canonical UPN and new one match, "
                                 "nothing to do.\n");
        ret = EOK;
        goto done;
    }

    DEBUG(SSSDBG_TRACE_LIBS, "Replacing canonical UPN [%s] with [%s] " \
                              "for user [%s].\n",
                              cached_canonical_upn == NULL ?
                                                 "empty" : cached_canonical_upn,
                              upn, user);

    new_attrs = sysdb_new_attrs(tmp_ctx);
    if (new_attrs == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_attrs_add_string(new_attrs, SYSDB_CANONICAL_UPN, upn);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
        goto done;
    }

    ret = sysdb_transaction_start(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              "Error %d starting transaction (%s)\n", ret, strerror(ret));
        goto done;
    }
    in_transaction = true;

    ret = sysdb_set_entry_attr(sysdb, res->msgs[0]->dn, new_attrs,
                               cached_canonical_upn == NULL ? SYSDB_MOD_ADD :
                                                              SYSDB_MOD_REP);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed [%d][%s].\n",
                                  ret, strerror(ret));
        goto done;
    }

    ret = sysdb_transaction_commit(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to commit transaction!\n");
        goto done;
    }
    in_transaction = false;

    ret = EOK;

done:
    if (in_transaction) {
        sret = sysdb_transaction_cancel(sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
        }
    }

    talloc_free(tmp_ctx);

    return ret;
}
Example #25
0
static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
                      struct group *grp, const char *real_name,
                      const char *alias, uint64_t cache_timeout)
{
    errno_t ret, sret;
    struct sysdb_attrs *attrs = NULL;
    const char *cased_alias;
    const char *lc_gr_name = NULL;
    TALLOC_CTX *tmp_ctx;
    time_t now = time(NULL);
    bool in_transaction = false;

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    DEBUG_GR_MEM(SSSDBG_TRACE_LIBS, grp);

    ret = sysdb_transaction_start(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
        goto done;
    }
    in_transaction = true;

    if (grp->gr_mem && grp->gr_mem[0]) {
        attrs = sysdb_new_attrs(tmp_ctx);
        if (!attrs) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_users_from_str_list(
                  attrs, SYSDB_MEMBER, dom->name,
                  (const char *const *)grp->gr_mem);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not add group members\n");
            goto done;
        }

        /* Create ghost users */
        ret = proxy_process_missing_users(sysdb, dom, attrs, grp, now);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not add missing members\n");
            goto done;
        }
    }

    if (dom->case_sensitive == false || alias) {
        if (!attrs) {
            attrs = sysdb_new_attrs(tmp_ctx);
            if (!attrs) {
                DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n");
                ret = ENOMEM;
                goto done;
            }
        }
    }

    if (dom->case_sensitive == false) {
        lc_gr_name = sss_tc_utf8_str_tolower(attrs, grp->gr_name);
        if (lc_gr_name == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
            ret = ENOMEM;
            goto done;
        }

        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_gr_name);
        if (ret != EOK) {
            goto done;
        }
    }

    if (alias) {
        cased_alias = sss_get_cased_name(attrs, alias, dom->case_sensitive);
        if (!cased_alias) {
            ret = ENOMEM;
            DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
            goto done;
        }

        if (lc_gr_name == NULL || strcmp(cased_alias, lc_gr_name)) {
            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
            if (ret) {
                DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
                goto done;
            }
        }
    }

    ret = sysdb_store_group(dom,
                            real_name,
                            grp->gr_gid,
                            attrs,
                            cache_timeout,
                            now);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, "Could not add group to cache\n");
        goto done;
    }

    ret = sysdb_transaction_commit(sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Could not commit transaction: [%s]\n",
              strerror(ret));
        goto done;
    }
    in_transaction = false;

done:
    if (in_transaction) {
        sret = sysdb_transaction_cancel(sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
        }
    }
    talloc_free(tmp_ctx);
    return ret;
}
Example #26
0
static errno_t sudosrv_cached_rules_by_user(TALLOC_CTX *mem_ctx,
                                            struct sss_domain_info *domain,
                                            uid_t cli_uid,
                                            uid_t orig_uid,
                                            const char *username,
                                            char **groupnames,
                                            struct sysdb_attrs ***_rules,
                                            uint32_t *_num_rules)
{
    TALLOC_CTX *tmp_ctx;
    struct sysdb_attrs **rules;
    uint32_t num_rules;
    uint32_t i;
    const char *filter;
    const char *val;
    errno_t ret;
    const char *attrs[] = { SYSDB_OBJECTCLASS,
                            SYSDB_SUDO_CACHE_AT_CN,
                            SYSDB_SUDO_CACHE_AT_HOST,
                            SYSDB_SUDO_CACHE_AT_COMMAND,
                            SYSDB_SUDO_CACHE_AT_OPTION,
                            SYSDB_SUDO_CACHE_AT_RUNAS,
                            SYSDB_SUDO_CACHE_AT_RUNASUSER,
                            SYSDB_SUDO_CACHE_AT_RUNASGROUP,
                            SYSDB_SUDO_CACHE_AT_NOTBEFORE,
                            SYSDB_SUDO_CACHE_AT_NOTAFTER,
                            SYSDB_SUDO_CACHE_AT_ORDER,
                            NULL };

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        return ENOMEM;
    }

    filter = sysdb_sudo_filter_user(tmp_ctx, username, groupnames, orig_uid);
    if (filter == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = sudosrv_query_cache(tmp_ctx, domain, attrs, filter,
                              &rules, &num_rules);
    if (ret != EOK) {
        goto done;
    }

    val = talloc_asprintf(tmp_ctx, "#%"SPRIuid, cli_uid);
    if (val == NULL) {
        ret = ENOMEM;
        goto done;
    }

    /* Add sudoUser: #uid to prevent conflicts with fqnames. */
    DEBUG(SSSDBG_TRACE_FUNC, "Replacing sudoUser attribute with "
          "sudoUser: %s\n", val);
    for (i = 0; i < num_rules; i++) {
        ret = sysdb_attrs_add_string(rules[i], SYSDB_SUDO_CACHE_AT_USER, val);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to alter sudoUser attribute "
                  "[%d]: %s\n", ret, sss_strerror(ret));
        }
    }

    *_rules = talloc_steal(mem_ctx, rules);
    *_num_rules = num_rules;

    ret = EOK;

done:
    talloc_free(tmp_ctx);
    return ret;
}
Example #27
0
static errno_t sdap_save_netgroup(TALLOC_CTX *memctx,
                                  struct sysdb_ctx *ctx,
                                  struct sss_domain_info *dom,
                                  struct sdap_options *opts,
                                  struct sysdb_attrs *attrs,
                                  char **_timestamp,
                                  time_t now)
{
    struct ldb_message_element *el;
    struct sysdb_attrs *netgroup_attrs;
    const char *name = NULL;
    int ret;
    char *timestamp = NULL;
    char **missing = NULL;

    ret = sysdb_attrs_get_el(attrs,
                             opts->netgroup_map[SDAP_AT_NETGROUP_NAME].sys_name,
                             &el);
    if (ret) goto fail;
    if (el->num_values == 0) {
        ret = EINVAL;
        goto fail;
    }
    name = (const char *)el->values[0].data;

    netgroup_attrs = sysdb_new_attrs(memctx);
    if (!netgroup_attrs) {
        ret = ENOMEM;
        goto fail;
    }

    ret = sdap_attrs_add_string(attrs, SYSDB_ORIG_DN,
                                "original DN",
                                name, netgroup_attrs);
    if (ret != EOK) {
        goto fail;
    }

    ret = sysdb_attrs_get_el(attrs,
                         opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
                         &el);
    if (ret) {
        goto fail;
    }
    if (el->num_values == 0) {
        DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n",
                  name));
    } else {
        ret = sysdb_attrs_add_string(netgroup_attrs,
                         opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name,
                         (const char*)el->values[0].data);
        if (ret) {
            goto fail;
        }
        timestamp = talloc_strdup(memctx, (const char*)el->values[0].data);
        if (!timestamp) {
            ret = ENOMEM;
            goto fail;
        }
    }

    ret = sdap_attrs_add_list(attrs,
                        opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name,
                        "netgroup triple",
                        name, netgroup_attrs);
    if (ret != EOK) {
        goto fail;
    }

    ret = sdap_attrs_add_list(attrs,
                        opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name,
                        "original members",
                        name, netgroup_attrs);
    if (ret != EOK) {
        goto fail;
    }

    ret = sdap_attrs_add_list(attrs, SYSDB_NETGROUP_MEMBER,
                        "members", name, netgroup_attrs);
    if (ret != EOK) {
        goto fail;
    }

    DEBUG(6, ("Storing info for netgroup %s\n", name));

    ret = sdap_save_all_names(name, attrs, !dom->case_sensitive,
                              netgroup_attrs);
    if (ret != EOK) {
        DEBUG(1, ("Failed to save netgroup names\n"));
        goto fail;
    }

    /* Make sure that any attributes we requested from LDAP that we
     * did not receive are also removed from the sysdb
     */
    ret = list_missing_attrs(attrs, opts->netgroup_map, SDAP_OPTS_NETGROUP,
                             attrs, &missing);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to list missing attributes\n"));
        goto fail;
    }

    ret = sysdb_add_netgroup(ctx, name, NULL, netgroup_attrs, missing,
                             dom->netgroup_timeout, now);
    if (ret) goto fail;

    if (_timestamp) {
        *_timestamp = timestamp;
    }

    return EOK;

fail:
    DEBUG(2, ("Failed to save netgroup %s\n", name));
    return ret;
}