Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
9.5 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright � Microsoft Corporation. All rights reserved.
  4. //
  5. // CreateMutexAsProcess.CPP
  6. //
  7. // Purpose: Create a mutex NOT using impersonation
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include <brodcast.h>
  12. #include <CreateMutexAsProcess.h>
  13. #include "MultiPlat.h"
  14. #include <cominit.h>
  15. //
  16. //
  17. // precompiled security descriptor
  18. // System and NetworkService has full access
  19. //
  20. // since this is RELATIVE, it will work on both IA32 and Win64
  21. //
  22. DWORD g_PrecSD[] = {
  23. 0x80040001 , 0x00000044 , 0x00000050 , 0x00000000 ,
  24. 0x00000014 , 0x00300002 , 0x00000002 , 0x00140000 ,
  25. 0x001f0001 , 0x00000101 , 0x05000000 , 0x00000012 ,
  26. 0x00140000 , 0x001f0001 , 0x00000101 , 0x05000000 ,
  27. 0x00000014 , 0x00000101 , 0x05000000 , 0x00000014 ,
  28. 0x00000101 , 0x05000000 , 0x00000014
  29. };
  30. DWORD g_SizeSD = 0;
  31. DWORD g_RuntimeSD [
  32. (
  33. sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
  34. (2 * (sizeof(SID)+SID_MAX_SUB_AUTHORITIES*sizeof(DWORD))) +
  35. sizeof(ACL) +
  36. (3 * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
  37. (3 * (sizeof(SID)+SID_MAX_SUB_AUTHORITIES*sizeof(DWORD)))
  38. )/sizeof(DWORD)
  39. ];
  40. typedef
  41. BOOLEAN ( * fnRtlValidRelativeSecurityDescriptor)(
  42. IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
  43. IN ULONG SecurityDescriptorLength,
  44. IN SECURITY_INFORMATION RequiredInformation
  45. );
  46. fnRtlValidRelativeSecurityDescriptor RtlValidRelativeSecurityDescriptor;
  47. //
  48. // Build a SD with owner == This
  49. // group == This
  50. // DACL
  51. // ACE[0] MUTEX_ALL_ACCESS Owner
  52. // ACE[1] MUTEX_ALL_ACCESS System
  53. ///////////////////////////////////////////////////////////////////
  54. BOOL
  55. CreateSD( )
  56. {
  57. if (!RtlValidRelativeSecurityDescriptor)
  58. {
  59. HMODULE hModule = GetModuleHandleW(L"ntdll.dll");
  60. if (hModule)
  61. {
  62. RtlValidRelativeSecurityDescriptor = (fnRtlValidRelativeSecurityDescriptor)GetProcAddress(hModule,"RtlValidRelativeSecurityDescriptor");
  63. if (!RtlValidRelativeSecurityDescriptor)
  64. {
  65. return FALSE;
  66. }
  67. }
  68. }
  69. HANDLE hToken;
  70. BOOL bRet;
  71. bRet = OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken);
  72. if (bRet)
  73. {
  74. TOKEN_USER * pToken_User;
  75. DWORD dwSize = sizeof(TOKEN_USER)+sizeof(SID)+(SID_MAX_SUB_AUTHORITIES*sizeof(DWORD));
  76. pToken_User = (TOKEN_USER *)_alloca(dwSize);
  77. bRet = GetTokenInformation(hToken,TokenUser,pToken_User,dwSize,&dwSize);
  78. if (bRet)
  79. {
  80. SID SystemSid = { SID_REVISION,
  81. 1,
  82. SECURITY_NT_AUTHORITY,
  83. SECURITY_LOCAL_SYSTEM_RID
  84. };
  85. SID NetworkSid = { SID_REVISION,
  86. 1,
  87. SECURITY_NT_AUTHORITY,
  88. SECURITY_NETWORK_SERVICE_RID
  89. };
  90. PSID pSIDUser = pToken_User->User.Sid;
  91. dwSize = GetLengthSid(pSIDUser);
  92. DWORD dwSids = 3; // Owner and System and NetworkService
  93. DWORD ACLLength = (ULONG) sizeof(ACL) +
  94. (dwSids * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) + dwSize + sizeof(SystemSid) + sizeof(NetworkSid);
  95. DWORD dwSizeSD = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + dwSize + dwSize + ACLLength;
  96. SECURITY_DESCRIPTOR_RELATIVE * pLocalSD = (SECURITY_DESCRIPTOR_RELATIVE *)_alloca(dwSizeSD);
  97. memset(pLocalSD,0,sizeof(SECURITY_DESCRIPTOR_RELATIVE));
  98. pLocalSD->Revision = SECURITY_DESCRIPTOR_REVISION;
  99. pLocalSD->Control = SE_DACL_PRESENT|SE_SELF_RELATIVE;
  100. //SetSecurityDescriptorOwner(pLocalSD,pSIDUser,FALSE);
  101. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE),pSIDUser,dwSize);
  102. pLocalSD->Owner = (DWORD)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  103. //SetSecurityDescriptorGroup(pLocalSD,pSIDUser,FALSE);
  104. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize,pSIDUser,dwSize);
  105. pLocalSD->Group = (DWORD)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize);
  106. PACL pDacl = (PACL)_alloca(ACLLength);
  107. bRet = InitializeAcl( pDacl,
  108. ACLLength,
  109. ACL_REVISION);
  110. if (bRet)
  111. {
  112. bRet = AddAccessAllowedAceEx (pDacl,ACL_REVISION,0,MUTEX_ALL_ACCESS,&SystemSid);
  113. if (bRet)
  114. {
  115. bRet = AddAccessAllowedAceEx (pDacl,ACL_REVISION,0,MUTEX_ALL_ACCESS,&NetworkSid);
  116. if (bRet)
  117. {
  118. bRet = AddAccessAllowedAceEx (pDacl,ACL_REVISION,0,MUTEX_ALL_ACCESS,pSIDUser);
  119. if (bRet)
  120. {
  121. //bRet = SetSecurityDescriptorDacl(pLocalSD,TRUE,pDacl,FALSE);
  122. memcpy((BYTE*)pLocalSD+sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize+dwSize,pDacl,ACLLength);
  123. pLocalSD->Dacl = (DWORD)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)+dwSize+dwSize);
  124. if (RtlValidRelativeSecurityDescriptor(pLocalSD,
  125. dwSizeSD,
  126. OWNER_SECURITY_INFORMATION|
  127. GROUP_SECURITY_INFORMATION|
  128. DACL_SECURITY_INFORMATION))
  129. {
  130. g_SizeSD = dwSizeSD;
  131. memcpy(g_RuntimeSD,pLocalSD,dwSizeSD);
  132. }
  133. else
  134. {
  135. bRet = FALSE;
  136. }
  137. }
  138. }
  139. }
  140. }
  141. }
  142. CloseHandle(hToken);
  143. }
  144. return bRet;
  145. };
  146. CreateMutexAsProcess::CreateMutexAsProcess(const WCHAR *cszMutexName) : m_hMutex ( NULL )
  147. {
  148. BOOL bCreatedAndWaited = FALSE;
  149. BOOL bImpersonated = TRUE;
  150. BOOL bReverted = FALSE;
  151. BOOL bProceed = FALSE;
  152. HANDLE hThreadToken = INVALID_HANDLE_VALUE;
  153. // The mutex will need to be opened in the process's context. If two impersonated
  154. // threads need the mutex, we can't have the second one get an access denied when
  155. // opening the mutex.
  156. if ( OpenThreadToken (
  157. GetCurrentThread(),
  158. TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE,
  159. TRUE,
  160. &hThreadToken
  161. )
  162. )
  163. {
  164. if ( RevertToSelf() )
  165. {
  166. bReverted = TRUE;
  167. }
  168. else
  169. {
  170. LogMessage2 ( L"Failed to revert to self: (%d)", GetLastError() );
  171. #if DBG == 1
  172. // for testing purpose I will let process break
  173. ::DebugBreak();
  174. #endif
  175. }
  176. }
  177. else
  178. {
  179. DWORD dwError = ::GetLastError ();
  180. LogMessage2 ( L"Failed to open thread token: (%d)", dwError );
  181. if ( ERROR_ACCESS_DENIED == dwError )
  182. {
  183. // we failed to open thread token on behalf of process
  184. // we are running as NETWORK SERVICE so it would be "by design"
  185. #if DBG == 1
  186. // for testing purpose I will let process break
  187. ::DebugBreak();
  188. #endif
  189. }
  190. else if ( ERROR_NO_TOKEN == dwError || ERROR_NO_IMPERSONATION_TOKEN == dwError )
  191. {
  192. bImpersonated = FALSE;
  193. }
  194. }
  195. if ( ( bImpersonated && bReverted ) || ! bImpersonated )
  196. {
  197. m_hMutex = OpenMutexW(MUTEX_ALL_ACCESS,FALSE,cszMutexName);
  198. if (NULL == m_hMutex)
  199. {
  200. SECURITY_ATTRIBUTES sa;
  201. if (0 == g_SizeSD)
  202. {
  203. if (CreateSD())
  204. {
  205. sa.nLength = g_SizeSD;
  206. sa.lpSecurityDescriptor = (LPVOID)g_RuntimeSD;
  207. sa.bInheritHandle = FALSE;
  208. }
  209. else
  210. {
  211. sa.nLength = sizeof(g_PrecSD);
  212. sa.lpSecurityDescriptor = (LPVOID)g_PrecSD;
  213. sa.bInheritHandle = FALSE;
  214. }
  215. }
  216. else
  217. {
  218. sa.nLength = g_SizeSD;
  219. sa.lpSecurityDescriptor = (LPVOID)g_RuntimeSD;
  220. sa.bInheritHandle = FALSE;
  221. }
  222. m_hMutex = CreateMutexW(&sa, FALSE, cszMutexName);
  223. }
  224. if ( m_hMutex != NULL )
  225. {
  226. if ( bImpersonated )
  227. {
  228. if ( ImpersonateLoggedOnUser ( hThreadToken ) )
  229. {
  230. bProceed = TRUE;
  231. }
  232. else
  233. {
  234. LogErrorMessage2 ( L"Failed to return to impersonation (%d)", GetLastError() );
  235. #if DBG == 1
  236. // for testing purpose I will let process break
  237. ::DebugBreak();
  238. #endif
  239. }
  240. }
  241. else
  242. {
  243. bProceed = TRUE;
  244. }
  245. if ( bProceed )
  246. {
  247. DWORD dwWaitResult = WAIT_OBJECT_0;
  248. dwWaitResult = WaitForSingleObject(m_hMutex, INFINITE);
  249. if ( dwWaitResult == WAIT_OBJECT_0 )
  250. {
  251. bCreatedAndWaited = TRUE;
  252. }
  253. else
  254. {
  255. #if DBG == 1
  256. // for testing purpose I will let process break
  257. ::DebugBreak();
  258. #endif
  259. }
  260. }
  261. }
  262. else
  263. {
  264. LogErrorMessage2 ( L"Failed to open mutex: %s", cszMutexName );
  265. if ( bImpersonated )
  266. {
  267. if ( !ImpersonateLoggedOnUser ( hThreadToken ) )
  268. {
  269. LogErrorMessage2 ( L"Failed to return to impersonation (%d)", GetLastError() );
  270. #if DBG == 1
  271. // for testing purpose I will let process break
  272. ::DebugBreak();
  273. #endif
  274. }
  275. }
  276. #if DBG == 1
  277. // for testing purpose I will let process break
  278. ::DebugBreak();
  279. #endif
  280. }
  281. }
  282. if ( ! bCreatedAndWaited )
  283. {
  284. if ( hThreadToken != INVALID_HANDLE_VALUE )
  285. {
  286. CloseHandle(hThreadToken);
  287. hThreadToken = INVALID_HANDLE_VALUE;
  288. }
  289. if (m_hMutex)
  290. {
  291. ReleaseMutex(m_hMutex);
  292. CloseHandle(m_hMutex);
  293. m_hMutex = NULL;
  294. }
  295. // we need to throw here to avoid concurrent access
  296. throw CFramework_Exception( L"CreateMutexAsProcess failed", HRESULT_FROM_WIN32 ( ::GetLastError () ) ) ;
  297. }
  298. }
  299. CreateMutexAsProcess::~CreateMutexAsProcess()
  300. {
  301. if (m_hMutex)
  302. {
  303. ReleaseMutex(m_hMutex);
  304. CloseHandle(m_hMutex);
  305. }
  306. }