CreateProcess - file privileges
-
K I know theres loads on this topic but couldnt find anything which solves my dilemma. I have a multi-threaded service with a time event which is monitored using cached information in a singleton com object i then wish to launch a process in a given directory i.e. zip some files up - Scheduler kindof app. Now my problem is I've been using CreateProcess with no probs - however here it comes if I set the directory for which I wish to launch the process to have permissions for only a certain user - ie full control and i remove the everyone group then I get the error: "the client does not have the required permissions." :( Now I get this error 1: When Im debugging the service i.e. Im logged in as fred, and fred has the full access permissions on the directory in question. 2: When I set the service to use the same account and not the system account. Now I looked into CreateProcessAsUser using LoginUser with the token - same problem. Not the best solution if it worked as i dont wish to pass or store the login credentials would much rather use the security credentials of the process so hence looked at: GetCurrentProcess, OpenProcessToken and AdjustTokenPrivileges. Still to no avail now i know i must be doing some wrong and missing something obvious so would appreciate any help. Heres a snippet not clean but general idea: HANDLE HToken = NULL; DWORD dwAccess = TOKEN_ALL_ACCESS; HANDLE hServProcess = GetCurrentProcess (); if (OpenProcessToken (hServProcess, dwAccess, &HToken)) { LUID luid; TOKEN_PRIVILEGES newState, oldState; DWORD rl; LookupPrivilegeValue (_T(""), SE_SECURITY_NAME, &luid); newState.PrivilegeCount = 1; newState.Privileges[0].Luid = luid; newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges (HToken, FALSE, &newState , sizeof(oldState), &oldState, &rl)) { rl = GetLastError(); return rl; } // execute zip process if(CreateProcessAsUser(HToken , NULL , settings , NULL , NULL , TRUE , CREATE_NO_WINDOW , NULL , m_pSchedule->DirectoryBuff , &st , &proc) == 0); } Many thx to anyone who responds - sorry its a long post
-
K I know theres loads on this topic but couldnt find anything which solves my dilemma. I have a multi-threaded service with a time event which is monitored using cached information in a singleton com object i then wish to launch a process in a given directory i.e. zip some files up - Scheduler kindof app. Now my problem is I've been using CreateProcess with no probs - however here it comes if I set the directory for which I wish to launch the process to have permissions for only a certain user - ie full control and i remove the everyone group then I get the error: "the client does not have the required permissions." :( Now I get this error 1: When Im debugging the service i.e. Im logged in as fred, and fred has the full access permissions on the directory in question. 2: When I set the service to use the same account and not the system account. Now I looked into CreateProcessAsUser using LoginUser with the token - same problem. Not the best solution if it worked as i dont wish to pass or store the login credentials would much rather use the security credentials of the process so hence looked at: GetCurrentProcess, OpenProcessToken and AdjustTokenPrivileges. Still to no avail now i know i must be doing some wrong and missing something obvious so would appreciate any help. Heres a snippet not clean but general idea: HANDLE HToken = NULL; DWORD dwAccess = TOKEN_ALL_ACCESS; HANDLE hServProcess = GetCurrentProcess (); if (OpenProcessToken (hServProcess, dwAccess, &HToken)) { LUID luid; TOKEN_PRIVILEGES newState, oldState; DWORD rl; LookupPrivilegeValue (_T(""), SE_SECURITY_NAME, &luid); newState.PrivilegeCount = 1; newState.Privileges[0].Luid = luid; newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges (HToken, FALSE, &newState , sizeof(oldState), &oldState, &rl)) { rl = GetLastError(); return rl; } // execute zip process if(CreateProcessAsUser(HToken , NULL , settings , NULL , NULL , TRUE , CREATE_NO_WINDOW , NULL , m_pSchedule->DirectoryBuff , &st , &proc) == 0); } Many thx to anyone who responds - sorry its a long post
Try this, but instead of using SE_SHUTDOWN_NAME use SE_SECURITY_NAME BOOL bSuccess = FALSE; HANDLE hTokenHandle; // First off , get a handle for this process HANDLE hProcess = GetCurrentProcess(); LUID tmpLuid; TOKEN_PRIVILEGES tkp, tkpNewButIgnored; DWORD lBufferNeeded; // Now open the Attribute Token //bSuccess = OpenProcessToken(hProcess, 0x20 | 0x08, &hTokenHandle); bSuccess = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenHandle); // Get the present attribute bSuccess = LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME , &tmpLuid); // now change it tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = tmpLuid; //tkp.Privileges[0].Attributes = 0x02; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bSuccess = AdjustTokenPrivileges(hTokenHandle, FALSE, &tkp, sizeof(tkpNewButIgnored), &tkpNewButIgnored, &lBufferNeeded); if(bSuccess == FALSE){ CString sErr = FormatSystemError(GetLastError()); ::MessageBox(NULL, sErr, "", MB_OK); } bSuccess = CloseHandle(hTokenHandle); ps. FormatSystemError(DWORD dwError) is my own function CString CMainDlg::FormatSystemError(DWORD dwErr, BOOL bWithMsgBox){ LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default //MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), // US English (LPTSTR) &lpMsgBuf, 0, NULL ); if(bWithMsgBox == TRUE){ ::MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); } CString _s((LPCSTR)lpMsgBuf); LocalFree(lpMsgBuf); return _s; }
-
Try this, but instead of using SE_SHUTDOWN_NAME use SE_SECURITY_NAME BOOL bSuccess = FALSE; HANDLE hTokenHandle; // First off , get a handle for this process HANDLE hProcess = GetCurrentProcess(); LUID tmpLuid; TOKEN_PRIVILEGES tkp, tkpNewButIgnored; DWORD lBufferNeeded; // Now open the Attribute Token //bSuccess = OpenProcessToken(hProcess, 0x20 | 0x08, &hTokenHandle); bSuccess = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenHandle); // Get the present attribute bSuccess = LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME , &tmpLuid); // now change it tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = tmpLuid; //tkp.Privileges[0].Attributes = 0x02; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bSuccess = AdjustTokenPrivileges(hTokenHandle, FALSE, &tkp, sizeof(tkpNewButIgnored), &tkpNewButIgnored, &lBufferNeeded); if(bSuccess == FALSE){ CString sErr = FormatSystemError(GetLastError()); ::MessageBox(NULL, sErr, "", MB_OK); } bSuccess = CloseHandle(hTokenHandle); ps. FormatSystemError(DWORD dwError) is my own function CString CMainDlg::FormatSystemError(DWORD dwErr, BOOL bWithMsgBox){ LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default //MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), // US English (LPTSTR) &lpMsgBuf, 0, NULL ); if(bWithMsgBox == TRUE){ ::MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); } CString _s((LPCSTR)lpMsgBuf); LocalFree(lpMsgBuf); return _s; }
Many thx. Looks like it solved the problem with the privileges only problem now is the call to CreateProcessAsUser fails with GetLastError returning "The Operation completed successfully" :( and no, the process was not started. if(CreateProcessAsUser(HToken , NULL , "myapp.exe" // present in system32 , NULL , NULL , TRUE , NORMAL_PRIORITY_CLASS , NULL , m_pSchedule->DirectoryBuff , &st , &proc) == 0) { ... GetLastError, CloseHandle(HToken), return } CloseHandle(HToken); btw Im launching a dos program (I dont wish to c the window) - before, when using CreateProcess, I was using the flag CREATE_NOWINDOW which was successful.
-
Many thx. Looks like it solved the problem with the privileges only problem now is the call to CreateProcessAsUser fails with GetLastError returning "The Operation completed successfully" :( and no, the process was not started. if(CreateProcessAsUser(HToken , NULL , "myapp.exe" // present in system32 , NULL , NULL , TRUE , NORMAL_PRIORITY_CLASS , NULL , m_pSchedule->DirectoryBuff , &st , &proc) == 0) { ... GetLastError, CloseHandle(HToken), return } CloseHandle(HToken); btw Im launching a dos program (I dont wish to c the window) - before, when using CreateProcess, I was using the flag CREATE_NOWINDOW which was successful.
I do not know about creating a process as a user, but I did the following.. CString _sTitle("Title of the window"); STARTUPINFO stInfo; PROCESS_INFORMATION psInfo; ZeroMemory(&stInfo, sizeof(STARTUPINFO)); ZeroMemory(&psInfo, sizeof(PROCESS_INFORMATION)); stInfo.cb = sizeof(stInfo); stInfo.cbReserved2 = NULL; stInfo.lpDesktop = NULL; stInfo.dwFlags = STARTF_USESHOWWINDOW; stInfo.wShowWindow = SW_SHOW; stInfo.lpTitle = _sTitle.GetBuffer(_sTitle.GetLength()); _sTitle.ReleaseBuffer(); CreateProcess("watchdog.exe", "cmdline params" , NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE , NULL, NULL, &stInfo, &psInfo); // Wait a bit for the process to init // But maximal 5 seconds WaitForInputIdle(psInfo.hProcess, 5000); It might be that the process is initializing ?
-
I do not know about creating a process as a user, but I did the following.. CString _sTitle("Title of the window"); STARTUPINFO stInfo; PROCESS_INFORMATION psInfo; ZeroMemory(&stInfo, sizeof(STARTUPINFO)); ZeroMemory(&psInfo, sizeof(PROCESS_INFORMATION)); stInfo.cb = sizeof(stInfo); stInfo.cbReserved2 = NULL; stInfo.lpDesktop = NULL; stInfo.dwFlags = STARTF_USESHOWWINDOW; stInfo.wShowWindow = SW_SHOW; stInfo.lpTitle = _sTitle.GetBuffer(_sTitle.GetLength()); _sTitle.ReleaseBuffer(); CreateProcess("watchdog.exe", "cmdline params" , NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE , NULL, NULL, &stInfo, &psInfo); // Wait a bit for the process to init // But maximal 5 seconds WaitForInputIdle(psInfo.hProcess, 5000); It might be that the process is initializing ?
Thx Phil for the reply - yeah CreateProcess works fine was using that before but CreateProcessAsUser is the painful culprit :( unfortunately I'm still left with an uninitialised PROCESS_INFORMATION object when the call fails - and GetLastError says it completed successfully :(