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.

208 lines
5.9 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corp. All rights reserved.
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines the class PostEapRestrictions.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "ias.h"
  11. #include "posteap.h"
  12. #include "sdoias.h"
  13. IASREQUESTSTATUS PostEapRestrictions::onSyncRequest(
  14. IRequest* pRequest
  15. ) throw ()
  16. {
  17. try
  18. {
  19. IASTL::IASRequest request(pRequest);
  20. IASRESPONSE response = request.get_Response();
  21. if (response == IAS_RESPONSE_INVALID)
  22. {
  23. IASATTRIBUTE* state = IASPeekAttribute(
  24. request,
  25. RADIUS_ATTRIBUTE_STATE,
  26. IASTYPE_OCTET_STRING
  27. );
  28. if ((state != 0) && (state->Value.OctetString.dwLength > 0))
  29. {
  30. // If we made it here, then we have a Challenge-Reponse that no
  31. // handler recognized, so we discard.
  32. request.SetResponse(
  33. IAS_RESPONSE_DISCARD_PACKET,
  34. IAS_UNEXPECTED_REQUEST
  35. );
  36. return IAS_REQUEST_STATUS_HANDLED;
  37. }
  38. }
  39. IASREASON result;
  40. if (!CheckCertificateEku(request))
  41. {
  42. result = IAS_INVALID_CERT_EKU;
  43. }
  44. else
  45. {
  46. GenerateSessionTimeout(request);
  47. result = IAS_SUCCESS;
  48. // We apply user restrictions to Access-Rejects as well, so we only
  49. // want to set Access-Accept if the response code is still invalid.
  50. // This should only be true for unauthenticated requests.
  51. if (response == IAS_RESPONSE_INVALID)
  52. {
  53. request.SetResponse(IAS_RESPONSE_ACCESS_ACCEPT, IAS_SUCCESS);
  54. }
  55. }
  56. if (result != IAS_SUCCESS)
  57. {
  58. request.SetResponse(IAS_RESPONSE_ACCESS_REJECT, result);
  59. }
  60. }
  61. catch (const _com_error&)
  62. {
  63. pRequest->SetResponse(IAS_RESPONSE_DISCARD_PACKET, IAS_INTERNAL_ERROR);
  64. }
  65. return IAS_REQUEST_STATUS_HANDLED;
  66. }
  67. bool PostEapRestrictions::CheckCertificateEku(IASTL::IASRequest& request)
  68. {
  69. // Is it an EAP-TLS request or a PEAP request?
  70. IASTL::IASAttribute eapType;
  71. DWORD attributeId = IAS_ATTRIBUTE_EAP_TYPEID;
  72. if ( !eapType.load(request, attributeId) )
  73. {
  74. // should never go there. At least one EAP type should be enabled
  75. return true;
  76. }
  77. if (eapType->Value.Integer != 13)
  78. {
  79. // Neither EAP-TLS nor PEAP-TLS
  80. return true;
  81. }
  82. // Here it is either EAP-TLS or PEAP-TLS
  83. // Are there any constraints on the certificate EKU?
  84. AttributeVector allowed;
  85. allowed.load(request, IAS_ATTRIBUTE_ALLOWED_CERTIFICATE_EKU);
  86. if (allowed.empty())
  87. {
  88. return true;
  89. }
  90. //////////
  91. // Check the constraints.
  92. //////////
  93. AttributeVector actual;
  94. actual.load(request, IAS_ATTRIBUTE_CERTIFICATE_EKU);
  95. for (AttributeVector::iterator i = actual.begin();
  96. i != actual.end();
  97. ++i)
  98. {
  99. const char* actualOid = GetAnsiString(*(i->pAttribute));
  100. if (actualOid != 0)
  101. {
  102. for (AttributeVector::iterator j = allowed.begin();
  103. j != allowed.end();
  104. ++j)
  105. {
  106. const char* allowedOid = GetAnsiString(*(j->pAttribute));
  107. if ((allowedOid != 0) && (strcmp(allowedOid, actualOid) == 0))
  108. {
  109. return true;
  110. }
  111. }
  112. }
  113. }
  114. return false;
  115. }
  116. void PostEapRestrictions::GenerateSessionTimeout(IASTL::IASRequest& request)
  117. {
  118. // retrieve the generate-session-timeout attribute.
  119. IASATTRIBUTE* generate = IASPeekAttribute(
  120. request,
  121. IAS_ATTRIBUTE_GENERATE_SESSION_TIMEOUT,
  122. IASTYPE_BOOLEAN
  123. );
  124. if ((generate == 0) || !generate->Value.Boolean)
  125. {
  126. IASTraceString("Auto-generation of Session-Timeout is disabled.");
  127. return;
  128. }
  129. // retrieve all the ms-session-timeout and session-timeout from the request.
  130. DWORD attrIDs[] =
  131. {
  132. MS_ATTRIBUTE_SESSION_TIMEOUT,
  133. RADIUS_ATTRIBUTE_SESSION_TIMEOUT
  134. };
  135. AttributeVector sessionTimeouts;
  136. if (!sessionTimeouts.load(request, RTL_NUMBER_OF(attrIDs), attrIDs))
  137. {
  138. IASTraceString("Session-Timeout not present.");
  139. return;
  140. }
  141. DWORD minTimeout = MAXDWORD;
  142. // get the minimum value found. Store it in the local min value (seconds)
  143. for (AttributeVector::const_iterator i = sessionTimeouts.begin();
  144. i != sessionTimeouts.end();
  145. ++i)
  146. {
  147. IASTracePrintf("Session-Timeout = %lu", i->pAttribute->Value.Integer);
  148. if (i->pAttribute->Value.Integer < minTimeout)
  149. {
  150. minTimeout = i->pAttribute->Value.Integer;
  151. }
  152. }
  153. IASTracePrintf("Consensus Session-Timeout = %lu", minTimeout);
  154. // delete all the session-timeout from the request
  155. request.RemoveAttributesByType(2, attrIDs);
  156. // add one session-timeout with the new value to the request
  157. IASTL::IASAttribute sessionTimeout(true);
  158. sessionTimeout->dwId = RADIUS_ATTRIBUTE_SESSION_TIMEOUT;
  159. sessionTimeout->Value.itType = IASTYPE_INTEGER;
  160. sessionTimeout->Value.Integer = minTimeout;
  161. sessionTimeout.setFlag(IAS_INCLUDE_IN_ACCEPT);
  162. sessionTimeout.store(request);
  163. }
  164. const char* PostEapRestrictions::GetAnsiString(IASATTRIBUTE& attr)
  165. {
  166. if (attr.Value.itType != IASTYPE_STRING)
  167. {
  168. return 0;
  169. }
  170. DWORD error = IASAttributeAnsiAlloc(&attr);
  171. if (error != NO_ERROR)
  172. {
  173. IASTL::issue_error(HRESULT_FROM_WIN32(error));
  174. }
  175. return attr.Value.String.pszAnsi;
  176. }