| 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 |