1 /* 2 * $Header$ 3 * 4 * Copyright 2008 Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include <windows.h> 28 #include "secure.hxx" 29 30 extern "C" { 31 #include "cci_debugging.h" 32 } 33 34 CcOsLock SecureClient::s_lock; 35 DWORD SecureClient::s_refcount = 0; 36 DWORD SecureClient::s_error = 0; 37 HANDLE SecureClient::s_hToken = 0; 38 39 #include "util.h" 40 41 #define SC "SecureClient::" 42 43 DWORD 44 SecureClient::Attach( 45 ) 46 { 47 CcAutoLock AL(s_lock); 48 if (s_hToken) { 49 s_refcount++; 50 return 0; 51 } 52 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, 53 &s_hToken)) { 54 s_refcount++; 55 s_error = 0; 56 } else { 57 s_hToken = 0; 58 s_error = GetLastError(); 59 } 60 return s_error; 61 } 62 63 DWORD 64 SecureClient::Detach( 65 ) 66 { 67 CcAutoLock AL(s_lock); 68 s_refcount--; 69 if (s_refcount) return 0; 70 if (!s_hToken) return 0; 71 DWORD error = 0; 72 if (!CloseHandle(s_hToken)) 73 error = GetLastError(); 74 s_hToken = 0; 75 s_error = 0; 76 return error; 77 } 78 79 DWORD SecureClient::Token(HANDLE& hToken) { 80 // This function will not do automatic initialization. 81 CcAutoLock AL(s_lock); 82 hToken = 0; 83 if (!s_hToken) { 84 cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error); 85 return s_error ? s_error : ERROR_INVALID_HANDLE; 86 } 87 else { 88 DWORD status = 0; 89 if (!DuplicateHandle(GetCurrentProcess(), s_hToken, 90 GetCurrentProcess(), &hToken, 0, FALSE, 91 DUPLICATE_SAME_ACCESS)) { 92 status = GetLastError(); 93 cci_debug_printf(" Could not duplicate handle (%u)", status); 94 } 95 return status; 96 } 97 } 98 99 void 100 SecureClient::Start(SecureClient*& s) { 101 s = new SecureClient; 102 } 103 104 void 105 SecureClient::Stop(SecureClient*& s) { 106 delete s; 107 s = 0; 108 } 109 110 /////////////////////////////////////////////////////////////////////////////// 111 112 /* This constructor turns off impersonation. 113 * It is OK for OpenThreadToken to return an error -- that just means impersonation 114 * is off. 115 */ 116 SecureClient::SecureClient(): 117 m_Error(0), 118 m_hToken(0), 119 m_NeedRestore(false) { 120 121 HANDLE hThread = GetCurrentThread(); 122 HANDLE hThDuplicate; 123 124 int status = DuplicateHandle( GetCurrentProcess(), 125 hThread, 126 GetCurrentProcess(), 127 &hThDuplicate, 128 TOKEN_ALL_ACCESS, 129 FALSE, 130 0); 131 if (!status) return; 132 133 if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) { 134 m_Error = GetLastError(); 135 return; 136 } 137 if (SetThreadToken(&hThDuplicate, NULL)) { 138 m_NeedRestore = true; 139 } else { 140 m_Error = GetLastError(); 141 } 142 CloseHandle(hThDuplicate); 143 } 144 145 SecureClient::~SecureClient() { 146 if (m_NeedRestore) { 147 HANDLE hThread = GetCurrentThread(); 148 if (!SetThreadToken(&hThread, m_hToken)) { 149 m_Error = cci_check_error(GetLastError()); 150 } 151 } 152 if (m_hToken) { 153 if (!CloseHandle(m_hToken)) { 154 m_Error = cci_check_error(GetLastError()); 155 } 156 } 157 } 158 159 DWORD SecureClient::Error() { 160 return m_Error; 161 }