Source code of Windows XP (NT5)
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.

246 lines
7.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: srvprot.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 09-26-97 jbanes LSA integration stuff.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <pct1msg.h>
  19. #include <pct1prot.h>
  20. #include <ssl2msg.h>
  21. #include <ssl3msg.h>
  22. #include <ssl2prot.h>
  23. /* The main purpose of this handler is to determine what kind of protocol
  24. * the client hello is
  25. */
  26. SP_STATUS WINAPI
  27. ServerProtocolHandler(
  28. PSPContext pContext,
  29. PSPBuffer pCommInput,
  30. PSPBuffer pCommOutput)
  31. {
  32. SP_STATUS pctRet = PCT_INT_ILLEGAL_MSG;
  33. PBYTE pb;
  34. PBYTE pbClientHello;
  35. DWORD dwVersion;
  36. DWORD dwEnabledProtocols;
  37. /* PCTv1.0 Hello starts with
  38. * RECORD_LENGTH_MSB (ignore)
  39. * RECORD_LENGTH_LSB (ignore)
  40. * PCT1_CLIENT_HELLO (must be equal)
  41. * PCT1_CLIENT_VERSION_MSB (if version greater than PCTv1)
  42. * PCT1_CLIENT_VERSION_LSB (if version greater than PCTv1)
  43. *
  44. * ... PCT hello ...
  45. */
  46. /* Microsft Unihello starts with
  47. * RECORD_LENGTH_MSB (ignore)
  48. * RECORD_LENGTH_LSB (ignore)
  49. * SSL2_CLIENT_HELLO (must be equal)
  50. * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3)
  51. * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3)
  52. *
  53. * ... SSLv2 Compatable Hello ...
  54. */
  55. /* SSLv2 Hello starts with
  56. * RECORD_LENGTH_MSB (ignore)
  57. * RECORD_LENGTH_LSB (ignore)
  58. * SSL2_CLIENT_HELLO (must be equal)
  59. * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3)
  60. * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3)
  61. *
  62. * ... SSLv2 Hello ...
  63. */
  64. /* SSLv3 Type 2 Hello starts with
  65. * RECORD_LENGTH_MSB (ignore)
  66. * RECORD_LENGTH_LSB (ignore)
  67. * SSL2_CLIENT_HELLO (must be equal)
  68. * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv3)
  69. * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv3)
  70. *
  71. * ... SSLv2 Compatable Hello ...
  72. */
  73. /* SSLv3 Type 3 Hello starts with
  74. * 0x15 Hex (HANDSHAKE MESSAGE)
  75. * VERSION MSB
  76. * VERSION LSB
  77. * RECORD_LENGTH_MSB (ignore)
  78. * RECORD_LENGTH_LSB (ignore)
  79. * HS TYPE (CLIENT_HELLO)
  80. * 3 bytes HS record length
  81. * HS Version
  82. * HS Version
  83. */
  84. dwEnabledProtocols = pContext->pCredGroup->grbitEnabledProtocols;
  85. // We need at least 5 bytes to determine what we have.
  86. if (pCommInput->cbData < 5)
  87. {
  88. return(PCT_INT_INCOMPLETE_MSG);
  89. }
  90. pb = pCommInput->pvBuffer;
  91. // If the first byte is 0x15, then check if we have a
  92. // SSLv3 Type3 client hello
  93. if(pb[0] == SSL3_CT_HANDSHAKE)
  94. {
  95. //
  96. // This is an SSL3 ClientHello.
  97. //
  98. // We need at least foo bytes to determine what we have.
  99. if (pCommInput->cbData < sizeof(SWRAP) + sizeof(SHSH) + 2)
  100. {
  101. return(PCT_INT_INCOMPLETE_MSG);
  102. }
  103. pbClientHello = pb + sizeof(SWRAP) + sizeof(SHSH);
  104. dwVersion = COMBINEBYTES(pbClientHello[0], pbClientHello[1]);
  105. if(dwVersion > 0x300 && (0 != (SP_PROT_TLS1_SERVER & dwEnabledProtocols)))
  106. {
  107. DebugLog((DEB_TRACE, "SSL3 ClientHello received, selected TLS\n"));
  108. pContext->dwProtocol = SP_PROT_TLS1_SERVER;
  109. }
  110. else if(0 != (SP_PROT_SSL3_SERVER & dwEnabledProtocols))
  111. {
  112. DebugLog((DEB_TRACE, "SSL3 ClientHello received, selected SSL3\n"));
  113. pContext->dwProtocol = SP_PROT_SSL3_SERVER;
  114. }
  115. else
  116. {
  117. return SP_LOG_RESULT(PCT_INT_SPECS_MISMATCH);
  118. }
  119. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  120. pContext->DecryptHandler = Ssl3DecryptHandler;
  121. pctRet = Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput);
  122. return(pctRet);
  123. }
  124. else
  125. {
  126. //
  127. // Assuming SSL2 (or compatible) ClientHello
  128. //
  129. dwVersion = COMBINEBYTES(pb[3], pb[4]);
  130. }
  131. if(dwVersion >= PCT_VERSION_1)
  132. {
  133. //
  134. // This is a PCT ClientHello.
  135. //
  136. if(!(SP_PROT_PCT1_SERVER & dwEnabledProtocols))
  137. {
  138. return SP_LOG_RESULT(PCT_ERR_SPECS_MISMATCH);
  139. }
  140. // We're running PCT, so set up the PCT handlers
  141. DebugLog((DEB_TRACE, "PCT ClientHello received, selected PCT\n"));
  142. pContext->dwProtocol = SP_PROT_PCT1_SERVER;
  143. pContext->ProtocolHandler = Pct1ServerProtocolHandler;
  144. pContext->DecryptHandler = Pct1DecryptHandler;
  145. return(Pct1ServerProtocolHandler(pContext, pCommInput, pCommOutput));
  146. }
  147. if(dwVersion >= SSL2_CLIENT_VERSION)
  148. {
  149. // we're either receiving ssl2, ssl3, or pct1 compat
  150. PSSL2_CLIENT_HELLO pRawHello = pCommInput->pvBuffer;
  151. // Do we have one client hello message with at least one
  152. // cipher spec.
  153. if (pCommInput->cbData < (sizeof(SSL2_CLIENT_HELLO)+2))
  154. {
  155. return(PCT_INT_INCOMPLETE_MSG);
  156. }
  157. // We must have at least one cipher spec
  158. if(COMBINEBYTES(pRawHello->CipherSpecsLenMsb, pRawHello->CipherSpecsLenLsb) < 1)
  159. {
  160. return(SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG));
  161. }
  162. // Does client support TLS?
  163. if((dwVersion >= TLS1_CLIENT_VERSION) &&
  164. (0 != (SP_PROT_TLS1_SERVER & dwEnabledProtocols)))
  165. {
  166. DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected TLS\n"));
  167. pContext->State = UNI_STATE_RECVD_UNIHELLO;
  168. pContext->dwProtocol = SP_PROT_TLS1_SERVER;
  169. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  170. pContext->DecryptHandler = Ssl3DecryptHandler;
  171. return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
  172. }
  173. // Does client support SSL3?
  174. if((dwVersion >= SSL3_CLIENT_VERSION) &&
  175. (0 != (SP_PROT_SSL3TLS1_SERVERS & dwEnabledProtocols)))
  176. {
  177. DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected SSL3\n"));
  178. pContext->State = UNI_STATE_RECVD_UNIHELLO;
  179. pContext->dwProtocol = SP_PROT_SSL3_SERVER;
  180. pContext->ProtocolHandler = Ssl3ProtocolHandler;
  181. pContext->DecryptHandler = Ssl3DecryptHandler;
  182. return(Ssl3ProtocolHandler(pContext, pCommInput, pCommOutput));
  183. }
  184. // Is the PCT compatability flag set?
  185. if(pRawHello->VariantData[0] == PCT_SSL_COMPAT)
  186. {
  187. // Get the pct version.
  188. dwVersion = COMBINEBYTES(pRawHello->VariantData[1], pRawHello->VariantData[2]);
  189. }
  190. // Does client support PCT?
  191. if((dwVersion >= PCT_VERSION_1) &&
  192. (0 != (SP_PROT_PCT1_SERVER & dwEnabledProtocols)))
  193. {
  194. DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected PCT\n"));
  195. pContext->State = UNI_STATE_RECVD_UNIHELLO;
  196. pContext->dwProtocol = SP_PROT_PCT1_SERVER;
  197. pContext->ProtocolHandler = Pct1ServerProtocolHandler;
  198. pContext->DecryptHandler = Pct1DecryptHandler;
  199. return(Pct1ServerProtocolHandler(pContext, pCommInput, pCommOutput));
  200. }
  201. // Does client support SSL2?
  202. if((dwVersion >= SSL2_CLIENT_VERSION) &&
  203. (0 != (SP_PROT_SSL2_SERVER & dwEnabledProtocols)))
  204. {
  205. DebugLog((DEB_TRACE, "SSL2 ClientHello received, selected SSL2\n"));
  206. pContext->dwProtocol = SP_PROT_SSL2_SERVER;
  207. pContext->ProtocolHandler = Ssl2ServerProtocolHandler;
  208. pContext->DecryptHandler = Ssl2DecryptHandler;
  209. return(Ssl2ServerProtocolHandler(pContext, pCommInput, pCommOutput));
  210. }
  211. return(SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG));
  212. }
  213. return (pctRet);
  214. }