diff options
author | mturk <mturk@13f79535-47bb-0310-9956-ffa450edef68> | 2005-01-16 07:30:46 +0000 |
---|---|---|
committer | mturk <mturk@13f79535-47bb-0310-9956-ffa450edef68> | 2005-01-16 07:30:46 +0000 |
commit | 6489c816b5a63e87891fc62834802468056858d6 (patch) | |
tree | 0a9b23290364285a9658c3df99c4bfa3d929a60e | |
parent | dae8ad5c39d3a9b323a4952b02f1175b5dd25287 (diff) | |
download | libapr-6489c816b5a63e87891fc62834802468056858d6.tar.gz |
Added apr_procattr_user_set and apr_procattr_group_set to allow setting uid/gid for newly created processes using apr_proc_create.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@125349 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | include/apr.h.in | 2 | ||||
-rw-r--r-- | include/apr.hnw | 2 | ||||
-rw-r--r-- | include/apr.hw | 2 | ||||
-rw-r--r-- | include/apr_thread_proc.h | 21 | ||||
-rw-r--r-- | include/arch/unix/apr_arch_threadproc.h | 2 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_threadproc.h | 5 | ||||
-rw-r--r-- | threadproc/beos/proc.c | 13 | ||||
-rw-r--r-- | threadproc/netware/proc.c | 12 | ||||
-rw-r--r-- | threadproc/os2/proc.c | 13 | ||||
-rw-r--r-- | threadproc/unix/proc.c | 52 | ||||
-rw-r--r-- | threadproc/win32/proc.c | 152 |
12 files changed, 272 insertions, 7 deletions
@@ -1,5 +1,8 @@ Changes for APR 1.1.0 + *) Added apr_procattr_user_set and apr_procattr_group_set + setting the user and group for new processes. [Mladen Turk] + *) Add APR Multicast functions; including support for Source-Specific Multicast from Colm MacCarthaigh. [Paul Querna] diff --git a/include/apr.h.in b/include/apr.h.in index 47a8495da..d1332921d 100644 --- a/include/apr.h.in +++ b/include/apr.h.in @@ -227,6 +227,8 @@ extern "C" { #define APR_HAS_XTHREAD_FILES 0 #define APR_HAS_OS_UUID @osuuid@ +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 + /* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible * to poll on files/pipes. */ diff --git a/include/apr.hnw b/include/apr.hnw index 13a84e6d2..e8d14dc8b 100644 --- a/include/apr.hnw +++ b/include/apr.hnw @@ -194,6 +194,8 @@ extern "C" { #define APR_HAS_XTHREAD_FILES 0 #define APR_HAS_OS_UUID 0 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 + /* Netware can poll on files/pipes. */ #define APR_FILES_AS_SOCKETS 1 diff --git a/include/apr.hw b/include/apr.hw index cc26f3aa8..fa22e489a 100644 --- a/include/apr.hw +++ b/include/apr.hw @@ -223,9 +223,11 @@ #ifndef _WIN32_WCE #define APR_HAVE_STRICMP 1 #define APR_HAVE_STRNICMP 1 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 1 #else #define APR_HAVE_STRICMP 0 #define APR_HAVE_STRNICMP 0 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 #endif /** @} */ diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h index db591699f..fa0b97d3a 100644 --- a/include/apr_thread_proc.h +++ b/include/apr_thread_proc.h @@ -529,6 +529,27 @@ APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, apr_int32_t addrspace); +/** + * Set the username used for running process + * @param attr The procattr we care about. + * @param username The username used + * @param password User password if needed. Password is needed on WIN32 + * or any other platform having + * APR_PROCATTR_USER_SET_REQUIRES_PASSWORD set. + */ +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password); + +/** + * Set the group used for running process + * @param attr The procattr we care about. + * @param groupname The group name used + */ +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname); + + #if APR_HAS_FORK /** * This is currently the only non-portable call in APR. This executes diff --git a/include/arch/unix/apr_arch_threadproc.h b/include/arch/unix/apr_arch_threadproc.h index 6173869b4..c789bca97 100644 --- a/include/arch/unix/apr_arch_threadproc.h +++ b/include/arch/unix/apr_arch_threadproc.h @@ -97,6 +97,8 @@ struct apr_procattr_t { #endif apr_child_errfn_t *errfn; apr_int32_t errchk; + apr_uid_t uid; + apr_gid_t gid; }; #endif /* ! THREAD_PROC_H */ diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h index f752fd7df..ef8340ddd 100644 --- a/include/arch/win32/apr_arch_threadproc.h +++ b/include/arch/win32/apr_arch_threadproc.h @@ -56,6 +56,11 @@ struct apr_procattr_t { apr_int32_t detached; apr_child_errfn_t *errfn; apr_int32_t errchk; +#ifndef _WIN32_WCE + HANDLE user_token; + LPSECURITY_ATTRIBUTES sa; + LPVOID sd; +#endif }; struct apr_thread_once_t { diff --git a/threadproc/beos/proc.c b/threadproc/beos/proc.c index 71dd5a88f..9f1dd4cbb 100644 --- a/threadproc/beos/proc.c +++ b/threadproc/beos/proc.c @@ -403,3 +403,16 @@ APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32 { return APR_ENOTIMPL; } + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/netware/proc.c b/threadproc/netware/proc.c index fa23af6b7..7db665921 100644 --- a/threadproc/netware/proc.c +++ b/threadproc/netware/proc.c @@ -435,3 +435,15 @@ APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32 return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/os2/proc.c b/threadproc/os2/proc.c index 4edb45221..7fa9dc7c2 100644 --- a/threadproc/os2/proc.c +++ b/threadproc/os2/proc.c @@ -601,3 +601,16 @@ APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize) { return APR_ENOTIMPL; } + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/unix/proc.c b/threadproc/unix/proc.c index 9273c1124..45e967614 100644 --- a/threadproc/unix/proc.c +++ b/threadproc/unix/proc.c @@ -29,6 +29,7 @@ APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, } (*new)->pool = pool; (*new)->cmdtype = APR_PROGRAM; + (*new)->uid = (*new)->gid = -1; return APR_SUCCESS; } @@ -280,6 +281,36 @@ APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + apr_status_t rv; + apr_gid_t gid; + + if ((rv = apr_uid_get(&attr->uid, &gid, username, + attr->pool)) != APR_SUCCESS) { + attr->uid = -1; + return rv; + } + + /* Use default user group if not already set */ + if (attr->gid == -1) { + attr->gid = gid; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + apr_status_t rv; + + if ((rv = apr_gid_get(&attr->gid, groupname, attr->pool)) != APR_SUCCESS) + attr->gid = -1; + return rv; +} + APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname, const char * const *args, @@ -385,6 +416,27 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, } } + /* Only try to switch if we are running as root */ + if (attr->gid != -1 && !geteuid()) { + apr_status_t rv; + if ((status = setgid(attr->gid))) { + if (attr->errfn) { + attr->errfn(pool, errno, "setting of group failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + } + + if (attr->uid != -1 && !geteuid()) { + apr_status_t rv; + if ((status = setuid(attr->uid))) { + if (attr->errfn) { + attr->errfn(pool, errno, "setting of user failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + } + if ((status = limit_proc(attr)) != APR_SUCCESS) { if (attr->errfn) { attr->errfn(pool, errno, "setting of resource limits failed"); diff --git a/threadproc/win32/proc.c b/threadproc/win32/proc.c index 191d682d4..069a8e409 100644 --- a/threadproc/win32/proc.c +++ b/threadproc/win32/proc.c @@ -200,6 +200,116 @@ APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, return APR_SUCCESS; } +static apr_status_t attr_cleanup(void *theattr) +{ + apr_procattr_t *attr = (apr_procattr_t *)theattr; + if (attr->user_token) + CloseHandle(attr->user_token); + attr->user_token = NULL; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + HANDLE user; + apr_wchar_t *wusername = NULL; + apr_wchar_t *wpassword = NULL; + apr_status_t rv; + apr_size_t len, wlen; + + if (apr_os_level >= APR_WIN_NT_4) + { + if (attr->user_token) { + /* Cannot set that twice */ + if (attr->errfn) { + attr->errfn(attr->pool, 0, + apr_pstrcat(attr->pool, + "function called twice" + " on username: ", username, NULL)); + } + return APR_EINVAL; + } + len = strlen(username) + 1; + wlen = len; + wusername = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t)); + if ((rv = apr_conv_utf8_to_ucs2(username, &len, wusername, &wlen)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(attr->pool, rv, + apr_pstrcat(attr->pool, + "utf8 to ucs2 conversion failed" + " on username: ", username, NULL)); + } + return rv; + } + len = strlen(password) + 1; + wlen = len; + wpassword = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t)); + if ((rv = apr_conv_utf8_to_ucs2(password, &len, wpassword, &wlen)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(attr->pool, rv, + apr_pstrcat(attr->pool, + "utf8 to ucs2 conversion failed" + " on password: ", password, NULL)); + } + return rv; + } + if (!LogonUserW(wusername, + NULL, + wpassword, + LOGON32_LOGON_NETWORK, + LOGON32_PROVIDER_DEFAULT, + &user)) { + /* Logon Failed */ + return apr_get_os_error(); + } + memset(wpassword, 0, wlen * sizeof(apr_wchar_t)); + /* Get the primary token for user */ + if (!DuplicateTokenEx(user, + TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, + NULL, + SecurityImpersonation, + TokenPrimary, + &(attr->user_token))) { + /* Failed to duplicate the user token */ + rv = apr_get_os_error(); + CloseHandle(user); + return rv; + } + CloseHandle(user); + + attr->sd = apr_pcalloc(attr->pool, SECURITY_DESCRIPTOR_MIN_LENGTH); + InitializeSecurityDescriptor(attr->sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(attr->sd, -1, 0, 0); + attr->sa = apr_palloc(attr->pool, sizeof(SECURITY_ATTRIBUTES)); + attr->sa->nLength = sizeof (SECURITY_ATTRIBUTES); + attr->sa->lpSecurityDescriptor = attr->sd; + attr->sa->bInheritHandle = TRUE; + + /* register the cleanup */ + apr_pool_cleanup_register(attr->pool, (void *)attr, + attr_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; + } + else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + /* Always return SUCCESS cause groups are irrelevant */ + return APR_SUCCESS; +} + static const char* has_space(const char *str) { const char *ch; @@ -614,13 +724,36 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, ? attr->child_err->filehand : INVALID_HANDLE_VALUE; } - rv = CreateProcessW(wprg, wcmd, /* Executable & Command line */ - NULL, NULL, /* Proc & thread security attributes */ - TRUE, /* Inherit handles */ - dwCreationFlags, /* Creation flags */ - pEnvBlock, /* Environment block */ - wcwd, /* Current directory name */ - &si, &pi); + if (attr->user_token) { + si.lpDesktop = L"Winsta0\\Default"; + if (!ImpersonateLoggedOnUser(attr->user_token)) { + /* failed to impersonate the logged user */ + rv = apr_get_os_error(); + CloseHandle(attr->user_token); + attr->user_token = NULL; + return rv; + } + rv = CreateProcessAsUserW(attr->user_token, + wprg, wcmd, + attr->sa, + NULL, + TRUE, + dwCreationFlags, + pEnvBlock, + wcwd, + &si, &pi); + + RevertToSelf(); + } + else { + rv = CreateProcessW(wprg, wcmd, /* Executable & Command line */ + NULL, NULL, /* Proc & thread security attributes */ + TRUE, /* Inherit handles */ + dwCreationFlags, /* Creation flags */ + pEnvBlock, /* Environment block */ + wcwd, /* Current directory name */ + &si, &pi); + } #else rv = CreateProcessW(wprg, wcmd, /* Executable & Command line */ NULL, NULL, /* Proc & thread security attributes */ @@ -754,3 +887,8 @@ APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, } return apr_get_os_error(); } + +APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize) +{ + return APR_ENOTIMPL; +} |