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.

359 lines
8.8 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation
  6. //
  7. // File: ktcore.cxx
  8. //
  9. // Contents: Kerberos Tunneller, core service thread routines
  10. //
  11. // History: 28-Jun-2001 t-ryanj Created
  12. //
  13. //------------------------------------------------------------------------
  14. #include "ktdebug.h"
  15. #include "ktcore.h"
  16. #include "ktcontrol.h"
  17. #include "ktcontext.h"
  18. #include "ktsock.h"
  19. #include "kthttp.h"
  20. #include "ktkerb.h"
  21. VOID
  22. KtDispatchPerContext(
  23. PKTCONTEXT pContext
  24. );
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Function: KtThreadCore
  28. //
  29. // Synopsis: Main loop for service threads.
  30. //
  31. // Effects:
  32. //
  33. // Arguments:
  34. //
  35. // Requires:
  36. //
  37. // Returns:
  38. //
  39. // Notes:
  40. //
  41. //--------------------------------------------------------------------------
  42. VOID
  43. KtThreadCore(
  44. VOID
  45. )
  46. {
  47. ULONG_PTR CompKey;
  48. LPOVERLAPPED pOverlapped = NULL;
  49. PKTCONTEXT pContext = NULL;
  50. DWORD IocpBytes;
  51. BOOL IocpSuccess;
  52. DWORD IocpError;
  53. //
  54. // Here's the main service loop. It ends when the service is stopped.
  55. //
  56. while( !KtIsStopped() )
  57. {
  58. //
  59. // Wait for a task to queue on the completion port.
  60. //
  61. IocpSuccess = GetQueuedCompletionStatus( KtIocp,
  62. &IocpBytes,
  63. &CompKey,
  64. &pOverlapped,
  65. INFINITE );
  66. //
  67. // Extrapolate the address of the context from the address of the
  68. // overlapped struct.
  69. //
  70. if( pOverlapped )
  71. {
  72. pContext = CONTAINING_RECORD( pOverlapped,
  73. KTCONTEXT,
  74. ol );
  75. }
  76. //
  77. // If there's an error on the Iocp, release any associated context if possible.
  78. //
  79. if( !IocpSuccess )
  80. {
  81. /* TODO: Event Log. */
  82. DebugLog( DEB_ERROR, "%s(%d): Error from GetQueuedCompletionStatus: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
  83. if( pContext )
  84. {
  85. DebugLog( DEB_TRACE, "%s(%d): Releasing context due to GQCS error.\n", __FILE__, __LINE__ );
  86. KtReleaseContext( pContext );
  87. }
  88. else
  89. {
  90. DebugLog( DEB_TRACE, "%s(%d): No completion packet dequeued.\n", __FILE__, __LINE__ );
  91. }
  92. //
  93. // Any completion key we have is invalid, so skip back to top of loop.
  94. //
  95. continue;
  96. }
  97. //
  98. // Dispatch the task to the appropriate routine.
  99. //
  100. switch( CompKey )
  101. {
  102. case KTCK_SERVICE_CONTROL:
  103. //
  104. // The specific control event was passed on the bytes argument.
  105. //
  106. KtServiceControlEvent(IocpBytes);
  107. break;
  108. case KTCK_CHECK_CONTEXT:
  109. //
  110. // The context may not exist. If the service is shutting down, it closes
  111. // all pending connections, which will cause completion to be posted,
  112. // but since the context has already been destroyed, there's nothing to do.
  113. //
  114. if( pContext )
  115. KtDispatchPerContext(pContext);
  116. break;
  117. default:
  118. DebugLog( DEB_WARN, "%s(%d): Unhandled case: 0x%x.\n", __FILE__, __LINE__, CompKey );
  119. break;
  120. }
  121. }
  122. }
  123. //+-------------------------------------------------------------------------
  124. //
  125. // Function: KtDispatchPerContext
  126. //
  127. // Synopsis: This routine handles the sequence of events that happen
  128. // over the lifetime of a connection.
  129. //
  130. // Effects:
  131. //
  132. // Arguments:
  133. //
  134. // Requires:
  135. //
  136. // Returns:
  137. //
  138. // Notes:
  139. //
  140. //--------------------------------------------------------------------------
  141. VOID
  142. KtDispatchPerContext(
  143. PKTCONTEXT pContext
  144. )
  145. {
  146. switch( pContext->Status )
  147. {
  148. case KT_SOCK_CONNECT:
  149. //
  150. // First we need to prepare to accept other connections.
  151. // If we can't accept more incoming connections, this will
  152. // impact the entire service.
  153. //
  154. DebugLog( DEB_TRACE, "----==== Preparing to accept new connection ====----\n" );
  155. if( !KtSockAccept() )
  156. goto SvcError;
  157. //
  158. // Now we can complete the acceptance of the socket that
  159. // connected, then issue a read on that socket. If something
  160. // goes wrong here, we'll close the session.
  161. //
  162. if( !KtSockCompleteAccept(pContext) )
  163. goto SessError;
  164. if( !KtSockRead(pContext) )
  165. goto SessError;
  166. break;
  167. case KT_SOCK_READ:
  168. //
  169. // pContext->ol.InternalHigh holds the bytes transferred after a
  170. // socket operation. If it's zero, the other side has closed the
  171. // connection.
  172. //
  173. if( !pContext->ol.InternalHigh )
  174. goto SessError;
  175. pContext->emptybuf->bytesused = (ULONG)pContext->ol.InternalHigh;
  176. DebugLog( DEB_PEDANTIC, "%s(%d): %d bytes read from loopback.\n", __FILE__, __LINE__, pContext->emptybuf->bytesused );
  177. //
  178. // If we don't know how many bytes to look for yet, figure it out.
  179. //
  180. if( pContext->ExpectedLength == 0 )
  181. {
  182. if( !KtParseExpectedLength( pContext ) )
  183. goto SessError;
  184. DebugLog( DEB_TRACE, "%s(%d): Expected message length: %d.\n", __FILE__, __LINE__, pContext->ExpectedLength );
  185. }
  186. pContext->TotalBytes += pContext->emptybuf->bytesused;
  187. //
  188. // If there might be more to read, get more space and try to read more,
  189. // otherwise, coalesce everything we've read into one mammoth buffer,
  190. // then send that.
  191. //
  192. if( pContext->ExpectedLength > pContext->TotalBytes )
  193. {
  194. if( !KtGetMoreSpace( pContext, KTCONTEXT_BUFFER_LENGTH ) )
  195. goto SessError;
  196. if( !KtSockRead(pContext) )
  197. goto SessError;
  198. }
  199. else
  200. {
  201. DebugLog( DEB_TRACE, "%s(%d): %d bytes total read from loopback.\n", __FILE__, __LINE__, pContext->TotalBytes );
  202. if( !KtCoalesceBuffers( pContext ) )
  203. goto SessError;
  204. if( !KtFindProxy(pContext) )
  205. goto SessError;
  206. if( !KtHttpWrite(pContext) )
  207. goto SessError;
  208. }
  209. break;
  210. case KT_HTTP_WRITE:
  211. //
  212. // And now we read the response to our request.
  213. //
  214. pContext->ExpectedLength = 0;
  215. pContext->TotalBytes = 0;
  216. if( !KtHttpRead(pContext) )
  217. goto SessError;
  218. break;
  219. case KT_HTTP_READ:
  220. DebugLog( DEB_PEDANTIC, "%s(%d): %d bytes read from http.\n", __FILE__, __LINE__, pContext->emptybuf->bytesused );
  221. if( pContext->emptybuf->bytesused == 0 )
  222. {
  223. DebugLog( DEB_TRACE, "%s(%d): Data incomplete. Dropping connection.\n", __FILE__, __LINE__ );
  224. goto SessError;
  225. }
  226. //
  227. // If we don't know how many bytes to look for yet, figure it out.
  228. //
  229. if( pContext->ExpectedLength == 0 )
  230. {
  231. if( !KtParseExpectedLength( pContext ) )
  232. goto SessError;
  233. DebugLog( DEB_TRACE, "%s(%d): Expected message length: %d.\n", __FILE__, __LINE__, pContext->ExpectedLength );
  234. }
  235. //
  236. // Update the byte count
  237. //
  238. pContext->TotalBytes += pContext->emptybuf->bytesused;
  239. //
  240. // If we're expecting more, get more space and try to read more,
  241. // otherwise, coalesce everything we've read into one mammoth buffer,
  242. // relay that response back to our client.
  243. //
  244. if( pContext->ExpectedLength > pContext->TotalBytes )
  245. {
  246. if( !KtGetMoreSpace( pContext, KTCONTEXT_BUFFER_LENGTH ) )
  247. goto SessError;
  248. if( !KtHttpRead(pContext) )
  249. goto SessError;
  250. }
  251. else
  252. {
  253. DebugLog( DEB_TRACE, "%s(%d): %d total bytes read from http.\n", __FILE__, __LINE__, pContext->TotalBytes );
  254. if( !KtCoalesceBuffers(pContext) )
  255. goto SessError;
  256. //
  257. // If this is a debug build, let's generate some debug spew if
  258. // we get a kerb-error as a reply to one of our requests.
  259. //
  260. #if DBG
  261. KtParseKerbError(pContext);
  262. #endif
  263. if( !KtSockWrite(pContext) )
  264. goto SessError;
  265. }
  266. break;
  267. case KT_SOCK_WRITE:
  268. //
  269. // Once we've finished relaying our whole request-reponse pair,
  270. // we're done with this session.
  271. //
  272. DebugLog( DEB_TRACE, "%s(%d): %d bytes written to loopback.\n", __FILE__, __LINE__, pContext->ol.InternalHigh );
  273. KtReleaseContext(pContext);
  274. break;
  275. default:
  276. DebugLog( DEB_WARN, "%s(%d): Unhandled case: 0x%x.\n", __FILE__, __LINE__, pContext->Status );
  277. DsysAssert( pContext->Status == KT_SOCK_CONNECT ||
  278. pContext->Status == KT_SOCK_READ ||
  279. pContext->Status == KT_HTTP_WRITE ||
  280. pContext->Status == KT_HTTP_READ ||
  281. pContext->Status == KT_SOCK_WRITE );
  282. break;
  283. }
  284. return;
  285. SessError:
  286. DebugLog( DEB_TRACE, "%s(%d): Dropping connection due to session error.\n", __FILE__, __LINE__ );
  287. KtReleaseContext(pContext);
  288. return;
  289. SvcError:
  290. /* TODO: Event log. Pause service??? */
  291. return;
  292. }