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.

584 lines
14 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. NTSTATUS
  4. IPSecGetSPI(
  5. PIPSEC_GET_SPI pIpsecGetSPI
  6. )
  7. /*++
  8. Routine Description:
  9. This routine returns the SPI.
  10. Arguments:
  11. pIpsecGetSPI - Pointer to the ipsec get spi structure.
  12. Return Value:
  13. NTSTATUS - The status code from this routine.
  14. --*/
  15. {
  16. NTSTATUS ntStatus = STATUS_SUCCESS;
  17. //
  18. // If context was passed in, then there's a larval SA already setup.
  19. // This is the case for the initiator.
  20. //
  21. if (pIpsecGetSPI->Context) {
  22. ntStatus = IPSecInitiatorGetSPI(
  23. pIpsecGetSPI
  24. );
  25. }
  26. else {
  27. ntStatus = IPSecResponderGetSPI(
  28. pIpsecGetSPI
  29. );
  30. }
  31. return (ntStatus);
  32. }
  33. NTSTATUS
  34. IPSecInitiatorGetSPI(
  35. PIPSEC_GET_SPI pIpsecGetSPI
  36. )
  37. {
  38. NTSTATUS ntStatus = STATUS_SUCCESS;
  39. PIPSEC_ACQUIRE_CONTEXT pIpsecAcquireCtx = NULL;
  40. KIRQL kIrql;
  41. //
  42. // Sanity check the incoming context to see if it is actually
  43. // an SA block.
  44. //
  45. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  46. if (!NT_SUCCESS(IPSecValidateHandle(HandleToUlong(pIpsecGetSPI->Context),&pIpsecAcquireCtx, STATE_SA_LARVAL))) {
  47. ntStatus = STATUS_INVALID_PARAMETER;
  48. BAIL_ON_LOCK_NTSTATUS_ERROR(ntStatus);
  49. }
  50. pIpsecGetSPI->SPI = pIpsecAcquireCtx->pSA->sa_SPI;
  51. pIpsecAcquireCtx->pSA->sa_Flags |= FLAGS_SA_INITIATOR;
  52. ntStatus = STATUS_SUCCESS;
  53. lock:
  54. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  55. return (ntStatus);
  56. }
  57. NTSTATUS
  58. IPSecResponderGetSPI(
  59. PIPSEC_GET_SPI pIpsecGetSPI
  60. )
  61. {
  62. NTSTATUS ntStatus = STATUS_SUCCESS;
  63. KIRQL kIrql;
  64. PSA_TABLE_ENTRY pInboundSA = NULL;
  65. ULARGE_INTEGER uliSrcDstAddr = {0};
  66. PSA_TABLE_ENTRY pSA = NULL;
  67. PIPSEC_ACQUIRE_CONTEXT pIpsecAcquireCtx = NULL;
  68. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  69. if (pIpsecGetSPI->SPI) {
  70. if (!(pIpsecGetSPI->InstantiatedFilter.TunnelFilter)) {
  71. pInboundSA = IPSecLookupSABySPI(
  72. pIpsecGetSPI->SPI,
  73. pIpsecGetSPI->InstantiatedFilter.DestAddr
  74. );
  75. }
  76. else {
  77. pInboundSA = IPSecLookupSABySPI(
  78. pIpsecGetSPI->SPI,
  79. pIpsecGetSPI->InstantiatedFilter.TunnelAddr
  80. );
  81. }
  82. if (pInboundSA) {
  83. ntStatus = STATUS_UNSUCCESSFUL;
  84. BAIL_ON_LOCK_NTSTATUS_ERROR(ntStatus);
  85. }
  86. }
  87. ntStatus = IPSecResponderCreateLarvalSA(
  88. pIpsecGetSPI,
  89. uliSrcDstAddr,
  90. &pSA
  91. );
  92. BAIL_ON_LOCK_NTSTATUS_ERROR(ntStatus);
  93. //
  94. // Get the acquire Context and associate it with the larval SA.
  95. //
  96. pIpsecAcquireCtx = IPSecGetAcquireContext();
  97. if (!pIpsecAcquireCtx) {
  98. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  99. BAIL_ON_LOCK_NTSTATUS_ERROR(ntStatus);
  100. }
  101. pIpsecAcquireCtx->AcquireId = IPSecGetAcquireId();
  102. pIpsecAcquireCtx->pSA = pSA;
  103. pSA->sa_AcquireId = pIpsecAcquireCtx->AcquireId;
  104. pIpsecGetSPI->Context = UlongToHandle(pIpsecAcquireCtx->AcquireId);
  105. pSA->sa_AcquireCtx = pIpsecAcquireCtx;
  106. pIpsecGetSPI->SPI = pSA->sa_SPI;
  107. ntStatus = STATUS_SUCCESS;
  108. lock:
  109. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  110. return (ntStatus);
  111. }
  112. NTSTATUS
  113. IPSecResponderCreateLarvalSA(
  114. PIPSEC_GET_SPI pIpsecGetSPI,
  115. ULARGE_INTEGER uliAddr,
  116. PSA_TABLE_ENTRY * ppSA
  117. )
  118. {
  119. NTSTATUS ntStatus = STATUS_SUCCESS;
  120. PSA_TABLE_ENTRY pSA = NULL;
  121. KIRQL kIrql;
  122. ntStatus = IPSecCreateSA(&pSA);
  123. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  124. pSA->sa_Filter = NULL;
  125. pSA->sa_State = STATE_SA_LARVAL;
  126. IPSEC_BUILD_SRC_DEST_ADDR(
  127. pSA->sa_uliSrcDstAddr,
  128. pIpsecGetSPI->InstantiatedFilter.SrcAddr,
  129. pIpsecGetSPI->InstantiatedFilter.DestAddr
  130. );
  131. IPSEC_BUILD_SRC_DEST_MASK(
  132. pSA->sa_uliSrcDstMask,
  133. pIpsecGetSPI->InstantiatedFilter.SrcMask,
  134. pIpsecGetSPI->InstantiatedFilter.DestMask
  135. );
  136. IPSEC_BUILD_PROTO_PORT_LI(
  137. pSA->sa_uliProtoSrcDstPort,
  138. pIpsecGetSPI->InstantiatedFilter.Protocol,
  139. pIpsecGetSPI->InstantiatedFilter.SrcPort,
  140. pIpsecGetSPI->InstantiatedFilter.DestPort
  141. );
  142. ntStatus = IPSecResponderInsertInboundSA(
  143. pSA,
  144. pIpsecGetSPI,
  145. pIpsecGetSPI->InstantiatedFilter.TunnelFilter
  146. );
  147. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  148. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  149. InsertTailList(&g_ipsec.LarvalSAList, &pSA->sa_LarvalLinkage);
  150. IPSEC_INC_STATISTIC(dwNumPendingKeyOps);
  151. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  152. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  153. IPSecStartSATimer(
  154. pSA,
  155. IPSecSAExpired,
  156. pSA->sa_ExpiryTime
  157. );
  158. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  159. *ppSA = pSA;
  160. return (ntStatus);
  161. error:
  162. if (pSA) {
  163. IPSecFreeSA(pSA);
  164. }
  165. *ppSA = NULL;
  166. return (ntStatus);
  167. }
  168. NTSTATUS
  169. IPSecInitiatorCreateLarvalSA(
  170. PFILTER pFilter,
  171. ULARGE_INTEGER uliAddr,
  172. PSA_TABLE_ENTRY * ppSA,
  173. UCHAR DestType,
  174. PIPSEC_UDP_ENCAP_CONTEXT pEncapContext
  175. )
  176. {
  177. NTSTATUS ntStatus = STATUS_SUCCESS;
  178. PSA_TABLE_ENTRY pSA = NULL;
  179. ULARGE_INTEGER uliSrcDstAddr = {0};
  180. ULARGE_INTEGER uliSrcDstMask = {0};
  181. ULARGE_INTEGER uliProtoSrcDstPort = {0};
  182. KIRQL kIrql;
  183. ntStatus = IPSecCreateSA(&pSA);
  184. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  185. pSA->sa_Filter = pFilter;
  186. pSA->sa_State = STATE_SA_LARVAL;
  187. uliSrcDstAddr = uliAddr;
  188. uliSrcDstMask = pFilter->uliSrcDstMask;
  189. uliProtoSrcDstPort = pFilter->uliProtoSrcDstPort;
  190. IPSEC_BUILD_SRC_DEST_ADDR(
  191. pSA->sa_uliSrcDstAddr,
  192. DEST_ADDR,
  193. SRC_ADDR
  194. );
  195. IPSEC_BUILD_SRC_DEST_MASK(
  196. pSA->sa_uliSrcDstMask,
  197. DEST_MASK,
  198. SRC_MASK
  199. );
  200. IPSEC_BUILD_PROTO_PORT_LI(
  201. pSA->sa_uliProtoSrcDstPort,
  202. PROTO,
  203. DEST_PORT,
  204. SRC_PORT
  205. );
  206. pSA->sa_DestType=DestType;
  207. if (pEncapContext) {
  208. RtlCopyMemory(&pSA->sa_EncapContext,pEncapContext,sizeof(IPSEC_UDP_ENCAP_CONTEXT));
  209. }
  210. ntStatus = IPSecInitiatorInsertInboundSA(
  211. pSA,
  212. pFilter->TunnelFilter
  213. );
  214. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  215. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  216. InsertTailList(&g_ipsec.LarvalSAList, &pSA->sa_LarvalLinkage);
  217. IPSEC_INC_STATISTIC(dwNumPendingKeyOps);
  218. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  219. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  220. IPSecStartSATimer(
  221. pSA,
  222. IPSecSAExpired,
  223. pSA->sa_ExpiryTime
  224. );
  225. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  226. *ppSA = pSA;
  227. return (ntStatus);
  228. error:
  229. if (pSA) {
  230. IPSecFreeSA(pSA);
  231. }
  232. *ppSA = NULL;
  233. return (ntStatus);
  234. }
  235. NTSTATUS
  236. IPSecFindSA(
  237. BOOLEAN bTunnelFilter,
  238. ULARGE_INTEGER uliSrcDstAddr,
  239. ULARGE_INTEGER uliProtoSrcDstPort,
  240. PFILTER * ppFilter,
  241. PSA_TABLE_ENTRY * ppSA,
  242. IN PIPSEC_UDP_ENCAP_CONTEXT pNatContext
  243. )
  244. {
  245. NTSTATUS ntStatus = STATUS_SUCCESS;
  246. if (bTunnelFilter) {
  247. ntStatus = IPSecLookupTunnelSA(
  248. uliSrcDstAddr,
  249. uliProtoSrcDstPort,
  250. ppFilter,
  251. ppSA,
  252. FALSE,
  253. pNatContext
  254. );
  255. }
  256. else {
  257. #if GPC
  258. if (IS_GPC_ACTIVE()) {
  259. ntStatus = IPSecLookupGpcMaskedSA(
  260. uliSrcDstAddr,
  261. uliProtoSrcDstPort,
  262. ppFilter,
  263. ppSA,
  264. FALSE,
  265. pNatContext
  266. );
  267. }
  268. else {
  269. ntStatus = IPSecLookupMaskedSA(
  270. uliSrcDstAddr,
  271. uliProtoSrcDstPort,
  272. ppFilter,
  273. ppSA,
  274. FALSE,
  275. pNatContext
  276. );
  277. }
  278. #else
  279. ntStatus = IPSecLookupMaskedSA(
  280. uliSrcDstAddr,
  281. uliProtoSrcDstPort,
  282. ppFilter,
  283. ppSA,
  284. FALSE,
  285. pNatContext
  286. );
  287. #endif
  288. }
  289. return (ntStatus);
  290. }
  291. NTSTATUS
  292. IPSecResponderInsertInboundSA(
  293. PSA_TABLE_ENTRY pSA,
  294. PIPSEC_GET_SPI pIpsecGetSPI,
  295. BOOLEAN bTunnelFilter
  296. )
  297. {
  298. NTSTATUS ntStatus = STATUS_SUCCESS;
  299. PFILTER pFilter = NULL;
  300. PSA_TABLE_ENTRY pInboundSA = NULL;
  301. PLIST_ENTRY pSAChain = NULL;
  302. KIRQL kIrql;
  303. tSPI tSpi = 0;
  304. PSA_HASH pHash = NULL;
  305. ntStatus = IPSecFindSA(
  306. bTunnelFilter,
  307. pSA->sa_uliSrcDstAddr,
  308. pSA->sa_uliProtoSrcDstPort,
  309. &pFilter,
  310. &pInboundSA,
  311. NULL
  312. );
  313. if (!NT_SUCCESS(ntStatus)) {
  314. IPSecBufferEvent(
  315. pSA->SA_SRC_ADDR,
  316. EVENT_IPSEC_NEG_FAILURE,
  317. 1,
  318. FALSE
  319. );
  320. return (ntStatus);
  321. }
  322. ASSERT(pFilter);
  323. if (pIpsecGetSPI->InstantiatedFilter.Protocol != pFilter->PROTO ||
  324. pIpsecGetSPI->InstantiatedFilter.SrcPort != FI_SRC_PORT(pFilter) ||
  325. pIpsecGetSPI->InstantiatedFilter.DestPort != FI_DEST_PORT(pFilter)) {
  326. ntStatus = STATUS_OBJECT_TYPE_MISMATCH;
  327. return (ntStatus);
  328. }
  329. pSAChain = IPSecResolveSAChain(pFilter, pSA->SA_SRC_ADDR);
  330. InsertHeadList(pSAChain, &pSA->sa_FilterLinkage);
  331. pSA->sa_Flags |= FLAGS_SA_ON_FILTER_LIST;
  332. if (pFilter->Flags & FILTER_FLAGS_PASS_THRU) {
  333. pSA->sa_Flags |= FLAGS_SA_PASSTHRU_FILTER;
  334. }
  335. if (pFilter->TunnelFilter) {
  336. pSA->sa_Flags |= FLAGS_SA_TUNNEL;
  337. pSA->sa_TunnelAddr = pFilter->TunnelAddr;
  338. }
  339. //
  340. // Flush this filter from the cache table so that the SA instead of the
  341. // filter is matched on the next lookup.
  342. //
  343. if (IS_EXEMPT_FILTER(pFilter)) {
  344. IPSecInvalidateFilterCacheEntry(pFilter);
  345. }
  346. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql);
  347. tSpi = pIpsecGetSPI->SPI;
  348. ntStatus = IPSecAllocateSPI(&tSpi, pSA);
  349. if (!NT_SUCCESS(ntStatus)) {
  350. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  351. return (ntStatus);
  352. }
  353. pSA->sa_SPI = tSpi;
  354. IPSEC_HASH_SPI(
  355. (pSA->sa_TunnelAddr) ? pSA->sa_TunnelAddr : pSA->SA_DEST_ADDR,
  356. tSpi,
  357. pHash
  358. );
  359. InsertHeadList(&pHash->SAList, &pSA->sa_SPILinkage);
  360. pSA->sa_Flags |= FLAGS_SA_ON_SPI_HASH;
  361. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  362. return (STATUS_SUCCESS);
  363. }
  364. NTSTATUS
  365. IPSecInitiatorInsertInboundSA(
  366. PSA_TABLE_ENTRY pSA,
  367. BOOLEAN bTunnelFilter
  368. )
  369. {
  370. NTSTATUS ntStatus = STATUS_SUCCESS;
  371. PFILTER pFilter = NULL;
  372. PSA_TABLE_ENTRY pInboundSA = NULL;
  373. PLIST_ENTRY pSAChain = NULL;
  374. KIRQL kIrql;
  375. tSPI tSpi = 0;
  376. PSA_HASH pHash = NULL;
  377. ntStatus = IPSecFindSA(
  378. bTunnelFilter,
  379. pSA->sa_uliSrcDstAddr,
  380. pSA->sa_uliProtoSrcDstPort,
  381. &pFilter,
  382. &pInboundSA,
  383. NULL
  384. );
  385. if (!NT_SUCCESS(ntStatus)) {
  386. IPSecBufferEvent(
  387. pSA->SA_SRC_ADDR,
  388. EVENT_IPSEC_NEG_FAILURE,
  389. 1,
  390. FALSE
  391. );
  392. return (ntStatus);
  393. }
  394. if (ntStatus == STATUS_SUCCESS) {
  395. if (pInboundSA->sa_State == STATE_SA_LARVAL) {
  396. ntStatus = STATUS_DUPLICATE_OBJECTID;
  397. return (ntStatus);
  398. }
  399. }
  400. ASSERT(pFilter);
  401. pSAChain = IPSecResolveSAChain(pFilter, pSA->SA_SRC_ADDR);
  402. InsertHeadList(pSAChain, &pSA->sa_FilterLinkage);
  403. pSA->sa_Flags |= FLAGS_SA_ON_FILTER_LIST;
  404. if (pFilter->Flags & FILTER_FLAGS_PASS_THRU) {
  405. pSA->sa_Flags |= FLAGS_SA_PASSTHRU_FILTER;
  406. }
  407. if (pFilter->TunnelFilter) {
  408. pSA->sa_Flags |= FLAGS_SA_TUNNEL;
  409. pSA->sa_TunnelAddr = pFilter->TunnelAddr;
  410. }
  411. //
  412. // Flush this filter from the cache table so that the SA instead of the
  413. // filter is matched on the next lookup.
  414. //
  415. if (IS_EXEMPT_FILTER(pFilter)) {
  416. IPSecInvalidateFilterCacheEntry(pFilter);
  417. }
  418. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql);
  419. tSpi = 0;
  420. ntStatus = IPSecAllocateSPI(&tSpi, pSA);
  421. if (!NT_SUCCESS(ntStatus)) {
  422. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  423. return (ntStatus);
  424. }
  425. pSA->sa_SPI = tSpi;
  426. IPSEC_HASH_SPI(
  427. (pSA->sa_TunnelAddr) ? pSA->sa_TunnelAddr : pSA->SA_DEST_ADDR,
  428. tSpi,
  429. pHash
  430. );
  431. InsertHeadList(&pHash->SAList, &pSA->sa_SPILinkage);
  432. pSA->sa_Flags |= FLAGS_SA_ON_SPI_HASH;
  433. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  434. return (STATUS_SUCCESS);
  435. }