Exemple #1
0
enum nss_status _nss_sss_endpwent(void)
{
    enum nss_status nret;
    int errnop;

    sss_nss_lock();

    /* make sure we do not have leftovers, and release memory */
    sss_nss_getpwent_data_clean();

    nret = sss_nss_make_request(SSS_NSS_ENDPWENT,
                                NULL, NULL, NULL, &errnop);
    if (nret != NSS_STATUS_SUCCESS) {
        errno = errnop;
    }

    sss_nss_unlock();
    return nret;
}
Exemple #2
0
static errno_t sss_mc_refresh_ent(const char *name, enum sss_tools_ent ent)
{
    enum sss_cli_command cmd;
    struct sss_cli_req_data rd;
    uint8_t *repbuf = NULL;
    size_t replen;
    enum nss_status nret;
    errno_t ret;

    cmd = SSS_CLI_NULL;
    switch (ent) {
        case SSS_TOOLS_USER:
            cmd = SSS_NSS_GETPWNAM;
            break;
        case SSS_TOOLS_GROUP:
            cmd = SSS_NSS_GETGRNAM;
            break;
    }

    if (cmd == SSS_CLI_NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d][%s] to refresh\n",
              cmd, sss_cmd2str(cmd));
        return EINVAL;
    }

    rd.data = name;
    rd.len = strlen(name) + 1;

    sss_nss_lock();
    nret = sss_nss_make_request(cmd, &rd, &repbuf, &replen, &ret);
    sss_nss_unlock();

    free(repbuf);
    if (nret != NSS_STATUS_SUCCESS && nret != NSS_STATUS_NOTFOUND) {
        return EIO;
    }

    return EOK;
}
Exemple #3
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);
}
Exemple #4
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;
}
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;
}
Exemple #6
0
enum nss_status _nss_sss_getgrgid_r(gid_t gid, 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;
    enum nss_status nret;
    uint32_t group_gid;
    int ret;

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

    ret = sss_nss_mc_getgrgid(gid, 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;
    }

    group_gid = gid;
    rd.len = sizeof(uint32_t);
    rd.data = &group_gid;

    sss_nss_lock();

    nret = sss_nss_get_getgr_cache(NULL, gid, GETGR_GID,
                                   &repbuf, &replen, errnop);
    if (nret == NSS_STATUS_NOTFOUND) {
        nret = sss_nss_make_request(SSS_NSS_GETGRGID, &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(NULL, gid, GETGR_GID, &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;
}
Exemple #7
0
enum nss_status _nss_sss_initgroups_dyn(const char *user, gid_t group,
                                        long int *start, long int *size,
                                        gid_t **groups, long int limit,
                                        int *errnop)
{
    struct sss_cli_req_data rd;
    uint8_t *repbuf;
    size_t replen;
    enum nss_status nret;
    uint32_t *rbuf;
    uint32_t num_ret;
    long int l, max_ret;

    rd.len = strlen(user) +1;
    rd.data = user;

    sss_nss_lock();

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

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

    /* check we have enough space in the buffer */
    if ((*size - *start) < num_ret) {
        long int newsize;
        gid_t *newgroups;

        newsize = *size + num_ret;
        if ((limit > 0) && (newsize > limit)) {
            newsize = limit;
            max_ret = newsize - *start;
        }

        newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups));
        if (!newgroups) {
            *errnop = ENOMEM;
            free(repbuf);
            nret = NSS_STATUS_TRYAGAIN;
            goto out;
        }
        *groups = newgroups;
        *size = newsize;
    }

    rbuf = &((uint32_t *)repbuf)[2];
    for (l = 0; l < max_ret; l++) {
        (*groups)[*start] = rbuf[l];
        *start += 1;
    }

    free(repbuf);
    nret = NSS_STATUS_SUCCESS;

out:
    sss_nss_unlock();
    return nret;
}