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