コード例 #1
0
ファイル: nss_passwd.c プロジェクト: 3van/sssd
enum nss_status _nss_sss_getpwnam_r(const char *name, 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, name_len;
    uint32_t num_results;
    enum nss_status nret;
    int ret;

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

    ret = sss_strnlen(name, SSS_NAME_MAX, &name_len);
    if (ret != 0) {
        *errnop = EINVAL;
        return NSS_STATUS_NOTFOUND;
    }

    ret = sss_nss_mc_getpwnam(name, name_len, 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;
    }

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

    sss_nss_lock();

    /* previous thread might already initialize entry in mmap cache */
    ret = sss_nss_mc_getpwnam(name, name_len, 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_GETPWNAM, &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;
}
コード例 #2
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;
}
コード例 #3
0
ファイル: sss_autofs.c プロジェクト: stefwalter/sssd
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;
}
コード例 #4
0
ファイル: sss_autofs.c プロジェクト: stefwalter/sssd
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;
}
コード例 #5
0
ファイル: sss_autofs.c プロジェクト: stefwalter/sssd
errno_t
_sss_getautomntent_r(char **key, char **value, void *context)
{
    int errnop;
    errno_t ret;
    size_t name_len;
    struct sss_cli_req_data rd;
    uint8_t *repbuf = NULL;
    size_t replen;
    struct automtent *ctx;
    size_t ctr = 0;
    size_t data_len = 0;
    uint8_t *data;

    sss_nss_lock();

    ctx = (struct automtent *) context;
    if (!ctx) {
        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_getautomntent_data_return(ctx->mapname, key, value);
    if (ret == EOK) {
        /* The results are available from cache. Just advance the
         * cursor and return. */
        ctx->cursor++;
        ret = 0;
        goto out;
    }
    /* Don't try to handle any error codes, just go to the responder again */

    data_len = sizeof(uint32_t) +            /* mapname len */
               name_len + 1 +                /* mapname\0   */
               sizeof(uint32_t) +            /* index into the map */
               sizeof(uint32_t);             /* num entries to retreive */

    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, ctx->cursor, &ctr);

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

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

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

    /* Got reply, let's save it and return from "cache" */
    ret = sss_getautomntent_data_save(ctx->mapname, &repbuf, replen);
    if (ret == ENOENT) {
        /* No results */
        *key = NULL;
        *value = NULL;
        goto out;
    } else if (ret != EOK) {
        /* Unexpected error */
        goto out;
    }

    ret = sss_getautomntent_data_return(ctx->mapname, key, value);
    if (ret != EOK) {
        goto out;
    }

    /* Advance the cursor so that we'll fetch the next map
     * next time getautomntent is called */
    ctx->cursor++;
    ret = 0;
out:
    sss_nss_unlock();
    return ret;
}
コード例 #6
0
ファイル: nss_group.c プロジェクト: nguay/SSSD
enum nss_status _nss_sss_getgrnam_r(const char *name, struct group *result,
                                    char *buffer, size_t buflen, int *errnop)
{
    struct sss_cli_req_data rd;
    struct sss_nss_gr_rep grrep;
    uint8_t *repbuf;
    size_t replen, len, name_len;
    enum nss_status nret;
    int ret;

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

    ret = sss_strnlen(name, SSS_NAME_MAX, &name_len);
    if (ret != 0) {
        *errnop = EINVAL;
        return NSS_STATUS_NOTFOUND;
    }

    ret = sss_nss_mc_getgrnam(name, name_len, 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;
    case EINVAL:
        /* if using the mmaped cache failed,
         * fall back to socket based comms */
        break;
    default:
        *errnop = EBADMSG;
        return NSS_STATUS_TRYAGAIN;
    }

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

    sss_nss_lock();

    nret = sss_nss_get_getgr_cache(name, 0, GETGR_NAME,
                                   &repbuf, &replen, errnop);
    if (nret == NSS_STATUS_NOTFOUND) {
        nret = sss_nss_make_request(SSS_NSS_GETGRNAM, &rd,
                                    &repbuf, &replen, errnop);
    }
    if (nret != NSS_STATUS_SUCCESS) {
        goto out;
    }

    grrep.result = result;
    grrep.buffer = buffer;
    grrep.buflen = buflen;

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

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

    len = replen - 8;
    ret = sss_nss_getgr_readrep(&grrep, repbuf+8, &len);
    if (ret == ERANGE) {
        sss_nss_save_getgr_cache(name, 0, GETGR_NAME, &repbuf, replen);
    } else {
        free(repbuf);
    }
    if (ret) {
        *errnop = ret;
        nret = NSS_STATUS_TRYAGAIN;
        goto out;
    }

    nret = NSS_STATUS_SUCCESS;

out:
    sss_nss_unlock();
    return nret;
}