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.

920 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: negsupp.cxx
  7. //
  8. // Contents: General (both win9x and nt) functions
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 02-09-00 RichardW Created - split from negotiat.cxx
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <lsapch.hxx>
  18. #ifdef WIN32_CHICAGO
  19. #include <kerb.hxx>
  20. #endif // WIN32_CHICAGO
  21. extern "C"
  22. {
  23. #include <align.h>
  24. #include <lm.h>
  25. #include <dsgetdc.h>
  26. #include <cryptdll.h>
  27. #ifndef WIN32_CHICAGO
  28. #include <spmgr.h>
  29. #endif
  30. #include "sesmgr.h"
  31. #include "spinit.h"
  32. }
  33. #include "negotiat.hxx"
  34. #ifdef WIN32_CHICAGO
  35. #include <debug.h>
  36. #include <rpc.h> // fpr SEC_WINNT_AUTH_IDENTITY_ANSI
  37. #define LsapChangeBuffer( o, n ) 0 ; CopyMemory( (n), (o),sizeof(SecBuffer) )
  38. #endif // WIN32_CHICAGO
  39. #include <stdio.h>
  40. BOOL fSPNEGOModuleStarted = FALSE;
  41. int
  42. SpnegoInitAsn(
  43. IN OUT ASN1encoding_t * pEnc,
  44. IN OUT ASN1decoding_t * pDec
  45. )
  46. {
  47. int Result = 0;
  48. ASN1error_e Asn1Err;
  49. if (!fSPNEGOModuleStarted)
  50. {
  51. fSPNEGOModuleStarted = TRUE;
  52. SPNEGO_Module_Startup();
  53. }
  54. if (pEnc != NULL)
  55. {
  56. Asn1Err = ASN1_CreateEncoder(
  57. SPNEGO_Module,
  58. pEnc,
  59. NULL, // pbBuf
  60. 0, // cbBufSize
  61. NULL // pParent
  62. );
  63. }
  64. else
  65. {
  66. Asn1Err = ASN1_CreateDecoder(
  67. SPNEGO_Module,
  68. pDec,
  69. NULL, // pbBuf
  70. 0, // cbBufSize
  71. NULL // pParent
  72. );
  73. }
  74. if (ASN1_SUCCESS != Asn1Err)
  75. {
  76. DebugLog((DEB_ERROR, "Failed to init ASN1: 0x%x\n",Asn1Err));
  77. Result = 1;
  78. goto Cleanup;
  79. }
  80. Cleanup:
  81. return(Result);
  82. }
  83. VOID
  84. SpnegoTermAsn(
  85. IN ASN1encoding_t pEnc,
  86. IN ASN1decoding_t pDec
  87. )
  88. {
  89. if (pEnc != NULL)
  90. {
  91. ASN1_CloseEncoder(pEnc);
  92. }
  93. else if (pDec != NULL)
  94. {
  95. ASN1_CloseDecoder(pDec);
  96. }
  97. //SPNEGO_Module_Cleanup();
  98. }
  99. int NTAPI
  100. SpnegoUnpackData(
  101. IN PUCHAR Data,
  102. IN ULONG DataSize,
  103. IN ULONG PduValue,
  104. OUT PVOID * DecodedData
  105. )
  106. {
  107. int Result = 0;
  108. ULONG OldPduValue;
  109. ASN1decoding_t pDec = NULL;
  110. ASN1error_e Asn1Err;
  111. if ((DataSize == 0) || (Data == NULL))
  112. {
  113. DebugLog((DEB_ERROR,"Trying to unpack NULL data\n"));
  114. return(1);
  115. }
  116. Result = SpnegoInitAsn(
  117. NULL,
  118. &pDec // we are decoding
  119. );
  120. if (Result != 0)
  121. {
  122. return(Result);
  123. }
  124. *DecodedData = NULL;
  125. Asn1Err = ASN1_Decode(
  126. pDec,
  127. DecodedData,
  128. PduValue,
  129. ASN1DECODE_SETBUFFER,
  130. (BYTE *) Data,
  131. DataSize
  132. );
  133. if (!ASN1_SUCCEEDED(Asn1Err))
  134. {
  135. if ((ASN1_ERR_BADARGS == Asn1Err) ||
  136. (ASN1_ERR_EOD == Asn1Err))
  137. {
  138. DebugLog((DEB_TRACE,"More input required to decode data %d.\n",PduValue));
  139. Result = 1;
  140. }
  141. else
  142. {
  143. DebugLog((DEB_WARN,"Failed to decode data: %d\n", Asn1Err ));
  144. Result = 1;
  145. }
  146. *DecodedData = NULL;
  147. }
  148. SpnegoTermAsn(NULL, pDec);
  149. return(Result);
  150. }
  151. int NTAPI
  152. SpnegoPackData(
  153. IN PVOID Data,
  154. IN ULONG PduValue,
  155. OUT PULONG DataSize,
  156. OUT PUCHAR * MarshalledData
  157. )
  158. {
  159. int Result = 0;
  160. PUCHAR Buffer = NULL;
  161. ASN1encoding_t pEnc = NULL;
  162. ASN1error_e Asn1Err;
  163. Result = SpnegoInitAsn(
  164. &pEnc, // we are encoding
  165. NULL
  166. );
  167. if (Result != 0)
  168. {
  169. goto Cleanup;
  170. }
  171. //
  172. // Encode the data type.
  173. //
  174. Asn1Err = ASN1_Encode(
  175. pEnc,
  176. Data,
  177. PduValue,
  178. ASN1ENCODE_ALLOCATEBUFFER,
  179. NULL, // pbBuf
  180. 0 // cbBufSize
  181. );
  182. if (!ASN1_SUCCEEDED(Asn1Err))
  183. {
  184. DebugLog((DEB_ERROR,"Failed to encode data: %d\n",Asn1Err));
  185. Result = 1;
  186. goto Cleanup;
  187. }
  188. else
  189. {
  190. //
  191. // when the oss compiler was used the allocation routines were configurable.
  192. // therefore, the encoded data could just be free'd using our
  193. // deallocator. in the new model we cannot configure the allocation routines
  194. // for encoding.
  195. // so we do not have to go and change every place where a free
  196. // of an encoded buffer is done, use our allocator to allocate a new buffer,
  197. // then copy the encoded data to it, and free the buffer that was allocated by
  198. // the encoding engine.
  199. //
  200. *MarshalledData = (PUCHAR)LsapAllocateLsaHeap(pEnc->len);
  201. if (*MarshalledData == NULL)
  202. {
  203. Result = 1;
  204. *DataSize = 0;
  205. }
  206. else
  207. {
  208. RtlCopyMemory(*MarshalledData, pEnc->buf, pEnc->len);
  209. *DataSize = pEnc->len;
  210. //DebugLog((DEB_ERROR,"encoded pdu size: %d\n",pEnc->len));
  211. //PrintBytes(pEnc->buf, pEnc->len);
  212. }
  213. ASN1_FreeEncoded(pEnc, pEnc->buf);
  214. }
  215. Cleanup:
  216. SpnegoTermAsn(pEnc, NULL);
  217. return(Result);
  218. }
  219. VOID
  220. SpnegoFreeData(
  221. IN ULONG PduValue,
  222. IN PVOID Data
  223. )
  224. {
  225. ASN1decoding_t pDec = NULL;
  226. if (ARGUMENT_PRESENT(Data))
  227. {
  228. int Result;
  229. Result = SpnegoInitAsn(
  230. NULL,
  231. &pDec // this is a decoded structure
  232. );
  233. if (Result == 0)
  234. {
  235. ASN1_FreeDecoded(pDec, Data, PduValue);
  236. SpnegoTermAsn(NULL, pDec);
  237. }
  238. }
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Function: NegpFreeObjectId
  243. //
  244. // Synopsis: Frees an object ID structure created by us
  245. //
  246. // Arguments: [Id] -- Id to free
  247. //
  248. // History: 8-09-96 RichardW Created
  249. //
  250. // Notes:
  251. //
  252. //----------------------------------------------------------------------------
  253. VOID
  254. NegpFreeObjectId(
  255. ObjectID Id)
  256. {
  257. ObjectID Next;
  258. while (Id) {
  259. Next = Id->next;
  260. LsapFreeLsaHeap( Id );
  261. Id = Next ;
  262. } ;
  263. }
  264. //+---------------------------------------------------------------------------
  265. //
  266. // Function: NegpFreeMechList
  267. //
  268. // Synopsis: Frees a Mechlist created by NecpCopyMechList
  269. //
  270. // Arguments: [Id] -- Id to free
  271. //
  272. // History: 8-09-96 RichardW Created
  273. //
  274. // Notes:
  275. //
  276. //----------------------------------------------------------------------------
  277. VOID
  278. NegpFreeMechList(
  279. struct MechTypeList *MechList)
  280. {
  281. struct MechTypeList *Next;
  282. Next = MechList;
  283. while (Next != NULL)
  284. {
  285. NegpFreeObjectId(Next->value);
  286. Next = Next->next ;
  287. } while ( Next );
  288. LsapFreeLsaHeap(MechList);
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Function: NegpDecodeObjectId
  293. //
  294. // Synopsis: Create an Object ID struct from a BER encoded Object ID
  295. //
  296. // Arguments: [Id] --
  297. // [Len] --
  298. //
  299. // History: 8-09-96 RichardW Created
  300. //
  301. // Notes:
  302. //
  303. //----------------------------------------------------------------------------
  304. ObjectID
  305. NegpDecodeObjectId(
  306. PUCHAR Id,
  307. DWORD Len)
  308. {
  309. ObjectID Root;
  310. ObjectID Tail;
  311. ObjectID Current;
  312. DWORD i, j;
  313. DWORD value;
  314. if ( Len < 3 )
  315. {
  316. return( NULL );
  317. }
  318. //
  319. // Check for BER type OBJECT_ID
  320. //
  321. if ( Id[ 0 ] != 0x06 )
  322. {
  323. return( NULL );
  324. }
  325. if ( Id[ 1 ] > 127 )
  326. {
  327. return( NULL );
  328. }
  329. Root = (struct ASN1objectidentifier_s *) LsapAllocateLsaHeap( sizeof( struct ASN1objectidentifier_s ) );
  330. Tail = (struct ASN1objectidentifier_s *) LsapAllocateLsaHeap( sizeof( struct ASN1objectidentifier_s ) );
  331. if ( !Root || !Tail )
  332. {
  333. if ( Root )
  334. {
  335. LsapFreeLsaHeap( Root );
  336. }
  337. if ( Tail )
  338. {
  339. LsapFreeLsaHeap( Tail );
  340. }
  341. return( NULL );
  342. }
  343. Root->value = (WORD) Id[2] / 40 ;
  344. Tail->value = (WORD) Id[2] % 40 ;
  345. Root->next = Tail ;
  346. i = 3 ;
  347. while ( i < Len )
  348. {
  349. j = 0;
  350. value = Id[ i ] & 0x7F ;
  351. while ( Id[i] & 0x80 )
  352. {
  353. value <<= 7;
  354. i++;
  355. j++;
  356. if ( (i >= Len) || ( j > sizeof( ULONG ) ) )
  357. {
  358. NegpFreeObjectId( Root );
  359. return( NULL );
  360. }
  361. value |= Id[ i ] & 0x7F ;
  362. }
  363. i++;
  364. Current = (struct ASN1objectidentifier_s *) LsapAllocateLsaHeap( sizeof( struct ASN1objectidentifier_s ) );
  365. if ( Current )
  366. {
  367. Current->value = value ;
  368. Current->next = NULL ;
  369. Tail->next = Current ;
  370. Tail = Current ;
  371. }
  372. else
  373. {
  374. NegpFreeObjectId( Root );
  375. return( NULL );
  376. }
  377. }
  378. return( Root );
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // Function: NegpCompareOid
  383. //
  384. // Synopsis: Standard compare function for OIDs:
  385. //
  386. // Arguments: [A] --
  387. // [B] --
  388. //
  389. // Returns: < 0 if A is "less than" B
  390. // > 0 if A is "greater than" B
  391. // 0 if A equals B
  392. //
  393. // History: 8-22-96 RichardW Created
  394. //
  395. // Notes:
  396. //
  397. //----------------------------------------------------------------------------
  398. int
  399. NegpCompareOid(
  400. ObjectID A,
  401. ObjectID B)
  402. {
  403. while ( A )
  404. {
  405. if ( A->value < B->value )
  406. {
  407. return( -1 );
  408. }
  409. if ( A->value > B->value )
  410. {
  411. return( 1 );
  412. }
  413. A = A->next ;
  414. B = B->next ;
  415. if ( ( A == NULL ) && ( B == NULL ) )
  416. {
  417. return( 0 );
  418. }
  419. if ( !B )
  420. {
  421. return( 1 );
  422. }
  423. if ( !A )
  424. {
  425. return( -1 );
  426. }
  427. }
  428. //
  429. // Never reached
  430. //
  431. return( 0 );
  432. }
  433. //+---------------------------------------------------------------------------
  434. //
  435. // Function: NegpDumpOid
  436. //
  437. // Synopsis: Debug-only dumper
  438. //
  439. // Arguments: [Banner] --
  440. // [Id] --
  441. //
  442. // History: 9-17-96 RichardW Created
  443. //
  444. // Notes:
  445. //
  446. //----------------------------------------------------------------------------
  447. VOID
  448. NegpDumpOid(
  449. PSTR Banner,
  450. ObjectID Id
  451. )
  452. {
  453. CHAR Oid[128];
  454. PSTR Next;
  455. int Count;
  456. Next = Oid;
  457. while ( Id )
  458. {
  459. Count = sprintf(Next, "%d.", Id->value );
  460. Next += Count;
  461. Id = Id->next;
  462. }
  463. DebugLog(( DEB_TRACE_NEG, "%s: %s\n", Banner, Oid ));
  464. }
  465. //+---------------------------------------------------------------------------
  466. //
  467. // Function: NegpBuildMechListFromCreds
  468. //
  469. // Synopsis: Builds a MechList from a credential struct
  470. //
  471. // Arguments: [Creds] -- Creds
  472. // [fPackageReq]
  473. // [MechList] -- Constructed mechlist
  474. //
  475. // History: 9-27-96 RichardW Created
  476. //
  477. // Notes: Returned MechList should be freed in a single call to LsapFreeHeap
  478. //
  479. //----------------------------------------------------------------------------
  480. SECURITY_STATUS
  481. NegpBuildMechListFromCreds(
  482. PNEG_CREDS Creds,
  483. ULONG fPackageReq,
  484. ULONG MechAttributes,
  485. struct MechTypeList ** MechList)
  486. {
  487. struct MechTypeList *pMechs = NULL;
  488. ULONG iCred, iMech = 0 ;
  489. SECURITY_STATUS Status = STATUS_SUCCESS;
  490. PNEG_PACKAGE Package ;
  491. NegReadLockCreds( Creds );
  492. if ( Creds->Count != 0 )
  493. {
  494. pMechs = (struct MechTypeList *) LsapAllocateLsaHeap(
  495. sizeof( struct MechTypeList ) * ( Creds->Count) );
  496. if ( pMechs )
  497. {
  498. for ( iCred = 0 ; iCred < Creds->Count ; iCred++ )
  499. {
  500. Package = Creds->Creds[ iCred ].Package ;
  501. if ( (Package->PackageFlags & fPackageReq) != fPackageReq)
  502. {
  503. continue;
  504. }
  505. pMechs[ iMech ].next = &pMechs[ iMech + 1 ];
  506. pMechs[ iMech ].value = Package->ObjectId ;
  507. iMech++ ;
  508. }
  509. if ( iMech != 0 )
  510. {
  511. pMechs[ iMech - 1 ].next = NULL ;
  512. }
  513. }
  514. else
  515. {
  516. Status = SEC_E_INSUFFICIENT_MEMORY;
  517. }
  518. }
  519. NegUnlockCreds( Creds );
  520. *MechList = pMechs;
  521. return( Status );
  522. }
  523. //+---------------------------------------------------------------------------
  524. //
  525. // Function: NegpCopyObjectId
  526. //
  527. // Synopsis: Duplicates an ObjectId
  528. //
  529. // Arguments: [ObjectId] = Object Id to copy
  530. //
  531. // History: 9-27-96 RichardW Created
  532. //
  533. // Notes: Returned ObjectId should be freed with NegpFreeObjectId
  534. //
  535. //----------------------------------------------------------------------------
  536. ObjectID
  537. NegpCopyObjectId(
  538. IN ObjectID Id
  539. )
  540. {
  541. ObjectID RootId = NULL;
  542. ObjectID NewId = NULL;
  543. ObjectID LastId = NULL;
  544. ObjectID NextId = NULL;
  545. NextId = Id;
  546. while (NextId != NULL)
  547. {
  548. NewId = (struct ASN1objectidentifier_s *) LsapAllocateLsaHeap(sizeof(struct ASN1objectidentifier_s));
  549. if (NewId == NULL)
  550. {
  551. goto Cleanup;
  552. }
  553. NewId->next = NULL;
  554. NewId->value = NextId->value;
  555. if (RootId == NULL)
  556. {
  557. RootId = NewId;
  558. }
  559. if (LastId != NULL)
  560. {
  561. LastId->next = NewId;
  562. }
  563. LastId = NewId;
  564. NextId= NextId->next;
  565. }
  566. return(RootId);
  567. Cleanup:
  568. if (RootId != NULL)
  569. {
  570. NegpFreeObjectId(RootId);
  571. }
  572. return(NULL);
  573. }
  574. //+---------------------------------------------------------------------------
  575. //
  576. // Function: NegpCopyMechList
  577. //
  578. // Synopsis: Duplicates a MechList
  579. //
  580. // Arguments: [Creds] -- Creds
  581. //
  582. // History: 9-27-96 RichardW Created
  583. //
  584. // Notes: Returned MechList should be freed with NegpFreeMechList
  585. //
  586. //----------------------------------------------------------------------------
  587. struct MechTypeList *
  588. NegpCopyMechList(
  589. struct MechTypeList *MechList)
  590. {
  591. struct MechTypeList *pMechs;
  592. struct MechTypeList *NextMech;
  593. ULONG i, Count;
  594. Count = 0;
  595. NextMech = MechList;
  596. while (NextMech != NULL)
  597. {
  598. Count++;
  599. NextMech = NextMech->next;
  600. }
  601. if (Count == 0)
  602. {
  603. return(NULL);
  604. }
  605. pMechs = (struct MechTypeList *) LsapAllocateLsaHeap(
  606. sizeof( struct MechTypeList ) * Count );
  607. if ( pMechs == NULL )
  608. {
  609. goto Cleanup;
  610. }
  611. RtlZeroMemory(
  612. pMechs,
  613. sizeof(struct MechTypeList) * Count
  614. );
  615. i = 0;
  616. NextMech = MechList;
  617. while (NextMech != NULL)
  618. {
  619. pMechs[i].value = NegpCopyObjectId(NextMech->value);
  620. if (pMechs[i].value == NULL)
  621. {
  622. goto Cleanup;
  623. }
  624. pMechs[i].next = NULL;
  625. if (i != 0)
  626. {
  627. pMechs[i-1].next = &pMechs[i];
  628. }
  629. NextMech = NextMech->next;
  630. i++;
  631. }
  632. return( pMechs );
  633. Cleanup:
  634. if (pMechs != NULL)
  635. {
  636. NegpFreeMechList (pMechs);
  637. }
  638. return(NULL);
  639. }
  640. //+-------------------------------------------------------------------------
  641. //
  642. // Function: NegpMapNegFlagsToContextFlags
  643. //
  644. // Synopsis: maps negotatie context flags to ASC_REQ_xxx flags
  645. //
  646. // Effects:
  647. //
  648. // Arguments:
  649. //
  650. // Requires:
  651. //
  652. // Returns:
  653. //
  654. // Notes:
  655. //
  656. //
  657. //--------------------------------------------------------------------------
  658. ULONG
  659. NegoMapNegFlagsToPackageFlags(
  660. IN int NegFlags
  661. )
  662. {
  663. ULONG ContextFlags = 0;
  664. if ((NegFlags & delegFlag) != 0)
  665. {
  666. ContextFlags |= ASC_REQ_DELEGATE;
  667. }
  668. if ((NegFlags & mutualFlag) != 0)
  669. {
  670. ContextFlags |= ASC_REQ_MUTUAL_AUTH;
  671. }
  672. if ((NegFlags & replayFlag) != 0)
  673. {
  674. ContextFlags |= ASC_REQ_REPLAY_DETECT;
  675. }
  676. if ((NegFlags & sequenceFlag) != 0)
  677. {
  678. ContextFlags |= ASC_REQ_SEQUENCE_DETECT;
  679. }
  680. if ((NegFlags & confFlag) != 0)
  681. {
  682. ContextFlags |= ASC_REQ_CONFIDENTIALITY;
  683. }
  684. if ((NegFlags & integFlag) != 0)
  685. {
  686. ContextFlags |= ASC_REQ_INTEGRITY;
  687. }
  688. return(ContextFlags);
  689. }
  690. //+-------------------------------------------------------------------------
  691. //
  692. // Function: NegpMapContextFlagsToNegFlags
  693. //
  694. // Synopsis: maps ISC_REQ_xxx flags to negotiate flags
  695. //
  696. // Effects:
  697. //
  698. // Arguments:
  699. //
  700. // Requires:
  701. //
  702. // Returns:
  703. //
  704. // Notes:
  705. //
  706. //
  707. //--------------------------------------------------------------------------
  708. int
  709. NegoMapNegFlasgToContextFlags(
  710. IN ULONG ContextFlags
  711. )
  712. {
  713. int NegFlags = 0;
  714. if ((ContextFlags & ISC_REQ_DELEGATE) != 0)
  715. {
  716. NegFlags |= delegFlag;
  717. }
  718. if ((ContextFlags & ISC_REQ_MUTUAL_AUTH) != 0)
  719. {
  720. NegFlags |= mutualFlag;
  721. }
  722. if ((ContextFlags & ISC_REQ_REPLAY_DETECT) != 0)
  723. {
  724. NegFlags |= replayFlag;
  725. }
  726. if ((ContextFlags & ISC_REQ_SEQUENCE_DETECT) != 0)
  727. {
  728. NegFlags |= sequenceFlag;
  729. }
  730. if ((ContextFlags & ISC_REQ_CONFIDENTIALITY) != 0)
  731. {
  732. NegFlags |= confFlag;
  733. }
  734. if ((ContextFlags & ISC_REQ_INTEGRITY) != 0)
  735. {
  736. NegFlags |= integFlag;
  737. }
  738. return(NegFlags);
  739. }
  740. int
  741. Neg_der_read_length(
  742. unsigned char **buf,
  743. LONG *bufsize,
  744. LONG * headersize
  745. )
  746. {
  747. unsigned char sf;
  748. LONG ret;
  749. if (*bufsize < 1)
  750. return(-1);
  751. *headersize = 0;
  752. sf = *(*buf)++;
  753. (*bufsize)--;
  754. (*headersize)++;
  755. if (sf & 0x80) {
  756. if ((sf &= 0x7f) > ((*bufsize)-1))
  757. return(-1);
  758. if (sf > sizeof(LONG))
  759. return (-1);
  760. ret = 0;
  761. for (; sf; sf--) {
  762. ret = (ret<<8) + (*(*buf)++);
  763. (*bufsize)--;
  764. (*headersize)++;
  765. }
  766. } else {
  767. ret = sf;
  768. }
  769. return(ret);
  770. }