Reputation: 21
I'm creating an application which listens on a port, and when a client makes a request, it spawns a new process with a different user using LogonUser,CreateProcessAsUser .
I've setup 2 events with CreateEvent() function to signal the child that WSADuplicateSocket is ready to pass the SOCKADD_STORAGEW structure to the child process via a memory mapped file.
The OpenEvent() in the child process keep failing with error 5 (access denied ) when it is spawned from the application.
If I manually run a child/client using (shift + right click, run as) the OpenEvent function successfully manages to open the event.
The event is created in the global namespace (Global\myevent) and for testing purposes I have created a null Dacl ( i have verified permission on the Event with winobj )passed to the the CreateEvent() function.
I don't see what I'm missing .
here the concerned code snippet:
Server:
SECURITY_ATTRIBUTES sa;
CreateNullDacl(&sa);
if ((ghParentFileMappingEvent = CreateEvent(&sa, TRUE, FALSE, szParentEventName)) == NULL) {
fprintf(stderr, "CreateEvent() failed: %d\n", GetLastError());
return false;
}
if ((ghChildFileMappingEvent = CreateEvent(&sa, TRUE, FALSE, szChildEventName)) == NULL) {
fprintf(stderr, "CreateEvent() failed: %d\n", GetLastError());
CloseHandle(ghParentFileMappingEvent);
return false;
}
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
SECURITY_ATTRIBUTES procSa;
CreateNullDacl(&procSa);
HANDLE htok;
if (!LogonUser(chall->user, ".", chall->pass, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &htok)) {
fprintf(stderr, "LogonUser() failed: %d\n", GetLastError());
return false;
}
if(CreateProcessAsUser(htok, 0, szChildComandLineBuf, &procSa, 0, FALSE, NULL, NULL, "C:\\Users\\ch99", &si, &pi)) {
//...
}
CLient spawned from CreateProcessAsUser()
if ((ghParentFileMappingEvent = OpenEventA(SYNCHRONIZE, FALSE, szParentEventName)) == 0) // return 5 , access denied
{
fprintf(fp, "OpenParentEvent failed: %d\n", GetLastError());
return INVALID_SOCKET;
}
if ((ghChildFileMappingEvent = OpenEventA(SYNCHRONIZE, FALSE, szChildEventName)) == 0) { // return 5 access denied
fprintf(fp, "OpenChildEvent failed: %d\n", GetLastError());
CloseHandle(ghParentFileMappingEvent);
ghParentFileMappingEvent = NULL;
return INVALID_SOCKET;
}
Thanks for your reply.
Upvotes: 1
Views: 565
Reputation: 21
After tried so many different thing, CreateEvent() keep returning access denied.
I have found a ugly workaround : in the SECURITY_ATTRIBUTES passed to CreateEvent() , i've set bInheritHandle to TRUE, and passed the handle value to the child process in argument .
At this point i'm able to use WaitForSingleObject() on the handle .
I'm realy curious to know why it didn't work as described in my first question...
Upvotes: 1
Reputation: 9700
Based on document of CreateProcessAsUser
:
A handle to the primary token that represents a user. The handle must have the TOKEN_QUERY, TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access rights.
The following code works for me:
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &htok))
printf("OpenProcessToken() failed: %d\n", GetLastError());
if (!CreateProcessAsUser(htok, L"childProc.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
printf("CreateProcessAsUser() failed: %d\n", GetLastError());
}
Or you can use CreateProcessWithToken
instead (this require run as administrator):
HANDLE htok;
if (!LogonUser(L"userName", L"domain", L"password", LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &htok)) {
printf("LogonUser() failed: %d\n", GetLastError());
return false;
}
if (!CreateProcessWithTokenW(htok, LOGON_WITH_PROFILE,L"childProc.exe", NULL, 0, NULL, NULL, &si, &pi)) {
printf("CreateProcessAsUser() failed: %d\n", GetLastError());
}
With both above methods, child process can open the event successfully.
For your code I get error code 1314 (A required privilege is not held by the client.) when calling CreateProcessAsUser
. Point out what am I missing and reproduce steps for your issue.
Upvotes: 0