errno_t _sss_endautomntent(void **context) { struct automtent *fctx; errno_t ret; int errnop; if (!context) return 0; sss_nss_lock(); sss_getautomntent_data_clean(); fctx = (struct automtent *) *context; free(fctx->mapname); free(fctx); sss_autofs_make_request(SSS_AUTOFS_ENDAUTOMNTENT, NULL, NULL, NULL, &errnop); if (errnop != 0) { ret = errnop; goto out; } ret = 0; out: sss_nss_unlock(); return ret; }
enum nss_status _nss_sss_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { enum nss_status nret; sss_nss_lock(); nret = internal_getgrent_r(result, buffer, buflen, errnop); sss_nss_unlock(); return nret; }
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; }
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; }
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; }
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; }
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; }
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; }