Пример #1
0
/* The repbuf is owned by the sss_getautomntent_data once this
 * function is called */
static errno_t
sss_getautomntent_data_save(const char *mapname, uint8_t **repbuf, size_t replen)
{
    size_t rp;
    uint32_t num;

    rp = 0;
    SAFEALIGN_COPY_UINT32(&num, *repbuf+rp, &rp);
    if (num == 0) {
        free(*repbuf);
        return ENOENT;
    }

    sss_getautomntent_data.mapname = strdup(mapname);
    if (sss_getautomntent_data.mapname == NULL) {
        free(*repbuf);
        return ENOENT;
    }

    sss_getautomntent_data.data = *repbuf;
    sss_getautomntent_data.len = replen;
    sss_getautomntent_data.ptr = rp;
    *repbuf = NULL;
    return EOK;
}
Пример #2
0
enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx,
        const uint8_t *bin_sid,
        size_t length,
        struct sss_dom_sid **_dom_sid)
{
    enum idmap_error_code err;
    struct sss_dom_sid *dom_sid;
    size_t i = 0;
    size_t p = 0;
    uint32_t val;

    CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);

    if (length > sizeof(struct sss_dom_sid)) return IDMAP_SID_INVALID;

    dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt);
    if (dom_sid == NULL) {
        return IDMAP_OUT_OF_MEMORY;
    }
    memset(dom_sid, 0, sizeof(struct sss_dom_sid));

    /* Safely copy in the SID revision number */
    dom_sid->sid_rev_num = (uint8_t) *(bin_sid + p);
    p++;

    /* Safely copy in the number of sub auth values */
    dom_sid->num_auths = (uint8_t) *(bin_sid + p);
    p++;

    /* Make sure we aren't being told to read more bin_sid
     * than can fit in the structure
     */
    if (dom_sid->num_auths > SID_SUB_AUTHS) {
        err = IDMAP_SID_INVALID;
        goto done;
    }

    /* Safely copy in the id_auth values */
    for (i = 0; i < SID_ID_AUTHS; i++) {
        dom_sid->id_auth[i] = (uint8_t) *(bin_sid + p);
        p++;
    }

    /* Safely copy in the sub_auths values */
    for (i = 0; i < dom_sid->num_auths; i++) {
        /* SID sub auth values in Active Directory are stored little-endian,
         * we store them in host order */
        SAFEALIGN_COPY_UINT32(&val, bin_sid + p, &p);
        dom_sid->sub_auths[i] = le32toh(val);
    }

    *_dom_sid = dom_sid;
    err = IDMAP_SUCCESS;

done:
    if (err != IDMAP_SUCCESS) {
        ctx->free_func(dom_sid, ctx->alloc_pvt);
    }
    return err;
}
Пример #3
0
enum idmap_error_code sss_idmap_dom_sid_to_bin_sid(struct sss_idmap_ctx *ctx,
        struct sss_dom_sid *dom_sid,
        uint8_t **_bin_sid,
        size_t *_length)
{
    enum idmap_error_code err;
    uint8_t *bin_sid;
    size_t length;
    size_t i = 0;
    size_t p = 0;
    uint32_t val;

    CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);

    if (dom_sid->num_auths > SID_SUB_AUTHS) {
        return IDMAP_SID_INVALID;
    }

    length = 2 + SID_ID_AUTHS + dom_sid->num_auths * 4;

    bin_sid = ctx->alloc_func(length, ctx->alloc_pvt);
    if (bin_sid == NULL) {
        return IDMAP_OUT_OF_MEMORY;
    }

    bin_sid[p] = dom_sid->sid_rev_num;
    p++;

    bin_sid[p] = dom_sid->num_auths;
    p++;

    for (i = 0; i < SID_ID_AUTHS; i++) {
        bin_sid[p] = dom_sid->id_auth[i];
        p++;
    }

    for (i = 0; i < dom_sid->num_auths; i++) {
        if (p + sizeof(uint32_t) > length) {
            err = IDMAP_SID_INVALID;
            goto done;
        }
        val = htole32(dom_sid->sub_auths[i]);
        SAFEALIGN_COPY_UINT32(bin_sid + p, &val, &p);
    }

    *_bin_sid = bin_sid;
    *_length = length;

    err = IDMAP_SUCCESS;
done:
    if (err != IDMAP_SUCCESS) {
        ctx->free_func(bin_sid, ctx->alloc_pvt);
    }
    return err;
}
Пример #4
0
errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
{
    uint8_t *body;
    size_t blen;
    errno_t ret;
    uint32_t terminator;

    sss_packet_get_body(cctx->creq->in, &body, &blen);
    if (blen >= sizeof(uint32_t)) {
        SAFEALIGN_COPY_UINT32(&terminator,
                              body + blen - sizeof(uint32_t),
                              NULL);
        if (terminator != SSS_END_OF_PAM_REQUEST) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n");
            ret = EINVAL;
            goto done;
        }
    }

    switch (cctx->cli_protocol_version->version) {
        case 1:
            ret = pam_parse_in_data(cctx->rctx->domains,
                                    cctx->rctx->default_domain, pd,
                                    body, blen);
            break;
        case 2:
            ret = pam_parse_in_data_v2(cctx->rctx->domains,
                                       cctx->rctx->default_domain, pd,
                                       body, blen);
            break;
        case 3:
            ret = pam_parse_in_data_v3(cctx->rctx->domains,
                                       cctx->rctx->default_domain, pd,
                                       body, blen);
            break;
        default:
            DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n",
                      cctx->cli_protocol_version->version);
            ret = EINVAL;
    }

done:
    return ret;
}
Пример #5
0
static int pam_parse_in_data_v2(struct sss_domain_info *domains,
                                const char *default_domain,
                                struct pam_data *pd,
                                uint8_t *body, size_t blen)
{
    size_t c;
    uint32_t type;
    uint32_t size;
    char *pam_user;
    int ret;
    uint32_t start;
    uint32_t terminator;

    if (blen < 4*sizeof(uint32_t)+2) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
        return EINVAL;
    }

    SAFEALIGN_COPY_UINT32(&start, body, NULL);
    SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL);

    if (start != SSS_START_OF_PAM_REQUEST
        || terminator != SSS_END_OF_PAM_REQUEST) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
        return EINVAL;
    }

    c = sizeof(uint32_t);
    do {
        SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);

        if (type == SSS_END_OF_PAM_REQUEST) {
            if (c != blen) return EINVAL;
        } else {
            SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);
            /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to
             * the remaining buffer */
            if (size > (blen - c - sizeof(uint32_t))) {
                DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n");
                return EINVAL;
            }

            switch(type) {
                case SSS_PAM_ITEM_USER:
                    ret = extract_string(&pam_user, size, body, blen, &c);
                    if (ret != EOK) return ret;

                    ret = sss_parse_name_for_domains(pd, domains,
                                                     default_domain, pam_user,
                                                     &pd->domain, &pd->user);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_SERVICE:
                    ret = extract_string(&pd->service, size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_TTY:
                    ret = extract_string(&pd->tty, size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_RUSER:
                    ret = extract_string(&pd->ruser, size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_RHOST:
                    ret = extract_string(&pd->rhost, size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_CLI_PID:
                    ret = extract_uint32_t(&pd->cli_pid, size,
                                           body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_AUTHTOK:
                    ret = extract_authtok_v2(pd->authtok,
                                             size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                case SSS_PAM_ITEM_NEWAUTHTOK:
                    ret = extract_authtok_v2(pd->newauthtok,
                                             size, body, blen, &c);
                    if (ret != EOK) return ret;
                    break;
                default:
                    DEBUG(SSSDBG_CRIT_FAILURE,
                          "Ignoring unknown data type [%d].\n", type);
                    c += size;
            }
        }

    } while(c < blen);

    if (pd->user == NULL || *pd->user == '\0') return EINVAL;

    DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);

    return EOK;

}
Пример #6
0
static int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr,
                                 uint8_t *buf, size_t *len)
{
    errno_t ret;
    size_t i, slen, dlen;
    char *sbuf;
    uint32_t c;

    if (*len < 13) { /* not enough space for data, bad packet */
        return EBADMSG;
    }

    SAFEALIGN_COPY_UINT32(&c, buf, NULL);
    pr->result->pw_uid = c;
    SAFEALIGN_COPY_UINT32(&c, buf+sizeof(uint32_t), NULL);
    pr->result->pw_gid = c;

    sbuf = (char *)&buf[8];
    slen = *len - 8;
    dlen = pr->buflen;

    i = 0;
    pr->result->pw_name = &(pr->buffer[i]);

    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->pw_name,
                                  NULL);
    if (ret != EOK) return ret;

    pr->result->pw_passwd = &(pr->buffer[i]);
    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->pw_passwd,
                                  NULL);
    if (ret != EOK) return ret;

    pr->result->pw_gecos = &(pr->buffer[i]);
    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->pw_gecos,
                                  NULL);
    if (ret != EOK) return ret;


    pr->result->pw_dir = &(pr->buffer[i]);
    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->pw_dir,
                                  NULL);
    if (ret != EOK) return ret;

    pr->result->pw_shell = &(pr->buffer[i]);
    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->pw_shell,
                                  NULL);
    if (ret != EOK) return ret;
    *len = slen - i;

    return 0;
}
Пример #7
0
static enum nss_status internal_getpwent_r(struct passwd *result,
                                           char *buffer, size_t buflen,
                                           int *errnop)
{
    struct sss_cli_req_data rd;
    struct sss_nss_pw_rep pwrep;
    uint8_t *repbuf;
    size_t replen;
    uint32_t num_results;
    enum nss_status nret;
    uint32_t num_entries;
    int ret;

    /* Caught once glibc passing in buffer == 0x0 */
    if (!buffer || !buflen) return ERANGE;

    /* if there are leftovers return the next one */
    if (sss_nss_getpwent_data.data != NULL &&
        sss_nss_getpwent_data.ptr < sss_nss_getpwent_data.len) {

        repbuf = sss_nss_getpwent_data.data + sss_nss_getpwent_data.ptr;
        replen = sss_nss_getpwent_data.len - sss_nss_getpwent_data.ptr;

        pwrep.result = result;
        pwrep.buffer = buffer;
        pwrep.buflen = buflen;

        ret = sss_nss_getpw_readrep(&pwrep, repbuf, &replen);
        if (ret) {
            *errnop = ret;
            return NSS_STATUS_TRYAGAIN;
        }

        /* advance buffer pointer */
        sss_nss_getpwent_data.ptr = sss_nss_getpwent_data.len - replen;

        return NSS_STATUS_SUCCESS;
    }

    /* release memory if any */
    sss_nss_getpwent_data_clean();

    /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
    num_entries = SSS_NSS_MAX_ENTRIES;
    rd.len = sizeof(uint32_t);
    rd.data = &num_entries;

    nret = sss_nss_make_request(SSS_NSS_GETPWENT, &rd,
                                &repbuf, &replen, errnop);
    if (nret != NSS_STATUS_SUCCESS) {
        return nret;
    }

    /* Get number of results from repbuf. */
    SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);

    /* no results if not found */
    if ((num_results == 0) || (replen - 8 == 0)) {
        free(repbuf);
        return NSS_STATUS_NOTFOUND;
    }

    sss_nss_getpwent_data.data = repbuf;
    sss_nss_getpwent_data.len = replen;
    sss_nss_getpwent_data.ptr = 8; /* skip metadata fields */

    /* call again ourselves, this will return the first result */
    return internal_getpwent_r(result, buffer, buflen, errnop);
}
Пример #8
0
enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result,
                                    char *buffer, size_t buflen, int *errnop)
{
    struct sss_cli_req_data rd;
    struct sss_nss_pw_rep pwrep;
    uint8_t *repbuf;
    size_t replen, len;
    uint32_t num_results;
    enum nss_status nret;
    uint32_t user_uid;
    int ret;

    /* Caught once glibc passing in buffer == 0x0 */
    if (!buffer || !buflen) return ERANGE;

    ret = sss_nss_mc_getpwuid(uid, result, buffer, buflen);
    switch (ret) {
    case 0:
        *errnop = 0;
        return NSS_STATUS_SUCCESS;
    case ERANGE:
        *errnop = ERANGE;
        return NSS_STATUS_TRYAGAIN;
    case ENOENT:
        /* fall through, we need to actively ask the parent
         * if no entry is found */
        break;
    default:
        /* if using the mmaped cache failed,
         * fall back to socket based comms */
        break;
    }

    user_uid = uid;
    rd.len = sizeof(uint32_t);
    rd.data = &user_uid;

    sss_nss_lock();

    /* previous thread might already initialize entry in mmap cache */
    ret = sss_nss_mc_getpwuid(uid, result, buffer, buflen);
    switch (ret) {
    case 0:
        *errnop = 0;
        nret = NSS_STATUS_SUCCESS;
        goto out;
    case ERANGE:
        *errnop = ERANGE;
        nret = NSS_STATUS_TRYAGAIN;
        goto out;
    case ENOENT:
        /* fall through, we need to actively ask the parent
         * if no entry is found */
        break;
    default:
        /* if using the mmaped cache failed,
         * fall back to socket based comms */
        break;
    }

    nret = sss_nss_make_request(SSS_NSS_GETPWUID, &rd,
                                &repbuf, &replen, errnop);
    if (nret != NSS_STATUS_SUCCESS) {
        goto out;
    }

    pwrep.result = result;
    pwrep.buffer = buffer;
    pwrep.buflen = buflen;

    /* Get number of results from repbuf. */
    SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);

    /* no results if not found */
    if (num_results == 0) {
        free(repbuf);
        nret = NSS_STATUS_NOTFOUND;
        goto out;
    }

    /* only 1 result is accepted for this function */
    if (num_results != 1) {
        *errnop = EBADMSG;
        free(repbuf);
        nret = NSS_STATUS_TRYAGAIN;
        goto out;
    }

    len = replen - 8;
    ret = sss_nss_getpw_readrep(&pwrep, repbuf+8, &len);
    free(repbuf);
    if (ret) {
        *errnop = ret;
        nret = NSS_STATUS_TRYAGAIN;
        goto out;
    }

    nret = NSS_STATUS_SUCCESS;

out:
    sss_nss_unlock();
    return nret;
}
Пример #9
0
static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
                               struct output *out)
{
    int ret;
    size_t inp_len;
    struct sss_cli_req_data rd;
    uint8_t *repbuf = NULL;
    size_t replen;
    int errnop;
    enum nss_status nret;
    uint32_t num_results;
    char *str = NULL;
    size_t data_len;
    uint32_t c;

    switch (cmd) {
    case SSS_NSS_GETSIDBYNAME:
    case SSS_NSS_GETNAMEBYSID:
    case SSS_NSS_GETIDBYSID:
        ret = sss_strnlen(inp.str, SSS_NAME_MAX, &inp_len);
        if (ret != EOK) {
            return EINVAL;
        }

        rd.len = inp_len + 1;
        rd.data = inp.str;

        break;
    case SSS_NSS_GETSIDBYID:
        rd.len = sizeof(uint32_t);
        rd.data = &inp.id;

        break;
    default:
        return EINVAL;
    }

    sss_nss_lock();

    nret = sss_nss_make_request(cmd, &rd, &repbuf, &replen, &errnop);
    if (nret != NSS_STATUS_SUCCESS) {
        ret = nss_status_to_errno(nret);
        goto done;
    }

    if (replen < 8) {
        ret = EBADMSG;
        goto done;
    }

    num_results = ((uint32_t *)repbuf)[0];
    if (num_results == 0) {
        ret = ENOENT;
        goto done;
    } else if (num_results > 1) {
        ret = EBADMSG;
        goto done;
    }

    out->type = ((uint32_t *)repbuf)[2];

    data_len = replen - DATA_START;

    switch(cmd) {
    case SSS_NSS_GETSIDBYID:
    case SSS_NSS_GETSIDBYNAME:
    case SSS_NSS_GETNAMEBYSID:
        if (data_len <= 1 || repbuf[replen - 1] != '\0') {
            ret = EBADMSG;
            goto done;
        }

        str = malloc(sizeof(char) * data_len);
        if (str == NULL) {
            ret = ENOMEM;
            goto done;
        }

        strncpy(str, (char *) repbuf + DATA_START, data_len);

        out->d.str = str;

        break;
    case SSS_NSS_GETIDBYSID:
        if (data_len != sizeof(uint32_t)) {
            ret = EBADMSG;
            goto done;
        }

        SAFEALIGN_COPY_UINT32(&c, repbuf + DATA_START, NULL);
        out->d.id = c;

        break;
    default:
        ret = EINVAL;
        goto done;
    }

    ret = EOK;

done:
    sss_nss_unlock();
    free(repbuf);
    if (ret != EOK) {
        free(str);
    }

    return ret;
}
Пример #10
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;
}
Пример #11
0
errno_t
_sss_setautomntent(const char *mapname, void **context)
{
    errno_t ret;
    int errnop;
    struct automtent *ctx;
    char *name;
    size_t name_len;
    struct sss_cli_req_data rd;
    uint8_t *repbuf = NULL;
    size_t replen;
    uint32_t num_results = 0;

    if (!mapname) return EINVAL;

    sss_nss_lock();

    /* Make sure there are no leftovers from previous runs */
    sss_getautomntent_data_clean();

    ret = sss_strnlen(mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
    if (ret != 0) {
        ret = EINVAL;
        goto out;
    }

    name = malloc(sizeof(char)*name_len + 1);
    if (name == NULL) {
        ret = ENOMEM;
        goto out;
    }
    strncpy(name, mapname, name_len + 1);

    rd.data = name;
    rd.len = name_len + 1;

    sss_autofs_make_request(SSS_AUTOFS_SETAUTOMNTENT, &rd,
                            &repbuf, &replen, &errnop);
    if (errnop != 0) {
        free(name);
        ret = errnop;
        goto out;
    }

    /* Get number of results from repbuf. */
    SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);

    /* no results if not found */
    if (num_results == 0) {
        free(name);
        free(repbuf);
        ret = ENOENT;
        goto out;
    }
    free(repbuf);

    ctx = malloc(sizeof(struct automtent));
    if (!ctx) {
        free(name);
        ret = ENOMEM;
        goto out;
    }

    ctx->mapname = strdup(name);
    if (!ctx->mapname) {
        free(name);
        free(ctx);
        ret = ENOMEM;
        goto out;
    }
    ctx->cursor = 0;
    free(name);

    *context = ctx;
    ret = 0;
out:
    sss_nss_unlock();
    return ret;
}
Пример #12
0
errno_t
_sss_getautomntbyname_r(const char *key, char **value, void *context)
{
    int errnop;
    errno_t ret;
    struct automtent *ctx;
    size_t key_len;
    size_t name_len;
    size_t data_len = 0;
    uint8_t *data;
    size_t ctr = 0;
    struct sss_cli_req_data rd;
    uint8_t *repbuf = NULL;
    size_t replen;

    char *buf;
    uint32_t len;
    uint32_t vallen;
    size_t rp;

    sss_nss_lock();

    ctx = (struct automtent *) context;
    if (!ctx || !key) {
        ret = EINVAL;
        goto out;
    }

    /* Be paranoid in case someone tries to smuggle in a huge map name */
    ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
    if (ret != 0) {
        ret = EINVAL;
        goto out;
    }

    ret = sss_strnlen(key, MAX_AUTOMNTKEYNAME_LEN, &key_len);
    if (ret != 0) {
        ret = EINVAL;
        goto out;
    }


    data_len = sizeof(uint32_t) +            /* mapname len */
               name_len + 1 +                /* mapname\0   */
               sizeof(uint32_t) +            /* keyname len */
               key_len + 1;                  /* keyname\0   */

    data = malloc(data_len);
    if (!data) {
        ret = ENOMEM;
        goto out;
    }

    SAFEALIGN_SET_UINT32(data, name_len, &ctr);

    safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr);

    SAFEALIGN_SET_UINT32(data+ctr, key_len, &ctr);

    safealign_memcpy(data+ctr, key, key_len + 1, &ctr);

    rd.data = data;
    rd.len = data_len;

    sss_autofs_make_request(SSS_AUTOFS_GETAUTOMNTBYNAME, &rd,
                            &repbuf, &replen, &errnop);
    free(data);
    if (errnop != 0) {
        ret = errnop;
        goto out;
    }

    /* Got reply, let's parse it */
    rp = 0;
    SAFEALIGN_COPY_UINT32(&len, repbuf+rp, &rp);
    if (len == 0) {
        /* No data */
        *value = NULL;
        ret = ENOENT;
        goto out;
    }

    SAFEALIGN_COPY_UINT32(&vallen, repbuf+rp, &rp);
    if (vallen > len-rp) {
        ret = EIO;
        goto out;
    }

    buf = malloc(vallen);
    if (!buf) {
        ret = ENOMEM;
        goto out;
    }

    safealign_memcpy(buf, repbuf+rp, vallen, &rp);
    *value = buf;

    ret = 0;
out:
    free(repbuf);
    sss_nss_unlock();
    return ret;
}
Пример #13
0
static errno_t
sss_getautomntent_data_return(const char *mapname, char **_key, char **_value)
{
    size_t dp;
    uint32_t len = 0;
    char *key = NULL;
    uint32_t keylen;
    char *value = NULL;
    uint32_t vallen;
    errno_t ret;

    if (sss_getautomntent_data.mapname == NULL ||
        sss_getautomntent_data.data == NULL ||
        sss_getautomntent_data.ptr >= sss_getautomntent_data.len) {
        /* We're done with this buffer */
        ret = ENOENT;
        goto done;
    }

    ret = strcmp(mapname, sss_getautomntent_data.mapname);
    if (ret != EOK) {
        /* The map we're looking for is not cached. Let responder
         * do an implicit setautomntent */
        ret = ENOENT;
        goto done;
    }

    dp = sss_getautomntent_data.ptr;

    SAFEALIGN_COPY_UINT32(&len, sss_getautomntent_data.data+dp, &dp);
    if (len + sss_getautomntent_data.ptr > sss_getautomntent_data.len) {
        /* len is bigger than the buffer */
        ret = EIO;
        goto done;
    }

    if (len == 0) {
        /* There are no more records. */
        *_key = NULL;
        *_value = NULL;
        ret = ENOENT;
        goto done;
    }

    SAFEALIGN_COPY_UINT32(&keylen, sss_getautomntent_data.data+dp, &dp);
    if (keylen + dp > sss_getautomntent_data.len) {
        ret = EIO;
        goto done;
    }

    key = malloc(keylen);
    if (!key) {
        ret = ENOMEM;
        goto done;
    }

    safealign_memcpy(key, sss_getautomntent_data.data+dp, keylen, &dp);

    SAFEALIGN_COPY_UINT32(&vallen, sss_getautomntent_data.data+dp, &dp);
    if (vallen + dp > sss_getautomntent_data.len) {
        ret = EIO;
        goto done;
    }

    value = malloc(vallen);
    if (!value) {
        ret = ENOMEM;
        goto done;
    }

    safealign_memcpy(value, sss_getautomntent_data.data+dp, vallen, &dp);

    sss_getautomntent_data.ptr = dp;
    *_key = key;
    *_value = value;
    return EOK;

done:
    free(key);
    free(value);
    sss_getautomntent_data_clean();
    return ret;
}
Пример #14
0
/* SSH public key request:
 * 
 * header:
 *   0..3: flags (unsigned int, must be combination of SSS_SSH_REQ_* flags)
 *   4..7: name length (unsigned int)
 *   8..X: name (null-terminated UTF-8 string)
 * alias (only included if flags & SSS_SSH_REQ_ALIAS):
 *   0..3: alias length (unsigned int)
 *   4..X: alias (null-terminated UTF-8 string)
 * domain (ony included if flags & SSS_SSH_REQ_DOMAIN):
 *   0..3: domain length (unsigned int, 0 means default domain)
 *   4..X: domain (null-terminated UTF-8 string)
 * 
 * SSH public key reply:
 * 
 * header:
 *   0..3: number of results (unsigned int)
 *   4..7: reserved (unsigned int, must be 0)
 * results (repeated for each result):
 *   0..3:     flags (unsigned int, must be 0)
 *   4..7:     name length (unsigned int)
 *   8..(X-1): name (null-terminated UTF-8 string)
 *   X..(X+3): key length (unsigned int)
 *   (X+4)..Y: key (public key data)
 */
errno_t
sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
                enum sss_cli_command command,
                const char *name,
                const char *domain,
                const char *alias,
                struct sss_ssh_ent **result)
{
    TALLOC_CTX *tmp_ctx;
    struct sss_ssh_ent *res = NULL;
    errno_t ret;
    uint32_t flags;
    uint32_t name_len;
    uint32_t alias_len = 0;
    uint32_t domain_len;
    size_t req_len;
    uint8_t *req = NULL;
    size_t c = 0;
    struct sss_cli_req_data rd;
    int req_ret, req_errno;
    uint8_t *rep = NULL;
    size_t rep_len;
    uint32_t count, reserved, len, i;

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

    /* build request */
    flags = 0;
    name_len = strlen(name)+1;
    req_len = 2*sizeof(uint32_t) + name_len;

    if (alias) {
        flags |= SSS_SSH_REQ_ALIAS;
        alias_len = strlen(alias)+1;
        req_len += sizeof(uint32_t) + alias_len;
    }

    flags |= SSS_SSH_REQ_DOMAIN;
    domain_len = domain ? (strlen(domain)+1) : 0;
    req_len += sizeof(uint32_t) + domain_len;

    req = talloc_array(tmp_ctx, uint8_t, req_len);
    if (!req) {
        ret = ENOMEM;
        goto done;
    }

    SAFEALIGN_SET_UINT32(req+c, flags, &c);
    SAFEALIGN_SET_UINT32(req+c, name_len, &c);
    safealign_memcpy(req+c, name, name_len, &c);
    if (alias) {
        SAFEALIGN_SET_UINT32(req+c, alias_len, &c);
        safealign_memcpy(req+c, alias, alias_len, &c);
    }
    SAFEALIGN_SET_UINT32(req+c, domain_len, &c);
    if (domain_len > 0) {
        safealign_memcpy(req+c, domain, domain_len, &c);
    }

    /* send request */
    rd.data = req;
    rd.len = req_len;

    req_ret = sss_ssh_make_request(command, &rd, &rep, &rep_len, &req_errno);
    if (req_errno != EOK) {
        ret = req_errno;
        goto done;
    }
    if (req_ret != SSS_STATUS_SUCCESS) {
        ret = EFAULT;
        goto done;
    }

    /* parse reply */
    c = 0;
    if (rep_len-c < 2*sizeof(uint32_t)) {
        ret = EINVAL;
        goto done;
    }

    SAFEALIGN_COPY_UINT32(&count, rep+c, &c);

    SAFEALIGN_COPY_UINT32(&reserved, rep+c, &c);
    if (reserved != 0) {
        ret = EINVAL;
        goto done;
    }

    res = talloc_zero(tmp_ctx, struct sss_ssh_ent);
    if (!res) {
        ret = ENOMEM;
        goto done;
    }

    if (count > 0) {
        res->pubkeys = talloc_zero_array(res, struct sss_ssh_pubkey, count);
        if (!res->pubkeys) {
            ret = ENOMEM;
            goto done;
        }

        res->num_pubkeys = count;
    }
Пример #15
0
static int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr,
                                 uint8_t *buf, size_t *len)
{
    errno_t ret;
    size_t i, l, slen, ptmem, pad, dlen, glen;
    char *sbuf;
    uint32_t mem_num;
    uint32_t c;

    if (*len < 11) { /* not enough space for data, bad packet */
        return EBADMSG;
    }

    SAFEALIGN_COPY_UINT32(&c, buf, NULL);
    pr->result->gr_gid = c;
    SAFEALIGN_COPY_UINT32(&mem_num, buf+sizeof(uint32_t), NULL);

    sbuf = (char *)&buf[8];
    slen = *len - 8;
    dlen = pr->buflen;

    pr->result->gr_name = &(pr->buffer[0]);
    i = 0;

    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->gr_name,
                                  NULL);
    if (ret != EOK) return ret;

    pr->result->gr_passwd = &(pr->buffer[i]);
    ret = sss_readrep_copy_string(sbuf, &i,
                                  &slen, &dlen,
                                  &pr->result->gr_passwd,
                                  NULL);
    if (ret != EOK) return ret;

    /* Make sure pr->buffer[i+pad] is 32 bit aligned */
    pad = 0;
    while((i + pad) % 4) {
        pad++;
    }

    /* now members */
    pr->result->gr_mem = (char **)&(pr->buffer[i+pad]);
    ptmem = (sizeof(char *) * (mem_num + 1)) + pad;
    if (ptmem > dlen) {
        return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */
    }
    dlen -= ptmem;
    ptmem += i;
    pr->result->gr_mem[mem_num] = NULL; /* terminate array */

    for (l = 0; l < mem_num; l++) {
        pr->result->gr_mem[l] = &(pr->buffer[ptmem]);
        ret = sss_readrep_copy_string(sbuf, &i,
                                      &slen, &dlen,
                                      &pr->result->gr_mem[l],
                                      &glen);
        if (ret != EOK) return ret;

        ptmem += glen + 1;
    }

    *len = slen -i;
    return 0;
}