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.

406 lines
10 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // blob.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the various 'blob' classes.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 08/24/1998 Original version.
  16. // 10/25/1998 New symbolic constants for ARAP.
  17. // 11/10/1998 Added isLmPresent().
  18. // 01/04/1999 MSChapError::insert takes a PPP error code.
  19. // 01/25/1999 MS-CHAP v2
  20. // 05/04/1999 New reason codes.
  21. // 05/11/1999 Fix RADIUS encryption.
  22. // 05/28/1999 Fix MS-MPPE-Keys format.
  23. // 02/17/2000 Key encryption is now handled by the protocol.
  24. //
  25. ///////////////////////////////////////////////////////////////////////////////
  26. #include <ias.h>
  27. #include <sdoias.h>
  28. #include <align.h>
  29. #include <algorithm>
  30. #include <cstdio>
  31. #include <samutil.h>
  32. #include <blob.h>
  33. bool MSChapResponse::isLmPresent() const throw ()
  34. {
  35. const BYTE* p = get().lmResponse + _LM_RESPONSE_LENGTH;
  36. do { } while (--p >= get().lmResponse && *p == 0);
  37. return p >= get().lmResponse;
  38. }
  39. bool MSChapCPW2::isLmPresent() const throw ()
  40. {
  41. // Do we have either an LM response or an LM hash.
  42. if ((get().flags[1] & 0x3) != 0x1) { return true; }
  43. // Now make sure the LM fields are zeroed out.
  44. const BYTE* p = get().oldLmHash +
  45. _ENCRYPTED_LM_OWF_PASSWORD_LENGTH + _LM_RESPONSE_LENGTH;
  46. do { } while (--p >= get().oldLmHash && *p == 0);
  47. return p >= get().oldLmHash;
  48. }
  49. //////////
  50. // Retrieves and assembles an MS-CHAP encrypted password. Returns 'true' if
  51. // the password is present, false otherwise.
  52. //////////
  53. BOOL MSChapEncPW::getEncryptedPassword(
  54. IASRequest& request,
  55. DWORD dwId,
  56. PBYTE buf
  57. )
  58. {
  59. //////////
  60. // Are there any attribute with the desired ID ?
  61. //////////
  62. IASAttributeVectorWithBuffer<8> attrs;
  63. if (attrs.load(request, dwId) == 0)
  64. {
  65. return false;
  66. }
  67. //////////
  68. // Allocate space on the stack for the blobs.
  69. //////////
  70. MSChapEncPW* begin = IAS_STACK_NEW(MSChapEncPW, attrs.size());
  71. MSChapEncPW* end = begin;
  72. //////////
  73. // Convert the attributes to password chunks and determine the total length.
  74. //////////
  75. DWORD length = 0;
  76. IASAttributeVector::iterator i;
  77. for (i = attrs.begin(); i != attrs.end(); ++i, ++end)
  78. {
  79. *end = blob_cast<MSChapEncPW>(i->pAttribute);
  80. length += end->getStringLength();
  81. }
  82. //////////
  83. // Do we have the right length ?
  84. //////////
  85. if (length != _SAMPR_ENCRYPTED_USER_PASSWORD_LENGTH)
  86. {
  87. _com_issue_error(IAS_MALFORMED_REQUEST);
  88. }
  89. //////////
  90. // Sort the chunks ...
  91. //////////
  92. std::sort(begin, end);
  93. //////////
  94. // ... then concatenate the strings into the buffer.
  95. //////////
  96. for ( ; begin != end; ++begin)
  97. {
  98. memcpy(buf, begin->get().string, begin->getStringLength());
  99. buf += begin->getStringLength();
  100. }
  101. return true;
  102. }
  103. void MSChapDomain::insert(
  104. IASRequest& request,
  105. BYTE ident,
  106. PCWSTR domain
  107. )
  108. {
  109. //////////
  110. // Allocate an attribute.
  111. //////////
  112. IASAttribute attr(true);
  113. //////////
  114. // Allocate memory for the blob.
  115. //////////
  116. int len = WideCharToMultiByte(CP_ACP, 0, domain, -1, 0, 0, 0, 0);
  117. Layout* val = (Layout*)CoTaskMemAlloc(len + sizeof(Layout));
  118. if (val == NULL) { _com_issue_error(E_OUTOFMEMORY); }
  119. //////////
  120. // Initialize the blob.
  121. //////////
  122. val->ident = ident;
  123. WideCharToMultiByte(CP_ACP, 0, domain, -1, (PSTR)val->string, len, 0, 0);
  124. //////////
  125. // Initialize the attribute and store.
  126. //////////
  127. attr->dwId = MS_ATTRIBUTE_CHAP_DOMAIN;
  128. attr->Value.itType = IASTYPE_OCTET_STRING;
  129. attr->Value.OctetString.lpValue = (PBYTE)val;
  130. attr->Value.OctetString.dwLength = len + sizeof(Layout) - 1;
  131. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  132. attr.store(request);
  133. }
  134. void MSChapError::insert(
  135. IASRequest& request,
  136. BYTE ident,
  137. DWORD errorCode
  138. )
  139. {
  140. //////////
  141. // Allocate an attribute.
  142. //////////
  143. IASAttribute attr(true);
  144. //////////
  145. // Format the error message.
  146. //////////
  147. CHAR buffer[32];
  148. sprintf(buffer, "E=%lu R=0 V=3", errorCode);
  149. //////////
  150. // Allocate memory for the blob.
  151. //////////
  152. ULONG len = strlen(buffer);
  153. Layout* val = (Layout*)CoTaskMemAlloc(len + sizeof(Layout));
  154. if (val == NULL) { _com_issue_error(E_OUTOFMEMORY); }
  155. //////////
  156. // Initialize the blob.
  157. //////////
  158. val->ident = ident;
  159. memcpy(val->string, buffer, len);
  160. //////////
  161. // Initialize the attribute and store.
  162. //////////
  163. attr->dwId = MS_ATTRIBUTE_CHAP_ERROR;
  164. attr->Value.itType = IASTYPE_OCTET_STRING;
  165. attr->Value.OctetString.lpValue = (PBYTE)val;
  166. attr->Value.OctetString.dwLength = len + sizeof(Layout);
  167. attr->dwFlags = IAS_INCLUDE_IN_REJECT;
  168. attr.store(request);
  169. }
  170. void MSChapMPPEKeys::insert(
  171. IASRequest& request,
  172. PBYTE lmKey,
  173. PBYTE ntKey,
  174. PBYTE challenge
  175. )
  176. {
  177. //////////
  178. // Allocate an attribute.
  179. //////////
  180. IASAttribute attr(true);
  181. //////////
  182. // Allocate memory for the value.
  183. //////////
  184. Layout* val = (Layout*)CoTaskMemAlloc(sizeof(Layout));
  185. if (val == NULL) { _com_issue_error(E_OUTOFMEMORY); }
  186. //////////
  187. // Initialize the blob.
  188. //////////
  189. memcpy(val->lmKey, lmKey, sizeof(val->lmKey));
  190. memcpy(val->ntKey, ntKey, sizeof(val->ntKey));
  191. memcpy(val->challenge, challenge, sizeof(val->challenge));
  192. //////////
  193. // Initialize the attribute and store.
  194. //////////
  195. attr->dwId = MS_ATTRIBUTE_CHAP_MPPE_KEYS;
  196. attr->Value.itType = IASTYPE_OCTET_STRING;
  197. attr->Value.OctetString.lpValue = (PBYTE)val;
  198. attr->Value.OctetString.dwLength = sizeof(Layout);
  199. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  200. attr.store(request);
  201. }
  202. // Convert a number to a hex representation.
  203. inline BYTE num2Digit(BYTE num) throw ()
  204. {
  205. return (num < 10) ? num + '0' : num + ('A' - 10);
  206. }
  207. void MSChap2Success::insert(
  208. IASRequest& request,
  209. BYTE ident,
  210. PBYTE authenticatorResponse
  211. )
  212. {
  213. //////////
  214. // Allocate an attribute.
  215. //////////
  216. IASAttribute attr(true);
  217. //////////
  218. // Allocate memory for the value.
  219. //////////
  220. Layout* val = (Layout*)CoTaskMemAlloc(sizeof(Layout));
  221. if (val == NULL) { _com_issue_error(E_OUTOFMEMORY); }
  222. //////////
  223. // Initialize the blob.
  224. //////////
  225. val->ident = ident;
  226. PBYTE p = val->string;
  227. *p++ = 'S';
  228. *p++ = '=';
  229. for (size_t i = 0; i < 20; ++i)
  230. {
  231. *p++ = num2Digit(authenticatorResponse[i] >> 4);
  232. *p++ = num2Digit(authenticatorResponse[i] & 0xF);
  233. }
  234. //////////
  235. // Initialize the attribute and store.
  236. //////////
  237. attr->dwId = MS_ATTRIBUTE_CHAP2_SUCCESS;
  238. attr->Value.itType = IASTYPE_OCTET_STRING;
  239. attr->Value.OctetString.lpValue = (PBYTE)val;
  240. attr->Value.OctetString.dwLength = sizeof(Layout);
  241. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  242. attr.store(request);
  243. }
  244. void MSMPPEKey::insert(
  245. IASRequest& request,
  246. ULONG keyLength,
  247. PBYTE key,
  248. BOOL isSendKey
  249. )
  250. {
  251. //////////
  252. // Allocate an attribute.
  253. //////////
  254. IASAttribute attr(true);
  255. //////////
  256. // Allocate memory for the value.
  257. //////////
  258. ULONG nbyte = ROUND_UP_COUNT(keyLength + 1, 16) + 2;
  259. Layout* val = (Layout*)CoTaskMemAlloc(nbyte);
  260. if (val == NULL) { _com_issue_error(E_OUTOFMEMORY); }
  261. memset(val, 0, nbyte);
  262. //////////
  263. // Initialize the blob.
  264. //////////
  265. val->keyLength = (BYTE)keyLength;
  266. memcpy(val->key, key, keyLength);
  267. //////////
  268. // Initialize the attribute, encrypt, and store.
  269. //////////
  270. attr->dwId = isSendKey ? MS_ATTRIBUTE_MPPE_SEND_KEY
  271. : MS_ATTRIBUTE_MPPE_RECV_KEY;
  272. attr->Value.itType = IASTYPE_OCTET_STRING;
  273. attr->Value.OctetString.lpValue = (PBYTE)val;
  274. attr->Value.OctetString.dwLength = nbyte;
  275. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  276. attr.store(request);
  277. }
  278. void ArapChallengeResponse::insert(
  279. IASRequest& request,
  280. DWORD NTResponse1,
  281. DWORD NTResponse2
  282. )
  283. {
  284. // Allocate an attribute.
  285. IASAttribute attr(true);
  286. // Pack the fields. These are already in network order.
  287. Layout value;
  288. memcpy(value.ntResponse1, &NTResponse1, 4);
  289. memcpy(value.ntResponse2, &NTResponse2, 4);
  290. // Store the value.
  291. attr.setOctetString(sizeof(value), (const BYTE*)&value);
  292. // Initialize the remaining fields.
  293. attr->dwId = RADIUS_ATTRIBUTE_ARAP_CHALLENGE_RESPONSE;
  294. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  295. // Insert the attribute into the request.
  296. attr.store(request);
  297. }
  298. void ArapFeatures::insert(
  299. IASRequest& request,
  300. DWORD PwdCreationDate,
  301. DWORD PwdExpiryDelta,
  302. DWORD CurrentTime
  303. )
  304. {
  305. // Allocate an attribute.
  306. IASAttribute attr(true);
  307. // Pack the fields.
  308. Layout value;
  309. value.changePasswordAllowed = 1; // Change password always allowed.
  310. value.minPasswordLength = 3; // Arbitrary.
  311. // These are already in network order.
  312. memcpy(value.pwdCreationDate, &PwdCreationDate, 4);
  313. memcpy(value.pwdExpiryDelta, &PwdExpiryDelta, 4);
  314. memcpy(value.currentTime, &CurrentTime, 4);
  315. // Store the value.
  316. attr.setOctetString(sizeof(value), (const BYTE*)&value);
  317. // Initialize the rest of the fields.
  318. attr->dwId = RADIUS_ATTRIBUTE_ARAP_FEATURES;
  319. attr->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  320. // Insert the attribute into the request.
  321. attr.store(request);
  322. }