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.

453 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: authen.cxx
  7. //
  8. // Contents: Authenticator verification code
  9. //
  10. // Classes: CAuthenticatorList
  11. //
  12. // Functions: Compare, AuthenAllocate, AuthenFree
  13. //
  14. // History: 4-04-93 WadeR Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <secpch2.hxx>
  18. #pragma hdrstop
  19. //
  20. // Security include files.
  21. //
  22. #include <kerbcomm.h>
  23. #include <authen.hxx>
  24. extern "C"
  25. {
  26. #include <md5.h>
  27. }
  28. typedef struct _KERB_AUTHEN_HEADER
  29. {
  30. LARGE_INTEGER tsTime;
  31. BYTE Checksum[MD5DIGESTLEN];
  32. } KERB_AUTHEN_HEADER, *PKERB_AUTHEN_HEADER;
  33. #define KERB_MAX_AUTHEN_SIZE 1024
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Function: Compare
  37. //
  38. // Synopsis: Compares two KerbInternalAuthenticators for RTL_GENERIC_TABLE
  39. //
  40. // Effects: none.
  41. //
  42. // Arguments: [Table] -- ignored
  43. // [FirstStruct] --
  44. // [SecondStruct] --
  45. //
  46. // Returns: GenericEqual, GenericLessThan, GenericGreaterThan.
  47. //
  48. // Algorithm: Sorts by TimeStamp first, than nonce, then principal, and
  49. // finally by realm
  50. //
  51. // History: 4-04-93 WadeR Created
  52. //
  53. // Notes: This must impose a complete ordering. The table package
  54. // will not allow an authenticator to be inserted in the table
  55. // if it is equal (according to this function) to one already
  56. // there.
  57. //
  58. //----------------------------------------------------------------------------
  59. RTL_GENERIC_COMPARE_RESULTS
  60. Compare(
  61. IN struct _RTL_GENERIC_TABLE *Table,
  62. IN PVOID FirstStruct,
  63. IN PVOID SecondStruct
  64. )
  65. {
  66. PKERB_AUTHEN_HEADER pOne, pTwo;
  67. RTL_GENERIC_COMPARE_RESULTS ret;
  68. int comp;
  69. pOne = (PKERB_AUTHEN_HEADER) FirstStruct ;
  70. pTwo = (PKERB_AUTHEN_HEADER) SecondStruct ;
  71. DsysAssert( (pOne != NULL) && (pTwo != NULL) );
  72. comp = memcmp( pOne->Checksum,
  73. pTwo->Checksum,
  74. MD5DIGESTLEN );
  75. if (comp > 0)
  76. {
  77. ret = GenericGreaterThan;
  78. }
  79. else if (comp < 0)
  80. {
  81. ret = GenericLessThan;
  82. }
  83. else
  84. {
  85. ret = GenericEqual;
  86. }
  87. return(ret);
  88. }
  89. //+---------------------------------------------------------------------------
  90. //
  91. // Function: AuthenAllocate
  92. //
  93. // Synopsis: Memory allocator for RTL_GENERIC_TABLE
  94. //
  95. // Effects: Allcoates memory.
  96. //
  97. // Arguments: [Table] -- ignored
  98. // [ByteSize] -- number of bytes to allocate
  99. //
  100. // Signals: Throws exception on failure.
  101. //
  102. // History: 4-04-93 WadeR Created
  103. //
  104. // Notes:
  105. //
  106. //----------------------------------------------------------------------------
  107. PVOID
  108. AuthenAllocate( struct _RTL_GENERIC_TABLE *Table, CLONG ByteSize )
  109. {
  110. return(MIDL_user_allocate ( ByteSize ) );
  111. }
  112. //+---------------------------------------------------------------------------
  113. //
  114. // Function: AuthenFree
  115. //
  116. // Synopsis: Memory deallacotor for the RTL_GENERIC_TABLE.
  117. //
  118. // Effects: frees memory.
  119. //
  120. // Arguments: [Table] -- ingnored
  121. // [Buffer] -- buffer to free
  122. //
  123. // History: 4-04-93 WadeR Created
  124. //
  125. // Notes:
  126. //
  127. //----------------------------------------------------------------------------
  128. VOID
  129. AuthenFree( struct _RTL_GENERIC_TABLE *Table, PVOID Buffer )
  130. {
  131. MIDL_user_free ( Buffer );
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // Member: CAuthenticatorList::CAuthenticatorList
  136. //
  137. // Synopsis: Initializes the authenticator list.
  138. //
  139. // Effects: Calls RtlInitializeGenericTable (does not allocate memory).
  140. //
  141. // Arguments: [tsMax] -- Maximum acceptable age for an authenticator.
  142. //
  143. // History: 4-04-93 WadeR Created
  144. //
  145. // Notes:
  146. //
  147. //----------------------------------------------------------------------------
  148. CAuthenticatorList::CAuthenticatorList(LARGE_INTEGER tsMax)
  149. :_tsMaxAge(tsMax)
  150. {
  151. NTSTATUS Status;
  152. // The last parameter is the "user defined context" for this table.
  153. // I have no idea what this means. As far as I can tell from the code
  154. // this "context" is never refered to by the table routines.
  155. RtlInitializeGenericTable( &_Table, Compare, AuthenAllocate, AuthenFree, NULL );
  156. Status = RtlInitializeCriticalSection(&_Mutex);
  157. DsysAssert(NT_SUCCESS(Status));
  158. }
  159. //+---------------------------------------------------------------------------
  160. //
  161. // Member: CAuthenticatorList::~CAuthenticatorList
  162. //
  163. // Synopsis: Destructor removes all authenticators in the list.
  164. //
  165. // Effects: Frees memory
  166. //
  167. // Arguments: (none)
  168. //
  169. // Algorithm: Uses "Age" to remove everything.
  170. //
  171. // History: 4-04-93 WadeR Created
  172. //
  173. // Notes:
  174. //
  175. //----------------------------------------------------------------------------
  176. CAuthenticatorList::~CAuthenticatorList()
  177. {
  178. LARGE_INTEGER tsForever;
  179. SetMaxTimeStamp( tsForever );
  180. (void) Age( tsForever );
  181. DsysAssert( RtlIsGenericTableEmpty( &_Table ) );
  182. RtlDeleteCriticalSection(&_Mutex);
  183. }
  184. //+---------------------------------------------------------------------------
  185. //
  186. // Member: CAuthenticatorList::SetMaxAge
  187. //
  188. // Synopsis: Changes the new maximum age for an Authenticator.
  189. //
  190. // Effects: May cause some authenticators to be aged out.
  191. //
  192. // Arguments: [tsNewMaxAge] --
  193. //
  194. // Algorithm:
  195. //
  196. // History: 24-May-94 wader Created
  197. //
  198. // Notes:
  199. //
  200. //----------------------------------------------------------------------------
  201. void
  202. CAuthenticatorList::SetMaxAge( LARGE_INTEGER tsNewMaxAge )
  203. {
  204. LARGE_INTEGER tsNow;
  205. LARGE_INTEGER tsCutoff;
  206. _tsMaxAge = tsNewMaxAge;
  207. GetSystemTimeAsFileTime((PFILETIME) &tsNow );
  208. tsCutoff.QuadPart = tsNow.QuadPart - _tsMaxAge.QuadPart;
  209. (void) Age( tsCutoff );
  210. }
  211. //+---------------------------------------------------------------------------
  212. //
  213. // Member: CAuthenticatorList::Age
  214. //
  215. // Synopsis: Deletes all entries from the table that are earlier than
  216. // the given time.
  217. //
  218. // Effects: Frees memory
  219. //
  220. // Arguments: [tsCutoffTime] -- Delete all elements before this time.
  221. //
  222. // Returns: number of elements deleted.
  223. //
  224. // Algorithm: Get the oldest element in the table. If it is older than
  225. // the time, delete it and loop back. Else return.
  226. //
  227. // History: 4-04-93 WadeR Created
  228. //
  229. // Notes: The table contains the packed forms of Authenticators (as
  230. // created by PackAuthenticator in Kerbsupp). The TimeStamp
  231. // must be first.
  232. //
  233. //----------------------------------------------------------------------------
  234. ULONG
  235. CAuthenticatorList::Age(const LARGE_INTEGER& tsCutoffTime)
  236. {
  237. PKERB_AUTHEN_HEADER pahOldest;
  238. BOOL fDeleted;
  239. ULONG cDeleted = 0;
  240. do
  241. {
  242. // Number 0 is the oldest element in the table.
  243. pahOldest = (PKERB_AUTHEN_HEADER) RtlGetElementGenericTable( &_Table, 0 );
  244. if ((pahOldest != NULL) &&
  245. (pahOldest->tsTime.QuadPart < tsCutoffTime.QuadPart))
  246. {
  247. fDeleted = RtlDeleteElementGenericTable( &_Table, pahOldest );
  248. DsysAssert( fDeleted );
  249. cDeleted++;
  250. }
  251. else
  252. {
  253. fDeleted = FALSE;
  254. }
  255. } while ( fDeleted );
  256. return(cDeleted);
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Member: CAuthenticatorList::Check
  261. //
  262. // Synopsis: Determines if an authenticator is valid.
  263. //
  264. // Effects: Allocates memory
  265. //
  266. // Arguments: [pedAuth] -- Authenticator to check (decrypted, but marshalled)
  267. //
  268. // Returns: KDC_ERR_NONE if authenticator is OK.
  269. // KRB_AP_ERR_SKEW if authenticator is expired (assumes clock skew).
  270. // KRB_AP_ERR_REPEAT if authenticator has been used already.
  271. // some other error if something throws an exception.
  272. //
  273. // Signals: none.
  274. //
  275. // Modifies: _Table
  276. //
  277. // History: 4-04-93 WadeR Created
  278. //
  279. // Notes:
  280. //
  281. //----------------------------------------------------------------------------
  282. KERBERR
  283. CAuthenticatorList::Check(
  284. IN PVOID Buffer,
  285. IN ULONG BufferLength,
  286. IN OPTIONAL PVOID OptionalBuffer,
  287. IN OPTIONAL ULONG OptionalBufferLength,
  288. IN PLARGE_INTEGER Time,
  289. IN BOOLEAN Insert
  290. )
  291. {
  292. PKERB_AUTHEN_HEADER pDataInTable = NULL;
  293. KERBERR KerbErr = KDC_ERR_NONE;
  294. //
  295. // Hold the mutex until we have finished the insert and the Age
  296. // operations.
  297. //
  298. RtlEnterCriticalSection(&_Mutex);
  299. __try
  300. {
  301. LARGE_INTEGER tsNow;
  302. LARGE_INTEGER tsCutoffPast;
  303. LARGE_INTEGER tsCutoffFuture;
  304. //
  305. // Determine the cut off time.
  306. //
  307. GetSystemTimeAsFileTime((PFILETIME) &tsNow );
  308. tsCutoffPast.QuadPart = tsNow.QuadPart - _tsMaxAge.QuadPart;
  309. tsCutoffFuture.QuadPart = tsNow.QuadPart + _tsMaxAge.QuadPart;
  310. if ((Time->QuadPart < tsCutoffPast.QuadPart) ||
  311. (Time->QuadPart > tsCutoffFuture.QuadPart))
  312. {
  313. KerbErr = KRB_AP_ERR_SKEW;
  314. }
  315. else
  316. {
  317. BOOLEAN fIsNew;
  318. KERB_AUTHEN_HEADER Header;
  319. MD5_CTX Md5Context;
  320. //
  321. // Store the first chunk of the authenticator. If the authenticator
  322. // doesn't fit on the stack, allocate some space on the heap.
  323. //
  324. Header.tsTime = *Time;
  325. MD5Init(
  326. &Md5Context
  327. );
  328. MD5Update(
  329. &Md5Context,
  330. (PBYTE) Buffer,
  331. BufferLength
  332. );
  333. if ((OptionalBuffer != NULL) && (OptionalBufferLength != 0))
  334. {
  335. MD5Update(
  336. &Md5Context,
  337. (PBYTE) OptionalBuffer,
  338. OptionalBufferLength
  339. );
  340. }
  341. MD5Final(
  342. &Md5Context
  343. );
  344. RtlCopyMemory(
  345. Header.Checksum,
  346. Md5Context.digest,
  347. MD5DIGESTLEN
  348. );
  349. if (!Insert)
  350. {
  351. pDataInTable = (PKERB_AUTHEN_HEADER)RtlLookupElementGenericTable(
  352. &_Table,
  353. &Header );
  354. if (NULL == pDataInTable)
  355. {
  356. KerbErr = KDC_ERR_NONE;
  357. }
  358. else
  359. {
  360. KerbErr = KRB_AP_ERR_REPEAT;
  361. }
  362. }
  363. else
  364. {
  365. RtlInsertElementGenericTable( &_Table,
  366. &Header,
  367. sizeof( KERB_AUTHEN_HEADER ),
  368. &fIsNew );
  369. if (fIsNew)
  370. {
  371. KerbErr = KDC_ERR_NONE;
  372. }
  373. else
  374. {
  375. KerbErr = KRB_AP_ERR_REPEAT;
  376. }
  377. }
  378. }
  379. // Age out the old ones.
  380. (void) Age( tsCutoffPast );
  381. }
  382. __except(EXCEPTION_EXECUTE_HANDLER)
  383. {
  384. KerbErr = KRB_ERR_GENERIC;
  385. }
  386. RtlLeaveCriticalSection(&_Mutex);
  387. return(KerbErr);
  388. }