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.

337 lines
9.1 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. ComInitr
  5. Abstract:
  6. This module implements the methods for the Communications Initiation Class.
  7. Author:
  8. Doug Barlow (dbarlow) 10/30/1996
  9. Environment:
  10. Win32, C++ w/ Exceptions
  11. Notes:
  12. --*/
  13. #define __SUBROUTINE__
  14. #ifndef WIN32_LEAN_AND_MEAN
  15. #define WIN32_LEAN_AND_MEAN
  16. #endif
  17. #include <windows.h>
  18. #include <limits.h>
  19. #include <WinSCard.h>
  20. #include <CalMsgs.h>
  21. #include <CalCom.h>
  22. #include <stdlib.h>
  23. #include <aclapi.h>
  24. HANDLE g_hCalaisShutdown = NULL; // This is used by the Send and Receive
  25. // methods of the CComChannel. It stays
  26. // NULL.
  27. //
  28. //==============================================================================
  29. //
  30. // CComInitiator
  31. //
  32. /*++
  33. Initiate:
  34. This method creates a communications channel object to the supplied target.
  35. Arguments:
  36. szName supplies the full file name of the target with which to initiate a
  37. connection.
  38. Return Value:
  39. None
  40. Throws:
  41. DWORDs representing any error conditions encountered.
  42. Author:
  43. Doug Barlow (dbarlow) 10/30/1996
  44. --*/
  45. #undef __SUBROUTINE__
  46. #define __SUBROUTINE__ DBGT("CComInitiator::Initiate")
  47. CComChannel *
  48. CComInitiator::Initiate(
  49. LPCTSTR szName,
  50. LPDWORD pdwVersion)
  51. const
  52. {
  53. LPCTSTR szPipeHdr = CalaisString(CALSTR_PIPEDEVICEHEADER);
  54. CComChannel *pChannel = NULL;
  55. CHandleObject hComPipe(DBGT("Comm Pipe Handle from CComInitiator::Initiate"));
  56. try
  57. {
  58. BOOL fSts;
  59. DWORD dwSts;
  60. DWORD cbPipeHeader = lstrlen(szPipeHdr) * sizeof(TCHAR);
  61. CBuffer bfPipeName;
  62. DWORD dwLen;
  63. HANDLE hStarted;
  64. DWORD nPipeNo;
  65. HKEY hCurrentKey;
  66. TCHAR szPipeNo[sizeof(nPipeNo)*2 + 1]; // Twice as many hex digits + zero
  67. DWORD cbData;
  68. DWORD ValueType;
  69. //
  70. // Build the pipe name.
  71. //
  72. dwLen = lstrlen(szName) * sizeof(TCHAR);
  73. bfPipeName.Presize(cbPipeHeader + dwLen + sizeof(szPipeNo));
  74. //
  75. // Build our Connect Request block.
  76. //
  77. CComChannel::CONNECT_REQMSG creq;
  78. CComChannel::CONNECT_RSPMSG crsp;
  79. hStarted = AccessStartedEvent();
  80. if ((NULL == hStarted) ||
  81. (WAIT_OBJECT_0 != WaitForSingleObject(hStarted, 0)))
  82. {
  83. throw (DWORD)SCARD_E_NO_SERVICE;
  84. }
  85. //
  86. // Open the Current key.
  87. //
  88. dwSts = RegOpenKeyEx(
  89. HKEY_LOCAL_MACHINE,
  90. _T("SOFTWARE\\Microsoft\\Cryptography\\Calais\\Current"),
  91. 0, // options (ignored)
  92. KEY_QUERY_VALUE,
  93. &hCurrentKey
  94. );
  95. if (ERROR_SUCCESS != dwSts)
  96. {
  97. CalaisWarning(
  98. __SUBROUTINE__,
  99. DBGT("Comm Initiator could not access the Current key: %1"),
  100. dwSts);
  101. throw dwSts;
  102. }
  103. cbData = sizeof(nPipeNo);
  104. dwSts = RegQueryValueEx(
  105. hCurrentKey,
  106. NULL, // Use key's unnamed value
  107. 0,
  108. &ValueType,
  109. (LPBYTE) &nPipeNo,
  110. &cbData);
  111. RegCloseKey(hCurrentKey);
  112. if (dwSts != ERROR_SUCCESS || ValueType != REG_DWORD)
  113. {
  114. CalaisWarning(
  115. __SUBROUTINE__,
  116. DBGT("Comm Initiator failed to query the Current value: %1"),
  117. dwSts);
  118. throw dwSts;
  119. }
  120. _itot(nPipeNo, szPipeNo, 16);
  121. bfPipeName.Set((LPCBYTE)szPipeHdr, cbPipeHeader);
  122. bfPipeName.Append((LPCBYTE)szName, dwLen);
  123. bfPipeName.Append((LPCBYTE)szPipeNo, sizeof(szPipeNo));
  124. {
  125. PSID pPipeOwnerSid;
  126. PSID pLocalServiceSid = NULL;
  127. PSECURITY_DESCRIPTOR pSD = NULL;
  128. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  129. RetryGetInfo:
  130. dwSts = GetNamedSecurityInfo(
  131. (LPTSTR)(LPCTSTR)bfPipeName,
  132. SE_FILE_OBJECT,
  133. OWNER_SECURITY_INFORMATION,
  134. &pPipeOwnerSid,
  135. NULL,
  136. NULL,
  137. NULL,
  138. &pSD);
  139. if (ERROR_SUCCESS != dwSts)
  140. {
  141. if (ERROR_PIPE_BUSY == dwSts)
  142. {
  143. fSts = WaitNamedPipe((LPCTSTR)bfPipeName, NMPWAIT_USE_DEFAULT_WAIT);
  144. if (!fSts)
  145. {
  146. dwSts = GetLastError();
  147. CalaisWarning(
  148. __SUBROUTINE__,
  149. DBGT("Comm Initiator could not wait for a communication pipe: %1"),
  150. dwSts);
  151. throw dwSts;
  152. }
  153. goto RetryGetInfo;
  154. }
  155. CalaisWarning(
  156. __SUBROUTINE__,
  157. DBGT("Comm Initiator could not get the security info: %1"),
  158. dwSts);
  159. throw dwSts;
  160. }
  161. if (!AllocateAndInitializeSid(
  162. &NtAuthority, 1, SECURITY_LOCAL_SERVICE_RID,
  163. 0, 0, 0, 0, 0, 0, 0,
  164. &pLocalServiceSid))
  165. {
  166. dwSts = GetLastError();
  167. CalaisWarning(
  168. __SUBROUTINE__,
  169. DBGT("Comm Initiator could not create SID: %1"),
  170. dwSts);
  171. }
  172. else
  173. {
  174. if (!EqualSid(pLocalServiceSid, pPipeOwnerSid))
  175. {
  176. dwSts = GetLastError();
  177. CalaisWarning(
  178. __SUBROUTINE__,
  179. DBGT("Comm Initiator could not verify the owner of the pipe: %1"),
  180. dwSts);
  181. }
  182. FreeSid(pLocalServiceSid);
  183. }
  184. LocalFree(pSD);
  185. if (ERROR_SUCCESS != dwSts)
  186. {
  187. throw dwSts;
  188. }
  189. }
  190. RetryCreate:
  191. hComPipe = CreateFile(
  192. (LPCTSTR)bfPipeName,
  193. GENERIC_READ | GENERIC_WRITE,
  194. 0,
  195. NULL,
  196. OPEN_EXISTING,
  197. FILE_ATTRIBUTE_NORMAL,
  198. NULL);
  199. if (!hComPipe.IsValid())
  200. {
  201. dwSts = hComPipe.GetLastError();
  202. switch (dwSts)
  203. {
  204. //
  205. // The resource manager isn't started.
  206. case ERROR_FILE_NOT_FOUND:
  207. CalaisWarning(
  208. __SUBROUTINE__,
  209. DBGT("Comm Initiator could not create communication pipe: %1"),
  210. dwSts);
  211. throw (DWORD)SCARD_E_NO_SERVICE;
  212. break;
  213. //
  214. // The pipe is busy.
  215. case ERROR_PIPE_BUSY:
  216. fSts = WaitNamedPipe((LPCTSTR)bfPipeName, NMPWAIT_USE_DEFAULT_WAIT);
  217. if (!fSts)
  218. {
  219. dwSts = GetLastError();
  220. CalaisWarning(
  221. __SUBROUTINE__,
  222. DBGT("Comm Initiator could not wait for a communication pipe: %1"),
  223. dwSts);
  224. throw dwSts;
  225. }
  226. goto RetryCreate;
  227. break;
  228. //
  229. // A hard error.
  230. default:
  231. CalaisWarning(
  232. __SUBROUTINE__,
  233. DBGT("Comm Initiator could not create communication pipe: %1"),
  234. dwSts);
  235. throw dwSts;
  236. }
  237. }
  238. creq.dwSync = 0;
  239. creq.dwVersion = *pdwVersion;
  240. //
  241. // Establish the communication.
  242. //
  243. pChannel = new CComChannel(hComPipe);
  244. if (NULL == pChannel)
  245. {
  246. dwSts = SCARD_E_NO_MEMORY;
  247. CalaisWarning(
  248. __SUBROUTINE__,
  249. DBGT("Com Initiator could not allocate a Comm Channel: %1"),
  250. dwSts);
  251. throw dwSts;
  252. }
  253. hComPipe.Relinquish();
  254. pChannel->Send(&creq, sizeof(creq));
  255. pChannel->Receive(&crsp, sizeof(crsp));
  256. if (ERROR_SUCCESS != crsp.dwStatus)
  257. throw crsp.dwStatus;
  258. //
  259. // Check the response.
  260. // In future versions, we may have to negotiate a version.
  261. //
  262. if (crsp.dwVersion != *pdwVersion)
  263. throw (DWORD)SCARD_F_COMM_ERROR;
  264. *pdwVersion = crsp.dwVersion;
  265. }
  266. catch (...)
  267. {
  268. if (NULL != pChannel)
  269. delete pChannel;
  270. if (hComPipe.IsValid())
  271. hComPipe.Close();
  272. throw;
  273. }
  274. return pChannel;
  275. }