summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormturk <mturk@13f79535-47bb-0310-9956-ffa450edef68>2005-01-16 07:30:46 +0000
committermturk <mturk@13f79535-47bb-0310-9956-ffa450edef68>2005-01-16 07:30:46 +0000
commit6489c816b5a63e87891fc62834802468056858d6 (patch)
tree0a9b23290364285a9658c3df99c4bfa3d929a60e
parentdae8ad5c39d3a9b323a4952b02f1175b5dd25287 (diff)
downloadlibapr-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--CHANGES3
-rw-r--r--include/apr.h.in2
-rw-r--r--include/apr.hnw2
-rw-r--r--include/apr.hw2
-rw-r--r--include/apr_thread_proc.h21
-rw-r--r--include/arch/unix/apr_arch_threadproc.h2
-rw-r--r--include/arch/win32/apr_arch_threadproc.h5
-rw-r--r--threadproc/beos/proc.c13
-rw-r--r--threadproc/netware/proc.c12
-rw-r--r--threadproc/os2/proc.c13
-rw-r--r--threadproc/unix/proc.c52
-rw-r--r--threadproc/win32/proc.c152
12 files changed, 272 insertions, 7 deletions
diff --git a/CHANGES b/CHANGES
index c37f27f42..eb6a40958 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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;
+}