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; }
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; }
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); }
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; }
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; }
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; }