OLD | NEW |
| (Empty) |
1 // Copyright 2008-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 // TODO(omaha): deprecate and use ATL::CAccessToken instead. | |
17 | |
18 #ifndef OMAHA_BASE_SCOPED_IMPERSONATION_H_ | |
19 #define OMAHA_BASE_SCOPED_IMPERSONATION_H_ | |
20 | |
21 #include <windows.h> | |
22 #include <atlsecurity.h> | |
23 #include "omaha/base/debug.h" | |
24 #include "omaha/base/error.h" | |
25 #include "omaha/base/logging.h" | |
26 #include "omaha/base/scoped_any.h" | |
27 | |
28 namespace omaha { | |
29 | |
30 inline void ImpersonateLoggedOnUserOrDie(HANDLE token) { | |
31 if (!::ImpersonateLoggedOnUser(token)) { | |
32 CORE_LOG(LE, (_T("[ImpersonateLoggedOnUser failed][0x%08x]"), | |
33 HRESULTFromLastError())); | |
34 ::RaiseException(EXCEPTION_IMPERSONATION_FAILED, | |
35 EXCEPTION_NONCONTINUABLE, | |
36 0, | |
37 NULL); | |
38 } | |
39 } | |
40 | |
41 inline void RevertToSelfOrDie() { | |
42 if (!::RevertToSelf()) { | |
43 CORE_LOG(LE, (_T("[RevertToSelf failed][0x%08x]"), HRESULTFromLastError())); | |
44 ::RaiseException(EXCEPTION_REVERT_IMPERSONATION_FAILED, | |
45 EXCEPTION_NONCONTINUABLE, | |
46 0, | |
47 NULL); | |
48 } | |
49 } | |
50 | |
51 inline HRESULT smart_impersonate_helper(HANDLE token) { | |
52 if (!token) { | |
53 return S_FALSE; | |
54 } | |
55 return ::ImpersonateLoggedOnUser(token) ? S_OK : HRESULTFromLastError(); | |
56 } | |
57 | |
58 inline void smart_unimpersonate_helper(HRESULT result) { | |
59 if (result == S_OK) { | |
60 RevertToSelfOrDie(); | |
61 } | |
62 } | |
63 | |
64 typedef close_fun<void (*)(HRESULT), smart_unimpersonate_helper> | |
65 close_impersonation; | |
66 | |
67 typedef value_const<HRESULT, E_FAIL> impersonation_not_init; | |
68 | |
69 typedef scoped_any<HRESULT, close_impersonation, impersonation_not_init> | |
70 scoped_impersonation_close; | |
71 | |
72 // Manages the calls to ImpersonateLoggedOnUser and RevertToSelf. The input | |
73 // token is allowed to be NULL in which case no impersonation/revert is | |
74 // performed. | |
75 struct scoped_impersonation { | |
76 explicit scoped_impersonation(HANDLE token) | |
77 : result_(smart_impersonate_helper(token)) { | |
78 HRESULT hr = result(); | |
79 if (token && SUCCEEDED(hr)) { | |
80 CORE_LOG(L3, (_T("[Impersonation succeeded]"))); | |
81 } else if (token && FAILED(hr)) { | |
82 CORE_LOG(LW, (_T("[Impersonation failed][0x%x]"), hr)); | |
83 } else if (!token) { | |
84 CORE_LOG(LW, (_T("[Impersonation requested but the token was null]"))); | |
85 } | |
86 } | |
87 | |
88 HRESULT result() const { return get(result_); } | |
89 | |
90 private: | |
91 const scoped_impersonation_close result_; | |
92 }; | |
93 | |
94 class scoped_revert_to_self { | |
95 public: | |
96 scoped_revert_to_self() { | |
97 token_.GetThreadToken(TOKEN_ALL_ACCESS); | |
98 if (token_.GetHandle()) { | |
99 RevertToSelfOrDie(); | |
100 } | |
101 } | |
102 ~scoped_revert_to_self() { | |
103 if (token_.GetHandle()) { | |
104 ImpersonateLoggedOnUserOrDie(token_.GetHandle()); | |
105 } | |
106 } | |
107 private: | |
108 CAccessToken token_; | |
109 }; | |
110 | |
111 // Calls a function member using the security context of the process, and | |
112 // re-impersonates after the call if the calling thread previously had a valid | |
113 // thread token. | |
114 // This is particularly useful when a thread running impersonated needs to | |
115 // revert to self, call a member function, and impersonate back. If the callee | |
116 // has a result type, it returns the result of the actual call as an out | |
117 // parameter. The function crashes the process if either revert to self or | |
118 // re-impersonation fails. | |
119 | |
120 // Callers for function members without arguments. | |
121 template <typename T, typename R> | |
122 R CallAsSelfAndImpersonate0(T* object, R (T::*pm)()) { | |
123 ASSERT1(object); | |
124 ASSERT1(pm); | |
125 | |
126 scoped_revert_to_self revert_to_self; | |
127 return (object->*pm)(); | |
128 } | |
129 | |
130 // Callers for __stdcall function members with one argument. | |
131 template <typename T, typename P1, typename R> | |
132 R StdCallAsSelfAndImpersonate1(T* object, R (__stdcall T::*pm)(P1), P1 p1) { | |
133 ASSERT1(object); | |
134 ASSERT1(pm); | |
135 | |
136 scoped_revert_to_self revert_to_self; | |
137 return (object->*pm)(p1); | |
138 } | |
139 | |
140 // Callers for function members with one argument. | |
141 template <typename T, typename P1, typename R> | |
142 R CallAsSelfAndImpersonate1(T* object, R (T::*pm)(P1), P1 p1) { | |
143 ASSERT1(object); | |
144 ASSERT1(pm); | |
145 | |
146 scoped_revert_to_self revert_to_self; | |
147 return (object->*pm)(p1); | |
148 } | |
149 | |
150 // Callers for function members with two arguments. | |
151 template <class T, typename P1, typename P2, class R> | |
152 R CallAsSelfAndImpersonate2(T* object, R (T::*pm)(P1, P2), P1 p1, P2 p2) { | |
153 ASSERT1(object); | |
154 ASSERT1(pm); | |
155 | |
156 scoped_revert_to_self revert_to_self; | |
157 return (object->*pm)(p1, p2); | |
158 } | |
159 | |
160 // Callers for function members with three arguments. | |
161 template <class T, typename P1, typename P2, typename P3, typename R> | |
162 R CallAsSelfAndImpersonate3(T* object, R (T::*pm)(P1, P2, P3), | |
163 P1 p1, P2 p2, P3 p3) { | |
164 ASSERT1(object); | |
165 ASSERT1(pm); | |
166 | |
167 scoped_revert_to_self revert_to_self; | |
168 return (object->*pm)(p1, p2, p3); | |
169 } | |
170 | |
171 } // namespace omaha | |
172 | |
173 #endif // OMAHA_BASE_SCOPED_IMPERSONATION_H_ | |
OLD | NEW |