Hi all,
Here is the patch that uses new function apr_procattr_user_set. It is conditionally compiled and if called before creating process, ensures that the process is created under different credentials.
The usage of such function is for httpd, to allow running the child process under different security, as well as cgi processes.
Those kind of thing is missing in httpd on WIN32, and increases the security to a higher level. Running child under different account IIS offers for long time by default, so this would be one 'attribute' less.
Regards, MT.
Index: apr_thread_proc.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_thread_proc.h,v
retrieving revision 1.112
diff -u -r1.112 apr_thread_proc.h
--- apr_thread_proc.h 23 Jun 2004 12:52:49 -0000 1.112
+++ apr_thread_proc.h 26 Aug 2004 10:20:52 -0000
@@ -472,6 +472,18 @@
APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr,
apr_int32_t detach);
+#if APR_HAVE_USER_SET
+/**
+ * Set the username and password used for creating process.
+ * @param attr The procattr we care about.
+ * @param username Username for creating process.
+ * @param passwor Password for username.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr,
+ const char *username,
+ const char *password);
+#endif
+
#if APR_HAVE_STRUCT_RLIMIT
/**
* Set the Resource Utilization limits when starting a new process.
Index: apr.hnw
===================================================================
RCS file: /home/cvspublic/apr/include/apr.hnw,v
retrieving revision 1.46
diff -u -r1.46 apr.hnw
--- apr.hnw 4 Jun 2004 23:22:00 -0000 1.46
+++ apr.hnw 26 Aug 2004 10:12:48 -0000
@@ -193,7 +193,8 @@
#define APR_HAS_LARGE_FILES 1
#define APR_HAS_XTHREAD_FILES 0
#define APR_HAS_OS_UUID 0
-
+#define APR_HAVE_USER_SET 0
+
/* Netware can poll on files/pipes.
*/
#define APR_FILES_AS_SOCKETS 1
Index: apr.hw
===================================================================
RCS file: /home/cvspublic/apr/include/apr.hw,v
retrieving revision 1.124
diff -u -r1.124 apr.hw
--- apr.hw 4 Jun 2004 23:22:00 -0000 1.124
+++ apr.hw 26 Aug 2004 09:59:36 -0000
@@ -223,9 +223,11 @@
#ifndef _WIN32_WCE
#define APR_HAVE_STRICMP 1
#define APR_HAVE_STRNICMP 1
+#define APR_HAVE_USER_SET 1
#else
#define APR_HAVE_STRICMP 0
#define APR_HAVE_STRNICMP 0
+#define APR_HAVE_USER_SET 0
#endif
/** @} */
Index: apr.h.in
===================================================================
RCS file: /home/cvspublic/apr/include/apr.h.in,v
retrieving revision 1.137
diff -u -r1.137 apr.h.in
--- apr.h.in 5 Jun 2004 11:52:43 -0000 1.137
+++ apr.h.in 26 Aug 2004 10:13:04 -0000
@@ -220,7 +220,8 @@
#define APR_HAS_LARGE_FILES @aprlfs@
#define APR_HAS_XTHREAD_FILES 0
#define APR_HAS_OS_UUID 0
-
+#define APR_HAVE_USER_SET 0
+
/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
* to poll on files/pipes.
*/
Index: apr_arch_threadproc.h
===================================================================
RCS file: /home/cvspublic/apr/include/arch/win32/apr_arch_threadproc.h,v
retrieving revision 1.4
diff -u -r1.4 apr_arch_threadproc.h
--- apr_arch_threadproc.h 24 Aug 2004 01:43:34 -0000 1.4
+++ apr_arch_threadproc.h 26 Aug 2004 12:36:54 -0000
@@ -56,6 +56,11 @@
apr_int32_t detached;
apr_child_errfn_t *errfn;
apr_int32_t errchk;
+#if APR_HAVE_USER_SET
+ HANDLE user_token;
+ LPSECURITY_ATTRIBUTES sa;
+ LPVOID sd;
+#endif
};
struct apr_thread_once_t {
Index: proc.c
===================================================================
RCS file: /home/cvspublic/apr/threadproc/win32/proc.c,v
retrieving revision 1.94
diff -u -r1.94 proc.c
--- proc.c 24 Aug 2004 01:43:34 -0000 1.94
+++ proc.c 26 Aug 2004 12:38:51 -0000
@@ -200,6 +200,89 @@
return APR_SUCCESS;
}
+#if APR_HAVE_USER_SET
+APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr,
+ const char *username,
+ const char *password)
+{
+ HANDLE user;
+ apr_wchar_t *wusername = NULL;
+ apr_wchar_t *wpassword = NULL;
+ apr_status_t rv;
+
+ if (apr_os_level >= APR_WIN_NT_4)
+ {
+ apr_size_t len = strlen(username) + 1;
+ apr_size_t 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();
+ }
+ /* 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);
+ 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;
+ }
+
+ 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;
+ return APR_SUCCESS;
+ }
+ else
+ return APR_ENOTIMPL;
+
+}
+#endif
+
static const char* has_space(const char *str)
{
const char *ch;
@@ -614,13 +697,29 @@
? 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";
+ 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 */
@@ -678,7 +777,6 @@
*/
if (!rv)
return apr_get_os_error();
-
/* XXX Orphaned handle warning - no fix due to broken apr_proc_t api.
*/
new->hproc = pi.hProcess;
Index: testproc.c
===================================================================
RCS file: /home/cvspublic/apr/test/testproc.c,v
retrieving revision 1.46
diff -u -r1.46 testproc.c
--- testproc.c 14 May 2004 14:43:22 -0000 1.46
+++ testproc.c 26 Aug 2004 11:52:25 -0000
@@ -21,6 +21,11 @@
#include "testutil.h"
#define TESTSTR "This is a test"
+/* You will need to create an account with
+ * 'Replace a process level token' priviledge set.
+ */
+#define USERNAME "test"
+#define PASSWORD "test"
static apr_proc_t newproc;
@@ -46,13 +51,19 @@
rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+#if APR_HAVE_USER_SET
+ rv = apr_procattr_user_set(attr, USERNAME, PASSWORD);
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+#endif
+
args[0] = "proc_child" EXTENSION;
args[1] = NULL;
rv = apr_proc_create(&newproc, "../proc_child" EXTENSION, args, NULL,
attr, p);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
-
+ if (rv)
+ return;
testfile = newproc.in;
length = strlen(TESTSTR);
smime.p7s
Description: S/MIME Cryptographic Signature
