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.

510 lines
11 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation
  6. //
  7. // File: ktsock.cxx
  8. //
  9. // Contents: Kerberos Tunneller, socket operations
  10. //
  11. // History: 28-Jun-2001 t-ryanj Created
  12. //
  13. //------------------------------------------------------------------------
  14. #include <Winsock2.h>
  15. #include <Mswsock.h>
  16. #include "ktdebug.h"
  17. #include "ktsock.h"
  18. #include "ktcontrol.h"
  19. #include "ktmem.h"
  20. #include "ktkerb.h"
  21. #define KDC_SERVICE_NAME "kerberos"
  22. #define KDC_FALLBACK_PORT 88
  23. SHORT KtListenPort;
  24. SOCKET KtListenSocket = INVALID_SOCKET;
  25. BOOL KtWSAStarted = FALSE;
  26. VOID
  27. KtInitListenPort(
  28. VOID
  29. )
  30. {
  31. PSERVENT krb5;
  32. //
  33. // Ask winsock what port kerberos works on. This should be defined in
  34. // %systemroot%\system32\drivers\etc\services
  35. // Note that winsock manages the servent struct, we don't need to free it.
  36. //
  37. if( krb5 = getservbyname( KDC_SERVICE_NAME, NULL ) )
  38. {
  39. KtListenPort = krb5->s_port;
  40. }
  41. else
  42. {
  43. DebugLog( DEB_WARN, "%s(%d): Could not determine kerberos port; falling back to port %d.\n", __FILE__, __LINE__, KDC_FALLBACK_PORT );
  44. KtListenPort = htons( KDC_FALLBACK_PORT );
  45. }
  46. }
  47. //+-------------------------------------------------------------------------
  48. //
  49. // Function: KtInitWinsock
  50. //
  51. // Synopsis: Starts winsock
  52. //
  53. // Effects:
  54. //
  55. // Arguments:
  56. //
  57. // Requires:
  58. //
  59. // Returns: Success value. If FALSE, GetLastError() for details.
  60. //
  61. // Notes:
  62. //
  63. //
  64. //--------------------------------------------------------------------------
  65. BOOL
  66. KtInitWinsock(
  67. VOID
  68. )
  69. {
  70. WORD wWinsockVersionRequested = MAKEWORD( 2,2 );
  71. WSADATA wsaData;
  72. DWORD WSAStartError;
  73. DsysAssert(!KtWSAStarted);
  74. WSAStartError = WSAStartup( wWinsockVersionRequested, &wsaData );
  75. if( WSAStartError == SOCKET_ERROR )
  76. {
  77. DebugLog( DEB_ERROR, "%s(%d): Error starting winsock: 0x%x.\n", __FILE__, __LINE__, WSAGetLastError() );
  78. SetLastError(WSAGetLastError());
  79. goto Cleanup;
  80. }
  81. KtInitListenPort();
  82. KtWSAStarted = TRUE;
  83. Cleanup:
  84. return KtWSAStarted;
  85. }
  86. //+-------------------------------------------------------------------------
  87. //
  88. // Function: KtCleanupWinsock
  89. //
  90. // Synopsis: Call WSACleanup, but only if winsock has been started.
  91. //
  92. // Effects:
  93. //
  94. // Arguments:
  95. //
  96. // Requires:
  97. //
  98. // Returns:
  99. //
  100. // Notes: If WSA isn't started, quietly do nothing.
  101. //
  102. //
  103. //--------------------------------------------------------------------------
  104. VOID
  105. KtCleanupWinsock(
  106. VOID
  107. )
  108. {
  109. if( KtWSAStarted )
  110. {
  111. WSACleanup();
  112. KtWSAStarted = FALSE;
  113. }
  114. }
  115. //+-------------------------------------------------------------------------
  116. //
  117. // Function: KtStartListening
  118. //
  119. // Synopsis: Starts listening for connections
  120. //
  121. // Effects: Initializes KtListenSocket.
  122. //
  123. // Arguments:
  124. //
  125. // Requires:
  126. //
  127. // Returns: Success value, if FALSE GetLastError() for details.
  128. //
  129. // Notes:
  130. //
  131. //
  132. //--------------------------------------------------------------------------
  133. BOOL
  134. KtStartListening(
  135. VOID
  136. )
  137. {
  138. BOOL fRet = TRUE;
  139. DWORD LastError;
  140. BOOL IocpSuccess;
  141. sockaddr_in sa;
  142. //
  143. // Initialize the address want to bind to.
  144. //
  145. sa.sin_family = AF_INET;
  146. sa.sin_port = KtListenPort;
  147. sa.sin_addr.S_un.S_addr = 0x0100007f; /* 127.0.0.1 :: loopback */
  148. //
  149. // Create the socket
  150. //
  151. DsysAssert(KtListenSocket==INVALID_SOCKET);
  152. KtListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  153. if( KtListenSocket == INVALID_SOCKET )
  154. {
  155. SetLastError(WSAGetLastError());
  156. DebugLog( DEB_ERROR, "%s(%d): Error creating listen socket: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  157. goto Error;
  158. }
  159. //
  160. // Bind it to the interface
  161. //
  162. LastError = bind( KtListenSocket, (sockaddr*)&sa, sizeof(sa) );
  163. if( LastError == SOCKET_ERROR )
  164. {
  165. SetLastError(WSAGetLastError());
  166. DebugLog( DEB_ERROR, "%s(%d): Error binding listen socket: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  167. goto Error;
  168. }
  169. //
  170. // Start Listening
  171. //
  172. LastError = listen( KtListenSocket, SOMAXCONN );
  173. if( LastError == SOCKET_ERROR )
  174. {
  175. SetLastError(WSAGetLastError());
  176. DebugLog( DEB_ERROR, "%s(%d): Error listening on listen socket: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  177. goto Error;
  178. }
  179. //
  180. // Associate the listen socket with the completion i/o port
  181. //
  182. IocpSuccess = (KtIocp == CreateIoCompletionPort( (HANDLE)KtListenSocket,
  183. KtIocp,
  184. KTCK_CHECK_CONTEXT,
  185. 0 ));
  186. if( !IocpSuccess )
  187. {
  188. DebugLog( DEB_ERROR, "%s(%d): Could not associate listen socket with iocp: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  189. goto Error;
  190. }
  191. //
  192. // Issue an accept
  193. //
  194. if( !KtSockAccept() )
  195. goto Error;
  196. Cleanup:
  197. return fRet;
  198. Error:
  199. fRet = FALSE;
  200. goto Cleanup;
  201. }
  202. //+-------------------------------------------------------------------------
  203. //
  204. // Function: KtStopListening
  205. //
  206. // Synopsis: Stops listening for new connections.
  207. //
  208. // Effects:
  209. //
  210. // Arguments:
  211. //
  212. // Requires:
  213. //
  214. // Returns:
  215. //
  216. // Notes: If the listen socket isn't valid, quietly do nothing.
  217. //
  218. //
  219. //--------------------------------------------------------------------------
  220. VOID
  221. KtStopListening(
  222. VOID
  223. )
  224. {
  225. if( KtListenSocket != INVALID_SOCKET )
  226. {
  227. closesocket(KtListenSocket);
  228. KtListenSocket = INVALID_SOCKET;
  229. }
  230. }
  231. //+-------------------------------------------------------------------------
  232. //
  233. // Function: KtSockAccept
  234. //
  235. // Synopsis: Issues a new AcceptEx on KtListenSocket.
  236. //
  237. // Effects:
  238. //
  239. // Arguments:
  240. //
  241. // Requires:
  242. //
  243. // Returns: Success value. If FALSE, GetLastError() for details.
  244. //
  245. // Notes:
  246. //
  247. //--------------------------------------------------------------------------
  248. BOOL
  249. KtSockAccept(
  250. VOID
  251. )
  252. {
  253. BOOL fRet = TRUE;
  254. BOOL AcceptSuccess;
  255. DWORD LastError;
  256. PKTCONTEXT pContext = NULL;
  257. SOCKET sock = INVALID_SOCKET;
  258. //
  259. // Create a socket.
  260. //
  261. sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  262. if( sock == INVALID_SOCKET )
  263. {
  264. SetLastError(WSAGetLastError());
  265. DebugLog( DEB_ERROR, "%s(%d): Error creating client socket: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  266. goto Error;
  267. }
  268. //
  269. // Create a new context
  270. //
  271. pContext = KtAcquireContext( sock, KTCONTEXT_BUFFER_LENGTH );
  272. if( !pContext )
  273. goto Error;
  274. sock = INVALID_SOCKET;
  275. //
  276. // Mark for a connect operation, and use AcceptEx to issue an overlapped
  277. // accept on the socket.
  278. //
  279. pContext->Status = KT_SOCK_CONNECT;
  280. AcceptSuccess = AcceptEx( KtListenSocket,
  281. pContext->sock,
  282. pContext->emptybuf->buffer, /* docbug: contrary to msdn, NULL here doesn't work */
  283. 0,
  284. sizeof( sockaddr_in ) + 16, /* these addrs require 16 bytes */
  285. sizeof( sockaddr_in ) + 16, /* of padding - see AcceptEx msdn */
  286. NULL,
  287. &(pContext->ol) );
  288. if( !AcceptSuccess && (WSAGetLastError() != ERROR_IO_PENDING) )
  289. {
  290. SetLastError(WSAGetLastError());
  291. DebugLog( DEB_ERROR, "%s(%d): Error issuing accept: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  292. goto Error;
  293. }
  294. Cleanup:
  295. return fRet;
  296. Error:
  297. if( sock != INVALID_SOCKET )
  298. closesocket(sock);
  299. if( pContext )
  300. KtReleaseContext( pContext );
  301. fRet = FALSE;
  302. goto Cleanup;
  303. }
  304. //+-------------------------------------------------------------------------
  305. //
  306. // Function: KtSockCompleteAccept
  307. //
  308. // Synopsis: Associates a new connection with the iocp.
  309. //
  310. // Effects:
  311. //
  312. // Arguments: pContext - Contains the info on the connection.
  313. //
  314. // Requires:
  315. //
  316. // Returns: Success value. If FALSE, GetLastError() for details.
  317. //
  318. // Notes:
  319. //
  320. //
  321. //--------------------------------------------------------------------------
  322. BOOL
  323. KtSockCompleteAccept(
  324. IN PKTCONTEXT pContext
  325. )
  326. {
  327. DWORD LastError;
  328. BOOL IocpSuccess;
  329. //
  330. // Associate the newly accepted socket with the completion port.
  331. //
  332. IocpSuccess = (KtIocp == CreateIoCompletionPort( (HANDLE)pContext->sock,
  333. KtIocp,
  334. KTCK_CHECK_CONTEXT,
  335. 0 ) );
  336. if( !IocpSuccess )
  337. {
  338. DebugLog( DEB_ERROR, "%s(%d): Error associating client socket with completion port: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  339. goto Cleanup;
  340. }
  341. DebugLog( DEB_TRACE, "%s(%d): Accepted new connection.\n", __FILE__, __LINE__ );
  342. Cleanup:
  343. return IocpSuccess;
  344. }
  345. //+-------------------------------------------------------------------------
  346. //
  347. // Function: KtSockRead
  348. //
  349. // Synopsis: Issues a Read.
  350. //
  351. // Effects:
  352. //
  353. // Arguments: pContext -
  354. //
  355. // Requires:
  356. //
  357. // Returns: Success value. If FALSE, GetLastError() for details.
  358. //
  359. // Notes:
  360. //
  361. //
  362. //--------------------------------------------------------------------------
  363. BOOL
  364. KtSockRead(
  365. IN PKTCONTEXT pContext
  366. )
  367. {
  368. BOOL fRet = TRUE;
  369. BOOL ReadFileSuccess;
  370. //
  371. // Zero the overlapped structure.
  372. //
  373. ZeroMemory( &(pContext->ol), sizeof(OVERLAPPED) );
  374. //
  375. // Mark for a read and use ReadFile to issue an overlapped read.
  376. //
  377. pContext->Status = KT_SOCK_READ;
  378. ReadFileSuccess = ReadFile( (HANDLE)pContext->sock,
  379. pContext->emptybuf->buffer,
  380. pContext->emptybuf->buflen,
  381. NULL,
  382. &(pContext->ol) );
  383. if( !ReadFileSuccess )
  384. {
  385. if( GetLastError() != ERROR_IO_PENDING )
  386. {
  387. DebugLog( DEB_ERROR, "%s(%d): Error issuing read: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  388. goto Error;
  389. }
  390. }
  391. Cleanup:
  392. return fRet;
  393. Error:
  394. fRet = FALSE;
  395. goto Cleanup;
  396. }
  397. //+-------------------------------------------------------------------------
  398. //
  399. // Function: KtSockWrite
  400. //
  401. // Synopsis: Issues a write.
  402. //
  403. // Effects:
  404. //
  405. // Arguments: pContext -
  406. //
  407. // Requires:
  408. //
  409. // Returns: Success value. If FALSE, GetLastError() for details.
  410. //
  411. // Notes:
  412. //
  413. //
  414. //--------------------------------------------------------------------------
  415. BOOL
  416. KtSockWrite(
  417. IN PKTCONTEXT pContext
  418. )
  419. {
  420. BOOL fRet = TRUE;
  421. BOOL WriteFileSuccess;
  422. ULONG cbNeeded;
  423. //
  424. // Zero the overlapped
  425. //
  426. ZeroMemory( &(pContext->ol), sizeof(OVERLAPPED) );
  427. //
  428. // Mark for Write and issue overlapped Write with WriteFile
  429. //
  430. pContext->Status = KT_SOCK_WRITE;
  431. WriteFileSuccess = WriteFile( (HANDLE)pContext->sock,
  432. pContext->buffers->buffer,
  433. pContext->buffers->buflen,
  434. NULL, /* bytes written - not used in async */
  435. &(pContext->ol) );
  436. if( !WriteFileSuccess )
  437. {
  438. if( GetLastError() != ERROR_IO_PENDING )
  439. {
  440. DebugLog( DEB_ERROR, "%s(%d): Error issuing write: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  441. goto Error;
  442. }
  443. }
  444. Cleanup:
  445. return fRet;
  446. Error:
  447. fRet = FALSE;
  448. goto Cleanup;
  449. }