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.

295 lines
8.2 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // userr.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class UserRestrictions.
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. #include <ias.h>
  15. #include <userr.h>
  16. #include <TimeOfDay.h>
  17. IASREQUESTSTATUS UserRestrictions::onSyncRequest(IRequest* pRequest) throw ()
  18. {
  19. try
  20. {
  21. IASRequest request(pRequest);
  22. IASREASON result;
  23. if (!checkAllowDialin(request))
  24. {
  25. result = IAS_DIALIN_DISABLED;
  26. }
  27. else if (!checkTimeOfDay(request))
  28. {
  29. result = IAS_INVALID_DIALIN_HOURS;
  30. }
  31. else if (!checkAuthenticationType(request))
  32. {
  33. result = IAS_INVALID_AUTH_TYPE;
  34. }
  35. else if (!checkCallingStationId(request))
  36. {
  37. result = IAS_INVALID_CALLING_STATION;
  38. }
  39. else if (!checkCalledStationId(request))
  40. {
  41. result = IAS_INVALID_CALLED_STATION;
  42. }
  43. else if (!checkAllowedPortType(request))
  44. {
  45. result = IAS_INVALID_PORT_TYPE;
  46. }
  47. else if (!checkPasswordMustChange(request))
  48. {
  49. result = IAS_CPW_NOT_ALLOWED;
  50. }
  51. else
  52. {
  53. result = IAS_SUCCESS;
  54. }
  55. if (result != IAS_SUCCESS)
  56. {
  57. request.SetResponse(IAS_RESPONSE_ACCESS_REJECT, result);
  58. }
  59. }
  60. catch (const _com_error&)
  61. {
  62. pRequest->SetResponse(IAS_RESPONSE_DISCARD_PACKET, IAS_INTERNAL_ERROR);
  63. }
  64. return IAS_REQUEST_STATUS_HANDLED;
  65. }
  66. BOOL UserRestrictions::checkAllowDialin(
  67. IAttributesRaw* request
  68. )
  69. {
  70. PIASATTRIBUTE attr = IASPeekAttribute(
  71. request,
  72. IAS_ATTRIBUTE_ALLOW_DIALIN,
  73. IASTYPE_BOOLEAN
  74. );
  75. return !attr || attr->Value.Boolean;
  76. }
  77. BOOL UserRestrictions::checkTimeOfDay(
  78. IAttributesRaw* request
  79. )
  80. {
  81. AttributeVector attrs;
  82. attrs.load(request, IAS_ATTRIBUTE_NP_TIME_OF_DAY);
  83. if (attrs.empty()) { return TRUE; }
  84. BYTE hourMap[IAS_HOUR_MAP_LENGTH];
  85. memset(hourMap, 0, sizeof(hourMap));
  86. for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  87. {
  88. IASAttributeUnicodeAlloc(i->pAttribute);
  89. if (!i->pAttribute->Value.String.pszWide) { issue_error(E_OUTOFMEMORY); }
  90. // Convert the text to an hour map.
  91. DWORD dw = IASHourMapFromText(
  92. i->pAttribute->Value.String.pszWide,
  93. TRUE,
  94. hourMap
  95. );
  96. if (dw != NO_ERROR)
  97. {
  98. issue_error(HRESULT_FROM_WIN32(dw));
  99. }
  100. }
  101. SYSTEMTIME now;
  102. GetLocalTime(&now);
  103. DWORD timeOut = ComputeTimeout(now, hourMap);
  104. if (timeOut == 0)
  105. {
  106. return FALSE;
  107. }
  108. if (timeOut != 0xFFFFFFFF)
  109. {
  110. // Add the Session-Timeout attribute to the request.
  111. // it'll be carried over to the response later on.
  112. IASAttribute sessionTimeout(true);
  113. sessionTimeout->dwId = MS_ATTRIBUTE_SESSION_TIMEOUT;
  114. sessionTimeout->Value.itType = IASTYPE_INTEGER;
  115. sessionTimeout->Value.Integer = timeOut;
  116. sessionTimeout.setFlag(IAS_INCLUDE_IN_ACCEPT);
  117. sessionTimeout.store(request);
  118. }
  119. return TRUE;
  120. }
  121. BOOL UserRestrictions::checkAuthenticationType(
  122. IAttributesRaw* request
  123. )
  124. {
  125. // special case for the external Auth provider
  126. PIASATTRIBUTE provider = IASPeekAttribute(
  127. request,
  128. IAS_ATTRIBUTE_PROVIDER_TYPE,
  129. IASTYPE_ENUM
  130. );
  131. _ASSERT(provider != 0);
  132. if (provider->Value.Enumerator == IAS_PROVIDER_EXTERNAL_AUTH)
  133. {
  134. return TRUE;
  135. }
  136. AttributeVector attrs;
  137. attrs.load(request, IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE);
  138. if (attrs.empty()) {return TRUE;}
  139. PIASATTRIBUTE attr = IASPeekAttribute(
  140. request,
  141. IAS_ATTRIBUTE_AUTHENTICATION_TYPE,
  142. IASTYPE_ENUM
  143. );
  144. DWORD authType = attr ? attr->Value.Enumerator : IAS_AUTH_NONE;
  145. // We bypass the check for BaseCamp extensions.
  146. if (authType == IAS_AUTH_CUSTOM) { return TRUE; }
  147. for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  148. {
  149. if (i->pAttribute->Value.Integer == authType) { return TRUE; }
  150. }
  151. return FALSE;
  152. }
  153. BOOL UserRestrictions::checkCallingStationId(
  154. IAttributesRaw* request
  155. )
  156. {
  157. return checkStringMatch(
  158. request,
  159. IAS_ATTRIBUTE_NP_CALLING_STATION_ID,
  160. RADIUS_ATTRIBUTE_CALLING_STATION_ID
  161. );
  162. }
  163. BOOL UserRestrictions::checkCalledStationId(
  164. IAttributesRaw* request
  165. )
  166. {
  167. return checkStringMatch(
  168. request,
  169. IAS_ATTRIBUTE_NP_CALLED_STATION_ID,
  170. RADIUS_ATTRIBUTE_CALLED_STATION_ID
  171. );
  172. }
  173. BOOL UserRestrictions::checkAllowedPortType(
  174. IAttributesRaw* request
  175. )
  176. {
  177. AttributeVector attrs;
  178. attrs.load(request, IAS_ATTRIBUTE_NP_ALLOWED_PORT_TYPES);
  179. if (attrs.empty()) { return TRUE; }
  180. PIASATTRIBUTE attr = IASPeekAttribute(
  181. request,
  182. RADIUS_ATTRIBUTE_NAS_PORT_TYPE,
  183. IASTYPE_ENUM
  184. );
  185. if (!attr) { return FALSE; }
  186. for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  187. {
  188. if (i->pAttribute->Value.Enumerator == attr->Value.Enumerator)
  189. {
  190. return TRUE;
  191. }
  192. }
  193. return FALSE;
  194. }
  195. // If the password must change, we check to see if the subsequent change
  196. // password request would be authorized. This prevents prompting the user for a
  197. // new password when he's not allowed to change it anyway.
  198. BOOL UserRestrictions::checkPasswordMustChange(
  199. IASRequest& request
  200. )
  201. {
  202. if (request.get_Reason() != IAS_PASSWORD_MUST_CHANGE)
  203. {
  204. return TRUE;
  205. }
  206. PIASATTRIBUTE attr = IASPeekAttribute(
  207. request,
  208. IAS_ATTRIBUTE_AUTHENTICATION_TYPE,
  209. IASTYPE_ENUM
  210. );
  211. DWORD cpwType;
  212. switch (attr ? attr->Value.Enumerator : IAS_AUTH_NONE)
  213. {
  214. case IAS_AUTH_MSCHAP:
  215. cpwType = IAS_AUTH_MSCHAP_CPW;
  216. break;
  217. case IAS_AUTH_MSCHAP2:
  218. cpwType = IAS_AUTH_MSCHAP2_CPW;
  219. break;
  220. default:
  221. return TRUE;
  222. }
  223. AttributeVector attrs;
  224. attrs.load(request, IAS_ATTRIBUTE_NP_AUTHENTICATION_TYPE);
  225. for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  226. {
  227. if (i->pAttribute->Value.Integer == cpwType) { return TRUE; }
  228. }
  229. return FALSE;
  230. }
  231. BOOL UserRestrictions::checkStringMatch(
  232. IAttributesRaw* request,
  233. DWORD allowedId,
  234. DWORD usedId
  235. )
  236. {
  237. AttributeVector attrs;
  238. attrs.load(request, allowedId);
  239. if (attrs.empty()) { return TRUE; }
  240. PIASATTRIBUTE attr = IASPeekAttribute(
  241. request,
  242. usedId,
  243. IASTYPE_OCTET_STRING
  244. );
  245. if (!attr) { return FALSE; }
  246. PCWSTR used = IAS_OCT2WIDE(attr->Value.OctetString);
  247. for (AttributeVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  248. {
  249. IASAttributeUnicodeAlloc(i->pAttribute);
  250. if (!i->pAttribute->Value.String.pszWide) { issue_error(E_OUTOFMEMORY); }
  251. if (!_wcsicmp(i->pAttribute->Value.String.pszWide, used)) { return TRUE; }
  252. }
  253. return FALSE;
  254. }