diff options
Diffstat (limited to 'src/nxt_process.c')
-rw-r--r-- | src/nxt_process.c | 335 |
1 files changed, 1 insertions, 334 deletions
diff --git a/src/nxt_process.c b/src/nxt_process.c index 0cb0fbdd..75c6ef25 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -14,8 +14,6 @@ #include <signal.h> static void nxt_process_start(nxt_task_t *task, nxt_process_t *process); -static nxt_int_t nxt_user_groups_get(nxt_task_t *task, nxt_mp_t *mp, - nxt_user_cred_t *uc); static nxt_int_t nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd); @@ -279,7 +277,7 @@ nxt_process_start(nxt_task_t *task, nxt_process_t *process) nxt_random_init(&thread->random); if (rt->capabilities.setid && init->user_cred != NULL) { - ret = nxt_user_cred_set(task, init->user_cred); + ret = nxt_credential_set(task, init->user_cred); if (ret != NXT_OK) { goto fail; } @@ -526,337 +524,6 @@ nxt_nanosleep(nxt_nsec_t ns) } -nxt_int_t -nxt_user_cred_get(nxt_task_t *task, nxt_mp_t *mp, nxt_user_cred_t *uc, - const char *group) -{ - struct group *grp; - struct passwd *pwd; - - nxt_errno = 0; - - pwd = getpwnam(uc->user); - - if (nxt_slow_path(pwd == NULL)) { - - if (nxt_errno == 0) { - nxt_alert(task, "getpwnam(\"%s\") failed, user \"%s\" not found", - uc->user, uc->user); - } else { - nxt_alert(task, "getpwnam(\"%s\") failed %E", uc->user, nxt_errno); - } - - return NXT_ERROR; - } - - uc->uid = pwd->pw_uid; - uc->base_gid = pwd->pw_gid; - - if (group != NULL && group[0] != '\0') { - nxt_errno = 0; - - grp = getgrnam(group); - - if (nxt_slow_path(grp == NULL)) { - - if (nxt_errno == 0) { - nxt_alert(task, - "getgrnam(\"%s\") failed, group \"%s\" not found", - group, group); - } else { - nxt_alert(task, "getgrnam(\"%s\") failed %E", group, nxt_errno); - } - - return NXT_ERROR; - } - - uc->base_gid = grp->gr_gid; - } - - nxt_debug(task, "about to get \"%s\" groups (uid:%d, base gid:%d)", - uc->user, uc->uid, uc->base_gid); - - if (nxt_user_groups_get(task, mp, uc) != NXT_OK) { - return NXT_ERROR; - } - -#if (NXT_DEBUG) - { - u_char *p, *end; - nxt_uint_t i; - u_char msg[NXT_MAX_ERROR_STR]; - - p = msg; - end = msg + NXT_MAX_ERROR_STR; - - for (i = 0; i < uc->ngroups; i++) { - p = nxt_sprintf(p, end, "%d%c", uc->gids[i], - i+1 < uc->ngroups ? ',' : '\0'); - } - - nxt_debug(task, "user \"%s\" has gids:%*s", uc->user, p - msg, msg); - } -#endif - - return NXT_OK; -} - - -#if (NXT_HAVE_GETGROUPLIST && !NXT_MACOSX) - -#define NXT_NGROUPS nxt_min(256, NGROUPS_MAX) - - -static nxt_int_t -nxt_user_groups_get(nxt_task_t *task, nxt_mp_t *mp, nxt_user_cred_t *uc) -{ - int ngroups; - gid_t groups[NXT_NGROUPS]; - - ngroups = NXT_NGROUPS; - - if (getgrouplist(uc->user, uc->base_gid, groups, &ngroups) < 0) { - if (nxt_slow_path(ngroups <= NXT_NGROUPS)) { - nxt_alert(task, "getgrouplist(\"%s\", %d, ...) failed %E", uc->user, - uc->base_gid, nxt_errno); - - return NXT_ERROR; - } - } - - if (ngroups > NXT_NGROUPS) { - if (ngroups > NGROUPS_MAX) { - ngroups = NGROUPS_MAX; - } - - uc->ngroups = ngroups; - - uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(gid_t)); - if (nxt_slow_path(uc->gids == NULL)) { - return NXT_ERROR; - } - - if (nxt_slow_path(getgrouplist(uc->user, uc->base_gid, uc->gids, - &ngroups) < 0)) { - - nxt_alert(task, "getgrouplist(\"%s\", %d) failed %E", uc->user, - uc->base_gid, nxt_errno); - - return NXT_ERROR; - } - - return NXT_OK; - } - - uc->ngroups = ngroups; - - uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(gid_t)); - if (nxt_slow_path(uc->gids == NULL)) { - return NXT_ERROR; - } - - nxt_memcpy(uc->gids, groups, ngroups * sizeof(gid_t)); - - return NXT_OK; -} - - -#else - -/* - * For operating systems that lack getgrouplist(3) or it's buggy (MacOS), - * nxt_user_groups_get() stores an array of groups IDs which should be - * set by the setgroups() function for a given user. The initgroups() - * may block a just forked worker process for some time if LDAP or NDIS+ - * is used, so nxt_user_groups_get() allows to get worker user groups in - * main process. In a nutshell the initgroups() calls getgrouplist() - * followed by setgroups(). However older Solaris lacks the getgrouplist(). - * Besides getgrouplist() does not allow to query the exact number of - * groups in some platforms, while NGROUPS_MAX can be quite large (e.g. - * 65536 on Linux). - * So nxt_user_groups_get() emulates getgrouplist(): at first the function - * saves the super-user groups IDs, then calls initgroups() and saves the - * specified user groups IDs, and then restores the super-user groups IDs. - * This works at least on Linux, FreeBSD, and Solaris, but does not work - * on MacOSX, getgroups(2): - * - * To provide compatibility with applications that use getgroups() in - * environments where users may be in more than {NGROUPS_MAX} groups, - * a variant of getgroups(), obtained when compiling with either the - * macros _DARWIN_UNLIMITED_GETGROUPS or _DARWIN_C_SOURCE defined, can - * be used that is not limited to {NGROUPS_MAX} groups. However, this - * variant only returns the user's default group access list and not - * the group list modified by a call to setgroups(2). - * - * For such cases initgroups() is used in worker process as fallback. - */ - -static nxt_int_t -nxt_user_groups_get(nxt_task_t *task, nxt_mp_t *mp, nxt_user_cred_t *uc) -{ - int nsaved, ngroups; - nxt_int_t ret; - nxt_gid_t *saved; - - nsaved = getgroups(0, NULL); - - if (nxt_slow_path(nsaved == -1)) { - nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); - return NXT_ERROR; - } - - nxt_debug(task, "getgroups(0, NULL): %d", nsaved); - - if (nsaved > NGROUPS_MAX) { - /* MacOSX case. */ - - uc->gids = NULL; - uc->ngroups = 0; - - return NXT_OK; - } - - saved = nxt_mp_alloc(mp, nsaved * sizeof(nxt_gid_t)); - - if (nxt_slow_path(saved == NULL)) { - return NXT_ERROR; - } - - ret = NXT_ERROR; - - nsaved = getgroups(nsaved, saved); - - if (nxt_slow_path(nsaved == -1)) { - nxt_alert(task, "getgroups(%d) failed %E", nsaved, nxt_errno); - goto free; - } - - nxt_debug(task, "getgroups(): %d", nsaved); - - if (initgroups(uc->user, uc->base_gid) != 0) { - if (nxt_errno == NXT_EPERM) { - nxt_log(task, NXT_LOG_NOTICE, - "initgroups(%s, %d) failed %E, ignored", - uc->user, uc->base_gid, nxt_errno); - - ret = NXT_OK; - - goto free; - - } else { - nxt_alert(task, "initgroups(%s, %d) failed %E", - uc->user, uc->base_gid, nxt_errno); - goto restore; - } - } - - ngroups = getgroups(0, NULL); - - if (nxt_slow_path(ngroups == -1)) { - nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); - goto restore; - } - - nxt_debug(task, "getgroups(0, NULL): %d", ngroups); - - uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(nxt_gid_t)); - - if (nxt_slow_path(uc->gids == NULL)) { - goto restore; - } - - ngroups = getgroups(ngroups, uc->gids); - - if (nxt_slow_path(ngroups == -1)) { - nxt_alert(task, "getgroups(%d) failed %E", ngroups, nxt_errno); - goto restore; - } - - uc->ngroups = ngroups; - - ret = NXT_OK; - -restore: - - if (nxt_slow_path(setgroups(nsaved, saved) != 0)) { - nxt_alert(task, "setgroups(%d) failed %E", nsaved, nxt_errno); - ret = NXT_ERROR; - } - -free: - - nxt_mp_free(mp, saved); - - return ret; -} - - -#endif - - -nxt_int_t -nxt_user_cred_set(nxt_task_t *task, nxt_user_cred_t *uc) -{ - nxt_debug(task, "user cred set: \"%s\" uid:%d base gid:%d", - uc->user, uc->uid, uc->base_gid); - - if (setgid(uc->base_gid) != 0) { - -#if (NXT_HAVE_CLONE) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The gid %d isn't valid in the " - "application namespace.", uc->base_gid); - return NXT_ERROR; - } -#endif - - nxt_alert(task, "setgid(%d) failed %E", uc->base_gid, nxt_errno); - return NXT_ERROR; - } - - if (uc->gids != NULL) { - if (setgroups(uc->ngroups, uc->gids) != 0) { - -#if (NXT_HAVE_CLONE) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The user \"%s\" (uid: %d) has " - "supplementary group ids not valid in the application " - "namespace.", uc->user, uc->uid); - return NXT_ERROR; - } -#endif - - nxt_alert(task, "setgroups(%i) failed %E", uc->ngroups, nxt_errno); - return NXT_ERROR; - } - - } else { - /* MacOSX fallback. */ - if (initgroups(uc->user, uc->base_gid) != 0) { - nxt_alert(task, "initgroups(%s, %d) failed %E", - uc->user, uc->base_gid, nxt_errno); - return NXT_ERROR; - } - } - - if (setuid(uc->uid) != 0) { - -#if (NXT_HAVE_CLONE) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The uid %d (user \"%s\") isn't " - "valid in the application namespace.", uc->uid, uc->user); - return NXT_ERROR; - } -#endif - - nxt_alert(task, "setuid(%d) failed %E", uc->uid, nxt_errno); - return NXT_ERROR; - } - - return NXT_OK; -} - - void nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i) { |