Beispiel #1
0
/*
 * Public interface for deleting groups
 */
int groupdel(TALLOC_CTX *mem_ctx,
            struct sysdb_ctx *sysdb,
            struct ops_ctx *data)
{
    struct ldb_dn *group_dn;
    int ret;

    data->sysdb_fqname = sss_create_internal_fqname(data,
                                                    data->name,
                                                    data->domain->name);
    if (data->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    group_dn = sysdb_group_dn(mem_ctx, data->domain, data->sysdb_fqname);
    if (group_dn == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct a group DN\n");
        return ENOMEM;
    }

    ret = sysdb_delete_entry(sysdb, group_dn, false);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "Removing group failed: %s (%d)\n", strerror(ret), ret);
    }

    flush_nscd_cache(NSCD_DB_GROUP);

    return ret;
}
Beispiel #2
0
/*
 * Public interface for modifying groups
 */
int groupmod(TALLOC_CTX *mem_ctx,
             struct ops_ctx *data)
{
    struct sysdb_attrs *attrs = NULL;
    struct ldb_dn *member_dn = NULL;
    int ret;

    data->sysdb_fqname = sss_create_internal_fqname(data,
                                                    data->name,
                                                    data->domain->name);
    if (data->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    if (data->addgroups || data->rmgroups) {
        member_dn = sysdb_group_dn(mem_ctx, data->domain, data->sysdb_fqname);
        if (!member_dn) {
            return ENOMEM;
        }
    }

    if (data->gid != 0) {
        attrs = sysdb_new_attrs(mem_ctx);
        if (!attrs) {
            return ENOMEM;
        }
        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, data->gid);
        if (ret) {
            return ret;
        }

        ret = sysdb_set_group_attr(data->domain, data->sysdb_fqname,
                                   attrs, SYSDB_MOD_REP);
        if (ret) {
            return ret;
        }
    }

    if (data->rmgroups != NULL) {
        ret = remove_from_groups(data, member_dn);
        if (ret) {
            return ret;
        }
    }

    if (data->addgroups != NULL) {
        ret = add_to_groups(data, member_dn);
        if (ret) {
            return ret;
        }
    }

    flush_nscd_cache(NSCD_DB_GROUP);

    return EOK;
}
Beispiel #3
0
static int set_group_in_ncache(struct sss_nc_ctx *ctx, bool permanent,
                              struct sss_domain_info *dom, const char *name)
{
    char *fqdn;
    int ret;

    fqdn = sss_create_internal_fqname(ctx, name, dom->name);
    ret = sss_ncache_set_group(ctx, permanent, dom, fqdn);
    talloc_free(fqdn);
    return ret;
}
Beispiel #4
0
static int check_user_in_ncache(struct sss_nc_ctx *ctx,
                                struct sss_domain_info *dom,
                                const char *name)
{
    char *fqdn;
    int ret;

    fqdn = sss_create_internal_fqname(ctx, name, dom->name);
    ret = sss_ncache_check_user(ctx, dom, fqdn);
    talloc_free(fqdn);
    return ret;
}
Beispiel #5
0
static const char *sssctl_create_filter(TALLOC_CTX *mem_ctx,
                                        struct sss_domain_info *dom,
                                        enum cache_object obj_type,
                                        const char *attr_name,
                                        const char *attr_value)
{
    const char *class;
    const char *filter;
    char *filter_value;
    bool qualify_attr = false;

    if (strcmp(attr_name, SYSDB_NAME) == 0) {
        if (obj_type == CACHED_USER || obj_type == CACHED_GROUP) {
            qualify_attr = true;
        }
    }

    switch (obj_type) {
    case CACHED_USER:
        class = SYSDB_USER_CLASS;
        break;
    case CACHED_GROUP:
        class = SYSDB_GROUP_CLASS;
        break;
    case CACHED_NETGROUP:
        class = SYSDB_NETGROUP_CLASS;
        break;
    default:
        DEBUG(SSSDBG_FATAL_FAILURE,
              "sssctl doesn't handle this object type (type=%d)\n", obj_type);
        return NULL;
    }

    if (qualify_attr) {
        filter_value = sss_create_internal_fqname(NULL, attr_value, dom->name);
    } else {
        filter_value = talloc_strdup(NULL, attr_value);
    }
    if (filter_value == NULL) {
        return NULL;
    }

    filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
                             class, attr_name, filter_value);
    talloc_free(filter_value);

    return filter;
}
Beispiel #6
0
static errno_t
cache_req_group_by_name_prepare_domain_data(struct cache_req *cr,
                                            struct cache_req_data *data,
                                            struct sss_domain_info *domain)
{
    TALLOC_CTX *tmp_ctx;
    const char *name;
    errno_t ret;

    if (cr->data->name.name == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n");
        return ERR_INTERNAL;
    }

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

    name = sss_get_cased_name(tmp_ctx, cr->data->name.name,
                              domain->case_sensitive);
    if (name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space);
    if (name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    name = sss_create_internal_fqname(tmp_ctx, name, domain->name);
    if (name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    talloc_zfree(data->name.lookup);
    data->name.lookup = talloc_steal(data, name);

    ret = EOK;

done:
    talloc_free(tmp_ctx);
    return ret;
}
Beispiel #7
0
/*
 * Public interface for adding groups
 */
int groupadd(struct ops_ctx *data)
{
    int ret;

    data->sysdb_fqname = sss_create_internal_fqname(data,
                                                    data->name,
                                                    data->domain->name);
    if (data->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    ret = sysdb_add_group(data->domain, data->sysdb_fqname, data->gid, NULL, 0, 0);
    if (ret == EOK) {
        flush_nscd_cache(NSCD_DB_GROUP);
    }
    return ret;
}
Beispiel #8
0
int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx,
                        const char *name,
                        struct ops_ctx *out)
{
    struct ldb_result *res;
    const char *str;
    int ret;

    out->sysdb_fqname = sss_create_internal_fqname(out, name,
                                                   out->domain->name);
    if (out->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    ret = sysdb_getgrnam(mem_ctx, out->domain, out->sysdb_fqname, &res);
    if (ret) {
        return ret;
    }

    switch (res->count) {
    case 0:
        DEBUG(SSSDBG_CRIT_FAILURE, "No result for sysdb_getgrnam call\n");
        return ENOENT;

    case 1:
        /* fill ops_ctx */
        out->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        ret = sss_parse_internal_fqname(out, str, &out->name, NULL);
        if (ret != EOK) {
            return ENOMEM;
        }

        if (out->name == NULL) {
            return ENOMEM;
        }
        break;

    default:
        DEBUG(SSSDBG_CRIT_FAILURE,
              "More than one result for sysdb_getgrnam call\n");
        return EIO;
    }

    return EOK;
}
Beispiel #9
0
/*
 * Generic modify groups member
 */
static int mod_groups_member(struct sss_domain_info *dom,
                             char **grouplist,
                             struct ldb_dn *member_dn,
                             int optype)
{
    TALLOC_CTX *tmpctx;
    struct ldb_dn *parent_dn;
    int ret;
    int i;
    char *grp_sysdb_fqname = NULL;

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

/* FIXME: add transaction around loop */
    for (i = 0; grouplist[i]; i++) {
        grp_sysdb_fqname = sss_create_internal_fqname(tmpctx, grouplist[i],
                                                      dom->name);
        if (grp_sysdb_fqname == NULL) {
            ret = ENOMEM;
            goto done;
        }

        parent_dn = sysdb_group_dn(tmpctx, dom, grp_sysdb_fqname);
        if (!parent_dn) {
            ret = ENOMEM;
            goto done;
        }

        talloc_free(grp_sysdb_fqname);

        ret = sysdb_mod_group_member(dom, member_dn, parent_dn, optype);
        if (ret) {
            goto done;
        }
    }

    ret = EOK;

done:
    talloc_zfree(tmpctx);
    return ret;
}
Beispiel #10
0
static void create_groups(TALLOC_CTX *mem_ctx,
                          struct sss_domain_info *domain)
{
    errno_t ret;
    char *fqname;

    for (int i = 0; i < 2; i++) {
        fqname = sss_create_internal_fqname(mem_ctx,
                                            groups[i].name,
                                            domain->name);
        assert_non_null(fqname);

        ret = sysdb_add_group(domain, fqname, groups[i].gid,
                              NULL, 30, time(NULL));
        talloc_free(fqname);
        assert_int_equal(ret, EOK);
    }
}
Beispiel #11
0
/*
 * Public interface for adding users
 */
int useradd(TALLOC_CTX *mem_ctx,
            struct ops_ctx *data)
{
    int ret;

    data->sysdb_fqname = sss_create_internal_fqname(data,
                                                    data->name,
                                                    data->domain->name);
    if (data->sysdb_fqname == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = sysdb_add_user(data->domain, data->sysdb_fqname, data->uid, data->gid,
                         data->gecos, data->home, data->shell,
                         NULL, NULL, 0, 0);
    if (ret) {
        goto done;
    }

    if (data->addgroups) {
        struct ldb_dn *member_dn;

        member_dn = sysdb_user_dn(mem_ctx, data->domain, data->sysdb_fqname);
        if (!member_dn) {
            ret = ENOMEM;
            goto done;
        }

        ret = add_to_groups(data, member_dn);
        if (ret) {
            goto done;
        }
    }

    flush_nscd_cache(NSCD_DB_PASSWD);
    flush_nscd_cache(NSCD_DB_GROUP);

done:
    return ret;
}
Beispiel #12
0
static errno_t update_filter(struct cache_tool_ctx *tctx,
                             struct sss_domain_info *dinfo,
                             char *name, bool update, const char *fmt,
                             enum sss_cache_entry entry_type,
                             bool force_case_sensitivity,
                             char **_filter)
{
    errno_t ret;
    char *parsed_domain = NULL;
    char *parsed_name = NULL;
    TALLOC_CTX *tmp_ctx = NULL;
    char *use_name = NULL;
    char *filter;
    char *sanitized;
    char *lc_sanitized;

    if (!name || !update) {
        /* Nothing to do */
        return EOK;
    }

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory.\n");
        return ENOMEM;
    }

    ret = sss_parse_name(tmp_ctx, dinfo->names, name,
                         &parsed_domain, &parsed_name);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_name failed\n");
        goto done;
    }

    if (parsed_domain != NULL && strcasecmp(dinfo->name, parsed_domain) != 0) {
        /* We were able to parse the domain from given fqdn, but it
         * does not match with currently processed domain. */
        filter = NULL;
        ret = EOK;
        goto done;
    }

    if (!dinfo->case_sensitive && !force_case_sensitivity) {
        use_name = sss_tc_utf8_str_tolower(tmp_ctx, parsed_name);
        if (!use_name) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
            ret = ENOMEM;
            goto done;
        }
    } else {
        use_name = parsed_name;
    }

    switch (entry_type) {
        case TYPE_USER:
        case TYPE_GROUP:
            use_name = sss_create_internal_fqname(tmp_ctx, use_name, dinfo->name);
        default:
            break;
    }
    if (!use_name) {
        ret = ENOMEM;
        goto done;
    }

    ret = sss_filter_sanitize_for_dom(tmp_ctx, use_name, dinfo,
                                      &sanitized, &lc_sanitized);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to sanitize the given name.\n");
        goto done;
    }

    if (fmt) {
        if (!dinfo->case_sensitive && !force_case_sensitivity) {
            filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)(%s=%s))",
                                     SYSDB_NAME_ALIAS, lc_sanitized,
                                     SYSDB_NAME_ALIAS, sanitized);
        } else {
            filter = talloc_asprintf(tmp_ctx, fmt, SYSDB_NAME, sanitized);
        }
    } else {
        filter = talloc_strdup(tmp_ctx, sanitized);
    }
    if (filter == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
        ret = ENOMEM;
        goto done;
    }

    ret = EOK;

done:
    if (ret == EOK) {
        talloc_free(*_filter);
        *_filter = talloc_steal(tctx, filter);
    }

    talloc_free(tmp_ctx);
    return ret;

}
Beispiel #13
0
/*
 * Public interface for modifying users
 */
int usermod(TALLOC_CTX *mem_ctx,
            struct ops_ctx *data)
{
    struct sysdb_attrs *attrs = NULL;
    struct ldb_dn *member_dn = NULL;
    int ret;

    data->sysdb_fqname = sss_create_internal_fqname(data,
                                                    data->name,
                                                    data->domain->name);
    if (data->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    if (data->addgroups || data->rmgroups) {
        member_dn = sysdb_user_dn(mem_ctx, data->domain, data->sysdb_fqname);
        if (!member_dn) {
            return ENOMEM;
        }
    }

    ret = usermod_build_attrs(mem_ctx,
                              data->gecos,
                              data->home,
                              data->shell,
                              data->uid,
                              data->gid,
                              data->lock,
                              &attrs);
    if (ret != EOK) {
        return ret;
    }

    if (attrs->num != 0) {
        ret = sysdb_set_user_attr(data->domain, data->sysdb_fqname,
                                  attrs, SYSDB_MOD_REP);
        if (ret) {
            return ret;
        }
    }

    if (data->rmgroups != NULL) {
        ret = remove_from_groups(data, member_dn);
        if (ret) {
            return ret;
        }
    }

    if (data->addgroups != NULL) {
        ret = add_to_groups(data, member_dn);
        if (ret) {
            return ret;
        }
    }

    if (data->addattr) {
        ret = attr_op(data, data->addattr, SYSDB_MOD_ADD);
        if (ret) {
            return ret;
        }
    }

    if (data->setattr) {
        ret = attr_op(data, data->setattr, SYSDB_MOD_REP);
        if (ret) {
            return ret;
        }

    }

    if (data->delattr) {
        ret = attr_op(data, data->delattr, SYSDB_MOD_DEL);
        if (ret) {
            return ret;
        }
    }

    flush_nscd_cache(NSCD_DB_PASSWD);
    flush_nscd_cache(NSCD_DB_GROUP);

    return EOK;
}
Beispiel #14
0
static int get_gr_name(struct proxy_id_ctx *ctx,
                       struct sysdb_ctx *sysdb,
                       struct sss_domain_info *dom,
                       const char *i_name)
{
    TALLOC_CTX *tmpctx;
    struct group *grp;
    enum nss_status status;
    char *buffer = 0;
    size_t buflen = 0;
    bool delete_group = false;
    int ret;
    gid_t gid;
    struct ldb_result *cached_grp = NULL;
    const char *real_name = NULL;
    char *shortname_or_alias;

    DEBUG(SSSDBG_FUNC_DATA, "Searching group by name (%s)\n", i_name);

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

    ret = sss_parse_internal_fqname(tmpctx, i_name, &shortname_or_alias, NULL);
    if (ret != EOK) {
        goto done;
    }

    grp = talloc(tmpctx, struct group);
    if (!grp) {
        ret = ENOMEM;
        DEBUG(SSSDBG_CRIT_FAILURE,
              "proxy -> getgrnam_r failed for '%s': [%d] %s\n",
              i_name, ret, strerror(ret));
        goto done;
    }

    do {
        /* always zero out the grp structure */
        memset(grp, 0, sizeof(struct group));
        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
        if (!buffer) {
            ret = ENOMEM;
            goto done;
        }

        status = ctx->ops.getgrnam_r(shortname_or_alias, grp, buffer,
                                     buflen, &ret);
        ret = handle_getgr_result(status, grp, dom, &delete_group);
    } while (ret == EAGAIN);

    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              "getgrnam failed [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

    if (delete_group) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Group %s does not exist (or is invalid) on remote server,"
               " deleting!\n", i_name);

        ret = sysdb_delete_group(dom, i_name, 0);
        if (ret == ENOENT) {
            ret = EOK;
        }
        goto done;
    }

    gid = grp->gr_gid;

    /* Canonicalize the group name in case it was actually an alias */
    if (ctx->fast_alias == true) {
        ret = sysdb_getgrgid(tmpctx, dom, gid, &cached_grp);
        if (ret != EOK) {
            /* Non-fatal, attempt to canonicalize online */
            DEBUG(SSSDBG_TRACE_FUNC, "Request to cache failed [%d]: %s\n",
                  ret, strerror(ret));
        }

        if (ret == EOK && cached_grp->count == 1) {
            real_name = ldb_msg_find_attr_as_string(cached_grp->msgs[0],
                                                    SYSDB_NAME, NULL);
            if (!real_name) {
                DEBUG(SSSDBG_MINOR_FAILURE, "Cached group has no name?\n");
            }
        }
    }

    if (real_name == NULL) {
        talloc_zfree(buffer);
        buflen = 0;

        do {
            memset(grp, 0, sizeof(struct group));
            buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
            if (!buffer) {
                ret = ENOMEM;
                goto done;
            }

            status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);

            ret = handle_getgr_result(status, grp, dom, &delete_group);
        } while (ret == EAGAIN);

        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                "getgrgid failed [%d]: %s\n", ret, strerror(ret));
            goto done;
        }

        real_name = sss_create_internal_fqname(tmpctx, grp->gr_name, dom->name);
        if (real_name == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "Failed to create fqdn '%s'\n",
                  grp->gr_name);
            ret = ENOMEM;
            goto done;
        }
    }

    if (delete_group) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Group %s does not exist (or is invalid) on remote server,"
               " deleting!\n", i_name);

        ret = sysdb_delete_group(dom, i_name, gid);
        if (ret == ENOENT) {
            ret = EOK;
        }
        goto done;
    }

    ret = save_group(sysdb, dom, grp, real_name, i_name);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "Cannot save group [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

done:
    talloc_zfree(tmpctx);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "proxy -> getgrnam_r failed for '%s' <%d>: %s\n",
              i_name, ret, strerror(ret));
    }
    return ret;
}
Beispiel #15
0
/* =Getgrgid-wrapper======================================================*/
static int get_gr_gid(TALLOC_CTX *mem_ctx,
                      struct proxy_id_ctx *ctx,
                      struct sysdb_ctx *sysdb,
                      struct sss_domain_info *dom,
                      gid_t gid,
                      time_t now)
{
    TALLOC_CTX *tmpctx;
    struct group *grp;
    enum nss_status status;
    char *buffer = NULL;
    size_t buflen = 0;
    bool delete_group = false;
    int ret;
    char *name;

    DEBUG(SSSDBG_TRACE_FUNC, "Searching group by gid (%"SPRIgid")\n", gid);

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

    grp = talloc(tmpctx, struct group);
    if (!grp) {
        ret = ENOMEM;
        goto done;
    }

    do {
        /* always zero out the grp structure */
        memset(grp, 0, sizeof(struct group));
        buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
        if (!buffer) {
            ret = ENOMEM;
            goto done;
        }

        status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);

        ret = handle_getgr_result(status, grp, dom, &delete_group);
    } while (ret == EAGAIN);

    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              "getgrgid failed [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

    if (delete_group) {
        DEBUG(SSSDBG_TRACE_FUNC,
              "Group %"SPRIgid" does not exist (or is invalid) on remote "
               "server, deleting!\n", gid);

        ret = sysdb_delete_group(dom, NULL, gid);
        if (ret == ENOENT) {
            ret = EOK;
        }
        goto done;
    }

    name = sss_create_internal_fqname(tmpctx, grp->gr_name, dom->name);
    if (name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = save_group(sysdb, dom, grp, name, NULL);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "Cannot save user [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

done:
    talloc_zfree(tmpctx);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "proxy -> getgrgid_r failed for '%"SPRIgid"' <%d>: %s\n",
               gid, ret, strerror(ret));
    }
    return ret;
}
Beispiel #16
0
static int get_pw_name(struct proxy_id_ctx *ctx,
                       struct sss_domain_info *dom,
                       const char *i_name)
{
    TALLOC_CTX *tmpctx;
    struct passwd *pwd;
    enum nss_status status;
    char *buffer;
    size_t buflen;
    int ret;
    uid_t uid;
    bool del_user;
    struct ldb_result *cached_pwd = NULL;
    const char *real_name = NULL;
    char *shortname_or_alias;

    DEBUG(SSSDBG_TRACE_FUNC, "Searching user by name (%s)\n", i_name);

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

    ret = sss_parse_internal_fqname(tmpctx, i_name, &shortname_or_alias, NULL);
    if (ret != EOK) {
        goto done;
    }

    pwd = talloc_zero(tmpctx, struct passwd);
    if (!pwd) {
        ret = ENOMEM;
        goto done;
    }

    buflen = DEFAULT_BUFSIZE;
    buffer = talloc_size(tmpctx, buflen);
    if (!buffer) {
        ret = ENOMEM;
        goto done;
    }

    /* FIXME: should we move this call outside the transaction to keep the
     * transaction as short as possible ? */
    status = ctx->ops.getpwnam_r(shortname_or_alias, pwd, buffer, buflen, &ret);
    ret = handle_getpw_result(status, pwd, dom, &del_user);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "getpwnam failed [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

    if (del_user) {
        ret = delete_user(dom, i_name, 0);
        goto done;
    }

    uid = pwd->pw_uid;

    /* Canonicalize the username in case it was actually an alias */

    if (ctx->fast_alias == true) {
        ret = sysdb_getpwuid(tmpctx, dom, uid, &cached_pwd);
        if (ret != EOK) {
            /* Non-fatal, attempt to canonicalize online */
            DEBUG(SSSDBG_TRACE_FUNC, "Request to cache failed [%d]: %s\n",
                  ret, strerror(ret));
        }

        if (ret == EOK && cached_pwd->count == 1) {
            real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
                                                    SYSDB_NAME, NULL);
            if (!real_name) {
                DEBUG(SSSDBG_MINOR_FAILURE, "Cached user has no name?\n");
            }
        }
    }

    if (real_name == NULL) {
        memset(buffer, 0, buflen);

        status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
        ret = handle_getpw_result(status, pwd, dom, &del_user);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE,
                "getpwuid failed [%d]: %s\n", ret, strerror(ret));
            goto done;
        }

        real_name = sss_create_internal_fqname(tmpctx, pwd->pw_name, dom->name);
        if (real_name == NULL) {
            ret = ENOMEM;
            goto done;
        }
    }

    if (del_user) {
        ret = delete_user(dom, i_name, uid);
        goto done;
    }

    /* Both lookups went fine, we can save the user now */
    ret = save_user(dom, pwd, real_name, i_name);

done:
    talloc_zfree(tmpctx);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "proxy -> getpwnam_r failed for '%s' <%d>: %s\n",
               i_name, ret, strerror(ret));
    }
    return ret;
}
Beispiel #17
0
static int enum_users(TALLOC_CTX *mem_ctx,
                      struct proxy_id_ctx *ctx,
                      struct sysdb_ctx *sysdb,
                      struct sss_domain_info *dom)
{
    TALLOC_CTX *tmpctx;
    bool in_transaction = false;
    struct passwd *pwd;
    enum nss_status status;
    size_t buflen;
    char *buffer;
    char *newbuf;
    int ret;
    errno_t sret;
    bool again;
    char *name;

    DEBUG(SSSDBG_TRACE_LIBS, "Enumerating users\n");

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

    pwd = talloc_zero(tmpctx, struct passwd);
    if (!pwd) {
        ret = ENOMEM;
        goto done;
    }

    buflen = DEFAULT_BUFSIZE;
    buffer = talloc_size(tmpctx, buflen);
    if (!buffer) {
        ret = ENOMEM;
        goto done;
    }

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

    status = ctx->ops.setpwent();
    if (status != NSS_STATUS_SUCCESS) {
        ret = EIO;
        goto done;
    }

    do {
        again = false;

        /* always zero out the pwd structure */
        memset(pwd, 0, sizeof(struct passwd));

        /* get entry */
        status = ctx->ops.getpwent_r(pwd, buffer, buflen, &ret);

        switch (status) {
            case NSS_STATUS_TRYAGAIN:
                /* buffer too small ? */
                if (buflen < MAX_BUF_SIZE) {
                    buflen *= 2;
                }
                if (buflen > MAX_BUF_SIZE) {
                    buflen = MAX_BUF_SIZE;
                }
                newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
                if (!newbuf) {
                    ret = ENOMEM;
                    goto done;
                }
                buffer = newbuf;
                again = true;
                break;

            case NSS_STATUS_NOTFOUND:

                /* we are done here */
                DEBUG(SSSDBG_TRACE_LIBS, "Enumeration completed.\n");

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

            case NSS_STATUS_SUCCESS:

                DEBUG(SSSDBG_TRACE_LIBS,
                      "User found (%s, %"SPRIuid", %"SPRIgid")\n",
                       pwd->pw_name, pwd->pw_uid, pwd->pw_gid);

                /* uid=0 or gid=0 are invalid values */
                /* also check that the id is in the valid range for this domain
                 */
                if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
                    OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {

                    DEBUG(SSSDBG_OP_FAILURE, "User [%s] filtered out! (id out"
                        " of range)\n", pwd->pw_name);

                    again = true;
                    break;
                }

                name = sss_create_internal_fqname(tmpctx, pwd->pw_name, dom->name);
                if (name == NULL) {
                    DEBUG(SSSDBG_OP_FAILURE,
                          "failed to create internal name '%s'\n",
                          pwd->pw_name);
                    goto done;
                }
                ret = save_user(dom, pwd, name, NULL);
                if (ret) {
                    /* Do not fail completely on errors.
                     * Just report the failure to save and go on */
                    DEBUG(SSSDBG_OP_FAILURE, "Failed to store user %s."
                                " Ignoring.\n", pwd->pw_name);
                }
                again = true;
                break;

            case NSS_STATUS_UNAVAIL:
                /* "remote" backend unavailable. Enter offline mode */
                ret = ENXIO;
                break;

            default:
                ret = EIO;
                DEBUG(SSSDBG_OP_FAILURE, "proxy -> getpwent_r failed (%d)[%s]"
                            "\n", ret, strerror(ret));
                break;
        }
    } while (again);

done:
    talloc_zfree(tmpctx);
    if (in_transaction) {
        sret = sysdb_transaction_cancel(sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
        }
    }
    ctx->ops.endpwent();
    return ret;
}
Beispiel #18
0
static int get_pw_uid(struct proxy_id_ctx *ctx,
                      struct sss_domain_info *dom,
                      uid_t uid)
{
    TALLOC_CTX *tmpctx;
    struct passwd *pwd;
    enum nss_status status;
    char *buffer;
    size_t buflen;
    bool del_user = false;
    int ret;
    char *name;

    DEBUG(SSSDBG_TRACE_FUNC, "Searching user by uid (%"SPRIuid")\n", uid);

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

    pwd = talloc_zero(tmpctx, struct passwd);
    if (!pwd) {
        ret = ENOMEM;
        goto done;
    }

    buflen = DEFAULT_BUFSIZE;
    buffer = talloc_size(tmpctx, buflen);
    if (!buffer) {
        ret = ENOMEM;
        goto done;
    }

    status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
    ret = handle_getpw_result(status, pwd, dom, &del_user);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "getpwuid failed [%d]: %s\n", ret, strerror(ret));
        goto done;
    }

    if (del_user) {
        ret = delete_user(dom, NULL, uid);
        goto done;
    }

    name = sss_create_internal_fqname(tmpctx, pwd->pw_name, dom->name);
    if (name == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "failed to qualify name '%s'\n",
              pwd->pw_name);
        goto done;
    }
    ret = save_user(dom, pwd, name, NULL);

done:
    talloc_zfree(tmpctx);
    if (ret) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "proxy -> getpwuid_r failed for '%"SPRIuid"' <%d>: %s\n",
               uid, ret, strerror(ret));
    }
    return ret;
}
Beispiel #19
0
/*
 * getpwnam, getgrnam and friends
 */
int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx,
                        const char *name,
                        struct ops_ctx *out)
{
    struct ldb_result *res;
    const char *str;
    int ret;

    out->sysdb_fqname = sss_create_internal_fqname(out, name,
                                                   out->domain->name);
    if (out->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    ret = sysdb_getpwnam(mem_ctx, out->domain, out->sysdb_fqname, &res);
    if (ret) {
        return ret;
    }

    switch (res->count) {
    case 0:
        DEBUG(SSSDBG_CRIT_FAILURE, "No result for sysdb_getpwnam call\n");
        return ENOENT;

    case 1:
        /* fill ops_ctx */
        out->uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);

        out->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        ret = sss_parse_internal_fqname(out, str, &out->name, NULL);
        if (ret != EOK) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_GECOS, NULL);
        out->gecos = talloc_strdup(out, str);
        if (out->gecos == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_HOMEDIR, NULL);
        out->home = talloc_strdup(out, str);
        if (out->home == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, NULL);
        out->shell = talloc_strdup(out, str);
        if (out->shell == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_DISABLED, NULL);
        if (str == NULL) {
            out->lock = DO_UNLOCK;
        } else {
            if (strcasecmp(str, "true") == 0) {
                out->lock = DO_LOCK;
            } else if (strcasecmp(str, "false") == 0) {
                out->lock = DO_UNLOCK;
            } else { /* Invalid value */
                DEBUG(SSSDBG_OP_FAILURE, "Invalid value for %s attribute: %s\n",
                          SYSDB_DISABLED, str ? str : "NULL");
                return EIO;
            }
        }
        break;

    default:
        DEBUG(SSSDBG_CRIT_FAILURE,
              "More than one result for sysdb_getpwnam call\n");
        return EIO;
    }

    return EOK;
}
Beispiel #20
0
static errno_t sss_mc_refresh_nested_group(struct tools_ctx *tctx,
                                           const char *shortname)
{
    errno_t ret;
    struct ldb_message *msg = NULL;
    struct ldb_message_element *el;
    const char *attrs[] = { SYSDB_MEMBEROF,
                            SYSDB_NAME,
                            NULL };
    size_t i;
    char *parent_internal_name;
    char *parent_outname;
    char *internal_name;
    TALLOC_CTX *tmpctx;

    tmpctx = talloc_new(tctx);
    if (tmpctx == NULL) {
        return ENOMEM;
    }

    internal_name = sss_create_internal_fqname(tmpctx, shortname,
                                               tctx->local->name);
    if (internal_name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    ret = sss_mc_refresh_group(shortname);
    if (ret != EOK) {
        DEBUG(SSSDBG_MINOR_FAILURE,
              "Cannot refresh group %s from memory cache\n", shortname);
        /* try to carry on */
    }

    ret = sysdb_search_group_by_name(tmpctx, tctx->local, internal_name, attrs,
                                     &msg);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
               "Search failed: %s (%d)\n", strerror(ret), ret);
        goto done;
    }

    el = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
    if (!el || el->num_values == 0) {
        DEBUG(SSSDBG_TRACE_INTERNAL, "Group %s has no parents\n",
              internal_name);
        ret = EOK;
        goto done;
    }

    /* This group is nested. We need to invalidate all its parents, too */
    for (i=0; i < el->num_values; i++) {
        ret = sysdb_group_dn_name(tctx->sysdb, tmpctx,
                                  (const char *) el->values[i].data,
                                  &parent_internal_name);
        if (ret != EOK) {
            DEBUG(SSSDBG_MINOR_FAILURE, "Malformed DN [%s]? Skipping\n",
                  (const char *) el->values[i].data);
            talloc_free(parent_internal_name);
            continue;
        }

        parent_outname = sss_output_name(tmpctx, parent_internal_name,
                                         tctx->local->case_preserve, 0);
        if (parent_outname == NULL) {
            ret = ENOMEM;
            goto done;
        }

        ret = sss_mc_refresh_group(parent_outname);
        talloc_free(parent_internal_name);
        talloc_free(parent_outname);
        if (ret != EOK) {
            DEBUG(SSSDBG_MINOR_FAILURE,
                  "Cannot refresh group %s from memory cache\n", parent_outname);
            /* try to carry on */
        }
    }

    ret = EOK;

done:
    talloc_free(tmpctx);
    return ret;
}
Beispiel #21
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;
}
Beispiel #22
0
static int get_initgr(TALLOC_CTX *mem_ctx,
                      struct proxy_id_ctx *ctx,
                      struct sysdb_ctx *sysdb,
                      struct sss_domain_info *dom,
                      const char *i_name)
{
    TALLOC_CTX *tmpctx;
    bool in_transaction = false;
    struct passwd *pwd;
    enum nss_status status;
    char *buffer;
    size_t buflen;
    int ret;
    errno_t sret;
    bool del_user;
    uid_t uid;
    struct ldb_result *cached_pwd = NULL;
    const char *real_name = NULL;
    char *shortname_or_alias;

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

    ret = sss_parse_internal_fqname(tmpctx, i_name, &shortname_or_alias, NULL);
    if (ret != EOK) {
        goto done;
    }

    pwd = talloc_zero(tmpctx, struct passwd);
    if (!pwd) {
        ret = ENOMEM;
        goto fail;
    }

    buflen = DEFAULT_BUFSIZE;
    buffer = talloc_size(tmpctx, buflen);
    if (!buffer) {
        ret = ENOMEM;
        goto fail;
    }

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

    /* FIXME: should we move this call outside the transaction to keep the
     * transaction as short as possible ? */
    status = ctx->ops.getpwnam_r(shortname_or_alias, pwd,
                                 buffer, buflen, &ret);
    ret = handle_getpw_result(status, pwd, dom, &del_user);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
              "getpwnam failed [%d]: %s\n", ret, strerror(ret));
        goto fail;
    }

    if (del_user) {
        ret = delete_user(dom, i_name, 0);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not delete user\n");
            goto fail;
        }
        goto done;
    }

    uid = pwd->pw_uid;
    memset(buffer, 0, buflen);

    /* Canonicalize the username in case it was actually an alias */
    if (ctx->fast_alias == true) {
        ret = sysdb_getpwuid(tmpctx, dom, uid, &cached_pwd);
        if (ret != EOK) {
            /* Non-fatal, attempt to canonicalize online */
            DEBUG(SSSDBG_TRACE_FUNC, "Request to cache failed [%d]: %s\n",
                  ret, strerror(ret));
        }

        if (ret == EOK && cached_pwd->count == 1) {
            real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
                                                    SYSDB_NAME, NULL);
            if (!real_name) {
                DEBUG(SSSDBG_MINOR_FAILURE, "Cached user has no name?\n");
            }
        }
    }

    if (real_name == NULL) {
        memset(buffer, 0, buflen);

        status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
        ret = handle_getpw_result(status, pwd, dom, &del_user);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE,
                "getpwuid failed [%d]: %s\n", ret, strerror(ret));
            goto done;
        }

        real_name = sss_create_internal_fqname(tmpctx, pwd->pw_name, dom->name);
        if (real_name == NULL) {
            ret = ENOMEM;
            goto done;
        }
    }

    if (del_user) {
        ret = delete_user(dom, i_name, uid);
        if (ret) {
            DEBUG(SSSDBG_OP_FAILURE, "Could not delete user\n");
            goto fail;
        }
        goto done;
    }

    ret = save_user(dom, pwd, real_name, i_name);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE, "Could not save user\n");
        goto fail;
    }

    ret = get_initgr_groups_process(tmpctx, ctx, sysdb, dom, pwd);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "Could not process initgroups\n");
        goto fail;
    }

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

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