Beispiel #1
0
errno_t
nss_protocol_fill_sid(struct nss_ctx *nss_ctx,
                      struct nss_cmd_ctx *cmd_ctx,
                      struct sss_packet *packet,
                      struct cache_req_result *result)
{
    struct ldb_message *msg = result->msgs[0];
    struct sized_string sz_sid;
    enum sss_id_type id_type;
    const char *sid;
    size_t rp = 0;
    size_t body_len;
    uint8_t *body;
    errno_t ret;

    ret = nss_get_id_type(cmd_ctx, result, &id_type);
    if (ret != EOK) {
        return ret;
    }

    sid = ldb_msg_find_attr_as_string(msg, SYSDB_SID_STR, NULL);
    if (sid == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Missing SID.\n");
        return EINVAL;
    }

    to_sized_string(&sz_sid, sid);

    ret = sss_packet_grow(packet, sz_sid.len + 3 * sizeof(uint32_t));
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
        return ret;
    }

    sss_packet_get_body(packet, &body, &body_len);

    SAFEALIGN_SET_UINT32(&body[rp], 1, &rp); /* Num results. */
    SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
    SAFEALIGN_SET_UINT32(&body[rp], id_type, &rp);
    SAFEALIGN_SET_STRING(&body[rp], sz_sid.str, sz_sid.len, &rp);

    return EOK;
}
Beispiel #2
0
int sss_mmap_cache_gr_store(struct sss_mc_ctx *mcc,
                            struct sized_string *name,
                            struct sized_string *pw,
                            gid_t gid, size_t memnum,
                            char *membuf, size_t memsize)
{
    struct sss_mc_rec *rec;
    struct sss_mc_grp_data *data;
    struct sized_string gidkey;
    char gidstr[11];
    size_t data_len;
    size_t rec_len;
    size_t pos;
    int ret;

    ret = snprintf(gidstr, 11, "%ld", (long)gid);
    if (ret > 10) {
        return EINVAL;
    }
    to_sized_string(&gidkey, gidstr);

    data_len = name->len + pw->len + memsize;
    rec_len = sizeof(struct sss_mc_rec) +
              sizeof(struct sss_mc_grp_data) +
              data_len;
    if (rec_len > mcc->dt_size) {
        return ENOMEM;
    }

    rec = sss_mc_get_record(mcc, rec_len, name);

    data = (struct sss_mc_grp_data *)rec->data;
    pos = 0;

    MC_RAISE_BARRIER(rec);

    /* header */
    rec->len = rec_len;
    rec->expire = time(NULL) + mcc->valid_time_slot;
    rec->hash1 = sss_mc_hash(mcc, name->str, name->len);
    rec->hash2 = sss_mc_hash(mcc, gidkey.str, gidkey.len);

    /* group struct */
    data->name = MC_PTR_DIFF(data->strs, data);
    data->gid = gid;
    data->members = memnum;
    data->strs_len = data_len;
    memcpy(&data->strs[pos], name->str, name->len);
    pos += name->len;
    memcpy(&data->strs[pos], pw->str, pw->len);
    pos += pw->len;
    memcpy(&data->strs[pos], membuf, memsize);
    pos += memsize;

    MC_LOWER_BARRIER(rec);

    /* finally chain the rec in the hash table */
    /* name hash first */
    sss_mc_add_rec_to_chain(mcc, rec, rec->hash1);
    /* then gid */
    sss_mc_add_rec_to_chain(mcc, rec, rec->hash2);

    return EOK;
}
Beispiel #3
0
errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx *mcc,
                                struct sized_string *name,
                                struct sized_string *pw,
                                uid_t uid, gid_t gid,
                                struct sized_string *gecos,
                                struct sized_string *homedir,
                                struct sized_string *shell)
{
    struct sss_mc_rec *rec;
    struct sss_mc_pwd_data *data;
    struct sized_string uidkey;
    char uidstr[11];
    size_t data_len;
    size_t rec_len;
    size_t pos;
    int ret;

    ret = snprintf(uidstr, 11, "%ld", (long)uid);
    if (ret > 10) {
        return EINVAL;
    }
    to_sized_string(&uidkey, uidstr);

    data_len = name->len + pw->len + gecos->len + homedir->len + shell->len;
    rec_len = sizeof(struct sss_mc_rec) +
              sizeof(struct sss_mc_pwd_data) +
              data_len;
    if (rec_len > mcc->dt_size) {
        return ENOMEM;
    }

    rec = sss_mc_get_record(mcc, rec_len, name);

    data = (struct sss_mc_pwd_data *)rec->data;
    pos = 0;

    MC_RAISE_BARRIER(rec);

    /* header */
    rec->len = rec_len;
    rec->expire = time(NULL) + mcc->valid_time_slot;
    rec->hash1 = sss_mc_hash(mcc, name->str, name->len);
    rec->hash2 = sss_mc_hash(mcc, uidkey.str, uidkey.len);

    /* passwd struct */
    data->name = MC_PTR_DIFF(data->strs, data);
    data->uid = uid;
    data->gid = gid;
    data->strs_len = data_len;
    memcpy(&data->strs[pos], name->str, name->len);
    pos += name->len;
    memcpy(&data->strs[pos], pw->str, pw->len);
    pos += pw->len;
    memcpy(&data->strs[pos], gecos->str, gecos->len);
    pos += gecos->len;
    memcpy(&data->strs[pos], homedir->str, homedir->len);
    pos += homedir->len;
    memcpy(&data->strs[pos], shell->str, shell->len);
    pos += shell->len;

    MC_LOWER_BARRIER(rec);

    /* finally chain the rec in the hash table */
    /* name hash first */
    sss_mc_add_rec_to_chain(mcc, rec, rec->hash1);
    /* then uid */
    sss_mc_add_rec_to_chain(mcc, rec, rec->hash2);

    return EOK;
}
Beispiel #4
0
static errno_t process_attr_list(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
                                 const char **attr_list,
                                 struct sized_string **_keys,
                                 struct sized_string **_vals,
                                 size_t *array_size, size_t *sum,
                                 size_t *found)
{
    size_t c;
    size_t d;
    struct sized_string *keys;
    struct sized_string *vals;
    struct ldb_val val;
    struct ldb_message_element *el;
    bool use_base64;

    keys = *_keys;
    vals = *_vals;

    for (c = 0; attr_list[c] != NULL; c++) {
        el = ldb_msg_find_element(msg, attr_list[c]);
        if (el != NULL && el->num_values > 0) {
            if (el->num_values > 1) {
                *array_size += el->num_values;
                keys = talloc_realloc(mem_ctx, keys, struct sized_string,
                                      *array_size);
                vals = talloc_realloc(mem_ctx, vals, struct sized_string,
                                      *array_size);
                if (keys == NULL || vals == NULL) {
                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
                    return ENOMEM;
                }
            }

            use_base64 = false;
            if (strcmp(attr_list[c], SYSDB_USER_CERT) == 0) {
                use_base64 = true;
            }

            for (d = 0; d < el->num_values; d++) {
                to_sized_string(&keys[*found], attr_list[c]);
                *sum += keys[*found].len;
                if (use_base64) {
                    val.data = (uint8_t *)sss_base64_encode(vals,
                                                         el->values[d].data,
                                                         el->values[d].length);
                    if (val.data != NULL) {
                        val.length = strlen((char *)val.data);
                    }
                } else {
                    val = el->values[d];
                }

                if (val.data == NULL || val.data[val.length] != '\0') {
                    DEBUG(SSSDBG_CRIT_FAILURE,
                          "Unexpected attribute value found for [%s].\n",
                          attr_list[c]);
                    return EINVAL;
                }
                to_sized_string(&vals[*found], (const char *)val.data);
                *sum += vals[*found].len;

                (*found)++;
            }
        }
    }
Beispiel #5
0
errno_t
nss_protocol_fill_pwent(struct nss_ctx *nss_ctx,
                        struct nss_cmd_ctx *cmd_ctx,
                        struct sss_packet *packet,
                        struct cache_req_result *result)
{
    TALLOC_CTX *tmp_ctx;
    struct ldb_message *msg;
    struct sized_string pwfield;
    struct sized_string *name;
    struct sized_string gecos;
    struct sized_string homedir;
    struct sized_string shell;
    uint32_t gid;
    uint32_t uid;
    uint32_t num_results;
    size_t rp;
    size_t body_len;
    uint8_t *body;
    int i;
    errno_t ret;

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

    /* First two fields (length and reserved), filled up later. */
    ret = sss_packet_grow(packet, 2 * sizeof(uint32_t));
    if (ret != EOK) {
        return ret;
    }

    rp = 2 * sizeof(uint32_t);

    num_results = 0;
    for (i = 0; i < result->count; i++) {
        talloc_free_children(tmp_ctx);
        msg = result->msgs[i];

        /* Password field content. */
        to_sized_string(&pwfield, nss_get_pwfield(nss_ctx, result->domain));

        ret = nss_get_pwent(tmp_ctx, nss_ctx, result->domain, msg, &uid, &gid,
                            &name, &gecos, &homedir, &shell);
        if (ret != EOK) {
            continue;
        }

        /* Adjust packet size: uid, gid + string fields. */

        ret = sss_packet_grow(packet, 2 * sizeof(uint32_t)
                                          + name->len + gecos.len + homedir.len
                                          + shell.len + pwfield.len);
        if (ret != EOK) {
            goto done;
        }

        sss_packet_get_body(packet, &body, &body_len);

        /* Fill packet. */

        SAFEALIGN_SET_UINT32(&body[rp], uid, &rp);
        SAFEALIGN_SET_UINT32(&body[rp], gid, &rp);
        SAFEALIGN_SET_STRING(&body[rp], name->str, name->len, &rp);
        SAFEALIGN_SET_STRING(&body[rp], pwfield.str, pwfield.len, &rp);
        SAFEALIGN_SET_STRING(&body[rp], gecos.str, gecos.len, &rp);
        SAFEALIGN_SET_STRING(&body[rp], homedir.str, homedir.len, &rp);
        SAFEALIGN_SET_STRING(&body[rp], shell.str, shell.len, &rp);

        num_results++;

        /* Do not store entry in memory cache during enumeration or when
         * requested. */
        if (!cmd_ctx->enumeration
                && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) {
            ret = sss_mmap_cache_pw_store(&nss_ctx->pwd_mc_ctx, name, &pwfield,
                                          uid, gid, &gecos, &homedir, &shell);
            if (ret != EOK) {
                DEBUG(SSSDBG_MINOR_FAILURE,
                      "Failed to store user %s (%s) in mmap cache [%d]: %s!\n",
                      name->str, result->domain->name, ret, sss_strerror(ret));
            }
        }
    }

    ret = EOK;

done:
    talloc_free(tmp_ctx);

    if (ret != EOK) {
        sss_packet_set_size(packet, 0);
        return ret;
    }

    sss_packet_get_body(packet, &body, &body_len);
    SAFEALIGN_COPY_UINT32(body, &num_results, NULL);
    SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL); /* reserved */

    return EOK;
}
Beispiel #6
0
static errno_t
nss_get_pwent(TALLOC_CTX *mem_ctx,
              struct nss_ctx *nss_ctx,
              struct sss_domain_info *domain,
              struct ldb_message *msg,
              uint32_t *_uid,
              uint32_t *_gid,
              struct sized_string **_name,
              struct sized_string *_gecos,
              struct sized_string *_homedir,
              struct sized_string *_shell)
{
    const char *upn;
    const char *name;
    const char *gecos;
    const char *homedir;
    const char *shell;
    uint32_t gid;
    uint32_t uid;
    errno_t ret;

    /* Get fields. */
    upn = ldb_msg_find_attr_as_string(msg, SYSDB_UPN, NULL);
    name = sss_get_name_from_msg(domain, msg);
    gid = nss_get_gid(domain, msg);
    uid = sss_view_ldb_msg_find_attr_as_uint64(domain, msg, SYSDB_UIDNUM, 0);

    if (name == NULL || uid == 0 || gid == 0) {
        DEBUG(SSSDBG_OP_FAILURE,
              "Incomplete user object for %s[%u]! Skipping\n",
              name ? name : "<NULL>", uid);
        return EINVAL;
    }

    gecos = sss_view_ldb_msg_find_attr_as_string(domain, msg, SYSDB_GECOS,
                                                 NULL);
    homedir = nss_get_homedir(mem_ctx, nss_ctx, domain, msg, name, upn, uid);
    ret = nss_get_shell(nss_ctx, domain, msg, name, uid, &shell);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "failed retrieving shell for %s[%u], skipping [%d]: %s\n",
              name, uid, ret, sss_strerror(ret));
        return ret;
    }

    /* Convert to sized strings. */
    ret = sized_output_name(mem_ctx, nss_ctx->rctx, name, domain, _name);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "sized_output_name failed, skipping [%d]: %s\n",
              ret, sss_strerror(ret));
        return ret;
    }

    to_sized_string(_gecos, gecos == NULL ? "" : gecos);
    to_sized_string(_shell, shell);
    to_sized_string(_homedir, homedir);

    *_gid = gid;
    *_uid = uid;

    return EOK;
}