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
Attach()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
Detach()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
Token(HANDLE & hToken)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
Start(SecureClient * & s)100 SecureClient::Start(SecureClient*& s) {
101 s = new SecureClient;
102 }
103
104 void
Stop(SecureClient * & s)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 */
SecureClient()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
~SecureClient()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
Error()159 DWORD SecureClient::Error() {
160 return m_Error;
161 }