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.

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