Index: third_party/psutil/psutil/arch/mswindows/security.c |
diff --git a/third_party/psutil/psutil/arch/mswindows/security.c b/third_party/psutil/psutil/arch/mswindows/security.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ee6ff9d0fce1a86c88a2711b8a99d09e18373e51 |
--- /dev/null |
+++ b/third_party/psutil/psutil/arch/mswindows/security.c |
@@ -0,0 +1,233 @@ |
+/* |
+ * $Id: security.c 772 2010-11-03 13:51:11Z g.rodola $ |
+ * |
+ * Security related functions for Windows platform (Set privileges such as |
+ * SeDebug), as well as security helper functions. |
+ */ |
+ |
+#include <windows.h> |
+#include <Python.h> |
+ |
+/* |
+ * Convert a process handle to a process token handle. |
+ */ |
+HANDLE |
+token_from_handle(HANDLE hProcess) { |
+ HANDLE hToken = NULL; |
+ |
+ if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken) ) { |
+ return PyErr_SetFromWindowsErr(0); |
+ } |
+ |
+ return hToken; |
+} |
+ |
+ |
+/* |
+ * http://www.ddj.com/windows/184405986 |
+ * |
+ * theres a way to determine whether were running under the Local System |
+ * account. However (you guessed it), we have to call more Win32 functions to |
+ * determine this. Backing up through the code listing, we need to make another |
+ * call to GetTokenInformation, but instead of passing through the TOKEN_USER |
+ * constant, we pass through the TOKEN_PRIVILEGES constant. This value returns |
+ * an array of privileges that the account has in the environment. Iterating |
+ * through the array, we call the function LookupPrivilegeName looking for the |
+ * string SeTcbPrivilege. If the function returns this string, then this |
+ * account has Local System privileges |
+ */ |
+int HasSystemPrivilege(HANDLE hProcess) { |
+ DWORD i; |
+ DWORD dwSize = 0; |
+ DWORD dwRetval = 0; |
+ TCHAR privName[256]; |
+ DWORD dwNameSize = 256; |
+ //PTOKEN_PRIVILEGES tp = NULL; |
+ BYTE *pBuffer = NULL; |
+ TOKEN_PRIVILEGES* tp = NULL; |
+ HANDLE hToken = token_from_handle(hProcess); |
+ |
+ if (NULL == hToken) { |
+ return -1; |
+ } |
+ |
+ // call GetTokenInformation first to get the buffer size |
+ if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) { |
+ dwRetval = GetLastError(); |
+ // if it failed for a reason other than the buffer, bail out |
+ if (dwRetval != ERROR_INSUFFICIENT_BUFFER ) { |
+ PyErr_SetFromWindowsErr(dwRetval); |
+ return 0; |
+ } |
+ } |
+ |
+ // allocate buffer and call GetTokenInformation again |
+ //tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize); |
+ pBuffer = (BYTE *) malloc(dwSize); |
+ |
+ if (pBuffer == NULL) { |
+ PyErr_SetFromWindowsErr(0); |
+ LocalFree(pBuffer); |
+ return -1; |
+ } |
+ |
+ if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwSize, &dwSize) ) { |
+ PyErr_SetFromWindowsErr(0); |
+ LocalFree(pBuffer); |
+ return -1; |
+ } |
+ |
+ // convert the BYTE buffer to a TOKEN_PRIVILEGES struct pointer |
+ tp = (TOKEN_PRIVILEGES*)pBuffer; |
+ |
+ // check all the privileges looking for SeTcbPrivilege |
+ for(i=0; i < tp->PrivilegeCount; i++) { |
+ // reset the buffer contents and the buffer size |
+ strcpy(privName, ""); |
+ dwNameSize = sizeof(privName) / sizeof(TCHAR); |
+ if (! LookupPrivilegeName(NULL, |
+ &tp->Privileges[i].Luid, |
+ (LPTSTR)privName, |
+ &dwNameSize)) { |
+ |
+ PyErr_SetFromWindowsErr(0); |
+ free(pBuffer); |
+ return -1; |
+ } |
+ |
+ // if we find the SeTcbPrivilege then it's a LocalSystem process |
+ if (! lstrcmpi(privName, TEXT("SeTcbPrivilege"))) { |
+ free(pBuffer); |
+ return 1; |
+ } |
+ |
+ } //for |
+ |
+ free(pBuffer); |
+ return 0; |
+} |
+ |
+ |
+BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) |
+{ |
+ TOKEN_PRIVILEGES tp; |
+ LUID luid; |
+ TOKEN_PRIVILEGES tpPrevious; |
+ DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES); |
+ |
+ if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; |
+ |
+ // first pass. get current privilege setting |
+ tp.PrivilegeCount = 1; |
+ tp.Privileges[0].Luid = luid; |
+ tp.Privileges[0].Attributes = 0; |
+ |
+ AdjustTokenPrivileges( |
+ hToken, |
+ FALSE, |
+ &tp, |
+ sizeof(TOKEN_PRIVILEGES), |
+ &tpPrevious, |
+ &cbPrevious |
+ ); |
+ |
+ if (GetLastError() != ERROR_SUCCESS) return FALSE; |
+ |
+ // second pass. set privilege based on previous setting |
+ tpPrevious.PrivilegeCount = 1; |
+ tpPrevious.Privileges[0].Luid = luid; |
+ |
+ if(bEnablePrivilege) { |
+ tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); |
+ } |
+ |
+ else { |
+ tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & |
+ tpPrevious.Privileges[0].Attributes); |
+ } |
+ |
+ AdjustTokenPrivileges( |
+ hToken, |
+ FALSE, |
+ &tpPrevious, |
+ cbPrevious, |
+ NULL, |
+ NULL |
+ ); |
+ |
+ if (GetLastError() != ERROR_SUCCESS) return FALSE; |
+ |
+ return TRUE; |
+} |
+ |
+ |
+int SetSeDebug() |
+{ |
+ HANDLE hToken; |
+ if(! OpenThreadToken(GetCurrentThread(), |
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, |
+ FALSE, |
+ &hToken) |
+ ){ |
+ if (GetLastError() == ERROR_NO_TOKEN){ |
+ if (!ImpersonateSelf(SecurityImpersonation)){ |
+ //Log2File("Error setting impersonation [SetSeDebug()]", L_DEBUG); |
+ return 0; |
+ } |
+ if (!OpenThreadToken(GetCurrentThread(), |
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, |
+ FALSE, |
+ &hToken) |
+ ){ |
+ //Log2File("Error Opening Thread Token", L_DEBUG); |
+ return 0; |
+ } |
+ } |
+ } |
+ |
+ // enable SeDebugPrivilege (open any process) |
+ if (! SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)){ |
+ //Log2File("Error setting SeDebug Privilege [SetPrivilege()]", L_WARN); |
+ return 0; |
+ } |
+ |
+ CloseHandle(hToken); |
+ return 1; |
+} |
+ |
+ |
+int UnsetSeDebug() |
+{ |
+ HANDLE hToken; |
+ if(! OpenThreadToken(GetCurrentThread(), |
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, |
+ FALSE, |
+ &hToken) |
+ ){ |
+ if(GetLastError() == ERROR_NO_TOKEN){ |
+ if(! ImpersonateSelf(SecurityImpersonation)){ |
+ //Log2File("Error setting impersonation! [UnsetSeDebug()]", L_DEBUG); |
+ return 0; |
+ } |
+ |
+ if(!OpenThreadToken(GetCurrentThread(), |
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, |
+ FALSE, |
+ &hToken) |
+ ){ |
+ //Log2File("Error Opening Thread Token! [UnsetSeDebug()]", L_DEBUG); |
+ return 0; |
+ } |
+ } |
+ } |
+ |
+ //now disable SeDebug |
+ if(!SetPrivilege(hToken, SE_DEBUG_NAME, FALSE)){ |
+ //Log2File("Error unsetting SeDebug Privilege [SetPrivilege()]", L_WARN); |
+ return 0; |
+ } |
+ |
+ CloseHandle(hToken); |
+ return 1; |
+} |
+ |