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.

9176 lines
234 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: negotiat.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 11-15-95 RichardW Created for Cairo
  15. // 07-25-96 RichardW Added SNEGO support
  16. // 06-24-97 MikeSw Modified for SPNEGO
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <lsapch.hxx>
  20. #ifdef WIN32_CHICAGO
  21. #include <kerb.hxx>
  22. #endif // WIN32_CHICAGO
  23. extern "C"
  24. {
  25. #include <align.h>
  26. #include <lm.h>
  27. #include <dsgetdc.h>
  28. #include <cryptdll.h>
  29. #ifndef WIN32_CHICAGO
  30. #include <spmgr.h>
  31. #endif
  32. #include "sesmgr.h"
  33. #include "spinit.h"
  34. }
  35. #include "negotiat.hxx"
  36. #ifdef WIN32_CHICAGO
  37. #include <debug.h>
  38. #include <rpc.h> // fpr SEC_WINNT_AUTH_IDENTITY_ANSI
  39. #define LsapChangeBuffer( o, n ) 0 ; CopyMemory( (n), (o),sizeof(SecBuffer) )
  40. #endif // WIN32_CHICAGO
  41. #include <stdio.h>
  42. //
  43. // Possible states for the Accept and Init calls.
  44. //
  45. #define FIRST_CALL_NO_INPUT 0
  46. #define FIRST_CALL_WITH_INPUT 1
  47. #define LATER_CALL_NO_INPUT 2
  48. #define LATER_CALL_WITH_INPUT 3
  49. #define LATER_CALL_BIT 2
  50. #define BUFFER_PRESENT_BIT 1
  51. //
  52. // This define controls the proposed MA behavior v. the existing MA
  53. // behavior
  54. //
  55. #define NEW_MUTUAL_AUTH
  56. //
  57. // This defines the minimum buffer that spnego can use, when
  58. // fragment-to-fit is requested. This is 5 bytes, enough in
  59. // BER to encode the start of a 64K buffer. The five bytes,
  60. // for the curious, are:
  61. //
  62. // 0x60 0x8x 0xLL 0xLL 0xLL
  63. //
  64. // or application[0], and four bytes of length specifier.
  65. //
  66. #define SPNEGO_MINIMUM_BUFFER 5
  67. ULONG NegpUseSpnego = 1;
  68. ULONG NegpUseSnegoServer = 0;
  69. ULONG SyncTest = 0;
  70. SECPKG_FUNCTION_TABLE NegTable = {
  71. NULL,
  72. NULL,
  73. NegCallPackage,
  74. NegLogoffNotify,
  75. NegCallPackage, // UNTRUSTED Is the same!
  76. NegCallPackagePassthrough,
  77. NULL,
  78. #ifndef WIN32_CHICAGO
  79. NegLogonUserEx2,
  80. #else
  81. NULL,
  82. #endif
  83. NegInitialize,
  84. NegShutdown,
  85. NegGetInfo,
  86. NegAcceptCredentials,
  87. NegAcquireCredentialsHandle,
  88. NegQueryCredentialsAttributes,
  89. NegFreeCredentialsHandle,
  90. NegSaveCredentials,
  91. NegGetCredentials,
  92. NegDeleteCredentials,
  93. NegInitLsaModeContext,
  94. NegAcceptLsaModeContext,
  95. NegDeleteLsaModeContext,
  96. NegApplyControlToken,
  97. NegGetUserInfo,
  98. NegGetExtendedInformation,
  99. NegQueryContextAttributes,
  100. #ifndef WIN32_CHICAGO
  101. NegAddCredentials
  102. #endif
  103. };
  104. //
  105. // Microsoft Security Mechanisms OID Branch:
  106. //
  107. // iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) microsoft(311)
  108. // security(2)
  109. // mechanisms(2)
  110. //
  111. // Loopback Detect (9)
  112. // <RPCID> - The RPC Id is stuck here, e.g.
  113. // NTLM (10)
  114. // SSL (12)
  115. //
  116. UCHAR NegSpnegoMechEncodedOid[] =
  117. { 0x06, 0x7,
  118. 0x2b, 0x6,0x1,0x5,0x5,0x2};
  119. ObjectID NegSpnegoMechOid;
  120. UCHAR NegMSMechanismsOid[] = { 0x06, 0x0a, // DER prefix
  121. 0x2b, 0x06, 0x01, 0x04, 0x01,
  122. 0x82, 0x37, 0x02, 0x02, 0x00 };
  123. const UCHAR NegKerberosOid[] = { 0x06, 0x09, // DER prefix
  124. 0x2a, 0x86, 0x48, 0x86, 0xf7,
  125. 0x12, 0x01, 0x02, 0x02 };
  126. const UCHAR NegKerberosLegacyOid[] = { 0x06, 0x09, // DER prefix
  127. 0x2a, 0x86, 0x48, 0x82, 0xf7,
  128. 0x12, 0x01, 0x02, 0x02 };
  129. UNICODE_STRING NegLocalHostName_U ;
  130. WCHAR NegLocalHostName[] = L"localhost";
  131. DWORD_PTR NegPackageId;
  132. DWORD_PTR NtlmPackageId = NEG_INVALID_PACKAGE;
  133. ObjectID NegNtlmMechOid ;
  134. #ifndef WIN32_CHICAGO
  135. WCHAR NegPackageName[] = NEGOSSP_NAME ;
  136. WCHAR NegPackageComment[] = TEXT("Microsoft Package Negotiator");
  137. NT_PRODUCT_TYPE NegProductType;
  138. // computer names (protected by NegComputerNamesLock)
  139. UNICODE_STRING NegNetbiosComputerName_U;
  140. UNICODE_STRING NegDnsComputerName_U;
  141. #else
  142. TCHAR NegPackageName[] = NEGOSSP_NAME ;
  143. TCHAR NegPackageComment[] = TEXT("Microsoft Package Negotiator");
  144. #endif // WIN32_CHICAGO
  145. LIST_ENTRY NegPackageList;
  146. LIST_ENTRY NegCredList;
  147. #ifndef WIN32_CHICAGO
  148. LIST_ENTRY NegDefaultCredList ;
  149. RTL_RESOURCE NegLock;
  150. PLSAP_SECURITY_PACKAGE NegLsaPackage ;
  151. LIST_ENTRY NegLoopbackList ;
  152. LIST_ENTRY NegLogonSessionList ;
  153. RTL_CRITICAL_SECTION NegLogonSessionListLock ;
  154. RTL_CRITICAL_SECTION NegTrustListLock ;
  155. PNEG_TRUST_LIST NegTrustList ;
  156. LARGE_INTEGER NegTrustTime ;
  157. RTL_CRITICAL_SECTION NegComputerNamesLock;
  158. RTL_RESOURCE NegCredListLock;
  159. #else
  160. RTL_CRITICAL_SECTION NegLock;
  161. RTL_CRITICAL_SECTION NegCredListLock;
  162. #endif // WIN32_CHICAGO
  163. PVOID NegNotifyHandle;
  164. DWORD NegPackageCount;
  165. PUCHAR NegBlob;
  166. DWORD NegBlobSize;
  167. DWORD NegOptions;
  168. ULONG NegMachineState;
  169. BOOL NegUplevelDomain ;
  170. ULONG NegNegotiationControl = 1 ;
  171. HANDLE NegRegistryWatchEvent ;
  172. WCHAR NegComputerName[ DNS_MAX_NAME_LENGTH ];
  173. typedef struct _NEG_CONTEXT_REQ_MAP {
  174. #define NEG_CONFIG_REQUIRED 0x00000001
  175. #define NEG_CONFIG_OPTIONAL 0x00000002
  176. ULONG Level ;
  177. ULONG ConfigFlags ;
  178. ULONG ContextReq ;
  179. ULONG PackageFlag ;
  180. } NEG_CONTEXT_REQ_MAP, * PNEG_CONTEXT_REQ_MAP ;
  181. NEG_CONTEXT_REQ_MAP
  182. NegContextReqMap[] = {
  183. { 0, NEG_CONFIG_REQUIRED, (ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_INTEGRITY), SECPKG_FLAG_INTEGRITY },
  184. { 0, NEG_CONFIG_REQUIRED, (ISC_REQ_CONFIDENTIALITY) , SECPKG_FLAG_PRIVACY },
  185. { 2, NEG_CONFIG_OPTIONAL, (ISC_REQ_MUTUAL_AUTH), SECPKG_FLAG_MUTUAL_AUTH },
  186. { 0, 0, 0, 0 }
  187. };
  188. #ifndef WIN32_CHICAGO
  189. typedef DWORD (APIENTRY LOGON_NOTIFY)(
  190. LPCWSTR, PLUID, LPCWSTR, LPVOID,
  191. LPCWSTR, LPVOID, LPWSTR, LPVOID,
  192. LPWSTR * );
  193. typedef LOGON_NOTIFY * PLOGON_NOTIFY;
  194. VOID
  195. NegpNotifyNetworkProviders(
  196. IN PUNICODE_STRING UserName,
  197. IN PSECPKG_PRIMARY_CRED PrimaryCred
  198. );
  199. #endif // WIN32_CHICAGO
  200. //
  201. // Primary and secondary credentials used for LocalSystem
  202. //
  203. SECPKG_PRIMARY_CRED NegPrimarySystemCredentials;
  204. extern "C"
  205. SECURITY_STATUS
  206. SEC_ENTRY
  207. NegpValidateBuffer(
  208. PUCHAR Buffer,
  209. ULONG Length
  210. )
  211. {
  212. UCHAR Test ;
  213. ULONG ClaimedLength ;
  214. ULONG ByteCount ;
  215. ULONG i ;
  216. if ( Length == 0 )
  217. {
  218. return STATUS_SUCCESS ;
  219. }
  220. //
  221. // This does a poor man's validation of the BER encoded SNEGO buffer
  222. //
  223. //
  224. // First, make sure the first byte is a BER value for Context Specific
  225. //
  226. Test = Buffer[0] & 0xC0 ;
  227. if ( (Test != 0x80 ) &&
  228. (Test != 0x40 ) )
  229. {
  230. DebugLog(( DEB_ERROR, "Neg: Buffer does not lead off with 'Context' or 'Application' specific\n"));
  231. goto Bad_Buffer ;
  232. }
  233. //
  234. // Now, check the claimed size in the header with the size we were passed:
  235. //
  236. Buffer++ ;
  237. ClaimedLength = 0 ;
  238. if (*Buffer & 0x80)
  239. {
  240. ByteCount = *Buffer++ & 0x7f;
  241. for (i = 0; i < ByteCount ; i++ )
  242. {
  243. ClaimedLength <<= 8;
  244. ClaimedLength += *Buffer++;
  245. }
  246. }
  247. else
  248. {
  249. ByteCount = 0;
  250. ClaimedLength = *Buffer++;
  251. }
  252. if ( (ClaimedLength + 2 + ByteCount) != Length )
  253. {
  254. DebugLog(( DEB_ERROR, "Neg: Packet claimed length %x, actual length is %x\n",
  255. ClaimedLength + 2 + ByteCount, Length ));
  256. goto Bad_Buffer ;
  257. }
  258. return STATUS_SUCCESS ;
  259. Bad_Buffer:
  260. return STATUS_DATA_ERROR ;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: NegpFindPackage
  265. //
  266. // Synopsis: Scans the list of negotiable packages for a package id
  267. //
  268. // Arguments: [PackageId] --
  269. //
  270. // History: 8-13-96 RichardW Created
  271. //
  272. // Notes:
  273. //
  274. //----------------------------------------------------------------------------
  275. PNEG_PACKAGE
  276. NegpFindPackage(
  277. ULONG_PTR PackageId )
  278. {
  279. PNEG_PACKAGE Scan;
  280. NegReadLockList();
  281. Scan = (PNEG_PACKAGE) NegPackageList.Flink ;
  282. while ( Scan != (PNEG_PACKAGE) &NegPackageList )
  283. {
  284. if ( Scan->LsaPackage->dwPackageID == PackageId )
  285. {
  286. break;
  287. }
  288. Scan = (PNEG_PACKAGE) Scan->List.Flink ;
  289. }
  290. NegUnlockList();
  291. if ( Scan != (PNEG_PACKAGE) &NegPackageList )
  292. {
  293. return( Scan );
  294. }
  295. return( NULL );
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Function: NegpFindPackageByName
  300. //
  301. // Synopsis: Scans the list of negotiable packages for a package name
  302. //
  303. // Arguments: [PackageId] --
  304. //
  305. // History: 8-13-96 RichardW Created
  306. //
  307. // Notes:
  308. //
  309. //----------------------------------------------------------------------------
  310. PNEG_PACKAGE
  311. NegpFindPackageByName(
  312. PUNICODE_STRING PackageName )
  313. {
  314. PNEG_PACKAGE Scan;
  315. NegReadLockList();
  316. Scan = (PNEG_PACKAGE) NegPackageList.Flink ;
  317. while ( Scan != (PNEG_PACKAGE) &NegPackageList )
  318. {
  319. if ( RtlEqualUnicodeString(
  320. &Scan->LsaPackage->Name,
  321. PackageName,
  322. TRUE // case insensitive
  323. ))
  324. {
  325. break;
  326. }
  327. Scan = (PNEG_PACKAGE) Scan->List.Flink ;
  328. }
  329. NegUnlockList();
  330. if ( Scan != (PNEG_PACKAGE) &NegPackageList )
  331. {
  332. return( Scan );
  333. }
  334. return( NULL );
  335. }
  336. //+---------------------------------------------------------------------------
  337. //
  338. // Function: NegpFindPackageByOid
  339. //
  340. // Synopsis: Locates a security package by OID.
  341. //
  342. // Arguments: [Id] --
  343. //
  344. // History: 4-23-97 RichardW Created
  345. //
  346. // Notes:
  347. //
  348. //----------------------------------------------------------------------------
  349. PNEG_PACKAGE
  350. NegpFindPackageByOid(
  351. ObjectID Id
  352. )
  353. {
  354. PNEG_PACKAGE Scan ;
  355. PLIST_ENTRY List ;
  356. ULONG i ;
  357. NegReadLockList();
  358. List = NegPackageList.Flink ;
  359. Scan = NULL ;
  360. while ( List != &NegPackageList )
  361. {
  362. Scan = CONTAINING_RECORD( List, NEG_PACKAGE, List );
  363. if ( NegpCompareOid( Id, Scan->ObjectId ) == 0 )
  364. {
  365. break;
  366. }
  367. List = List->Flink ;
  368. Scan = NULL ;
  369. }
  370. NegUnlockList();
  371. return Scan ;
  372. }
  373. ULONG
  374. NegGetPackageCaps(
  375. ULONG ContextReq
  376. )
  377. {
  378. ULONG PackageCap = 0;
  379. PNEG_CONTEXT_REQ_MAP Scan ;
  380. Scan = NegContextReqMap ;
  381. while ( Scan->ContextReq )
  382. {
  383. if ( Scan->ConfigFlags & NEG_CONFIG_REQUIRED )
  384. {
  385. if ( (Scan->ContextReq & ContextReq ) != 0 )
  386. {
  387. PackageCap |= Scan->PackageFlag ;
  388. }
  389. }
  390. else if ( Scan->ConfigFlags & NEG_CONFIG_OPTIONAL )
  391. {
  392. if ( NegNegotiationControl >= Scan->Level )
  393. {
  394. if ( ( Scan->ContextReq & ContextReq ) != 0 )
  395. {
  396. PackageCap |= Scan->PackageFlag ;
  397. }
  398. }
  399. else
  400. {
  401. PackageCap |= 0 ;
  402. }
  403. }
  404. Scan++ ;
  405. }
  406. return PackageCap ;
  407. }
  408. #ifndef WIN32_CHICAGO
  409. //+---------------------------------------------------------------------------
  410. //
  411. // Function: NegPackageLoad
  412. //
  413. // Synopsis: Called by LSA whenever a package is loaded
  414. //
  415. // Arguments: [p] --
  416. //
  417. // History: 7-30-96 RichardW Created
  418. //
  419. // Notes:
  420. //
  421. //----------------------------------------------------------------------------
  422. DWORD
  423. WINAPI
  424. NegPackageLoad(
  425. PVOID p)
  426. {
  427. NTSTATUS Status ;
  428. PSECPKG_EVENT_NOTIFY Notify;
  429. PSECPKG_EVENT_PACKAGE_CHANGE Load;
  430. PNEG_PACKAGE Package;
  431. PNEG_PACKAGE ExtraPackage ;
  432. PLSAP_SECURITY_PACKAGE LsaPackage;
  433. PSECPKG_EXTENDED_INFORMATION Info ;
  434. SECPKG_EXTENDED_INFORMATION LocalInfo ;
  435. ObjectID ClaimedOid = NULL;
  436. UCHAR Prefix[ NEGOTIATE_MAX_PREFIX ] = { 0 };
  437. ULONG PrefixLength = 0 ;
  438. ULONG ExtraOidsCount = 0 ;
  439. ULONG i ;
  440. BOOLEAN fKerberosPackage = FALSE;
  441. Notify = (PSECPKG_EVENT_NOTIFY) p;
  442. if ( Notify->EventClass != NOTIFY_CLASS_PACKAGE_CHANGE )
  443. {
  444. return( 0 );
  445. }
  446. Load = ( PSECPKG_EVENT_PACKAGE_CHANGE ) Notify->EventData ;
  447. DebugLog((DEB_TRACE_NEG, "Package Change Event %d: %ws (%p) \n",
  448. Load->ChangeType, Load->PackageName.Buffer, Load->PackageId ));
  449. if ( Load->PackageId == NegPackageId )
  450. {
  451. DebugLog((DEB_TRACE_NEG, "Skipping own load notification\n"));
  452. NegLsaPackage = SpmpLocatePackage( NegPackageId );
  453. return( 0 );
  454. }
  455. //
  456. // If this is a package load, add the package to our list:
  457. //
  458. if ( Load->ChangeType == SECPKG_PACKAGE_CHANGE_LOAD )
  459. {
  460. Info = NULL ;
  461. LsaPackage = SpmpLookupPackage( &Load->PackageName );
  462. if (LsaPackage == NULL)
  463. {
  464. return( 0 );
  465. }
  466. if ( !( LsaPackage->fCapabilities & SECPKG_FLAG_NEGOTIABLE ) )
  467. {
  468. return( 0 );
  469. }
  470. //
  471. // If the package supports SP_INFO, query it to see if it has an
  472. // OID to use in negotiation.
  473. //
  474. if ( LsaPackage->fPackage & SP_INFO )
  475. {
  476. Status = LsapGetExtendedPackageInfo( LsaPackage,
  477. SecpkgGssInfo,
  478. &Info );
  479. if ( !NT_SUCCESS( Status ) )
  480. {
  481. Info = NULL ;
  482. }
  483. //
  484. // Make sure that the claimed OID doesn't conflict with
  485. // someone already loaded.
  486. //
  487. if ( Info )
  488. {
  489. ClaimedOid = NegpDecodeObjectId( Info->Info.GssInfo.EncodedId,
  490. Info->Info.GssInfo.EncodedIdLength );
  491. RtlCopyMemory( Prefix,
  492. Info->Info.GssInfo.EncodedId,
  493. Info->Info.GssInfo.EncodedIdLength );
  494. PrefixLength = Info->Info.GssInfo.EncodedIdLength ;
  495. //
  496. // note whether the primary GSS Oid is the kerberos Oid.
  497. // This allows us to swap the order of the Primary Oid with the legacy Oid
  498. // later on.
  499. //
  500. if ( (Info->Info.GssInfo.EncodedIdLength == sizeof(NegKerberosOid)) &&
  501. (memcmp(Info->Info.GssInfo.EncodedId, NegKerberosOid, sizeof(NegKerberosOid)) == 0 )
  502. )
  503. {
  504. fKerberosPackage = TRUE;
  505. }
  506. LsapFreeLsaHeap( Info );
  507. if (ClaimedOid == NULL)
  508. {
  509. Info = NULL;
  510. }
  511. else if ( NegpFindPackageByOid( ClaimedOid ) )
  512. {
  513. NegpFreeObjectId( ClaimedOid );
  514. return 0 ;
  515. }
  516. }
  517. //
  518. // Check if the package has any additional OIDs to support, or to compensate
  519. // for a spnego encoding problem.
  520. //
  521. Status = LsapGetExtendedPackageInfo( LsaPackage,
  522. SecpkgExtraOids,
  523. &Info );
  524. if ( !NT_SUCCESS( Status ) )
  525. {
  526. Info = NULL ;
  527. }
  528. LocalInfo.Class = SecpkgMutualAuthLevel ;
  529. LocalInfo.Info.MutualAuthLevel.MutualAuthLevel = NegNegotiationControl ;
  530. LsapSetExtendedPackageInfo(
  531. LsaPackage,
  532. SecpkgMutualAuthLevel,
  533. &LocalInfo );
  534. }
  535. //
  536. // If no ID, and Info is NULL, skip it.
  537. //
  538. if ( (LsaPackage->dwRPCID == SECPKG_ID_NONE) &&
  539. (ClaimedOid == NULL ) )
  540. {
  541. return( 0 );
  542. }
  543. if ( ( Info != NULL ) &&
  544. ( Info->Class == SecpkgExtraOids ) )
  545. {
  546. ExtraOidsCount = Info->Info.ExtraOids.OidCount ;
  547. }
  548. Package = (PNEG_PACKAGE) LsapAllocateLsaHeap( sizeof( NEG_PACKAGE ) );
  549. if ( Package )
  550. {
  551. Package->LsaPackage = LsaPackage ;
  552. Package->Flags = NEG_PACKAGE_INBOUND | NEG_PACKAGE_OUTBOUND ;
  553. if ( LsaPackage->fPackage & SP_PREFERRED )
  554. {
  555. Package->Flags |= NEG_PREFERRED ;
  556. }
  557. if ( LsaPackage->dwRPCID == RPC_C_AUTHN_WINNT )
  558. {
  559. Package->Flags |= NEG_NT4_COMPAT ;
  560. NtlmPackageId = Load->PackageId;
  561. //
  562. // Cheap and sleazy way of loading the necessary information
  563. // into the logon session, once we have all the packages loaded.
  564. //
  565. NegLsaPolicyChangeCallback( PolicyNotifyDnsDomainInformation );
  566. }
  567. Package->TokenSize = LsaPackage->TokenSize ;
  568. Package->PackageFlags = LsaPackage->fCapabilities ;
  569. Package->PrefixLen = PrefixLength ;
  570. RtlCopyMemory( Package->Prefix,
  571. Prefix,
  572. PrefixLength );
  573. //
  574. // add slack space for negotiate header.
  575. //
  576. NegLsaPackage->TokenSize = max( (LsaPackage->TokenSize+128),
  577. NegLsaPackage->TokenSize );
  578. DebugLog(( DEB_TRACE_NEG, "Loaded package %ws\n",
  579. Load->PackageName.Buffer ));
  580. NegWriteLockList();
  581. if ( ClaimedOid )
  582. {
  583. Package->ObjectId = ClaimedOid ;
  584. NegDumpOid( "Package claimed OID", Package->ObjectId );
  585. }
  586. else
  587. {
  588. NegMSMechanismsOid[ 0xb ] = (UCHAR) LsaPackage->dwRPCID ;
  589. Package->ObjectId = NegpDecodeObjectId( NegMSMechanismsOid,
  590. sizeof( NegMSMechanismsOid ) );
  591. NegDumpOid( "Assigned package OID", Package->ObjectId );
  592. if ( Package->Flags & NEG_NT4_COMPAT )
  593. {
  594. NegNtlmMechOid = NegpDecodeObjectId( NegMSMechanismsOid,
  595. sizeof( NegMSMechanismsOid ) );
  596. }
  597. }
  598. InsertTailList( &NegPackageList,
  599. &Package->List );
  600. NegPackageCount ++;
  601. if ( ExtraOidsCount )
  602. {
  603. Package->Flags |= NEG_PACKAGE_HAS_EXTRAS ;
  604. DebugLog(( DEB_TRACE_NEG, "Creating extra packages for %ws\n",
  605. Load->PackageName.Buffer ));
  606. for ( i = 0 ; i < ExtraOidsCount ; i++ )
  607. {
  608. ClaimedOid = NegpDecodeObjectId( Info->Info.ExtraOids.Oids[ i ].OidValue,
  609. Info->Info.ExtraOids.Oids[ i ].OidLength );
  610. if ( !NegpFindPackageByOid( ClaimedOid ))
  611. {
  612. //
  613. // If no one else has used this OID, allow it.
  614. //
  615. NegDumpOid( "Package claimed extra OID", ClaimedOid );
  616. ExtraPackage = (PNEG_PACKAGE) LsapAllocateLsaHeap( sizeof( NEG_PACKAGE ) );
  617. if ( ExtraPackage )
  618. {
  619. ExtraPackage->LsaPackage = Package->LsaPackage ;
  620. ExtraPackage->ObjectId = ClaimedOid ;
  621. ExtraPackage->RealPackage = Package ;
  622. ExtraPackage->Flags = NEG_PACKAGE_EXTRA_OID ;
  623. if ( Info->Info.ExtraOids.Oids[ i ].OidAttributes & SECPKG_CRED_INBOUND )
  624. {
  625. ExtraPackage->Flags |= NEG_PACKAGE_INBOUND ;
  626. }
  627. if ( Info->Info.ExtraOids.Oids[ i ].OidAttributes & SECPKG_CRED_OUTBOUND )
  628. {
  629. ExtraPackage->Flags |= NEG_PACKAGE_OUTBOUND ;
  630. }
  631. ExtraPackage->TokenSize = Package->TokenSize ;
  632. ExtraPackage->PackageFlags = Package->PackageFlags ;
  633. RtlCopyMemory(
  634. ExtraPackage->Prefix,
  635. Info->Info.ExtraOids.Oids[ i ].OidValue,
  636. Info->Info.ExtraOids.Oids[ i ].OidLength );
  637. ExtraPackage->PrefixLen = Info->Info.ExtraOids.Oids[ i ].OidLength ;
  638. //
  639. // **** NOTE: ****
  640. // For legacy compatibility reasons,
  641. // the broken Kerberos package Oid is re-ordered ahead
  642. // of the correct Oid value. The was done in order
  643. // to avoid an extra round-trip when communicating with
  644. // Win2000 machines. The negotiate protocol itself
  645. // recovers with additional round-trips; however,
  646. // Wininet is unable to reliably handle such a
  647. // circumstance.
  648. //
  649. if( fKerberosPackage &&
  650. (Info->Info.ExtraOids.Oids[ i ].OidLength == sizeof(NegKerberosLegacyOid)) &&
  651. (memcmp(Info->Info.ExtraOids.Oids[ i ].OidValue, NegKerberosLegacyOid, sizeof(NegKerberosLegacyOid)) == 0)
  652. )
  653. {
  654. ObjectID SwapOid;
  655. DebugLog((DEB_TRACE_NEG, "Re-ordering legacy Kerberos Oid\n"));
  656. SwapOid = Package->ObjectId;
  657. Package->ObjectId = ExtraPackage->ObjectId;
  658. ExtraPackage->ObjectId = SwapOid;
  659. }
  660. InsertTailList( &NegPackageList,
  661. &ExtraPackage->List );
  662. NegPackageCount ++;
  663. }
  664. else
  665. {
  666. //
  667. // Free the OID, skip this extra package
  668. //
  669. NegpFreeObjectId( ClaimedOid );
  670. }
  671. }
  672. else
  673. {
  674. //
  675. // Free it
  676. //
  677. NegpFreeObjectId( ClaimedOid );
  678. }
  679. }
  680. }
  681. NegUnlockList();
  682. }
  683. }
  684. else
  685. {
  686. //
  687. // It's either a select or an unload:
  688. //
  689. Package = NegpFindPackage( Load->PackageId );
  690. //
  691. // if we don't have this package (it may not have been negotiable)
  692. // return now.
  693. //
  694. if (Package == NULL)
  695. {
  696. return(0);
  697. }
  698. if ( Load->ChangeType == SECPKG_PACKAGE_CHANGE_SELECT )
  699. {
  700. Package->Flags |= NEG_PREFERRED ;
  701. }
  702. else
  703. {
  704. NegWriteLockList();
  705. RemoveEntryList( &Package->List );
  706. NegUnlockList();
  707. NegpFreeObjectId( Package->ObjectId );
  708. LsapFreeLsaHeap( Package );
  709. }
  710. }
  711. return( 0 );
  712. }
  713. #else // WIN32_CHICAGO
  714. //+---------------------------------------------------------------------------
  715. //
  716. // Function: NegPackageLoad
  717. //
  718. // Synopsis: Called by Negotiate package load only once
  719. //
  720. // Arguments: [p] --
  721. //
  722. // History: 10-02-97 ChandanS Created
  723. //
  724. // Notes:
  725. //
  726. //----------------------------------------------------------------------------
  727. DWORD
  728. WINAPI
  729. NegPackageLoad(
  730. BOOLEAN fLoad,
  731. DWORD dwPackageID,
  732. LPTSTR Name,
  733. DWORD fCapabilities,
  734. DWORD fPackage,
  735. DWORD dwRPCID,
  736. DWORD TokenSize
  737. )
  738. {
  739. NTSTATUS Status = STATUS_SUCCESS;
  740. PNEG_PACKAGE Package;
  741. PLSAP_SECURITY_PACKAGE LsaPackage;
  742. //
  743. // If this is a package load, add the package to our list:
  744. //
  745. DebugLog(( DEB_TRACE_NEG, "NegPackageLoad called for fLoad %d, dwPackageID %d, Name %d, fCapabilities 0x%x, dwRPCID %d, TokenSize %d\n", fLoad, dwPackageID, Name, fCapabilities, dwRPCID, TokenSize));
  746. if ( fLoad )
  747. {
  748. DebugLog(( DEB_TRACE_NEG, "package %s is being loaded\n", Name));
  749. Package = (PNEG_PACKAGE) LsapAllocateLsaHeap( sizeof( NEG_PACKAGE ) );
  750. if ( Package )
  751. {
  752. LsaPackage = (PLSAP_SECURITY_PACKAGE) LsapAllocateLsaHeap( sizeof( LSAP_SECURITY_PACKAGE ) );
  753. if ( !LsaPackage )
  754. {
  755. LsapFreeLsaHeap( Package );
  756. DebugLog(( DEB_TRACE_NEG, "package %s was not loaded\n", Name));
  757. return SEC_E_INSUFFICIENT_MEMORY;
  758. }
  759. DebugLog(( DEB_TRACE_NEG, "package %s is NOW loaded\n", Name));
  760. LsaPackage->dwPackageID = dwPackageID;
  761. LsaPackage->fCapabilities = fCapabilities;
  762. LsaPackage->fPackage = fPackage;
  763. LsaPackage->dwRPCID = dwRPCID;
  764. LsaPackage->TokenSize = TokenSize;
  765. Status = RtlCreateUnicodeStringFromAsciiz(
  766. &LsaPackage->Name,
  767. Name
  768. );
  769. Package->LsaPackage = LsaPackage ;
  770. Package->TokenSize = LsaPackage->TokenSize ;
  771. DebugLog(( DEB_TRACE_NEG, "Loaded package %ws\n",
  772. LsaPackage->Name.Buffer ));
  773. NegWriteLockList();
  774. NegMSMechanismsOid[ 0xb ] = (UCHAR) LsaPackage->dwRPCID ;
  775. Package->ObjectId = NegpDecodeObjectId( NegMSMechanismsOid,
  776. sizeof( NegMSMechanismsOid ) );
  777. NegDumpOid( "Assigned package OID", Package->ObjectId );
  778. InsertTailList( &NegPackageList,
  779. &Package->List );
  780. NegPackageCount ++;
  781. NegUnlockList();
  782. }
  783. else
  784. {
  785. DebugLog(( DEB_TRACE_NEG, "package %s was never loaded\n", Name));
  786. Status = SEC_E_INSUFFICIENT_MEMORY;
  787. }
  788. }
  789. else
  790. {
  791. DebugLog(( DEB_TRACE_NEG, "package %s is being unloaded\n", Name));
  792. //
  793. // It's either a select or an unload:
  794. //
  795. Package = NegpFindPackage( dwPackageID );
  796. //
  797. // if we don't have this package (it may not have been negotiable)
  798. // return now.
  799. //
  800. if (Package == NULL)
  801. {
  802. return(0);
  803. }
  804. NegWriteLockList();
  805. RemoveEntryList( &Package->List );
  806. NegUnlockList();
  807. NegpFreeObjectId( Package->ObjectId );
  808. LsapFreeLsaHeap( Package );
  809. }
  810. return( Status );
  811. }
  812. #endif // WIN32_CHICAGO
  813. //+---------------------------------------------------------------------------
  814. //
  815. // Function: NegpParseBuffers
  816. //
  817. // Synopsis: Parse out juicy bits
  818. //
  819. // Arguments: [pMessage] --
  820. // [pToken] --
  821. // [pEmpty] --
  822. //
  823. // History: 8-19-96 RichardW Created
  824. //
  825. // Notes:
  826. //
  827. //----------------------------------------------------------------------------
  828. SECURITY_STATUS
  829. NegpParseBuffers(
  830. PSecBufferDesc pMessage,
  831. BOOL Map,
  832. PSecBuffer * pToken,
  833. PSecBuffer * pEmpty)
  834. {
  835. ULONG i;
  836. SECURITY_STATUS scRet ;
  837. PSecBuffer pFirstBlank = NULL;
  838. PSecBuffer pWholeMessage = NULL;
  839. PSecBuffer pFirstToken = NULL;
  840. scRet = SEC_E_OK ;
  841. for (i = 0 ; i < pMessage->cBuffers ; i++ )
  842. {
  843. if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_TOKEN )
  844. {
  845. pWholeMessage = &pMessage->pBuffers[i];
  846. if ( pFirstToken == NULL )
  847. {
  848. pFirstToken = pWholeMessage;
  849. }
  850. if ( Map )
  851. {
  852. scRet = LsapMapClientBuffer( pWholeMessage, pWholeMessage );
  853. }
  854. if (pFirstBlank)
  855. {
  856. break;
  857. }
  858. }
  859. else if ( (pMessage->pBuffers[i].BufferType & (~SECBUFFER_ATTRMASK)) == SECBUFFER_EMPTY )
  860. {
  861. pFirstBlank = &pMessage->pBuffers[i];
  862. if (pWholeMessage)
  863. {
  864. break;
  865. }
  866. }
  867. }
  868. if (pToken)
  869. {
  870. // *pToken = pWholeMessage;
  871. //
  872. // NTBUG: 405976
  873. // down-level RDR supplies 2 SECBUFFER_TOKEN buffers, the second
  874. // one containing creds. Insure we return the first one.
  875. //
  876. *pToken = pFirstToken;
  877. }
  878. if (pEmpty)
  879. {
  880. *pEmpty = pFirstBlank;
  881. }
  882. return( scRet );
  883. }
  884. //+---------------------------------------------------------------------------
  885. //
  886. // Function: NegInitialize
  887. //
  888. // Synopsis: Initialize the built in negotiate package
  889. //
  890. // Arguments: [dwProtocol] --
  891. // [dwPackageID] --
  892. // [pParameters] --
  893. // [pPkgFunctions] --
  894. //
  895. // History: 7-26-96 RichardW Created
  896. //
  897. // Notes: This package must be the last package, since it must query
  898. // the others to find out their capabilities.
  899. //
  900. //----------------------------------------------------------------------------
  901. SECURITY_STATUS
  902. SEC_ENTRY
  903. NegInitialize(
  904. ULONG_PTR dwPackageID,
  905. PSECPKG_PARAMETERS pParameters,
  906. PLSA_SECPKG_FUNCTION_TABLE Table)
  907. {
  908. HKEY LsaKey ;
  909. int err ;
  910. DWORD size ;
  911. DWORD type ;
  912. NTSTATUS Status ;
  913. NegPackageId = dwPackageID;
  914. #ifndef WIN32_CHICAGO
  915. Status = RtlInitializeCriticalSection( &NegComputerNamesLock );
  916. if ( !NT_SUCCESS( Status ) )
  917. {
  918. return Status ;
  919. }
  920. NegNotifyHandle = LsaIRegisterNotification( NegPackageLoad,
  921. 0,
  922. NOTIFIER_TYPE_NOTIFY_EVENT,
  923. NOTIFY_CLASS_PACKAGE_CHANGE,
  924. 0,
  925. 0,
  926. 0 );
  927. InitializeListHead( &NegDefaultCredList );
  928. InitializeListHead( &NegLoopbackList );
  929. InitializeListHead( &NegLogonSessionList );
  930. Status = RtlInitializeCriticalSection( &NegLogonSessionListLock );
  931. if ( !NT_SUCCESS( Status ) )
  932. {
  933. return Status ;
  934. }
  935. Status = RtlInitializeCriticalSection( &NegTrustListLock );
  936. if ( !NT_SUCCESS( Status ) )
  937. {
  938. return Status ;
  939. }
  940. #endif // WIN32_CHICAGO
  941. RtlInitUnicodeString( &NegLocalHostName_U, NegLocalHostName );
  942. __try
  943. {
  944. RtlInitializeResource( &NegLock );
  945. Status = STATUS_SUCCESS ;
  946. }
  947. __except( EXCEPTION_EXECUTE_HANDLER )
  948. {
  949. Status = GetExceptionCode();
  950. }
  951. if ( !NT_SUCCESS( Status ) )
  952. {
  953. return Status ;
  954. }
  955. InitializeListHead( &NegPackageList );
  956. #ifndef WIN32_CHICAGO
  957. __try
  958. {
  959. RtlInitializeResource( &NegCredListLock );
  960. Status = STATUS_SUCCESS ;
  961. }
  962. __except( EXCEPTION_EXECUTE_HANDLER )
  963. {
  964. Status = GetExceptionCode();
  965. }
  966. if ( !NT_SUCCESS( Status ) )
  967. {
  968. return Status ;
  969. }
  970. #else
  971. Status = RtlInitializeCriticalSection( &NegCredListLock );
  972. if ( !NT_SUCCESS( Status ) )
  973. {
  974. return Status ;
  975. }
  976. #endif
  977. InitializeListHead( &NegCredList );
  978. NegPackageCount = 0;
  979. NegSpnegoMechOid = NegpDecodeObjectId(NegSpnegoMechEncodedOid, sizeof(NegSpnegoMechEncodedOid));
  980. if (NegSpnegoMechOid == NULL)
  981. {
  982. return(STATUS_INSUFFICIENT_RESOURCES);
  983. }
  984. NegMachineState = pParameters->MachineState;
  985. if ( ( pParameters->DomainSid != NULL ) &&
  986. ( pParameters->DnsDomainName.Length != 0 ) )
  987. {
  988. NegUplevelDomain = TRUE ;
  989. }
  990. #ifndef WIN32_CHICAGO
  991. //
  992. // Ignore the status - if we don't get a callback, then we can't support
  993. // dynamic domain change. If it succeeds, then great.
  994. //
  995. LsaIRegisterPolicyChangeNotificationCallback(
  996. NegLsaPolicyChangeCallback,
  997. PolicyNotifyDnsDomainInformation );
  998. LsaIRegisterNotification( NegParamChange,
  999. 0,
  1000. NOTIFIER_TYPE_NOTIFY_EVENT,
  1001. NOTIFY_CLASS_REGISTRY_CHANGE,
  1002. 0,
  1003. 0,
  1004. 0 );
  1005. //
  1006. // get the product type for loopback logic.
  1007. //
  1008. if (!RtlGetNtProductType( &NegProductType ) )
  1009. {
  1010. NegProductType = NtProductWinNt;
  1011. }
  1012. #endif
  1013. #ifdef WIN32_CHICAGO
  1014. err = RegOpenKeyEx(
  1015. HKEY_LOCAL_MACHINE,
  1016. TEXT("System\\CurrentControlSet\\Control\\SecurityProviders\\Negotiate"),
  1017. 0,
  1018. KEY_READ,
  1019. &LsaKey );
  1020. #else
  1021. err = RegOpenKeyEx(
  1022. HKEY_LOCAL_MACHINE,
  1023. TEXT("System\\CurrentControlSet\\Control\\Lsa"),
  1024. 0,
  1025. KEY_READ,
  1026. &LsaKey );
  1027. #endif
  1028. if ( err == 0 )
  1029. {
  1030. NegpReadRegistryParameters( LsaKey );
  1031. RegCloseKey( LsaKey );
  1032. }
  1033. return(S_OK);
  1034. }
  1035. VOID
  1036. NegpReadRegistryParameters(
  1037. HKEY LsaKey
  1038. )
  1039. {
  1040. DWORD size ;
  1041. DWORD type ;
  1042. int err ;
  1043. //
  1044. // These values are not MP sensitive, so we just blast the new value
  1045. // into them.
  1046. //
  1047. size = sizeof( DWORD );
  1048. err = RegQueryValueEx(
  1049. LsaKey,
  1050. TEXT("NegotiationLevel"),
  1051. NULL,
  1052. &type,
  1053. (LPBYTE) &NegNegotiationControl,
  1054. &size );
  1055. if ( err != 0 )
  1056. {
  1057. NegNegotiationControl = NEG_NEGLEVEL_COMPATIBILITY ;
  1058. }
  1059. #ifndef WIN32_CHICAGO
  1060. size = sizeof( DWORD );
  1061. err = RegQueryValueEx(
  1062. LsaKey,
  1063. TEXT("NegotiationLogLevel"),
  1064. NULL,
  1065. &type,
  1066. (LPBYTE) &NegEventLogLevel,
  1067. &size );
  1068. if ( err )
  1069. {
  1070. NegEventLogLevel = (1 << EVENTLOG_ERROR_TYPE ) |
  1071. (1 << EVENTLOG_WARNING_TYPE ) ;
  1072. }
  1073. #endif
  1074. }
  1075. //+---------------------------------------------------------------------------
  1076. //
  1077. // Function: NegGetInfo
  1078. //
  1079. // Synopsis: Negotiate Package GetInfo call
  1080. //
  1081. // Arguments: [pInfo] --
  1082. //
  1083. // History: 7-26-96 RichardW Created
  1084. //
  1085. // Notes:
  1086. //
  1087. //----------------------------------------------------------------------------
  1088. SECURITY_STATUS
  1089. SEC_ENTRY
  1090. NegGetInfo(PSecPkgInfo pInfo)
  1091. {
  1092. pInfo->wVersion = 1;
  1093. pInfo->wRPCID = NEGOSSP_RPCID ;
  1094. pInfo->fCapabilities = SECPKG_FLAG_INTEGRITY |
  1095. SECPKG_FLAG_PRIVACY |
  1096. SECPKG_FLAG_CONNECTION |
  1097. SECPKG_FLAG_MULTI_REQUIRED |
  1098. SECPKG_FLAG_EXTENDED_ERROR |
  1099. SECPKG_FLAG_IMPERSONATION |
  1100. SECPKG_FLAG_ACCEPT_WIN32_NAME |
  1101. SECPKG_FLAG_NEGOTIABLE |
  1102. SECPKG_FLAG_GSS_COMPATIBLE |
  1103. SECPKG_FLAG_LOGON;
  1104. pInfo->cbMaxToken = 500;
  1105. pInfo->Name = NEGOSSP_NAME;
  1106. pInfo->Comment = NegPackageComment;
  1107. return(S_OK);
  1108. }
  1109. //+---------------------------------------------------------------------------
  1110. //
  1111. // Function: NegAcceptCredentials
  1112. //
  1113. // Synopsis: Notification of a logon
  1114. //
  1115. // Arguments: [LogonType] --
  1116. // [UserName] --
  1117. // [PrimaryCred] --
  1118. // [SupplementalCreds] --
  1119. //
  1120. // History: 7-30-96 RichardW Created
  1121. //
  1122. // Notes:
  1123. //
  1124. //----------------------------------------------------------------------------
  1125. SECURITY_STATUS SEC_ENTRY
  1126. NegAcceptCredentials(
  1127. IN SECURITY_LOGON_TYPE LogonType,
  1128. IN PUNICODE_STRING UserName,
  1129. IN PSECPKG_PRIMARY_CRED PrimaryCred,
  1130. IN PSECPKG_SUPPLEMENTAL_CRED SupplementalCreds)
  1131. {
  1132. #ifndef WIN32_CHICAGO
  1133. LUID SystemId = SYSTEM_LUID;
  1134. NTSTATUS Status;
  1135. if (RtlEqualLuid(&PrimaryCred->LogonId, &SystemId))
  1136. {
  1137. //
  1138. // Stash away the LocalSystem credentials to use
  1139. // for NetworkService logons later on.
  1140. //
  1141. Status = NegpCopyCredsToBuffer(PrimaryCred,
  1142. NULL,
  1143. &NegPrimarySystemCredentials,
  1144. NULL);
  1145. return Status;
  1146. }
  1147. else if (LogonType == Service)
  1148. {
  1149. LUID LocalServiceId = LOCALSERVICE_LUID;
  1150. LUID NetworkServiceId = NETWORKSERVICE_LUID;
  1151. //
  1152. // Notify the network providers of the logon. Don't notify
  1153. // for SYSTEM, LocalService, or NetworkService.
  1154. //
  1155. if (!RtlEqualLuid(&PrimaryCred->LogonId, &LocalServiceId)
  1156. &&
  1157. !RtlEqualLuid(&PrimaryCred->LogonId, &NetworkServiceId))
  1158. {
  1159. NegpNotifyNetworkProviders(UserName, PrimaryCred);
  1160. }
  1161. }
  1162. #endif // WIN32_CHICAGO
  1163. return SEC_E_OK;
  1164. }
  1165. #ifndef WIN32_CHICAGO
  1166. //+-------------------------------------------------------------------------
  1167. //
  1168. // Function: NegpNotifyNetworkProviders
  1169. //
  1170. // Synopsis: Notifies network providers of a logon
  1171. //
  1172. // Effects:
  1173. //
  1174. // Arguments: [UserName] --
  1175. // [PrimaryCred] --
  1176. //
  1177. // Requires:
  1178. //
  1179. // Returns: Nothing since this is an advisory service to
  1180. // other network providers.
  1181. //
  1182. // Notes:
  1183. //
  1184. //--------------------------------------------------------------------------
  1185. VOID
  1186. NegpNotifyNetworkProviders(
  1187. IN PUNICODE_STRING UserName,
  1188. IN PSECPKG_PRIMARY_CRED PrimaryCred
  1189. )
  1190. {
  1191. MSV1_0_INTERACTIVE_LOGON OldLogon;
  1192. MSV1_0_INTERACTIVE_LOGON NewLogon;
  1193. static HMODULE s_hMprDll = NULL;
  1194. PLOGON_NOTIFY pfLogonNotify = NULL;
  1195. LPWSTR lpLogonScripts = NULL;
  1196. DWORD dwStatus;
  1197. if (s_hMprDll == NULL)
  1198. {
  1199. s_hMprDll = LoadLibrary(L"mpr.dll");
  1200. }
  1201. if (s_hMprDll != NULL)
  1202. {
  1203. pfLogonNotify = (PLOGON_NOTIFY) GetProcAddress(s_hMprDll,
  1204. "WNetLogonNotify");
  1205. if (pfLogonNotify != NULL)
  1206. {
  1207. NewLogon.MessageType = MsV1_0InteractiveLogon;
  1208. NewLogon.LogonDomainName = PrimaryCred->DomainName;
  1209. NewLogon.UserName = *UserName;
  1210. NewLogon.Password = PrimaryCred->Password;
  1211. RtlCopyMemory(&OldLogon, &NewLogon, sizeof(NewLogon));
  1212. dwStatus = pfLogonNotify(L"Windows NT Network Provider",
  1213. &PrimaryCred->LogonId,
  1214. L"MSV1_0:Interactive",
  1215. &NewLogon,
  1216. L"MSV1_0:Interactive",
  1217. &OldLogon,
  1218. L"SvcCtl", // StationName
  1219. NULL, // StationHandle
  1220. &lpLogonScripts); // LogonScripts
  1221. if (dwStatus == NO_ERROR)
  1222. {
  1223. LocalFree(lpLogonScripts);
  1224. }
  1225. }
  1226. }
  1227. }
  1228. #endif // WIN32_CHICAGO
  1229. //+-------------------------------------------------------------------------
  1230. //
  1231. // Function: NegpCopyCredsToBuffer
  1232. //
  1233. // Synopsis: Copies primary and supplemental creds into the supplied
  1234. // buffers
  1235. //
  1236. // Effects:
  1237. //
  1238. // Arguments: [PrimaryCred] --
  1239. // [SupplementalCred] --
  1240. // [PrimaryCredCopy] --
  1241. // [SupplementalCredCopy] --
  1242. //
  1243. // Requires:
  1244. //
  1245. // Returns:
  1246. //
  1247. // Notes: Leaves the SID and LUID blank. It is the caller's
  1248. // responsibility to fill these fields in.
  1249. //
  1250. //--------------------------------------------------------------------------
  1251. NTSTATUS
  1252. NegpCopyCredsToBuffer(
  1253. IN PSECPKG_PRIMARY_CRED PrimaryCred,
  1254. IN PSECPKG_SUPPLEMENTAL_CRED SupplementalCred,
  1255. OUT PSECPKG_PRIMARY_CRED PrimaryCredCopy OPTIONAL,
  1256. OUT PSECPKG_SUPPLEMENTAL_CRED SupplementalCredCopy OPTIONAL
  1257. )
  1258. {
  1259. NTSTATUS Status;
  1260. if (PrimaryCredCopy)
  1261. {
  1262. Status = LsapDuplicateString(&PrimaryCredCopy->DomainName,
  1263. &PrimaryCred->DomainName);
  1264. if (!NT_SUCCESS(Status))
  1265. {
  1266. goto ErrorExit;
  1267. }
  1268. Status = LsapDuplicateString(&PrimaryCredCopy->DownlevelName,
  1269. &PrimaryCred->DownlevelName);
  1270. if (!NT_SUCCESS(Status))
  1271. {
  1272. goto ErrorExit;
  1273. }
  1274. Status = LsapDuplicateString(&PrimaryCredCopy->Password,
  1275. &PrimaryCred->Password);
  1276. if (!NT_SUCCESS(Status))
  1277. {
  1278. goto ErrorExit;
  1279. }
  1280. PrimaryCredCopy->Flags = PRIMARY_CRED_CLEAR_PASSWORD;
  1281. }
  1282. if (SupplementalCredCopy)
  1283. {
  1284. Status = LsapDuplicateString(&SupplementalCredCopy->PackageName,
  1285. &SupplementalCred->PackageName);
  1286. if (!NT_SUCCESS(Status))
  1287. {
  1288. goto ErrorExit;
  1289. }
  1290. SupplementalCredCopy->Credentials = (PUCHAR) (SupplementalCredCopy + 1);
  1291. RtlCopyMemory(SupplementalCredCopy,
  1292. SupplementalCred->Credentials,
  1293. SupplementalCred->CredentialSize);
  1294. }
  1295. return( SEC_E_OK );
  1296. ErrorExit:
  1297. if (PrimaryCredCopy)
  1298. {
  1299. LsapFreeLsaHeap(PrimaryCredCopy->DomainName.Buffer);
  1300. LsapFreeLsaHeap(PrimaryCredCopy->DownlevelName.Buffer);
  1301. LsapFreeLsaHeap(PrimaryCredCopy->Password.Buffer);
  1302. }
  1303. return( STATUS_NO_MEMORY );
  1304. }
  1305. //+-------------------------------------------------------------------------
  1306. //
  1307. // Function: NegpCaptureSuppliedCreds
  1308. //
  1309. // Synopsis: Captures a SEC_WINNT_AUTH_IDENTITY_EX structure from
  1310. // the client
  1311. //
  1312. // Effects:
  1313. //
  1314. // Arguments: AuthorizationData - Client address of auth data
  1315. // PackageList - List of packages from the auth data.
  1316. //
  1317. // Requires:
  1318. //
  1319. // Returns:
  1320. //
  1321. // Notes:
  1322. //
  1323. //
  1324. //--------------------------------------------------------------------------
  1325. NTSTATUS
  1326. NegpCaptureSuppliedCreds(
  1327. IN PVOID AuthorizationData,
  1328. OUT PNEG_PACKAGE ** ReturnedPackageList,
  1329. OUT PULONG ReturnedPackageCount,
  1330. OUT PBOOL ExplicitCreds,
  1331. OUT PBOOL DomainExplicitCreds
  1332. )
  1333. {
  1334. NTSTATUS Status = STATUS_SUCCESS;
  1335. SEC_WINNT_AUTH_IDENTITY_EXW IdentityEx = {0};
  1336. SEC_WINNT_AUTH_IDENTITY_W * Identity;
  1337. PSTR PackageList = NULL;
  1338. UNICODE_STRING PackageString = {0};
  1339. ULONG PackageListLength;
  1340. ULONG CharSize = sizeof(WCHAR);
  1341. ULONG Index;
  1342. ULONG PackageCount;
  1343. ULONG PackageIndex;
  1344. ULONG ExclusionIndex ;
  1345. ULONG FinalIndex ;
  1346. ULONG PossiblePackageCount ;
  1347. ULONG i, j;
  1348. PNEG_PACKAGE * LocalPackageList = NULL;
  1349. PNEG_PACKAGE * ExclusionList = NULL ;
  1350. PNEG_PACKAGE * FinalList = NULL ;
  1351. PNEG_PACKAGE Package ;
  1352. PLIST_ENTRY List ;
  1353. PNEG_PACKAGE PackageScan ;
  1354. UNICODE_STRING TempString;
  1355. PWSTR Scan, EndPoint, Comma ;
  1356. *ReturnedPackageList = NULL;
  1357. *ReturnedPackageCount = 0;
  1358. *ExplicitCreds = FALSE ;
  1359. *DomainExplicitCreds = FALSE ;
  1360. //
  1361. // First capture the base structure
  1362. //
  1363. Status = LsapCopyFromClientBuffer(
  1364. NULL,
  1365. sizeof(SEC_WINNT_AUTH_IDENTITY_W),
  1366. &IdentityEx,
  1367. AuthorizationData
  1368. );
  1369. if (!NT_SUCCESS(Status))
  1370. {
  1371. DebugLog((DEB_ERROR,"Failed to copy auth data from %p client address: 0x%x\n",
  1372. AuthorizationData, Status ));
  1373. *ExplicitCreds = TRUE ;
  1374. Status = STATUS_SUCCESS;
  1375. goto Cleanup;
  1376. }
  1377. //
  1378. // Check if this is the right structure
  1379. //
  1380. if (IdentityEx.Version != SEC_WINNT_AUTH_IDENTITY_VERSION)
  1381. {
  1382. Identity = (PSEC_WINNT_AUTH_IDENTITY_W) &IdentityEx ;
  1383. if ( (Identity->UserLength > 0 ) ||
  1384. (Identity->DomainLength > 0 ) ||
  1385. (Identity->PasswordLength > 0 ||
  1386. Identity->Password != NULL) )
  1387. {
  1388. *ExplicitCreds = TRUE ;
  1389. if( Identity->DomainLength )
  1390. {
  1391. *DomainExplicitCreds = TRUE;
  1392. }
  1393. }
  1394. goto Cleanup;
  1395. }
  1396. //
  1397. // Copy the whole data structure now
  1398. //
  1399. Status = LsapCopyFromClientBuffer(
  1400. NULL,
  1401. sizeof(SEC_WINNT_AUTH_IDENTITY_EXW),
  1402. &IdentityEx,
  1403. AuthorizationData
  1404. );
  1405. if (!NT_SUCCESS(Status))
  1406. {
  1407. DebugLog((DEB_ERROR,"Failed to copy auth data from %p client address: 0x%x\n",
  1408. AuthorizationData, Status ));
  1409. *ExplicitCreds = TRUE ;
  1410. //
  1411. // Mask this error, as it may have been data for another package.
  1412. //
  1413. Status = STATUS_SUCCESS;
  1414. goto Cleanup;
  1415. }
  1416. //
  1417. // Check to see if this contains a list of packages
  1418. //
  1419. //
  1420. if (IdentityEx.Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
  1421. {
  1422. CharSize = sizeof(CHAR);
  1423. }
  1424. //
  1425. // If there was no packge list in the data, return now.
  1426. //
  1427. if ( ( IdentityEx.UserLength > 0 ) ||
  1428. ( IdentityEx.DomainLength > 0 ) ||
  1429. ( IdentityEx.PasswordLength > 0 ||
  1430. IdentityEx.Password != NULL ) )
  1431. {
  1432. *ExplicitCreds = TRUE ;
  1433. if( IdentityEx.DomainLength )
  1434. {
  1435. *DomainExplicitCreds = TRUE;
  1436. }
  1437. }
  1438. if ((IdentityEx.Length < sizeof(SEC_WINNT_AUTH_IDENTITY_EXW)) ||
  1439. (IdentityEx.PackageList == NULL) ||
  1440. (IdentityEx.PackageListLength == 0))
  1441. {
  1442. Status = STATUS_SUCCESS;
  1443. goto Cleanup;
  1444. }
  1445. if ( (IdentityEx.PackageListLength + 1) * CharSize < IdentityEx.PackageListLength )
  1446. {
  1447. //
  1448. // Passed size is too large (we rolled over)
  1449. //
  1450. Status = STATUS_INVALID_PARAMETER ;
  1451. goto Cleanup ;
  1452. }
  1453. //
  1454. // Capture the package list itself
  1455. //
  1456. PackageList = (PSTR) LsapAllocateLsaHeap(CharSize * (IdentityEx.PackageListLength + 1));
  1457. if (PackageList == NULL)
  1458. {
  1459. Status = SEC_E_INSUFFICIENT_MEMORY;
  1460. goto Cleanup;
  1461. }
  1462. Status = LsapCopyFromClientBuffer(
  1463. NULL,
  1464. CharSize * IdentityEx.PackageListLength,
  1465. PackageList,
  1466. IdentityEx.PackageList
  1467. );
  1468. if (!NT_SUCCESS(Status))
  1469. {
  1470. DebugLog((DEB_ERROR,"Failed to copy package list\n"));
  1471. goto Cleanup;
  1472. }
  1473. //
  1474. // Conver the package list into a useable form, including changing
  1475. // character sets.
  1476. //
  1477. if (CharSize == sizeof(CHAR))
  1478. {
  1479. ((LPSTR)PackageList)[IdentityEx.PackageListLength] = '\0';
  1480. if ( !RtlCreateUnicodeStringFromAsciiz(
  1481. &PackageString,
  1482. PackageList
  1483. ) )
  1484. {
  1485. goto Cleanup;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. ((LPWSTR)PackageList)[IdentityEx.PackageListLength] = L'\0';
  1491. RtlInitUnicodeString(
  1492. &PackageString,
  1493. (LPWSTR) PackageList
  1494. );
  1495. PackageList = NULL;
  1496. }
  1497. //
  1498. // Scan through counting for ',' separators to get a count of packages.
  1499. //
  1500. PackageCount = 1;
  1501. for (Index = 0; Index < PackageString.Length / sizeof(WCHAR) ; Index++ )
  1502. {
  1503. if (PackageString.Buffer[Index] == L',')
  1504. {
  1505. PackageCount++;
  1506. }
  1507. }
  1508. //
  1509. // If there was nothing in the list, continue as if it wasn't there
  1510. //
  1511. if (PackageCount == 0)
  1512. {
  1513. Status = STATUS_SUCCESS;
  1514. goto Cleanup;
  1515. }
  1516. //
  1517. // Allocate the package list
  1518. //
  1519. LocalPackageList = (PNEG_PACKAGE *) LsapAllocateLsaHeap( PackageCount * sizeof( PNEG_PACKAGE ) );
  1520. if (LocalPackageList == NULL)
  1521. {
  1522. Status = SEC_E_INSUFFICIENT_MEMORY;
  1523. goto Cleanup;
  1524. }
  1525. ExclusionList = (PNEG_PACKAGE *) LsapAllocateLsaHeap( PackageCount * sizeof( PNEG_PACKAGE ) );
  1526. if ( ExclusionList == NULL )
  1527. {
  1528. Status = SEC_E_INSUFFICIENT_MEMORY ;
  1529. goto Cleanup ;
  1530. }
  1531. //
  1532. // Now go through the string of packages and build the list
  1533. //
  1534. PackageIndex = 0;
  1535. ExclusionIndex = 0;
  1536. TempString.Buffer = PackageString.Buffer;
  1537. TempString.Length = 0;
  1538. TempString.MaximumLength = PackageString.MaximumLength;
  1539. Index = 0;
  1540. Scan = PackageString.Buffer ;
  1541. EndPoint = Scan + (PackageString.Length / sizeof( WCHAR ));
  1542. while ( Scan < EndPoint )
  1543. {
  1544. Comma = wcschr( Scan, L',' );
  1545. if ( Comma )
  1546. {
  1547. *Comma = L'\0' ;
  1548. }
  1549. if ( *Scan == L'!' )
  1550. {
  1551. //
  1552. // This entry is an exclusion. Skip past the ! char,
  1553. // and try to find a package
  1554. //
  1555. Scan++ ;
  1556. if ( Scan != Comma )
  1557. {
  1558. RtlInitUnicodeString( &TempString, Scan );
  1559. ExclusionList[ ExclusionIndex ] = NegpFindPackageByName( &TempString );
  1560. if ( ExclusionList[ ExclusionIndex ] != NULL )
  1561. {
  1562. ExclusionIndex++ ;
  1563. }
  1564. }
  1565. }
  1566. else
  1567. {
  1568. //
  1569. // This entry is a request. Try to find the package
  1570. //
  1571. RtlInitUnicodeString( &TempString, Scan );
  1572. LocalPackageList[ PackageIndex ] = NegpFindPackageByName( &TempString );
  1573. if ( LocalPackageList[ PackageIndex ] != NULL )
  1574. {
  1575. PackageIndex++ ;
  1576. }
  1577. }
  1578. if ( Comma )
  1579. {
  1580. *Comma = L',';
  1581. Scan = Comma + 1 ;
  1582. }
  1583. else
  1584. {
  1585. Scan = EndPoint ;
  1586. }
  1587. }
  1588. //
  1589. // Now, we have two lists. We have an ExclusionList, of packages that the caller
  1590. // does not want, and a package list, a list of things that the caller does want.
  1591. // Merge the list according to the requests
  1592. //
  1593. PossiblePackageCount = NegPackageCount ;
  1594. FinalIndex = 0 ;
  1595. FinalList = (PNEG_PACKAGE *) LsapAllocateLsaHeap( PossiblePackageCount * sizeof( PNEG_PACKAGE ) );
  1596. if ( FinalList == NULL )
  1597. {
  1598. Status = SEC_E_INSUFFICIENT_MEMORY ;
  1599. goto Cleanup ;
  1600. }
  1601. for ( i = 0 ; i < PackageIndex ; i++ )
  1602. {
  1603. //
  1604. // Pick a package off the request list
  1605. //
  1606. Package = LocalPackageList[ i ];
  1607. //
  1608. // Scan through the exclusion list, see if we need to skip it.
  1609. //
  1610. for ( j = 0 ; j < ExclusionIndex ; j++ )
  1611. {
  1612. if ( Package == ExclusionList[ j ] )
  1613. {
  1614. break;
  1615. }
  1616. }
  1617. if ( j < ExclusionIndex )
  1618. {
  1619. //
  1620. // if we broke out of the loop, we found this on the exclusion list.
  1621. // skip it by continuing the for-i loop.
  1622. //
  1623. continue;
  1624. }
  1625. //
  1626. // Ok, this package is not excluded. So add it to the final list
  1627. //
  1628. FinalList[ FinalIndex ] = Package;
  1629. FinalIndex++ ;
  1630. //
  1631. // See if this package has "extra" packages by the same name with
  1632. // other OIDs associated with it
  1633. //
  1634. if ( (Package->Flags & NEG_PACKAGE_HAS_EXTRAS) != 0 )
  1635. {
  1636. //
  1637. // Ok, there are a set of packages associated with this package. Walk the
  1638. // package list, and stick the extras into this one.
  1639. //
  1640. NegReadLockList();
  1641. List = NegPackageList.Flink ;
  1642. while ( List != &NegPackageList )
  1643. {
  1644. PackageScan = CONTAINING_RECORD( List, NEG_PACKAGE, List );
  1645. if ( PackageScan->RealPackage == Package )
  1646. {
  1647. FinalList[ FinalIndex ] = PackageScan ;
  1648. FinalIndex++ ;
  1649. }
  1650. List = List->Flink ;
  1651. }
  1652. NegUnlockList();
  1653. }
  1654. }
  1655. if ( (PackageIndex == 0) &&
  1656. (ExclusionIndex != 0 ) )
  1657. {
  1658. //
  1659. // Only an exclusion list was provided. Walk all the packages,
  1660. // and add those that are not excluded.
  1661. //
  1662. NegReadLockList();
  1663. List = NegPackageList.Flink ;
  1664. while ( List != &NegPackageList )
  1665. {
  1666. PackageScan = CONTAINING_RECORD( List, NEG_PACKAGE, List );
  1667. if ( ( PackageScan->Flags & NEG_PACKAGE_EXTRA_OID ) != 0 )
  1668. {
  1669. Package = PackageScan->RealPackage ;
  1670. }
  1671. else
  1672. {
  1673. Package = PackageScan ;
  1674. }
  1675. for ( i = 0 ; i < ExclusionIndex ; i++ )
  1676. {
  1677. if ( Package == ExclusionList[ i ] )
  1678. {
  1679. break;
  1680. }
  1681. }
  1682. if ( i < ExclusionIndex )
  1683. {
  1684. continue;
  1685. }
  1686. FinalList[ FinalIndex ] = PackageScan ;
  1687. FinalIndex++ ;
  1688. }
  1689. NegUnlockList();
  1690. }
  1691. //
  1692. // If no packages succeeded, return an error
  1693. //
  1694. if (PackageIndex == 0)
  1695. {
  1696. Status = SEC_E_SECPKG_NOT_FOUND;
  1697. goto Cleanup;
  1698. }
  1699. *ReturnedPackageCount = FinalIndex;
  1700. *ReturnedPackageList = FinalList;
  1701. FinalList = NULL;
  1702. Cleanup:
  1703. if (PackageList != NULL)
  1704. {
  1705. LsapFreeLsaHeap(PackageList);
  1706. if (PackageString.Buffer != NULL)
  1707. {
  1708. RtlFreeUnicodeString( &PackageString );
  1709. }
  1710. }
  1711. else
  1712. {
  1713. if (PackageString.Buffer != NULL)
  1714. {
  1715. LsapFreeLsaHeap(PackageString.Buffer);
  1716. }
  1717. }
  1718. if (LocalPackageList != NULL)
  1719. {
  1720. LsapFreeLsaHeap(LocalPackageList);
  1721. }
  1722. if ( ExclusionList != NULL )
  1723. {
  1724. LsapFreeLsaHeap( ExclusionList );
  1725. }
  1726. if ( FinalList != NULL )
  1727. {
  1728. LsapFreeLsaHeap( FinalList );
  1729. }
  1730. return(Status);
  1731. }
  1732. //+-------------------------------------------------------------------------
  1733. //
  1734. // Function: NegpBuildPackageList
  1735. //
  1736. // Synopsis: Builds the list of packages for the caller
  1737. //
  1738. // Effects:
  1739. //
  1740. // Arguments:
  1741. //
  1742. // Requires:
  1743. //
  1744. // Returns:
  1745. //
  1746. // Notes:
  1747. //
  1748. //
  1749. //--------------------------------------------------------------------------
  1750. NTSTATUS
  1751. NegpBuildPackageList(
  1752. IN ULONG_PTR LogonPackageId,
  1753. IN ULONG fCredentials,
  1754. OUT PNEG_PACKAGE ** ReturnedPackageList,
  1755. OUT PULONG ReturnedPackageCount
  1756. )
  1757. {
  1758. NTSTATUS Status = STATUS_SUCCESS;
  1759. PNEG_PACKAGE Package;
  1760. PNEG_PACKAGE ClientNegPackage = NULL;
  1761. PNEG_PACKAGE *PackageList = NULL;
  1762. PLIST_ENTRY Scan ;
  1763. ULONG PackageIndex = 0;
  1764. ULONG PackageMask ;
  1765. *ReturnedPackageList = NULL;
  1766. *ReturnedPackageCount = 0;
  1767. PackageList = (PNEG_PACKAGE *) LsapAllocateLsaHeap(NegPackageCount * sizeof(PNEG_PACKAGE));
  1768. if (PackageList == NULL)
  1769. {
  1770. Status = SEC_E_INSUFFICIENT_MEMORY;
  1771. goto Cleanup;
  1772. }
  1773. //
  1774. // Find the client's logon package
  1775. //
  1776. Scan = NegPackageList.Flink ;
  1777. Package = (PNEG_PACKAGE) NegPackageList.Flink ;
  1778. while ( Scan != &NegPackageList )
  1779. {
  1780. Package = CONTAINING_RECORD( Scan, NEG_PACKAGE, List );
  1781. if (Package->LsaPackage->dwPackageID == LogonPackageId)
  1782. {
  1783. ClientNegPackage = Package;
  1784. break;
  1785. }
  1786. Scan = Scan->Flink ;
  1787. }
  1788. //
  1789. // Compute a mask of package flags to use as part of the selection
  1790. // process. This is currently based on the credential use flags passed in
  1791. //
  1792. PackageMask = 0 ;
  1793. if ( fCredentials & SECPKG_CRED_INBOUND )
  1794. {
  1795. PackageMask |= NEG_PACKAGE_INBOUND ;
  1796. }
  1797. if ( fCredentials & SECPKG_CRED_OUTBOUND )
  1798. {
  1799. PackageMask |= NEG_PACKAGE_OUTBOUND ;
  1800. }
  1801. //
  1802. // Build the list of packages, with the logon package first
  1803. //
  1804. if ( ClientNegPackage )
  1805. {
  1806. PackageList[ PackageIndex ] = ClientNegPackage ;
  1807. PackageIndex = 1;
  1808. }
  1809. Scan = NegPackageList.Flink ;
  1810. while ( Scan != &NegPackageList )
  1811. {
  1812. Package = CONTAINING_RECORD( Scan, NEG_PACKAGE, List );
  1813. //
  1814. // ClientNegPackage has already been processed, skip it
  1815. //
  1816. if ( Package != ClientNegPackage )
  1817. {
  1818. //
  1819. // Make sure that the package flags support the request.
  1820. //
  1821. if ( (Package->Flags & PackageMask ) == PackageMask )
  1822. {
  1823. PackageList[PackageIndex] = Package;
  1824. PackageIndex++;
  1825. }
  1826. }
  1827. Scan = Scan->Flink ;
  1828. }
  1829. *ReturnedPackageList = PackageList;
  1830. PackageList = NULL;
  1831. *ReturnedPackageCount = PackageIndex;
  1832. Cleanup:
  1833. if (PackageList != NULL)
  1834. {
  1835. LsapFreeLsaHeap(PackageList);
  1836. }
  1837. return(Status);
  1838. }
  1839. //+-------------------------------------------------------------------------
  1840. //
  1841. // Function: NegpCheckForDuplicateCreds
  1842. //
  1843. // Synopsis: Check to see if this is a duplicate of another
  1844. // credential
  1845. //
  1846. // Effects:
  1847. //
  1848. // Arguments:
  1849. //
  1850. // Requires:
  1851. //
  1852. // Returns:
  1853. //
  1854. // Notes:
  1855. //
  1856. //
  1857. //--------------------------------------------------------------------------
  1858. BOOLEAN
  1859. NegpCheckForDuplicateCreds(
  1860. IN PNEG_CREDS * Credential
  1861. )
  1862. {
  1863. PLIST_ENTRY Next;
  1864. PNEG_CREDS MatchCred;
  1865. PNEG_CREDS LocalCred = *Credential;
  1866. NegReadLockCredList();
  1867. for (Next = NegCredList.Flink; Next != &NegCredList; Next = Next->Flink )
  1868. {
  1869. MatchCred = CONTAINING_RECORD(
  1870. Next,
  1871. NEG_CREDS,
  1872. List
  1873. );
  1874. if(!( MatchCred->ClientProcessId == LocalCred->ClientProcessId ) )
  1875. {
  1876. continue;
  1877. }
  1878. if(!RtlEqualLuid( &MatchCred->ClientLogonId, &LocalCred->ClientLogonId ) )
  1879. {
  1880. continue;
  1881. }
  1882. //
  1883. // Check if this credential has the same credentials
  1884. // as the one we just created. Make sure they are both
  1885. // from user or kernel mode (don't mix'n'match)
  1886. //
  1887. if ( ( MatchCred->Count == LocalCred->Count ) &&
  1888. ( MatchCred->Flags == LocalCred->Flags ) &&
  1889. ( (MatchCred->Flags & NEGCRED_DUP_MASK ) == (LocalCred->Flags & NEGCRED_DUP_MASK ) ) )
  1890. {
  1891. if ( !RtlEqualMemory(
  1892. MatchCred->Creds,
  1893. LocalCred->Creds,
  1894. LocalCred->Count * sizeof( NEG_CRED_HANDLE ) ) )
  1895. {
  1896. ULONG i ;
  1897. DebugLog(( DEB_TRACE_NEG, "Same Process, same count, differing handles?\n" ));
  1898. for ( i = 0 ; i < LocalCred->Count ; i++ )
  1899. {
  1900. DebugLog(( DEB_TRACE_NEG, " %d: new <%p : %p> existing (%p : %p)\n",
  1901. i,
  1902. LocalCred->Creds[i].Handle.dwLower,
  1903. LocalCred->Creds[i].Handle.dwUpper,
  1904. MatchCred->Creds[i].Handle.dwLower,
  1905. MatchCred->Creds[i].Handle.dwUpper ));
  1906. }
  1907. }
  1908. else
  1909. {
  1910. ULONG_PTR PackageId;
  1911. ULONG i ;
  1912. NegWriteLockCreds( MatchCred );
  1913. if( MatchCred->RefCount == 0 )
  1914. {
  1915. NegUnlockCreds( MatchCred );
  1916. continue;
  1917. }
  1918. MatchCred->RefCount++ ;
  1919. NegUnlockCreds( MatchCred );
  1920. NegUnlockCredList();
  1921. //
  1922. // blot out the handle so the refcount is kept in sync
  1923. // with what the underlying packages believe.
  1924. //
  1925. PackageId = GetCurrentPackageId();
  1926. for ( i = 0 ; i < LocalCred->Count ; i++ )
  1927. {
  1928. #ifndef WIN32_CHICAGO
  1929. if( (LocalCred->Creds[i].Flags & NEG_CREDHANDLE_EXTRA_OID) == 0 )
  1930. {
  1931. WLsaFreeCredHandle( &LocalCred->Creds[i].Handle );
  1932. }
  1933. #else
  1934. FreeCredentialsHandle( &LocalCred->Creds[i].Handle );
  1935. #endif // WIN32_CHICAGO
  1936. LocalCred->Creds[i].Handle.dwLower = NEG_INVALID_PACKAGE;
  1937. LocalCred->Creds[i].Handle.dwUpper = NEG_INVALID_PACKAGE;
  1938. }
  1939. SetCurrentPackageId( PackageId );
  1940. NegpReleaseCreds( LocalCred, FALSE );
  1941. *Credential = MatchCred ;
  1942. return TRUE;
  1943. }
  1944. }
  1945. }
  1946. NegUnlockCredList( );
  1947. return FALSE;
  1948. }
  1949. SECURITY_STATUS
  1950. NegpAcquireCredHandle(
  1951. PSECURITY_STRING psPrincipal,
  1952. ULONG fCredentials,
  1953. PLUID pLogonID,
  1954. PVOID pvAuthData,
  1955. PVOID pvGetKeyFn,
  1956. PVOID pvGetKeyArgument,
  1957. PULONG_PTR pdwHandle,
  1958. PTimeStamp ptsExpiry)
  1959. {
  1960. NEG_CRED_HANDLE Creds[ NEG_MECH_LIMIT ];
  1961. PNEG_CRED_HANDLE pCreds = NULL;
  1962. DWORD i = 0;
  1963. ULONG Index;
  1964. BOOL FreeCreds = FALSE;
  1965. PNEG_PACKAGE Package;
  1966. PNEG_PACKAGE ClientNegPackage = NULL;
  1967. PNEG_PACKAGE * AuthPackageList = NULL;
  1968. ULONG AuthPackageCount = 0;
  1969. SECURITY_STATUS scRet = STATUS_SUCCESS;
  1970. TimeStamp Expiry = { 0 };
  1971. PNEG_CREDS pNegCreds = NULL ;
  1972. ULONG_PTR PackageId;
  1973. SECPKG_CLIENT_INFO ClientInfo;
  1974. #ifndef WIN32_CHICAGO
  1975. PLSA_CALL_INFO CallInfo ;
  1976. PLSAP_LOGON_SESSION LogonSession = NULL;
  1977. PNEG_LOGON_SESSION NegLogonSession = NULL ;
  1978. PSession pSession ;
  1979. TimeStamp MinExpiry = { 0xFFFFFFFF, 0x7FFFFFFF };
  1980. #else
  1981. TimeStamp MinExpiry = 0x7FFFFFFFFFFFFFFF ;
  1982. #endif // WIN32_CHICAGO
  1983. PLUID ClientLogonId;
  1984. ULONG_PTR ClientPackage = -1;
  1985. ULONG_PTR ClientDefaultPackage = -1;
  1986. BOOL ExplicitCreds = FALSE ;
  1987. BOOL DomainExplicitCreds = FALSE ;
  1988. LUID LocalSystem = SYSTEM_LUID ;
  1989. BOOLEAN EnableLoopback = TRUE;
  1990. DebugLog(( DEB_TRACE_NEG, "NegAcquireCredentialsHandle: Get a Negotiate CredHandle:\n"));
  1991. //
  1992. // Determine caller info
  1993. //
  1994. scRet = LsapGetClientInfo(&ClientInfo);
  1995. if (!NT_SUCCESS(scRet))
  1996. {
  1997. goto Cleanup;
  1998. }
  1999. #ifndef WIN32_CHICAGO
  2000. CallInfo = LsapGetCurrentCall();
  2001. pSession = GetCurrentSession();
  2002. #endif
  2003. //
  2004. // Get the callers Logon ID so we can determine what package to try first
  2005. //
  2006. if (ARGUMENT_PRESENT(pLogonID) && ((pLogonID->LowPart != 0) || (pLogonID->HighPart != 0)))
  2007. {
  2008. ClientLogonId = pLogonID;
  2009. }
  2010. else
  2011. {
  2012. ClientLogonId = &ClientInfo.LogonId;
  2013. }
  2014. #ifndef WIN32_CHICAGO
  2015. //
  2016. // Now find out what package logged this user on
  2017. //
  2018. NegLogonSession = NegpLocateLogonSession( ClientLogonId );
  2019. if ( NegLogonSession == NULL )
  2020. {
  2021. LogonSession = LsapLocateLogonSession( ClientLogonId );
  2022. if (LogonSession != NULL)
  2023. {
  2024. PLSAP_SECURITY_PACKAGE LsaPackage ;
  2025. ClientPackage = LogonSession->CreatingPackage;
  2026. LsapReleaseLogonSession( LogonSession );
  2027. //
  2028. // If this was done by an old style package, that is,
  2029. // an NT4 style auth pkg, *or* some one calling MSV in
  2030. // the old fashioned way, reset the value to the negotiate
  2031. // ID to allow full negotiation range.
  2032. //
  2033. LsaPackage = SpmpLocatePackage( ClientPackage );
  2034. if ( LsaPackage )
  2035. {
  2036. if ( ( LsaPackage->fPackage & SPM_AUTH_PKG_FLAG ) != 0 )
  2037. {
  2038. ClientPackage = NegPackageId ;
  2039. }
  2040. }
  2041. }
  2042. }
  2043. else
  2044. {
  2045. ClientPackage = NegLogonSession->DefaultPackage ;
  2046. NegpDerefLogonSession( NegLogonSession );
  2047. NegLogonSession = NULL ;
  2048. }
  2049. #endif // WIN32_CHICAGO
  2050. ClientDefaultPackage = ClientPackage;
  2051. NegReadLockList();
  2052. //
  2053. // If authentication data was passed in, capture it now to see
  2054. // if it includes a subset of the packages to use.
  2055. //
  2056. if (ARGUMENT_PRESENT(pvAuthData))
  2057. {
  2058. ClientPackage = (ULONG_PTR) -1 ;
  2059. scRet = NegpCaptureSuppliedCreds(
  2060. pvAuthData,
  2061. &AuthPackageList,
  2062. &AuthPackageCount,
  2063. &ExplicitCreds,
  2064. &DomainExplicitCreds
  2065. );
  2066. if (!NT_SUCCESS(scRet))
  2067. {
  2068. NegUnlockList();
  2069. goto Cleanup;
  2070. }
  2071. }
  2072. //
  2073. // turn off loopback detection when:
  2074. // 1. explicit credentials were supplied.
  2075. // 2. Product is domain controller, and client is local system account
  2076. // (this will cause system->system to auth using machine account.)
  2077. //
  2078. if( ExplicitCreds )
  2079. {
  2080. EnableLoopback = FALSE;
  2081. }
  2082. if (!RtlEqualLuid( ClientLogonId, &LocalSystem ))
  2083. {
  2084. if( ClientPackage == NegPackageId )
  2085. {
  2086. ExplicitCreds = TRUE ;
  2087. }
  2088. } else {
  2089. #ifndef WIN32_CHICAGO
  2090. if( NegProductType == NtProductLanManNt )
  2091. {
  2092. EnableLoopback = FALSE;
  2093. }
  2094. #endif // !WIN32_CHICAGO
  2095. }
  2096. //
  2097. // Build the list of packages that we'll call to get credentials
  2098. //
  2099. if (AuthPackageCount == 0)
  2100. {
  2101. scRet = NegpBuildPackageList(
  2102. ClientPackage,
  2103. fCredentials,
  2104. &AuthPackageList,
  2105. &AuthPackageCount
  2106. );
  2107. if (!NT_SUCCESS(scRet))
  2108. {
  2109. NegUnlockList();
  2110. goto Cleanup;
  2111. }
  2112. }
  2113. if ( AuthPackageCount < NEG_MECH_LIMIT )
  2114. {
  2115. pCreds = Creds;
  2116. ZeroMemory( Creds, sizeof(Creds) );
  2117. }
  2118. else
  2119. {
  2120. pCreds = (PNEG_CRED_HANDLE) LsapAllocatePrivateHeap( NegPackageCount *
  2121. sizeof( NEG_CRED_HANDLE ) );
  2122. if ( !pCreds )
  2123. {
  2124. NegUnlockList();
  2125. scRet = SEC_E_INSUFFICIENT_MEMORY;
  2126. goto Cleanup;
  2127. }
  2128. }
  2129. i = 0;
  2130. for (Index = 0; Index < AuthPackageCount ; Index++ )
  2131. {
  2132. BOOLEAN SkipAcquire = FALSE;
  2133. PackageId = GetCurrentPackageId();
  2134. #ifdef WIN32_CHICAGO
  2135. ANSI_STRING AnsiString1 = { 0 }, AnsiString2 = { 0 };
  2136. scRet = RtlUnicodeStringToAnsiString( &AnsiString1,
  2137. &AuthPackageList[Index]->LsaPackage->Name,
  2138. TRUE);
  2139. if ( NT_SUCCESS( scRet ) )
  2140. {
  2141. scRet = RtlUnicodeStringToAnsiString( &AnsiString2,
  2142. psPrincipal,
  2143. TRUE);
  2144. }
  2145. if ( NT_SUCCESS( scRet ) )
  2146. {
  2147. scRet = AcquireCredentialsHandle( AnsiString2.Buffer,
  2148. AnsiString1.Buffer,
  2149. fCredentials,
  2150. pLogonID,
  2151. pvAuthData,
  2152. (SEC_GET_KEY_FN) pvGetKeyFn,
  2153. pvGetKeyArgument,
  2154. &pCreds[i].Handle,
  2155. &Expiry );
  2156. }
  2157. #else
  2158. ULONG_PTR ThisPackageId = (ULONG_PTR)AuthPackageList[Index]->LsaPackage->dwPackageID;
  2159. DWORD j;
  2160. //
  2161. // mask off the DEFAULT flag, since only we understand it
  2162. //
  2163. //
  2164. // skip calling the package if there are multiple aliases (oids)
  2165. // that point to the same underlying package.
  2166. // note: NegpReleaseCreds() duplicate handle values are ignored
  2167. // during credential release.
  2168. //
  2169. for( j = 0 ; j < i ; j ++ )
  2170. {
  2171. if( pCreds[j].Handle.dwLower == ThisPackageId )
  2172. {
  2173. CopyMemory( &pCreds[i].Handle, &pCreds[j].Handle, sizeof(pCreds[i].Handle) );
  2174. SkipAcquire = TRUE;
  2175. break;
  2176. }
  2177. }
  2178. if( !SkipAcquire )
  2179. {
  2180. scRet = WLsaAcquireCredHandle( psPrincipal,
  2181. &AuthPackageList[Index]->LsaPackage->Name,
  2182. fCredentials & ( SECPKG_CRED_BOTH),
  2183. pLogonID,
  2184. pvAuthData,
  2185. pvGetKeyFn,
  2186. pvGetKeyArgument,
  2187. &pCreds[i].Handle,
  2188. &Expiry );
  2189. pCreds[i].Flags = 0;
  2190. } else {
  2191. //
  2192. // no need to AddCredHandle(), as, that would put us out of sync with
  2193. // the underlying package ref count.
  2194. //
  2195. pCreds[i].Flags = NEG_CREDHANDLE_EXTRA_OID;
  2196. scRet = SEC_E_OK;
  2197. }
  2198. #endif // WIN32_CHICAGO
  2199. SetCurrentPackageId( PackageId );
  2200. if ( NT_SUCCESS( scRet ) )
  2201. {
  2202. if( !SkipAcquire )
  2203. {
  2204. DebugLog((DEB_TRACE_NEG, " Added %p:%p, %ws\n",
  2205. pCreds[i].Handle.dwUpper, pCreds[i].Handle.dwLower,
  2206. AuthPackageList[Index]->LsaPackage->Name.Buffer ));
  2207. } else {
  2208. DebugLog((DEB_TRACE_NEG, " Skipped %p:%p, %ws (duplicate)\n",
  2209. pCreds[i].Handle.dwUpper, pCreds[i].Handle.dwLower,
  2210. AuthPackageList[Index]->LsaPackage->Name.Buffer ));
  2211. }
  2212. #ifdef WIN32_CHICAGO
  2213. if ( Expiry < MinExpiry )
  2214. {
  2215. MinExpiry = Expiry ;
  2216. }
  2217. #else
  2218. if ( Expiry.QuadPart < MinExpiry.QuadPart )
  2219. {
  2220. MinExpiry.QuadPart = Expiry.QuadPart ;
  2221. }
  2222. #endif
  2223. pCreds[i].Package = AuthPackageList[Index];
  2224. i++;
  2225. }
  2226. else
  2227. {
  2228. DebugLog((DEB_TRACE_NEG, "Failed %x to get a cred handle for %ws\n",
  2229. scRet, AuthPackageList[Index]->LsaPackage->Name.Buffer ));
  2230. }
  2231. }
  2232. NegUnlockList();
  2233. if ( i == 0 )
  2234. {
  2235. //
  2236. // Did not get any subordinate credentials, return an error now
  2237. //
  2238. scRet = SEC_E_NO_CREDENTIALS;
  2239. goto Cleanup;
  2240. }
  2241. //
  2242. // Now, allocate our cred structure, and copy all the found cred handles
  2243. // into it.
  2244. //
  2245. pNegCreds = (PNEG_CREDS) LsapAllocateLsaHeap( sizeof( NEG_CREDS ) +
  2246. sizeof( NEG_CRED_HANDLE ) * ( i - ANYSIZE_ARRAY ) );
  2247. if ( pNegCreds == NULL)
  2248. {
  2249. scRet = SEC_E_INSUFFICIENT_MEMORY;
  2250. goto Cleanup;
  2251. }
  2252. FreeCreds = TRUE ;
  2253. pNegCreds->Count = i;
  2254. pNegCreds->Flags = 0 ;
  2255. pNegCreds->Tag = NEGCRED_TAG ;
  2256. pNegCreds->DefaultPackage = ClientDefaultPackage;
  2257. if ( fCredentials & NEGOTIATE_ALLOW_NTLM )
  2258. {
  2259. pNegCreds->Flags |= NEGCRED_ALLOW_NTLM ;
  2260. }
  2261. if ( fCredentials & NEGOTIATE_NEG_NTLM )
  2262. {
  2263. pNegCreds->Flags |= NEGCRED_NEG_NTLM ;
  2264. }
  2265. #ifndef WIN32_CHICAGO
  2266. //
  2267. // WARNING: Change to w2k behavior. Enabling loopback detection
  2268. // to switch to NTLM
  2269. //
  2270. if ( EnableLoopback )
  2271. {
  2272. pNegCreds->Flags |= NEGCRED_NTLM_LOOPBACK ;
  2273. }
  2274. pNegCreds->ClientLogonId = *ClientLogonId ;
  2275. #endif
  2276. InitializeListHead( &pNegCreds->AdditionalCreds );
  2277. pNegCreds->ClientProcessId = ClientInfo.ProcessID;
  2278. pNegCreds->Expiry = MinExpiry ;
  2279. RtlCopyMemory(
  2280. pNegCreds->Creds,
  2281. pCreds,
  2282. i * sizeof( NEG_CRED_HANDLE ) );
  2283. #ifndef WIN32_CHICAGO
  2284. if ( ( CallInfo->CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) != 0 )
  2285. {
  2286. pNegCreds->Flags |= NEGCRED_KERNEL_CALLER ;
  2287. }
  2288. #endif
  2289. if ( ExplicitCreds )
  2290. {
  2291. pNegCreds->Flags |= NEGCRED_EXPLICIT_CREDS ;
  2292. if( DomainExplicitCreds )
  2293. {
  2294. pNegCreds->Flags |= NEGCRED_DOMAIN_EXPLICIT_CREDS ;
  2295. }
  2296. }
  2297. //
  2298. // If this isn't a duplicate, return
  2299. // a new credential
  2300. //
  2301. if (!NegpCheckForDuplicateCreds(
  2302. &pNegCreds
  2303. ))
  2304. {
  2305. //
  2306. // Finish creating the credential
  2307. //
  2308. scRet = RtlInitializeCriticalSection( &pNegCreds->CredLock );
  2309. if ( !NT_SUCCESS( scRet ) )
  2310. {
  2311. goto Cleanup ;
  2312. }
  2313. pNegCreds->RefCount = 1;
  2314. if ( ( fCredentials & NEG_CRED_DONT_LINK ) == 0 )
  2315. {
  2316. NegWriteLockCredList();
  2317. InsertTailList( &NegCredList,
  2318. &pNegCreds->List );
  2319. NegUnlockCredList();
  2320. }
  2321. }
  2322. *pdwHandle = (ULONG_PTR) pNegCreds ;
  2323. *ptsExpiry = pNegCreds->Expiry;
  2324. scRet = SEC_E_OK;
  2325. FreeCreds = FALSE ;
  2326. Cleanup:
  2327. if (!NT_SUCCESS(scRet))
  2328. {
  2329. //
  2330. // Free all the handles. Because the WLsa calls set the package
  2331. // ID make sure we always reset it.
  2332. //
  2333. PackageId = GetCurrentPackageId();
  2334. while ( i-- )
  2335. {
  2336. #ifndef WIN32_CHICAGO
  2337. if( (pCreds[i].Flags & NEG_CREDHANDLE_EXTRA_OID) == 0 )
  2338. {
  2339. WLsaFreeCredHandle( &pCreds[i].Handle );
  2340. }
  2341. #else
  2342. FreeCredentialsHandle( &pCreds[i].Handle );
  2343. #endif // WIN32_CHICAGO
  2344. SetCurrentPackageId( PackageId );
  2345. }
  2346. }
  2347. if ( FreeCreds )
  2348. {
  2349. if ( pNegCreds )
  2350. {
  2351. LsapFreeLsaHeap( pNegCreds );
  2352. }
  2353. }
  2354. if ( (pCreds != NULL ) &&
  2355. (pCreds != Creds ) )
  2356. {
  2357. LsapFreePrivateHeap( pCreds );
  2358. }
  2359. if (AuthPackageList != NULL)
  2360. {
  2361. LsapFreeLsaHeap(AuthPackageList);
  2362. }
  2363. DsysAssert( NegLogonSession == NULL );
  2364. DebugLog(( DEB_TRACE_NEG, "NegAcquireCredentialsHandle: returned 0x%x\n", scRet));
  2365. return(scRet);
  2366. }
  2367. //+---------------------------------------------------------------------------
  2368. //
  2369. // Function: NegAcquireCredentialsHandle
  2370. //
  2371. // Synopsis: Acquire a Negotiate credential handle
  2372. //
  2373. // Arguments: [psPrincipal] --
  2374. // [fCredentials] --
  2375. // [pLogonID] --
  2376. // [pvAuthData] --
  2377. // [pvGetKeyFn] --
  2378. // [pvGetKeyArgument] --
  2379. // [pdwHandle] --
  2380. // [ptsExpiry] --
  2381. //
  2382. // Requires:
  2383. //
  2384. // Returns:
  2385. //
  2386. // Signals:
  2387. //
  2388. // Modifies:
  2389. //
  2390. // Algorithm:
  2391. //
  2392. // History: 7-26-96 RichardW Created
  2393. //
  2394. // Notes:
  2395. //
  2396. //----------------------------------------------------------------------------
  2397. SECURITY_STATUS SEC_ENTRY
  2398. NegAcquireCredentialsHandle(
  2399. PSECURITY_STRING psPrincipal,
  2400. ULONG fCredentials,
  2401. PLUID pLogonID,
  2402. PVOID pvAuthData,
  2403. PVOID pvGetKeyFn,
  2404. PVOID pvGetKeyArgument,
  2405. PULONG_PTR pdwHandle,
  2406. PTimeStamp ptsExpiry)
  2407. {
  2408. return NegpAcquireCredHandle(
  2409. psPrincipal,
  2410. fCredentials,
  2411. pLogonID,
  2412. pvAuthData,
  2413. pvGetKeyFn,
  2414. pvGetKeyArgument,
  2415. pdwHandle,
  2416. ptsExpiry );
  2417. }
  2418. //+---------------------------------------------------------------------------
  2419. //
  2420. // Function: SpQueryCredentialsAttributes
  2421. //
  2422. // Synopsis: Implements QueryCredentialsAttributes by passing off to the
  2423. // first package that we got a cred handle from.
  2424. //
  2425. // Arguments: [dwCredHandle] --
  2426. // [dwAttribute] --
  2427. // [Buffer] --
  2428. //
  2429. // History: 9-17-96 RichardW Created
  2430. //
  2431. // Notes:
  2432. //
  2433. //----------------------------------------------------------------------------
  2434. SECURITY_STATUS
  2435. NegQueryCredentialsAttributes(
  2436. LSA_SEC_HANDLE dwCredHandle,
  2437. ULONG dwAttribute,
  2438. PVOID Buffer)
  2439. {
  2440. PNEG_CREDS Creds;
  2441. SECURITY_STATUS Status;
  2442. ULONG_PTR PackageId ;
  2443. CredHandle TempCredHandle;
  2444. Creds = (PNEG_CREDS) dwCredHandle ;
  2445. NegReadLockCreds( Creds );
  2446. TempCredHandle = Creds->Creds[0].Handle;
  2447. NegUnlockCreds( Creds );
  2448. PackageId = GetCurrentPackageId();
  2449. #ifndef WIN32_CHICAGO
  2450. Status = WLsaQueryCredAttributes(
  2451. &TempCredHandle,
  2452. dwAttribute,
  2453. Buffer );
  2454. #else // WIN32_CHICAGO
  2455. Status = QueryCredentialsAttributes(
  2456. &TempCredHandle,
  2457. dwAttribute,
  2458. Buffer );
  2459. #endif // WIN32_CHICAGO
  2460. SetCurrentPackageId( PackageId );
  2461. return( Status );
  2462. }
  2463. //+---------------------------------------------------------------------------
  2464. //
  2465. // Function: NegpReleaseCreds
  2466. //
  2467. // Synopsis: Releases credential storage when ref count goes to zero
  2468. //
  2469. // Arguments: [pCreds] --
  2470. //
  2471. // History: 8-12-96 RichardW Created
  2472. //
  2473. // Notes:
  2474. //
  2475. //----------------------------------------------------------------------------
  2476. VOID
  2477. NegpReleaseCreds(
  2478. PNEG_CREDS pCreds,
  2479. BOOLEAN CleanupCall
  2480. )
  2481. {
  2482. BOOL NoLock = FALSE ;
  2483. //
  2484. // Remove it from the list:
  2485. //
  2486. if ( pCreds->List.Flink )
  2487. {
  2488. RemoveEntryList( &pCreds->List );
  2489. DebugLog(( DEB_TRACE_NEG, "Releasing credentials %p\n", pCreds ));
  2490. }
  2491. else
  2492. {
  2493. NoLock = TRUE ;
  2494. DebugLog(( DEB_TRACE_NEG, "Releasing credentials %p (dups or lockless)\n", pCreds ));
  2495. }
  2496. #ifndef WIN32_CHICAGO
  2497. if ( pCreds->Flags & NEGCRED_MULTI )
  2498. {
  2499. while ( !IsListEmpty( &pCreds->AdditionalCreds ) )
  2500. {
  2501. PLIST_ENTRY Scan ;
  2502. PNEG_CREDS AltCreds ;
  2503. Scan = RemoveHeadList( &pCreds->AdditionalCreds );
  2504. AltCreds = CONTAINING_RECORD( Scan, NEG_CREDS, List );
  2505. NegFreeCredentialsHandle((ULONG_PTR) AltCreds);
  2506. }
  2507. }
  2508. #endif // WIN32_CHICAGO
  2509. if ( !NoLock )
  2510. {
  2511. NegUnlockCreds( pCreds );
  2512. RtlDeleteCriticalSection( &pCreds->CredLock );
  2513. }
  2514. //
  2515. // free the embedded package creds.
  2516. //
  2517. if( !CleanupCall )
  2518. {
  2519. ULONG_PTR PackageId;
  2520. DWORD i;
  2521. //
  2522. // Free all associated handles:
  2523. //
  2524. i = pCreds->Count;
  2525. PackageId = GetCurrentPackageId();
  2526. while ( i-- )
  2527. {
  2528. if (((pCreds->Creds[i].Flags & NEG_CREDHANDLE_EXTRA_OID) == 0) &&
  2529. (pCreds->Creds[i].Handle.dwLower != 0) &&
  2530. (pCreds->Creds[i].Handle.dwLower != SPMGR_PKG_ID ) )
  2531. {
  2532. #ifndef WIN32_CHICAGO
  2533. NTSTATUS scRet;
  2534. scRet = WLsaFreeCredHandle( &pCreds->Creds[i].Handle );
  2535. if( !NT_SUCCESS(scRet) )
  2536. {
  2537. DebugLog(( DEB_ERROR, "Failed freeing credential %p:%p %x\n",
  2538. pCreds->Creds[i].Handle.dwUpper,
  2539. pCreds->Creds[i].Handle.dwLower,
  2540. scRet ));
  2541. //DsysAssert( NT_SUCCESS(scRet) );
  2542. }
  2543. #else // WIN32_CHICAGO
  2544. FreeCredentialsHandle( &pCreds->Creds[i].Handle );
  2545. #endif // WIN32_CHICAGO
  2546. }
  2547. SetCurrentPackageId( PackageId );
  2548. }
  2549. }
  2550. LsapFreeLsaHeap( pCreds );
  2551. }
  2552. //+---------------------------------------------------------------------------
  2553. //
  2554. // Function: NegFreeCredentialsHandle
  2555. //
  2556. // Synopsis: Release a negotiate cred handle
  2557. //
  2558. // Arguments: [dwHandle] --
  2559. //
  2560. // History: 7-26-96 RichardW Created
  2561. //
  2562. // Notes:
  2563. //
  2564. //----------------------------------------------------------------------------
  2565. SECURITY_STATUS
  2566. SEC_ENTRY
  2567. NegFreeCredentialsHandle(
  2568. LSA_SEC_HANDLE dwHandle
  2569. )
  2570. {
  2571. PNEG_CREDS pCreds;
  2572. ULONG DereferenceCount = 1;
  2573. BOOLEAN CleanupCall = FALSE;
  2574. #ifndef WIN32_CHICAGO
  2575. SECPKG_CALL_INFO CallInfo;
  2576. if(LsapGetCallInfo(&CallInfo))
  2577. {
  2578. //
  2579. // nego internally calls NegFreeCredentialsHandle, so, insure
  2580. // the refcount is always non-zero.
  2581. // realistically speaking, the callcount is only > 1 on cleanup
  2582. // disposition, but there is no reason to potentially destabilize
  2583. // this already tenuous issue.
  2584. //
  2585. if( CallInfo.CallCount )
  2586. {
  2587. DereferenceCount = CallInfo.CallCount;
  2588. }
  2589. CleanupCall = ( (CallInfo.Attributes & SECPKG_CALL_CLEANUP) != 0 );
  2590. }
  2591. #endif
  2592. pCreds = (PNEG_CREDS) dwHandle ;
  2593. NegWriteLockCreds( pCreds );
  2594. ASSERT( pCreds->RefCount >= DereferenceCount );
  2595. pCreds->RefCount -= DereferenceCount;
  2596. if ( pCreds->RefCount == 0 )
  2597. {
  2598. NegUnlockCreds( pCreds );
  2599. NegWriteLockCredList();
  2600. NegWriteLockCreds( pCreds );
  2601. if( pCreds->RefCount == 0 )
  2602. {
  2603. NegpReleaseCreds( pCreds, CleanupCall );
  2604. } else {
  2605. NegUnlockCreds( pCreds );
  2606. }
  2607. NegUnlockCredList();
  2608. }
  2609. else
  2610. {
  2611. NegUnlockCreds( pCreds );
  2612. }
  2613. return( SEC_E_OK );
  2614. }
  2615. //+---------------------------------------------------------------------------
  2616. //
  2617. // Function: NegpCreateContext
  2618. //
  2619. // Synopsis: Creates and zeroes a context
  2620. //
  2621. // Arguments: (none)
  2622. //
  2623. // History: 10-05-96 RichardW Created
  2624. //
  2625. // Notes:
  2626. //
  2627. //----------------------------------------------------------------------------
  2628. PNEG_CONTEXT
  2629. NegpCreateContext(
  2630. VOID
  2631. )
  2632. {
  2633. PNEG_CONTEXT Context ;
  2634. Context = (PNEG_CONTEXT) LsapAllocatePrivateHeap( sizeof( NEG_CONTEXT ) );
  2635. if ( Context )
  2636. {
  2637. ZeroMemory( Context, sizeof( NEG_CONTEXT ) );
  2638. Context->CheckMark = NEGCONTEXT_CHECK ;
  2639. Context->Flags |= NEG_CONTEXT_UPLEVEL ;
  2640. }
  2641. return( Context );
  2642. }
  2643. //+---------------------------------------------------------------------------
  2644. //
  2645. // Function: NegpDeleteContext
  2646. //
  2647. // Synopsis: Free the data behind a context
  2648. //
  2649. // Arguments: [Context] --
  2650. //
  2651. // History: 10-05-96 RichardW Created
  2652. //
  2653. // Notes:
  2654. //
  2655. //----------------------------------------------------------------------------
  2656. VOID
  2657. NegpDeleteContext(
  2658. PNEG_CONTEXT Context
  2659. )
  2660. {
  2661. ULONG_PTR PackageId;
  2662. if ( !Context )
  2663. {
  2664. return ;
  2665. }
  2666. DsysAssert( Context->CheckMark == NEGCONTEXT_CHECK );
  2667. if (Context->CheckMark != NEGCONTEXT_CHECK )
  2668. {
  2669. return;
  2670. }
  2671. if ( Context->Target.Buffer )
  2672. {
  2673. LsapFreePrivateHeap( Context->Target.Buffer );
  2674. }
  2675. if ( Context->Check && Context->Buffer )
  2676. {
  2677. Context->Check->Finish( & Context->Buffer );
  2678. }
  2679. if ( Context->MappedBuffer.pvBuffer != NULL)
  2680. {
  2681. LsapFreeLsaHeap(
  2682. Context->MappedBuffer.pvBuffer
  2683. );
  2684. }
  2685. if ( Context->Message )
  2686. {
  2687. LsapFreeLsaHeap( Context->Message );
  2688. }
  2689. if ( ( Context->Handle.dwLower != 0 ) &&
  2690. ( Context->Handle.dwLower != SPMGR_PKG_ID ) )
  2691. {
  2692. PackageId = GetCurrentPackageId();
  2693. #ifdef WIN32_CHICAGO
  2694. DeleteSecurityContext( &Context->Handle );
  2695. #else
  2696. WLsaDeleteContext( &Context->Handle );
  2697. #endif
  2698. SetCurrentPackageId(PackageId);
  2699. }
  2700. //
  2701. // If we referenced the credential, free it now.
  2702. //
  2703. if (Context->Creds != NULL)
  2704. {
  2705. NegFreeCredentialsHandle((ULONG_PTR) Context->Creds);
  2706. }
  2707. if (Context->SupportedMechs != NULL)
  2708. {
  2709. if ((Context->Flags & NEG_CONTEXT_FREE_EACH_MECH))
  2710. {
  2711. NegpFreeMechList(Context->SupportedMechs);
  2712. }
  2713. else
  2714. {
  2715. LsapFreeLsaHeap(Context->SupportedMechs);
  2716. }
  2717. }
  2718. DebugLog(( DEB_TRACE_NEG, "Deleting context %x\n", Context ));
  2719. LsapFreePrivateHeap( Context );
  2720. }
  2721. //+---------------------------------------------------------------------------
  2722. //
  2723. // Function: NegpFindPackageForOid
  2724. //
  2725. // Synopsis: Returns index for a package matching the OID passed in
  2726. //
  2727. // Arguments: [Creds] --
  2728. // [Oid] --
  2729. //
  2730. // History: 9-25-96 RichardW Created
  2731. //
  2732. // Notes:
  2733. //
  2734. //----------------------------------------------------------------------------
  2735. ULONG_PTR
  2736. NegpFindPackageForOid(
  2737. PNEG_CREDS Creds,
  2738. ObjectID Oid)
  2739. {
  2740. ULONG i;
  2741. NegDumpOid( "Compare Mechanism", Oid );
  2742. for ( i = 0 ; i < Creds->Count ; i++ )
  2743. {
  2744. if ( NegpCompareOid( Oid,
  2745. Creds->Creds[i].Package->ObjectId ) == 0 )
  2746. {
  2747. return( i );
  2748. }
  2749. }
  2750. return( NEG_INVALID_PACKAGE );
  2751. }
  2752. //+---------------------------------------------------------------------------
  2753. //
  2754. // Function: NegBuildRequestToken
  2755. //
  2756. // Synopsis: Generates a NegotiateRequest token, for either client or server
  2757. // side inits. Generates a NEG_CONTEXT and the token to be sent
  2758. // to the other side.
  2759. //
  2760. // Effects: Lots of work
  2761. //
  2762. // Arguments: [ServerSideInit] --
  2763. // [Creds] --
  2764. // [pszTargetName] --
  2765. // [fContextReq] --
  2766. // [TargetDataRep] --
  2767. // [ServerMechs] --
  2768. // [pContext] --
  2769. // [pOutput] --
  2770. //
  2771. // History: 9-30-96 RichardW Created
  2772. //
  2773. // Notes:
  2774. //
  2775. //----------------------------------------------------------------------------
  2776. SECURITY_STATUS
  2777. NegBuildRequestToken(
  2778. IN BOOL ServerSideInit,
  2779. IN PNEG_CREDS Creds,
  2780. IN PSECURITY_STRING pszTargetName,
  2781. IN ULONG fContextReq,
  2782. IN ULONG TargetDataRep,
  2783. IN struct MechTypeList *ServerMechs,
  2784. IN PSECURITY_STRING NegotiateHint,
  2785. OUT PNEG_CONTEXT * pContext,
  2786. OUT PSecBufferDesc pOutput,
  2787. PTimeStamp ptsExpiry)
  2788. {
  2789. InitialNegToken Request ;
  2790. SECURITY_STATUS scRet ;
  2791. SECURITY_STATUS scRetPrior = STATUS_SUCCESS;
  2792. struct MechTypeList CommonMechs[ NEG_MECH_LIMIT ];
  2793. struct MechTypeList *MechList = CommonMechs;
  2794. ULONG MatchingPackages[ NEG_MECH_LIMIT ];
  2795. struct MechTypeList *pMechs ;
  2796. struct MechTypeList *SourceMechs = NULL;
  2797. PVOID SourceMechsToFree = NULL ;
  2798. ULONG MechCount ;
  2799. ULONG i ;
  2800. ULONG_PTR CredIndex ;
  2801. PNEG_CONTEXT Context = NULL ;
  2802. PSession pSession ;
  2803. SecPkgCredentials_NamesW Names ;
  2804. DWORD NameLength ;
  2805. ANSI_STRING NarrowName = {0};
  2806. PSession pClientClone ;
  2807. ULONG_PTR PackageId ;
  2808. PNEG_PACKAGE Package ;
  2809. SecBuffer DesiredToken = { 0 } ;
  2810. SecBuffer InputBuffer ;
  2811. SecBufferDesc DTDescription ;
  2812. SecBufferDesc DTInput ;
  2813. SecBufferDesc NullInput = { 0 };
  2814. PSecBuffer pToken ;
  2815. CtxtHandle InitialHandle ;
  2816. ASN1octetstring_t EncodedData = {0};
  2817. int Result ;
  2818. ULONG PackageReq = 0 ;
  2819. BOOL DirectSecurityPacket = FALSE ;
  2820. BOOL UseHint = FALSE ;
  2821. BOOL HintPresent = FALSE ;
  2822. ULONG PackageReqFlags ;
  2823. BOOL BufferSizeReset = FALSE ;
  2824. BOOL OrderByMech = FALSE ;
  2825. BOOL MechListReordered = FALSE ;
  2826. CredHandle TempCredHandle;
  2827. PNEG_PACKAGE LastPackage = NULL ;
  2828. #ifndef WIN32_CHICAGO
  2829. PLSA_CALL_INFO CallInfo ;
  2830. #endif
  2831. //
  2832. // Make sure there is an output buffer
  2833. //
  2834. scRet = NegpParseBuffers( pOutput, TRUE, &pToken, NULL );
  2835. if ( !NT_SUCCESS( scRet ) )
  2836. {
  2837. DebugLog(( DEB_ERROR, "Failed to map buffers, %x\n", scRet ));
  2838. goto Cleanup ;
  2839. }
  2840. //
  2841. // If there is no output buffer, fail now
  2842. //
  2843. if (pToken == NULL)
  2844. {
  2845. DebugLog((DEB_TRACE_NEG,"No output token for NegBuildRequestToken\n"));
  2846. scRet = SEC_E_INVALID_TOKEN;
  2847. goto Cleanup;
  2848. }
  2849. #ifndef WIN32_CHICAGO
  2850. CallInfo = LsapGetCurrentCall();
  2851. if ( !ServerSideInit )
  2852. {
  2853. if ( CallInfo->CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE )
  2854. {
  2855. //
  2856. // Mask off the mutual bit for now
  2857. //
  2858. PackageReq = NegGetPackageCaps( fContextReq & (~(ISC_REQ_MUTUAL_AUTH)) );
  2859. }
  2860. else
  2861. {
  2862. PackageReq = NegGetPackageCaps( fContextReq );
  2863. }
  2864. }
  2865. else
  2866. {
  2867. PackageReq = 0xFFFFFFFF ;
  2868. }
  2869. #else
  2870. PackageReq = NegGetPackageCaps( fContextReq );
  2871. #endif
  2872. //
  2873. // First, gather up the mechanisms that the other guys supports. If
  2874. // we don't know, assume all of ours:
  2875. //
  2876. if ( ServerMechs )
  2877. {
  2878. SourceMechs = ServerMechs ;
  2879. }
  2880. else
  2881. {
  2882. scRet = NegpBuildMechListFromCreds(
  2883. Creds,
  2884. PackageReq,
  2885. (ServerSideInit ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND ),
  2886. &SourceMechs );
  2887. if ( !NT_SUCCESS(scRet) )
  2888. {
  2889. return( scRet );
  2890. }
  2891. //
  2892. // Save a copy of this pointer. The list may be rearranged later, but
  2893. // we need to free this "original" pointer.
  2894. //
  2895. SourceMechsToFree = SourceMechs ;
  2896. }
  2897. //
  2898. // Initialize some pointers so we know if we need to free anything.
  2899. //
  2900. DesiredToken.pvBuffer = NULL ;
  2901. Context = NULL ;
  2902. //
  2903. // if we're honoring server hints, then go by the mech list
  2904. //
  2905. OrderByMech = ( ( NegOptions & NEGOPT_HONOR_SERVER_PREF ) != 0 );
  2906. #ifndef WIN32_CHICAGO
  2907. //
  2908. // Special case the local loopback to use NTLM. Analyze the target name. If it
  2909. // is an SPN, and it is our hostname in there, rearrange the mech list to put
  2910. // NTLM first (note, for local case, NTLM will essentially dup the token). This
  2911. // function cannot fail.
  2912. //
  2913. if ( ((Creds->Flags & NEGCRED_NTLM_LOOPBACK) != 0)
  2914. #if 0
  2915. && ((Creds->Flags & NEGCRED_EXPLICIT_CREDS) == 0)
  2916. #endif
  2917. )
  2918. {
  2919. if ( NegpRearrangeMechsIfNeccessary( &SourceMechs, pszTargetName, &DirectSecurityPacket ) )
  2920. {
  2921. OrderByMech = TRUE ;
  2922. MechListReordered = TRUE ;
  2923. }
  2924. }
  2925. #endif
  2926. //
  2927. // Scan through the list, building up the list of common mechanisms.
  2928. // Also, maintain a count, and determine the first matching package to
  2929. // generate our desired token. Depending on local configuration, we
  2930. // will either honor the server's preferences, or our own.
  2931. //
  2932. pMechs = SourceMechs ;
  2933. MechCount = 0;
  2934. NegReadLockCreds( Creds );
  2935. //
  2936. // BUGUG: check for supported options for the context requirements.
  2937. //
  2938. if ( OrderByMech )
  2939. {
  2940. //
  2941. // Walk the server list first.
  2942. //
  2943. while ( pMechs )
  2944. {
  2945. CredIndex = NegpFindPackageForOid( Creds, pMechs->value );
  2946. if ( CredIndex != NEG_INVALID_PACKAGE )
  2947. {
  2948. CommonMechs[ MechCount ].value =
  2949. Creds->Creds[ CredIndex ].Package->ObjectId ;
  2950. CommonMechs[ MechCount ].next = &CommonMechs[ MechCount + 1 ];
  2951. MatchingPackages[ MechCount] = (ULONG) CredIndex;
  2952. MechCount ++ ;
  2953. if (MechCount == NEG_MECH_LIMIT)
  2954. {
  2955. break;
  2956. }
  2957. }
  2958. pMechs = pMechs->next ;
  2959. }
  2960. }
  2961. else
  2962. {
  2963. //
  2964. // Walk the local cred list first:
  2965. //
  2966. for ( i = 0 ; i < Creds->Count ; i++ )
  2967. {
  2968. pMechs = SourceMechs ;
  2969. while ( pMechs )
  2970. {
  2971. if ( NegpCompareOid( pMechs->value,
  2972. Creds->Creds[ i ].Package->ObjectId ) == 0 )
  2973. {
  2974. CommonMechs[ MechCount ].value =
  2975. Creds->Creds[ i ].Package->ObjectId ;
  2976. CommonMechs[ MechCount ].next = &CommonMechs[ MechCount + 1 ];
  2977. MatchingPackages[ MechCount] = i;
  2978. MechCount++;
  2979. break;
  2980. }
  2981. //
  2982. // Note: Right now, the limit on protocols is 16. We may need to
  2983. // increase that.
  2984. //
  2985. if (MechCount == NEG_MECH_LIMIT)
  2986. {
  2987. break;
  2988. }
  2989. pMechs = pMechs->next ;
  2990. }
  2991. }
  2992. }
  2993. //
  2994. // Ok, at this point, we have the desired security package (cred handle)
  2995. // in MatchingPackage, MechCount contains the number of mechs in common.
  2996. //
  2997. // Note: These can be zero, that is that we have no mechs in common.
  2998. //
  2999. NegUnlockCreds( Creds );
  3000. if ( MechCount == 0 )
  3001. {
  3002. //
  3003. // No common packages:
  3004. //
  3005. DebugLog(( DEB_TRACE_NEG, "No common packages\n"));
  3006. scRet = SEC_E_INVALID_TOKEN ;
  3007. goto Cleanup ;
  3008. }
  3009. //
  3010. // Patch up list:
  3011. //
  3012. CommonMechs[ MechCount - 1 ].next = NULL ;
  3013. //
  3014. // Start assembling request token:
  3015. //
  3016. ZeroMemory( &Request, sizeof( Request ) );
  3017. //
  3018. // Create the negotiate context
  3019. //
  3020. Context = NegpCreateContext() ;
  3021. if ( !Context )
  3022. {
  3023. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  3024. goto Cleanup ;
  3025. }
  3026. if ( !ServerSideInit )
  3027. {
  3028. //
  3029. // Store target name away
  3030. //
  3031. scRet = LsapDuplicateString2( &Context->Target, pszTargetName );
  3032. if ( !NT_SUCCESS( scRet ) )
  3033. {
  3034. goto Cleanup ;
  3035. }
  3036. //
  3037. // Use the supplied mechs. If these were passed from the server,
  3038. // make sure we don't free them before using them.
  3039. //
  3040. if ( Context->SupportedMechs )
  3041. {
  3042. DebugLog((DEB_TRACE_NEG, "Context %p already has MechList ?\n", Context ));
  3043. }
  3044. if ( ( SourceMechs == ServerMechs ) ||
  3045. ( MechListReordered ) )
  3046. {
  3047. Context->SupportedMechs = NegpCopyMechList(MechList);
  3048. if (Context->SupportedMechs == NULL)
  3049. {
  3050. scRet = SEC_E_INSUFFICIENT_MEMORY;
  3051. goto Cleanup;
  3052. }
  3053. Context->Flags |= NEG_CONTEXT_FREE_EACH_MECH;
  3054. }
  3055. else
  3056. {
  3057. Context->SupportedMechs = SourceMechs;
  3058. SourceMechs = NULL;
  3059. }
  3060. if ( fContextReq & ISC_REQ_MUTUAL_AUTH )
  3061. {
  3062. Context->Flags |= NEG_CONTEXT_MUTUAL_AUTH ;
  3063. }
  3064. }
  3065. if (Context->Creds == NULL)
  3066. {
  3067. Context->Creds = Creds ;
  3068. //
  3069. // Reference the credentials so they don't go away unexpectedly
  3070. //
  3071. NegWriteLockCreds(Creds);
  3072. Creds->RefCount++;
  3073. NegUnlockCreds(Creds);
  3074. }
  3075. PackageReqFlags = fContextReq | ISC_REQ_MUTUAL_AUTH ;
  3076. PackageReqFlags &= (~(ISC_REQ_ALLOCATE_MEMORY ));
  3077. i = 0;
  3078. do
  3079. {
  3080. UseHint = FALSE ;
  3081. HintPresent = FALSE ;
  3082. Context->CredIndex = MatchingPackages[i] ;
  3083. NegReadLockCreds( Creds );
  3084. Package = Creds->Creds[ MatchingPackages[i] ].Package ;
  3085. #ifndef WIN32_CHICAGO
  3086. if ( NegNegotiationControl < NEG_NEGLEVEL_NO_DOWNGRADE )
  3087. {
  3088. //
  3089. // If we're allowing downgrade, if the next package is
  3090. // the NT4 compatibility package, and we are not
  3091. // responding to a server list of mechs, and we haven't
  3092. // reordered the list specifically to use NTLM for loopback,
  3093. // go direct
  3094. //
  3095. if ( ( (Package->Flags & NEG_NT4_COMPAT ) != 0 ) &&
  3096. ( ServerMechs == NULL ) &&
  3097. ( (Creds->Flags & NEGCRED_NEG_NTLM ) == 0 ) &&
  3098. ( !MechListReordered ) )
  3099. {
  3100. DebugLog(( DEB_TRACE_NEG, "Dropping back to pure NTLM\n" ));
  3101. DirectSecurityPacket = TRUE ;
  3102. }
  3103. }
  3104. #endif // WIN32_CHICAGO
  3105. //
  3106. // Now, divergent behavior. For a server side request token, we need to
  3107. // grab some hint data. On a client side request, we ping the desired
  3108. // mechanism to generate a "hopeful" blob for the server.
  3109. //
  3110. if ( ServerSideInit )
  3111. {
  3112. NTSTATUS TempStatus;
  3113. if ( Creds->ServerBufferLength == 0 )
  3114. {
  3115. DebugLog(( DEB_TRACE_NEG, "Gathering up server name for hint\n" ));
  3116. //
  3117. // We need to query credential handle 0 to find out
  3118. // what the name of the person is, so that we can send it
  3119. // back in the hints. However, just calling querycredattributes
  3120. // would make the package write the data to the client process,
  3121. // when we need it here. So, we swap out our session, and substitute
  3122. // a clone of the client session, with the INPROC flag set. The
  3123. // helpers will check for this flag, and do a little dance to
  3124. // keep the memory local.
  3125. //
  3126. #ifndef WIN32_CHICAGO
  3127. pSession = GetCurrentSession();
  3128. TempStatus = CloneSession( pSession, &pClientClone, SESFLAG_INPROC );
  3129. //
  3130. // WARNING: This code block has the braces only in NT builds, not
  3131. // in Win9x builds. Balance them carefully if you modify this portion.
  3132. //
  3133. if ( NT_SUCCESS( TempStatus ) )
  3134. {
  3135. SpmpReferenceSession( pClientClone );
  3136. SetCurrentSession( pClientClone );
  3137. PackageId = GetCurrentPackageId();
  3138. #endif // WIN32_CHICAGO
  3139. //
  3140. // Make a copy of the handle because we can't hold a lock
  3141. // while calling outside the Negotiate package.
  3142. //
  3143. TempCredHandle = Creds->Creds[0].Handle;
  3144. NegUnlockCreds(Creds);
  3145. #ifndef WIN32_CHICAGO
  3146. TempStatus = WLsaQueryCredAttributes(
  3147. &TempCredHandle,
  3148. SECPKG_CRED_ATTR_NAMES,
  3149. &Names );
  3150. #else
  3151. TempStatus = QueryCredentialsAttributes(
  3152. &TempCredHandle,
  3153. SECPKG_CRED_ATTR_NAMES,
  3154. &Names );
  3155. #endif // WIN32_CHICAGO
  3156. SetCurrentPackageId( PackageId );
  3157. NegReadLockCreds( Creds);
  3158. if ( NT_SUCCESS( TempStatus ) )
  3159. {
  3160. UNICODE_STRING TempString;
  3161. RtlInitUnicodeString(
  3162. &TempString,
  3163. Names.sUserName
  3164. );
  3165. TempStatus = RtlUnicodeStringToAnsiString(
  3166. &NarrowName,
  3167. &TempString,
  3168. TRUE // allocate destination
  3169. );
  3170. if (NT_SUCCESS(TempStatus))
  3171. {
  3172. Request.negToken.u.negTokenInit.bit_mask |= NegTokenInit_negHints_present ;
  3173. Request.negToken.u.negTokenInit.negHints.hintName = NarrowName.Buffer ;
  3174. Request.negToken.u.negTokenInit.negHints.bit_mask |= hintName_present;
  3175. }
  3176. LsapFreeLsaHeap( Names.sUserName );
  3177. }
  3178. //
  3179. // Ignore failures from above because it was really only a hint.
  3180. //
  3181. scRet = STATUS_SUCCESS;
  3182. #ifndef WIN32_CHICAGO
  3183. SetCurrentSession( pSession );
  3184. //
  3185. // Deref and clean up clone session
  3186. //
  3187. SpmpDereferenceSession( pClientClone );
  3188. }
  3189. #endif // WIN32_CHICAGO
  3190. }
  3191. NegUnlockCreds( Creds );
  3192. }
  3193. else
  3194. {
  3195. CredHandle TempCredHandle;
  3196. //
  3197. // Make a copy of the handle because we can't hold a lock
  3198. // while calling outside the Negotiate package.
  3199. //
  3200. TempCredHandle = Creds->Creds[0].Handle;
  3201. NegUnlockCreds(Creds);
  3202. //
  3203. // Client side call. Here, we call down to the desired package,
  3204. // and have it generate a blob to be encoded and sent over to the
  3205. // server.
  3206. //
  3207. if ( DesiredToken.pvBuffer )
  3208. {
  3209. //
  3210. // If we're coming through this loop again, free the current buffer
  3211. // and allocate one of appropriate size for the current package.
  3212. //
  3213. LsapFreeLsaHeap( DesiredToken.pvBuffer );
  3214. }
  3215. DesiredToken.pvBuffer = LsapAllocateLsaHeap( Package->TokenSize );
  3216. if (DesiredToken.pvBuffer == NULL)
  3217. {
  3218. scRet = SEC_E_INSUFFICIENT_MEMORY;
  3219. goto Cleanup;
  3220. }
  3221. DesiredToken.cbBuffer = Package->TokenSize ;
  3222. DesiredToken.BufferType = SECBUFFER_TOKEN ;
  3223. DTDescription.ulVersion = SECBUFFER_VERSION ;
  3224. DTDescription.cBuffers = 1;
  3225. DTDescription.pBuffers = &DesiredToken ;
  3226. DTInput.ulVersion = SECBUFFER_VERSION;
  3227. //
  3228. // If negotiation information was provided, use it
  3229. //
  3230. if (ARGUMENT_PRESENT(NegotiateHint) &&
  3231. (NegotiateHint->Length != 0)
  3232. #ifndef WIN32_CHICAGO
  3233. && ( NegNegotiationControl < NEG_NEGLEVEL_COMPATIBILITY )
  3234. #endif
  3235. )
  3236. {
  3237. DTInput.cBuffers = 1;
  3238. DTInput.pBuffers = &InputBuffer;
  3239. InputBuffer.pvBuffer = NegotiateHint->Buffer;
  3240. InputBuffer.cbBuffer = NegotiateHint->Length;
  3241. InputBuffer.BufferType = SECBUFFER_NEGOTIATION_INFO;
  3242. HintPresent = TRUE ;
  3243. }
  3244. else
  3245. {
  3246. DTInput.cBuffers = 0;
  3247. DTInput.pBuffers = 0;
  3248. HintPresent = FALSE ;
  3249. }
  3250. InitialHandle.dwUpper = 0;
  3251. InitialHandle.dwLower = 0;
  3252. DebugLog(( DEB_TRACE_NEG, "Getting initial token from preferred package '%ws'\n",
  3253. Package->LsaPackage->Name.Buffer ));
  3254. PackageId = GetCurrentPackageId();
  3255. RetryWithHintPoint:
  3256. //
  3257. // This goto label is used for retry with hint in low security setting, and
  3258. // retry with a larger buffer in the case where kerberos exceeds its max token
  3259. // value.
  3260. //
  3261. //
  3262. // Move this into a local. The WLsaInit code will blot out the cred handle
  3263. // for the secur32.dll if the context changes.
  3264. //
  3265. TempCredHandle = Creds->Creds[ MatchingPackages[i] ].Handle ;
  3266. LastPackage = Creds->Creds[ MatchingPackages[ i ] ].Package ;
  3267. if( NT_SUCCESS( scRetPrior ) ||
  3268. (TempCredHandle.dwLower != Creds->Creds[ MatchingPackages[i-1] ].Handle.dwLower)
  3269. )
  3270. {
  3271. #ifndef WIN32_CHICAGO
  3272. scRet = WLsaInitContext(&TempCredHandle,
  3273. &InitialHandle,
  3274. pszTargetName,
  3275. PackageReqFlags,
  3276. 0,
  3277. TargetDataRep,
  3278. (UseHint ? &DTInput : &NullInput ),
  3279. 0,
  3280. &Context->Handle,
  3281. &DTDescription,
  3282. &Context->Attributes,
  3283. ptsExpiry,
  3284. &Context->Mapped,
  3285. &Context->MappedBuffer
  3286. );
  3287. #else
  3288. ANSI_STRING TempAnsiString;
  3289. NTSTATUS TempStatus = RtlUnicodeStringToAnsiString(
  3290. &TempAnsiString,
  3291. pszTargetName,
  3292. TRUE // allocate destination
  3293. );
  3294. scRet = InitializeSecurityContext(
  3295. &TempCredHandle,
  3296. &InitialHandle,
  3297. TempAnsiString.Buffer,
  3298. PackageReqFlags,
  3299. 0,
  3300. TargetDataRep,
  3301. (UseHint ? &DTInput : &NullInput),
  3302. 0,
  3303. &Context->Handle,
  3304. &DTDescription,
  3305. &Context->Attributes,
  3306. ptsExpiry
  3307. );
  3308. #endif
  3309. scRetPrior = scRet;
  3310. }
  3311. SetCurrentPackageId( PackageId );
  3312. DebugLog(( DEB_TRACE_NEG, "WLsaInitContext( %ws, %ws ) returned %x\n",
  3313. pszTargetName->Buffer,
  3314. Creds->Creds[ MatchingPackages[i] ].Package->LsaPackage->Name.Buffer,
  3315. scRet ));
  3316. Context->CallCount++ ;
  3317. if ( !NT_SUCCESS( scRet ) )
  3318. {
  3319. DebugLog(( DEB_TRACE_NEG, "Failed %x getting token from preferred package '%ws'\n",
  3320. scRet, Package->LsaPackage->Name.Buffer ));
  3321. if ( ( scRet == STATUS_BUFFER_TOO_SMALL ) &&
  3322. ( BufferSizeReset == FALSE ) )
  3323. {
  3324. LsapFreeLsaHeap( DesiredToken.pvBuffer );
  3325. //
  3326. // This is technically not multi thread safe, but this is a comparatively
  3327. // rare event. The buffer size will never be set less than the original
  3328. // claimed size from the package, so at worst, we'll get stuck in this realloc
  3329. // loop twice.
  3330. //
  3331. if ( DesiredToken.cbBuffer > Package->TokenSize )
  3332. {
  3333. Package->TokenSize = DesiredToken.cbBuffer ;
  3334. }
  3335. DesiredToken.pvBuffer = LsapAllocateLsaHeap( DesiredToken.cbBuffer );
  3336. if ( DesiredToken.pvBuffer == NULL )
  3337. {
  3338. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  3339. }
  3340. else
  3341. {
  3342. BufferSizeReset = TRUE ;
  3343. scRetPrior = STATUS_SUCCESS;
  3344. goto RetryWithHintPoint ;
  3345. }
  3346. }
  3347. #ifndef WIN32_CHICAGO
  3348. if ( (HintPresent) &&
  3349. (!(UseHint)) &&
  3350. ( ( scRet == SEC_E_TARGET_UNKNOWN ) ||
  3351. ( scRet == STATUS_NO_TRUST_SAM_ACCOUNT ) ||
  3352. ( scRet == STATUS_NO_LOGON_SERVERS ) ) &&
  3353. (NegNegotiationControl < NEG_NEGLEVEL_COMPATIBILITY ) )
  3354. {
  3355. DebugLog(( DEB_TRACE_NEG, "Retrying with hint name %ws\n",
  3356. NegotiateHint->Buffer ));
  3357. UseHint = TRUE ;
  3358. scRetPrior = STATUS_SUCCESS;
  3359. goto RetryWithHintPoint ;
  3360. }
  3361. #endif
  3362. if ( DesiredToken.pvBuffer )
  3363. {
  3364. LsapFreeLsaHeap( DesiredToken.pvBuffer );
  3365. DesiredToken.pvBuffer = NULL ;
  3366. }
  3367. }
  3368. else
  3369. {
  3370. //
  3371. // On success, check for a null session indication. If we got a "null
  3372. // session" from the security package, then we need to make sure that it
  3373. // is not uplevel, if NTLM is enabled on the machine.
  3374. //
  3375. if ( ( Context->Attributes & ISC_RET_NULL_SESSION ) != 0 )
  3376. {
  3377. if ( NtlmPackageId != NEG_INVALID_PACKAGE )
  3378. {
  3379. //
  3380. // NTLM is enabled. If this is not NTLM, blow away the context
  3381. // until we get to NTLM. First, override the returned status with
  3382. // a "special" status code that will get us through the retry logic
  3383. // below. Then, delete the existing context.
  3384. //
  3385. if ( (Creds->Creds[ MatchingPackages[ i ] ].Package->Flags & NEG_NT4_COMPAT) == 0 )
  3386. {
  3387. scRet = SEC_E_BAD_PKGID ;
  3388. #ifdef WIN32_CHICAGO
  3389. DeleteSecurityContext( &Context->Handle );
  3390. #else
  3391. WLsaDeleteContext( &Context->Handle );
  3392. #endif
  3393. Context->Attributes = 0 ;
  3394. }
  3395. }
  3396. }
  3397. }
  3398. Context->LastStatus = scRet ;
  3399. Context->Flags |= NEG_CONTEXT_PACKAGE_CALLED;
  3400. }
  3401. //
  3402. // If the packages failed, take it out of the list
  3403. //
  3404. if (!NT_SUCCESS(scRet))
  3405. {
  3406. MechList = CommonMechs[i].next;
  3407. MechCount--;
  3408. //
  3409. // kerberos can authoritatively return STATUS_WRONG_PASSWORD
  3410. // if the creds were not valid. No reason to continue at that point.
  3411. //
  3412. if((scRet == STATUS_WRONG_PASSWORD || scRet == STATUS_LOGON_FAILURE) &&
  3413. ((Creds->Flags & NEGCRED_DOMAIN_EXPLICIT_CREDS) != 0))
  3414. {
  3415. DebugLog(( DEB_TRACE_NEG, "Status code %x from Initialize causing us to break out\n",
  3416. scRet ));
  3417. goto Cleanup;
  3418. }
  3419. if (( NegNegotiationControl > NEG_NEGLEVEL_NO_SECURITY ) &&
  3420. ( ( Creds->Flags & NEGCRED_EXPLICIT_CREDS ) == 0 ) &&
  3421. ( ( Creds->Flags & NEGCRED_ALLOW_NTLM ) == 0 ) )
  3422. {
  3423. BOOL BreakOut ;
  3424. BOOL Downgrade = TRUE;
  3425. //
  3426. // Ok, we need to do some advance filtering on the
  3427. // return status, to see if we should progress or not.
  3428. //
  3429. switch ( scRet )
  3430. {
  3431. //
  3432. // Special case for null session going to NTLM:
  3433. //
  3434. case SEC_E_BAD_PKGID:
  3435. BreakOut = FALSE ;
  3436. break;
  3437. case SEC_E_TARGET_UNKNOWN:
  3438. case STATUS_NO_TRUST_SAM_ACCOUNT:
  3439. case STATUS_KDC_UNKNOWN_ETYPE:
  3440. case STATUS_NETWORK_UNREACHABLE:
  3441. case SEC_E_NO_CREDENTIALS: // eg, Kerberos has no creds for local account case
  3442. BreakOut = FALSE ;
  3443. break;
  3444. case STATUS_WRONG_PASSWORD:
  3445. case STATUS_LOGON_FAILURE:
  3446. case STATUS_NO_SUCH_USER:
  3447. case STATUS_TIME_DIFFERENCE_AT_DC:
  3448. case SEC_E_TIME_SKEW:
  3449. case STATUS_SMARTCARD_SUBSYSTEM_FAILURE:
  3450. case STATUS_SMARTCARD_WRONG_PIN:
  3451. case STATUS_SMARTCARD_NO_CARD:
  3452. case STATUS_PASSWORD_MUST_CHANGE:
  3453. case STATUS_PASSWORD_EXPIRED:
  3454. {
  3455. BreakOut = TRUE;
  3456. Downgrade = FALSE;
  3457. break;
  3458. }
  3459. case STATUS_NO_LOGON_SERVERS:
  3460. {
  3461. //
  3462. // If we truly logged on with NTLM, keep going
  3463. //
  3464. if (Creds->DefaultPackage == NtlmPackageId)
  3465. {
  3466. BreakOut = FALSE;
  3467. } else {
  3468. BreakOut = TRUE;
  3469. }
  3470. break;
  3471. }
  3472. default:
  3473. BreakOut = TRUE ;
  3474. break;
  3475. }
  3476. DebugLog(( DEB_TRACE_NEG, "Status code %x causing us to %s\n",
  3477. scRet, (BreakOut ? "break out" : "continue") ));
  3478. if ( BreakOut )
  3479. {
  3480. if( Downgrade )
  3481. {
  3482. #ifndef WIN32_CHICAGO
  3483. NegpReportEvent(
  3484. EVENTLOG_WARNING_TYPE,
  3485. NEGOTIATE_DOWNGRADE_DETECTED,
  3486. CATEGORY_NEGOTIATE,
  3487. scRet,
  3488. 2,
  3489. pszTargetName,
  3490. &LastPackage->LsaPackage->Name
  3491. );
  3492. #endif
  3493. //
  3494. // Tell the caller the explicit reason for the failure since
  3495. // NTLM might very well have suceeded.
  3496. //
  3497. scRet = STATUS_DOWNGRADE_DETECTED;
  3498. }
  3499. break;
  3500. }
  3501. }
  3502. }
  3503. i++;
  3504. } while (!NT_SUCCESS(scRet) && (MechCount != 0));
  3505. if (!NT_SUCCESS(scRet))
  3506. {
  3507. #ifndef WIN32_CHICAGO
  3508. NegpReportEvent(
  3509. EVENTLOG_WARNING_TYPE,
  3510. NEGOTIATE_INVALID_SERVER,
  3511. CATEGORY_NEGOTIATE,
  3512. scRet,
  3513. 1,
  3514. pszTargetName
  3515. );
  3516. #endif
  3517. DebugLog((DEB_ERROR,"No packages could initialize\n"));
  3518. goto Cleanup;
  3519. }
  3520. if ( MechCount == 0 )
  3521. {
  3522. #ifndef WIN32_CHICAGO
  3523. NegpReportEvent(
  3524. EVENTLOG_WARNING_TYPE,
  3525. NEGOTIATE_INVALID_SERVER,
  3526. CATEGORY_NEGOTIATE,
  3527. 0,
  3528. 1,
  3529. pszTargetName
  3530. );
  3531. #endif
  3532. scRet = SEC_E_INVALID_TOKEN ;
  3533. //
  3534. // No common packages:
  3535. //
  3536. DebugLog(( DEB_TRACE_NEG, "No common packages\n"));
  3537. goto Cleanup ;
  3538. }
  3539. #ifndef WIN32_CHICAGO
  3540. if ( LastPackage )
  3541. {
  3542. NegpReportEvent(
  3543. EVENTLOG_INFORMATION_TYPE,
  3544. NEGOTIATE_PACKAGE_SELECTED,
  3545. CATEGORY_NEGOTIATE,
  3546. 0,
  3547. 2,
  3548. pszTargetName,
  3549. &LastPackage->LsaPackage->Name
  3550. );
  3551. }
  3552. #endif
  3553. if ( !DirectSecurityPacket )
  3554. {
  3555. Request.negToken.choice = negTokenInit_chosen ;
  3556. Request.negToken.u.negTokenInit.mechTypes = MechList ;
  3557. Request.negToken.u.negTokenInit.bit_mask |= NegTokenInit_mechTypes_present ;
  3558. //
  3559. // Okay, now we have all the pieces. Assemble the token:
  3560. //
  3561. if ( DesiredToken.pvBuffer )
  3562. {
  3563. Request.negToken.u.negTokenInit.mechToken.length = DesiredToken.cbBuffer ;
  3564. Request.negToken.u.negTokenInit.mechToken.value = (PUCHAR) DesiredToken.pvBuffer ;
  3565. Request.negToken.u.negTokenInit.bit_mask |= NegTokenInit_mechToken_present ;
  3566. }
  3567. //
  3568. // Add in the SPNEGO mechanism id
  3569. //
  3570. Request.spnegoMech = NegSpnegoMechOid;
  3571. Result = SpnegoPackData(
  3572. &Request,
  3573. InitialNegToken_PDU,
  3574. &(EncodedData.length),
  3575. &(EncodedData.value));
  3576. if ( Result )
  3577. {
  3578. DebugLog((DEB_ERROR, "Failed to encode data: %d\n", Result ));
  3579. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  3580. goto Cleanup ;
  3581. }
  3582. }
  3583. else
  3584. {
  3585. EncodedData.length = DesiredToken.cbBuffer ;
  3586. EncodedData.value = (PUCHAR) DesiredToken.pvBuffer ;
  3587. DesiredToken.pvBuffer = NULL ;
  3588. }
  3589. //
  3590. // Okay, got the token into a contiguous mass. Package it up for the caller
  3591. //
  3592. if ( fContextReq & ISC_REQ_ALLOCATE_MEMORY )
  3593. {
  3594. //
  3595. // Easy: The caller asked for us to allocate memory for them, so
  3596. // let the LSA do it.
  3597. //
  3598. pToken->pvBuffer = EncodedData.value ;
  3599. pToken->cbBuffer = EncodedData.length ;
  3600. EncodedData.value = NULL;
  3601. }
  3602. else
  3603. {
  3604. //
  3605. // The caller has a buffer that we're supposed to use. Make sure we
  3606. // can fit.
  3607. //
  3608. if ( (ULONG) EncodedData.length < pToken->cbBuffer )
  3609. {
  3610. RtlCopyMemory( pToken->pvBuffer,
  3611. EncodedData.value,
  3612. EncodedData.length );
  3613. pToken->cbBuffer = EncodedData.length ;
  3614. }
  3615. else if ( ( ( fContextReq & ISC_REQ_FRAGMENT_TO_FIT ) != 0 ) &&
  3616. ( pToken->cbBuffer >= SPNEGO_MINIMUM_BUFFER ) )
  3617. {
  3618. //
  3619. // Ok, we need to whack the context to indicate that we are
  3620. // fragmenting, and return only what the caller can handle.
  3621. //
  3622. Context->Message = EncodedData.value ;
  3623. Context->TotalSize = EncodedData.length ;
  3624. Context->Flags |= NEG_CONTEXT_FRAGMENTING ;
  3625. //
  3626. // set this to NULL so it doesn't get freed later
  3627. //
  3628. EncodedData.value = NULL ;
  3629. RtlCopyMemory(
  3630. pToken->pvBuffer,
  3631. Context->Message,
  3632. pToken->cbBuffer );
  3633. Context->CurrentSize = pToken->cbBuffer ;
  3634. }
  3635. else
  3636. {
  3637. DebugLog(( DEB_TRACE_NEG, "Supplied buffer is too small\n" ));
  3638. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  3639. goto Cleanup ;
  3640. }
  3641. }
  3642. //
  3643. // We have created the token, encoded it, and stuck it in a return buffer.
  3644. // We have created the context record, and it is ready. We're done!
  3645. //
  3646. if ( !DirectSecurityPacket )
  3647. {
  3648. *pContext = Context ;
  3649. Context = NULL;
  3650. scRet = SEC_I_CONTINUE_NEEDED ;
  3651. }
  3652. #ifndef WIN32_CHICAGO
  3653. else
  3654. {
  3655. DebugLog(( DEB_TRACE_NEG, "Replacing handle, current status is %x\n", scRet ));
  3656. LsapChangeHandle( HandleReplace,
  3657. NULL,
  3658. &Context->Handle );
  3659. *pContext = NULL ;
  3660. Context->Handle.dwLower = 0 ;
  3661. Context->Handle.dwUpper = 0 ;
  3662. //
  3663. // Context will be freed during cleanup.
  3664. //
  3665. }
  3666. #endif
  3667. Cleanup:
  3668. if ( !ServerMechs )
  3669. {
  3670. //
  3671. // No server mechs means we allocated and used one based on our
  3672. // cred handle. Free it.
  3673. //
  3674. if (SourceMechs != NULL)
  3675. {
  3676. if ( MechListReordered )
  3677. {
  3678. LsapFreeLsaHeap( SourceMechsToFree );
  3679. }
  3680. else
  3681. {
  3682. LsapFreeLsaHeap( SourceMechs );
  3683. }
  3684. }
  3685. }
  3686. if (EncodedData.value != NULL)
  3687. {
  3688. LsapFreeLsaHeap(EncodedData.value);
  3689. }
  3690. if ( DesiredToken.pvBuffer )
  3691. {
  3692. LsapFreeLsaHeap( DesiredToken.pvBuffer );
  3693. }
  3694. if ( Context )
  3695. {
  3696. NegpDeleteContext( Context );
  3697. }
  3698. if (NarrowName.Buffer != NULL)
  3699. {
  3700. RtlFreeAnsiString(&NarrowName);
  3701. }
  3702. return( scRet );
  3703. }
  3704. //+---------------------------------------------------------------------------
  3705. //
  3706. // Function: NegGenerateInitialToken
  3707. //
  3708. // Synopsis: Client side init
  3709. //
  3710. // Arguments: [dwCreds] --
  3711. // [Target] --
  3712. // [fContextReq] --
  3713. // [TargetDataRep] --
  3714. // [pInput] --
  3715. // [pdwNewContext] --
  3716. // [pOutput] --
  3717. // [pfContextAttr] --
  3718. // [ptsExpiry] --
  3719. // [pfMapContext] --
  3720. // [pContextData] --
  3721. //
  3722. // History: 9-30-96 RichardW Created
  3723. //
  3724. // Notes:
  3725. //
  3726. //----------------------------------------------------------------------------
  3727. SECURITY_STATUS
  3728. NegGenerateInitialToken(
  3729. ULONG_PTR dwCreds,
  3730. PSECURITY_STRING Target,
  3731. ULONG fContextReq,
  3732. ULONG TargetDataRep,
  3733. PSecBufferDesc pInput,
  3734. PULONG_PTR pdwNewContext,
  3735. PSecBufferDesc pOutput,
  3736. PULONG pfContextAttr,
  3737. PTimeStamp ptsExpiry,
  3738. PBYTE pfMapContext,
  3739. PSecBuffer pContextData)
  3740. {
  3741. SECURITY_STATUS scRet;
  3742. PSecBuffer Buffer;
  3743. PNEG_CREDS Creds;
  3744. PNEG_CONTEXT Context;
  3745. //
  3746. // Initialize stuff:
  3747. //
  3748. Creds = (PNEG_CREDS) dwCreds ;
  3749. //
  3750. // Fall through to common code with normal initial token:
  3751. //
  3752. scRet = NegBuildRequestToken( FALSE,
  3753. Creds,
  3754. Target,
  3755. fContextReq,
  3756. TargetDataRep,
  3757. NULL,
  3758. NULL,
  3759. &Context,
  3760. pOutput,
  3761. ptsExpiry );
  3762. if ( NT_SUCCESS( scRet ) )
  3763. {
  3764. //
  3765. // Successfully built token. Set flags:
  3766. //
  3767. *pfContextAttr = ( ISC_RET_INTERMEDIATE_RETURN ) |
  3768. ( fContextReq & ISC_REQ_ALLOCATE_MEMORY ?
  3769. ISC_RET_ALLOCATED_MEMORY : 0 ) ;
  3770. *pfMapContext = FALSE ;
  3771. if ( Context )
  3772. {
  3773. *pdwNewContext = (DWORD_PTR) Context ;
  3774. }
  3775. }
  3776. return( scRet );
  3777. }
  3778. //+---------------------------------------------------------------------------
  3779. //
  3780. // Function: NegGenerateServerRequest
  3781. //
  3782. // Synopsis: Server side init
  3783. //
  3784. // Arguments: [dwCreds] --
  3785. // [fContextReq] --
  3786. // [TargetDataRep] --
  3787. // [pInput] --
  3788. // [pdwNewContext] --
  3789. // [pOutput] --
  3790. // [pfContextAttr] --
  3791. // [ptsExpiry] --
  3792. // [pfMapContext] --
  3793. // [pContextData] --
  3794. //
  3795. // History: 9-30-96 RichardW Created
  3796. //
  3797. // Notes:
  3798. //
  3799. //----------------------------------------------------------------------------
  3800. SECURITY_STATUS
  3801. NegGenerateServerRequest(
  3802. ULONG_PTR dwCreds,
  3803. ULONG fContextReq,
  3804. ULONG TargetDataRep,
  3805. PSecBufferDesc pInput,
  3806. PULONG_PTR pdwNewContext,
  3807. PSecBufferDesc pOutput,
  3808. PULONG pfContextAttr,
  3809. PTimeStamp ptsExpiry,
  3810. PBYTE pfMapContext,
  3811. PSecBuffer pContextData)
  3812. {
  3813. SECURITY_STATUS scRet;
  3814. PSecBuffer Buffer;
  3815. PNEG_CREDS Creds;
  3816. PNEG_CONTEXT Context;
  3817. //
  3818. // Initialize stuff:
  3819. //
  3820. Creds = (PNEG_CREDS) dwCreds ;
  3821. //
  3822. // Fall through to common code with normal initial token:
  3823. //
  3824. scRet = NegBuildRequestToken( TRUE,
  3825. Creds,
  3826. NULL,
  3827. fContextReq,
  3828. TargetDataRep,
  3829. NULL,
  3830. NULL,
  3831. &Context,
  3832. pOutput,
  3833. ptsExpiry );
  3834. if ( NT_SUCCESS( scRet ) )
  3835. {
  3836. //
  3837. // Successfully built token. Set flags:
  3838. //
  3839. *pfContextAttr = ( fContextReq & ASC_REQ_ALLOCATE_MEMORY ?
  3840. ASC_RET_ALLOCATED_MEMORY : 0 ) ;
  3841. *pfMapContext = FALSE ;
  3842. *pdwNewContext = (DWORD_PTR) Context ;
  3843. }
  3844. return( scRet );
  3845. }
  3846. //+---------------------------------------------------------------------------
  3847. //
  3848. // Function: NegCrackServerRequestAndReply
  3849. //
  3850. // Synopsis: Client side Init with Neg token from the server
  3851. //
  3852. // Arguments: [dwCreds] --
  3853. // [Target] --
  3854. // [fContextReq] --
  3855. // [TargetDataRep] --
  3856. // [pInput] --
  3857. // [pdwNewContext] --
  3858. // [pOutput] --
  3859. // [pfContextAttr] --
  3860. // [ptsExpiry] --
  3861. // [pfMapContext] --
  3862. // [pContextData] --
  3863. //
  3864. // History: 9-30-96 RichardW Created
  3865. //
  3866. // Notes:
  3867. //
  3868. //----------------------------------------------------------------------------
  3869. SECURITY_STATUS
  3870. NegCrackServerRequestAndReply(
  3871. ULONG_PTR dwCreds,
  3872. PSECURITY_STRING Target,
  3873. ULONG fContextReq,
  3874. ULONG TargetDataRep,
  3875. PSecBufferDesc pInput,
  3876. PULONG_PTR pdwNewContext,
  3877. PSecBufferDesc pOutput,
  3878. PULONG pfContextAttr,
  3879. PTimeStamp ptsExpiry,
  3880. PBYTE pfMapContext,
  3881. PSecBuffer pContextData)
  3882. {
  3883. SECURITY_STATUS scRet;
  3884. struct InitialNegToken * Request = NULL ;
  3885. ASN1octetstring_t EncodedData;
  3886. int Result;
  3887. ULONG Pdu = InitialNegToken_PDU;
  3888. PSecBuffer Buffer;
  3889. struct MechTypeList *pMechs = NULL;
  3890. PNEG_CREDS Creds ;
  3891. PNEG_CONTEXT Context = NULL ;
  3892. UNICODE_STRING NegotiateHint = {0};
  3893. ANSI_STRING AnsiHint = {0};
  3894. RtlInitUnicodeString(
  3895. &NegotiateHint,
  3896. NULL
  3897. );
  3898. //
  3899. // Initialize stuff:
  3900. //
  3901. //
  3902. // First, verify the input buffer contains a Request token, and crack it.
  3903. //
  3904. scRet = NegpParseBuffers( pInput, TRUE, &Buffer, NULL );
  3905. if ( !Buffer )
  3906. {
  3907. scRet = SEC_E_INVALID_TOKEN;
  3908. goto Cleanup;
  3909. }
  3910. if ( !NT_SUCCESS( scRet ) )
  3911. {
  3912. goto Cleanup;
  3913. }
  3914. Creds = (PNEG_CREDS) dwCreds ;
  3915. EncodedData.value = (PUCHAR) Buffer->pvBuffer ;
  3916. EncodedData.length = Buffer->cbBuffer ;
  3917. Request = NULL ;
  3918. Result = SpnegoUnpackData(
  3919. EncodedData.value,
  3920. EncodedData.length,
  3921. Pdu,
  3922. (PVOID *)&Request);
  3923. if ( Result != 0 )
  3924. {
  3925. scRet = SEC_E_INVALID_TOKEN;
  3926. goto Cleanup;
  3927. }
  3928. //
  3929. // This function only handles Request tokens. If we ended up with a reply,
  3930. // then the server is in trouble, or we are...
  3931. //
  3932. if ( (Pdu != InitialNegToken_PDU) ||
  3933. (Request->negToken.choice == negTokenTarg_chosen) ||
  3934. NegpCompareOid(
  3935. Request->spnegoMech,
  3936. NegSpnegoMechOid)
  3937. )
  3938. {
  3939. scRet = SEC_E_INVALID_TOKEN;
  3940. goto Cleanup;
  3941. }
  3942. //
  3943. // Okay, the server has sent us a list of the packages that he supports,
  3944. // possibly some hints as well. We need to go through the list, and figure
  3945. // our common subset. At the same time, we need to select the one that we
  3946. // want to use, preferably the same as the first one from the server.
  3947. //
  3948. if ((Request->negToken.u.negTokenInit.bit_mask & NegTokenInit_mechTypes_present) != 0)
  3949. {
  3950. pMechs = Request->negToken.u.negTokenInit.mechTypes ;
  3951. }
  3952. //
  3953. // Get the negotation hint out.
  3954. //
  3955. if ((Request->negToken.u.negTokenInit.bit_mask & NegTokenInit_negHints_present) != 0)
  3956. {
  3957. if ((Request->negToken.u.negTokenInit.negHints.bit_mask & hintName_present) != 0)
  3958. {
  3959. RtlInitString(
  3960. &AnsiHint,
  3961. Request->negToken.u.negTokenInit.negHints.hintName
  3962. );
  3963. scRet = RtlAnsiStringToUnicodeString(
  3964. &NegotiateHint,
  3965. &AnsiHint,
  3966. TRUE // allocate destination
  3967. );
  3968. if (!NT_SUCCESS(scRet))
  3969. {
  3970. scRet= SEC_E_INSUFFICIENT_MEMORY;
  3971. goto Cleanup;
  3972. }
  3973. }
  3974. }
  3975. //
  3976. // Fall through to common code with normal initial token:
  3977. //
  3978. scRet = NegBuildRequestToken(
  3979. FALSE, // not server side
  3980. Creds,
  3981. Target,
  3982. fContextReq,
  3983. TargetDataRep,
  3984. pMechs,
  3985. &NegotiateHint,
  3986. &Context,
  3987. pOutput,
  3988. ptsExpiry );
  3989. Cleanup:
  3990. if ( Request )
  3991. {
  3992. SpnegoFreeData( Pdu, Request );
  3993. }
  3994. if (NegotiateHint.Buffer != NULL)
  3995. {
  3996. RtlFreeUnicodeString(&NegotiateHint);
  3997. }
  3998. if ( NT_SUCCESS( scRet ) )
  3999. {
  4000. //
  4001. // Successfully built token. Set flags:
  4002. //
  4003. *pfContextAttr = ( ISC_RET_INTERMEDIATE_RETURN ) |
  4004. ( fContextReq & ISC_REQ_ALLOCATE_MEMORY ?
  4005. ISC_RET_ALLOCATED_MEMORY : 0 ) ;
  4006. *pfMapContext = FALSE ;
  4007. *pdwNewContext = (DWORD_PTR) Context ;
  4008. }
  4009. return( scRet );
  4010. }
  4011. //+---------------------------------------------------------------------------
  4012. //
  4013. // Function: NegpCrackRequest
  4014. //
  4015. // Synopsis: Crack a Request package, and, based on the creds, determine
  4016. // what is supported.
  4017. //
  4018. // Arguments: [Creds] -- Creds to compare against
  4019. // [Request] -- Request to crack
  4020. // [MechIndex] -- selected package
  4021. // [MechList] -- Receives mech list from request
  4022. // [pPackage] -- Package pointer
  4023. //
  4024. // History: 9-25-96 RichardW Created
  4025. //
  4026. // Notes: Creds must be locked
  4027. //
  4028. //----------------------------------------------------------------------------
  4029. SECURITY_STATUS
  4030. NegpCrackRequest(
  4031. IN PNEG_CREDS Creds,
  4032. IN NegotiationToken * Request,
  4033. OUT PULONG_PTR MechIndex,
  4034. OUT struct MechTypeList ** MechList,
  4035. OUT PNEG_PACKAGE * pPackage,
  4036. OUT NEG_MATCH * pDesiredMatch)
  4037. {
  4038. DWORD i;
  4039. DWORD j;
  4040. ULONG MatchingPackage = (ULONG) -1;
  4041. struct MechTypeList *pMechs;
  4042. PNEG_PACKAGE Package;
  4043. NEG_MATCH DesiredMatch;
  4044. ULONG MechCount ;
  4045. pMechs = Request->u.negTokenInit.mechTypes ;
  4046. //
  4047. // First, support the "standard" by going through the whole list,
  4048. // and determining which ones we support.
  4049. //
  4050. Package = NULL ;
  4051. DesiredMatch = MatchUnknown ;
  4052. //
  4053. // For each mechanism, see if we have it in the creds. If we have it,
  4054. // mark it as acceptible. If this is the first acceptible mech, capture
  4055. // it as the now preferred mechanism.
  4056. //
  4057. while ( pMechs )
  4058. {
  4059. NegDumpOid( "Incoming Mechanism", pMechs->value );
  4060. for ( i = 0 ; i < Creds->Count ; i++ )
  4061. {
  4062. NegDumpOid( "Comparing to Mechanism", Creds->Creds[i].Package->ObjectId );
  4063. if ( NegpCompareOid( pMechs->value,
  4064. Creds->Creds[i].Package->ObjectId ) == 0 )
  4065. {
  4066. if ( !Package )
  4067. {
  4068. Package = Creds->Creds[i].Package ;
  4069. if ( DesiredMatch == MatchUnknown )
  4070. {
  4071. DesiredMatch = PreferredSucceed ;
  4072. }
  4073. else
  4074. {
  4075. DesiredMatch = MatchSucceed ;
  4076. }
  4077. MatchingPackage = i;
  4078. break;
  4079. }
  4080. }
  4081. }
  4082. pMechs = pMechs->next ;
  4083. if ( DesiredMatch == MatchUnknown )
  4084. {
  4085. DesiredMatch = MatchFailed ;
  4086. }
  4087. }
  4088. *MechIndex = MatchingPackage ;
  4089. *pPackage = Package ;
  4090. *MechList = Request->u.negTokenInit.mechTypes ;
  4091. *pDesiredMatch = DesiredMatch ;
  4092. return( 0 );
  4093. }
  4094. //+---------------------------------------------------------------------------
  4095. //
  4096. // Function: NegHandleSubsequentClientRequest
  4097. //
  4098. // Synopsis: Handles a client request after the initial NegTokenInit
  4099. //
  4100. // Arguments:
  4101. //
  4102. // History: 5-26-97 MikeSw Created
  4103. //
  4104. // Notes:
  4105. //
  4106. //----------------------------------------------------------------------------
  4107. SECURITY_STATUS
  4108. NegHandleSubsequentClientRequest(
  4109. ULONG_PTR dwCreds,
  4110. PNEG_CONTEXT Context,
  4111. ULONG fContextReq,
  4112. ULONG TargetDataRep,
  4113. ULONG Pdu,
  4114. NegotiationToken * Request,
  4115. PULONG_PTR pdwNewContext,
  4116. PSecBufferDesc pOutput,
  4117. PULONG pfContextAttr,
  4118. PTimeStamp ptsExpiry,
  4119. PBYTE pfMapContext,
  4120. PSecBuffer pContextData )
  4121. {
  4122. SECURITY_STATUS scRet = SEC_E_OK;
  4123. #ifndef WIN32_CHICAGO
  4124. PNEG_CREDS Creds ;
  4125. NegotiationToken Reply;
  4126. CredHandle TempCredHandle;
  4127. CtxtHandle TempHandle;
  4128. SecBufferDesc AcceptBufferDesc;
  4129. SecBuffer AcceptBuffer;
  4130. SecBufferDesc ResponseBufferDesc;
  4131. SecBuffer ResponseBuffer;
  4132. SecBuffer MappedBuffer;
  4133. PSecBuffer pToken;
  4134. BOOLEAN MappedContext;
  4135. ULONG_PTR PackageId;
  4136. ASN1octetstring_t EncodedData;
  4137. int Result;
  4138. PNEG_PACKAGE Package ;
  4139. EncodedData.value = NULL;
  4140. EncodedData.length = 0;
  4141. RtlZeroMemory(
  4142. &ResponseBuffer,
  4143. sizeof(SecBuffer)
  4144. );
  4145. RtlZeroMemory(
  4146. &MappedBuffer,
  4147. sizeof(SecBuffer)
  4148. );
  4149. //
  4150. // The negotiation context should have been created during the first call
  4151. // to AcceptSecurityContext, so if it isn't present this is an
  4152. // error.
  4153. //
  4154. if (Context == NULL)
  4155. {
  4156. scRet = SEC_E_INVALID_HANDLE;
  4157. goto Cleanup;
  4158. }
  4159. //
  4160. // Verify that there is an output token to return something in.
  4161. //
  4162. scRet = NegpParseBuffers( pOutput, TRUE, &pToken, NULL );
  4163. if ( !NT_SUCCESS( scRet ) || (pToken == NULL) )
  4164. {
  4165. DebugLog((DEB_TRACE_NEG, "No output token supplied to NegHandleSubs.ClientReq\n"));
  4166. scRet = SEC_E_INVALID_TOKEN;
  4167. goto Cleanup;
  4168. }
  4169. //
  4170. // Verify the creds passed in
  4171. //
  4172. Creds = (PNEG_CREDS) dwCreds ;
  4173. if (Creds == NULL)
  4174. {
  4175. Creds = Context->Creds;
  4176. }
  4177. else if (Creds != Context->Creds)
  4178. {
  4179. //
  4180. // Could be a multi:
  4181. //
  4182. if ( ( Creds->Flags & NEGCRED_MULTI ) == 0 )
  4183. {
  4184. DebugLog((DEB_TRACE_NEG, "Bad context handle passed to Accept: 0x%p instead of 0x%p\n",
  4185. Creds, Context->Creds ));
  4186. scRet = SEC_E_INVALID_HANDLE;
  4187. goto Cleanup;
  4188. }
  4189. //
  4190. // Walk the multi credential and verify the cred ptr?
  4191. //
  4192. Creds = Context->Creds ;
  4193. }
  4194. //
  4195. // if the security token area is empty, but the mechListMIC is
  4196. // present, then the client has completed (and we should have,
  4197. // also), and we should verify the mechListMIC.
  4198. //
  4199. if ( ( ( Request->u.negTokenTarg.responseToken.length == 0 ) &&
  4200. ( ( Context->Flags & NEG_CONTEXT_UPLEVEL ) != 0 ) ) ||
  4201. ( Request->u.negTokenTarg.bit_mask == 0 ) )
  4202. {
  4203. //
  4204. // Check the MIC:
  4205. //
  4206. SpnegoFreeData( Pdu, Request );
  4207. Request = NULL;
  4208. if ( Context->LastStatus != STATUS_SUCCESS )
  4209. {
  4210. return SEC_E_INVALID_TOKEN ;
  4211. }
  4212. if (Context->Mapped)
  4213. {
  4214. *pfMapContext = Context->Mapped;
  4215. *pContextData = Context->MappedBuffer;
  4216. RtlZeroMemory(
  4217. &Context->MappedBuffer,
  4218. sizeof(SecBuffer)
  4219. );
  4220. }
  4221. //
  4222. // Whack the output handle with the one returned from the
  4223. // package.
  4224. //
  4225. LsapChangeHandle( HandleReplace,
  4226. NULL,
  4227. &Context->Handle );
  4228. Context->Handle.dwLower = 0 ;
  4229. Context->Handle.dwUpper = 0 ;
  4230. pToken->cbBuffer = 0 ;
  4231. *ptsExpiry = Context->Expiry ;
  4232. Context = NULL ;
  4233. return STATUS_SUCCESS ;
  4234. }
  4235. //
  4236. // Get the locked information out of the credentials
  4237. //
  4238. NegReadLockCreds(Creds);
  4239. TempCredHandle = Creds->Creds[ Context->CredIndex ].Handle;
  4240. Package = Creds->Creds[Context->CredIndex].Package;
  4241. NegUnlockCreds(Creds);
  4242. //
  4243. // Build the input to AcceptSecurityContext
  4244. //
  4245. if ( Request->u.negTokenTarg.responseToken.length != 0 )
  4246. {
  4247. AcceptBuffer.pvBuffer = Request->u.negTokenTarg.responseToken.value;
  4248. AcceptBuffer.cbBuffer = Request->u.negTokenTarg.responseToken.length;
  4249. Context->Flags |= NEG_CONTEXT_UPLEVEL ;
  4250. }
  4251. else if ( Request->u.negTokenTarg.mechListMIC.length != 0 )
  4252. {
  4253. AcceptBuffer.pvBuffer = Request->u.negTokenTarg.mechListMIC.value ;
  4254. AcceptBuffer.cbBuffer = Request->u.negTokenTarg.mechListMIC.length ;
  4255. }
  4256. AcceptBuffer.BufferType = SECBUFFER_READONLY | SECBUFFER_TOKEN ;
  4257. AcceptBufferDesc.ulVersion = SECBUFFER_VERSION ;
  4258. AcceptBufferDesc.cBuffers = 1;
  4259. AcceptBufferDesc.pBuffers = &AcceptBuffer ;
  4260. ResponseBuffer.cbBuffer = Package->LsaPackage->TokenSize ;
  4261. ResponseBuffer.BufferType = SECBUFFER_TOKEN ;
  4262. ResponseBuffer.pvBuffer = LsapAllocateLsaHeap(
  4263. ResponseBuffer.cbBuffer );
  4264. if ( ResponseBuffer.pvBuffer == NULL )
  4265. {
  4266. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  4267. goto Cleanup ;
  4268. }
  4269. ResponseBufferDesc.ulVersion = SECBUFFER_VERSION ;
  4270. ResponseBufferDesc.cBuffers = 1;
  4271. ResponseBufferDesc.pBuffers = &ResponseBuffer ;
  4272. if ((Context->Flags & NEG_CONTEXT_PACKAGE_CALLED) != 0)
  4273. {
  4274. TempHandle = Context->Handle ;
  4275. }
  4276. else
  4277. {
  4278. TempHandle.dwUpper = TempHandle.dwLower = 0;
  4279. }
  4280. PackageId = GetCurrentPackageId();
  4281. //
  4282. // Call the package. Note that if the package has already mapped the
  4283. // context we don't want it overwriting the existing mapping. Hence,
  4284. // don't pass in the real value.
  4285. //
  4286. #ifndef WIN32_CHICAGO
  4287. scRet = WLsaAcceptContext(
  4288. &TempCredHandle,
  4289. &TempHandle,
  4290. &AcceptBufferDesc,
  4291. (fContextReq & (~(ASC_REQ_ALLOCATE_MEMORY))),
  4292. TargetDataRep,
  4293. &Context->Handle,
  4294. &ResponseBufferDesc,
  4295. &Context->Attributes,
  4296. &Context->Expiry,
  4297. &MappedContext,
  4298. &MappedBuffer );
  4299. #else
  4300. scRet = AcceptSecurityContext(
  4301. &TempCredHandle,
  4302. &TempHandle,
  4303. &AcceptBufferDesc,
  4304. (fContextReq & (~(ASC_REQ_ALLOCATE_MEMORY))),
  4305. TargetDataRep,
  4306. &Context->Handle,
  4307. &ResponseBufferDesc,
  4308. &Context->Attributes,
  4309. &Context->Expiry
  4310. );
  4311. #endif // WIN32_CHICAGO
  4312. #if DBG
  4313. NegReadLockCreds( Creds );
  4314. DebugLog(( DEB_TRACE_NEG, "WLsaAcceptContext( %ws ) returned %x\n",
  4315. Creds->Creds[ Context->CredIndex ].Package->LsaPackage->Name.Buffer,
  4316. scRet ));
  4317. NegUnlockCreds(Creds);
  4318. #endif
  4319. Context->CallCount++ ;
  4320. SetCurrentPackageId( PackageId );
  4321. //
  4322. // Done with request data
  4323. //
  4324. SpnegoFreeData( Pdu, Request );
  4325. Request = NULL;
  4326. if ( !NT_SUCCESS( scRet ) )
  4327. {
  4328. DebugLog((DEB_TRACE, "Neg Failure from package %d, %#x\n",
  4329. Context->CredIndex, scRet ));
  4330. DsysAssert( scRet != SEC_E_INVALID_HANDLE )
  4331. goto Cleanup;
  4332. }
  4333. Context->Flags |= NEG_CONTEXT_PACKAGE_CALLED;
  4334. Context->LastStatus = scRet ;
  4335. //
  4336. // Build the output token, another NegTokenTarg.
  4337. //
  4338. Reply.choice = negTokenTarg_chosen;
  4339. Reply.u.negTokenTarg.bit_mask = negResult_present;
  4340. if (ResponseBuffer.cbBuffer != 0)
  4341. {
  4342. Reply.u.negTokenTarg.bit_mask |= responseToken_present;
  4343. }
  4344. Reply.u.negTokenTarg.responseToken.value = (PUCHAR) ResponseBuffer.pvBuffer;
  4345. Reply.u.negTokenTarg.responseToken.length = (int) ResponseBuffer.cbBuffer;
  4346. //
  4347. // Fill in the negotation result field. In addition, fill in any
  4348. // context mapping data.
  4349. //
  4350. if ( MappedContext )
  4351. {
  4352. DsysAssert( !Context->Mapped );
  4353. Context->Mapped = TRUE ;
  4354. Context->MappedBuffer = MappedBuffer ;
  4355. RtlZeroMemory(
  4356. &MappedBuffer,
  4357. sizeof(SecBuffer)
  4358. );
  4359. }
  4360. //
  4361. // generate the MIC on the last blob
  4362. //
  4363. if ( scRet == SEC_E_OK )
  4364. {
  4365. //
  4366. // Once the mic is generated, the
  4367. // list of mechs is no longer needed.
  4368. //
  4369. if ( Context->SupportedMechs )
  4370. {
  4371. DebugLog(( DEB_TRACE_NEG, "Freeing mech list for %p\n", Context ));
  4372. if ((Context->Flags & NEG_CONTEXT_FREE_EACH_MECH))
  4373. {
  4374. NegpFreeMechList(Context->SupportedMechs);
  4375. }
  4376. else
  4377. {
  4378. LsapFreeLsaHeap(Context->SupportedMechs);
  4379. }
  4380. Context->SupportedMechs = NULL ;
  4381. }
  4382. }
  4383. if ( Context->LastStatus == SEC_E_OK )
  4384. {
  4385. Reply.u.negTokenTarg.negResult = accept_completed;
  4386. }
  4387. else
  4388. {
  4389. Reply.u.negTokenTarg.negResult = accept_incomplete;
  4390. }
  4391. if (scRet == SEC_E_OK)
  4392. {
  4393. if (Context->Mapped)
  4394. {
  4395. *pfMapContext = Context->Mapped;
  4396. *pContextData = Context->MappedBuffer;
  4397. RtlZeroMemory(
  4398. &Context->MappedBuffer,
  4399. sizeof(SecBuffer)
  4400. );
  4401. }
  4402. else if (MappedContext)
  4403. {
  4404. *pfMapContext = TRUE;
  4405. *pContextData = MappedBuffer;
  4406. RtlZeroMemory(
  4407. &MappedBuffer,
  4408. sizeof(SecBuffer)
  4409. );
  4410. }
  4411. }
  4412. *ptsExpiry = Context->Expiry;
  4413. *pfContextAttr = Context->Attributes;
  4414. //
  4415. // Encode reply token:
  4416. //
  4417. Result = SpnegoPackData(
  4418. &Reply,
  4419. NegotiationToken_PDU,
  4420. &(EncodedData.length),
  4421. &(EncodedData.value));
  4422. if (Result != 0)
  4423. {
  4424. scRet = SEC_E_INSUFFICIENT_MEMORY;
  4425. goto Cleanup;
  4426. }
  4427. DsysAssert( NT_SUCCESS(NegpValidateBuffer( EncodedData.value, EncodedData.length ) ) );
  4428. if ( fContextReq & ASC_REQ_ALLOCATE_MEMORY )
  4429. {
  4430. pToken->pvBuffer = EncodedData.value ;
  4431. *pfContextAttr |= ASC_RET_ALLOCATED_MEMORY ;
  4432. EncodedData.value = NULL ;
  4433. pToken->cbBuffer = EncodedData.length ;
  4434. }
  4435. else
  4436. {
  4437. if ( pToken->cbBuffer >= (ULONG) EncodedData.length )
  4438. {
  4439. RtlCopyMemory( pToken->pvBuffer,
  4440. EncodedData.value,
  4441. EncodedData.length );
  4442. pToken->cbBuffer = EncodedData.length ;
  4443. }
  4444. else if ( ( ( fContextReq & ASC_REQ_FRAGMENT_TO_FIT ) != 0 ) &&
  4445. ( pToken->cbBuffer >= SPNEGO_MINIMUM_BUFFER ) )
  4446. {
  4447. //
  4448. // Ok, we need to whack the context to indicate that we are
  4449. // fragmenting, and return only what the caller can handle.
  4450. //
  4451. Context->Message = EncodedData.value ;
  4452. Context->TotalSize = EncodedData.length ;
  4453. Context->Flags |= NEG_CONTEXT_FRAGMENTING ;
  4454. //
  4455. // set this to NULL so it doesn't get freed later
  4456. //
  4457. EncodedData.value = NULL ;
  4458. RtlCopyMemory(
  4459. pToken->pvBuffer,
  4460. Context->Message,
  4461. pToken->cbBuffer );
  4462. Context->CurrentSize = pToken->cbBuffer ;
  4463. }
  4464. else
  4465. {
  4466. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  4467. goto Cleanup ;
  4468. }
  4469. }
  4470. if (scRet == SEC_E_OK)
  4471. {
  4472. //
  4473. // Whack the output handle with the one returned from the
  4474. // package.
  4475. //
  4476. LsapChangeHandle( HandleReplace,
  4477. NULL,
  4478. &Context->Handle );
  4479. Context->Handle.dwLower = 0 ;
  4480. Context->Handle.dwUpper = 0 ;
  4481. Context = NULL ;
  4482. }
  4483. else
  4484. {
  4485. //
  4486. // Make sure we never say that we mapped when we are in the
  4487. // intermediate state.
  4488. //
  4489. DsysAssert( !(*pfMapContext) );
  4490. }
  4491. Cleanup:
  4492. if (EncodedData.value != NULL)
  4493. {
  4494. LsapFreeLsaHeap(EncodedData.value);
  4495. }
  4496. if (ResponseBuffer.pvBuffer != NULL)
  4497. {
  4498. LsapFreeLsaHeap(ResponseBuffer.pvBuffer);
  4499. }
  4500. if (MappedBuffer.pvBuffer != NULL)
  4501. {
  4502. LsapFreeLsaHeap(MappedBuffer.pvBuffer);
  4503. }
  4504. #endif // WIN32_CHICAGO
  4505. return(scRet);
  4506. }
  4507. //+-------------------------------------------------------------------------
  4508. //
  4509. // Function: NegHandleClientRequest
  4510. //
  4511. // Synopsis: Handles a call to AcceptSecurityContext other than an
  4512. // initial one with no input. This routine either figures our
  4513. // what package to call or calls a package already selected to
  4514. // do the Accept.
  4515. //
  4516. // Effects:
  4517. //
  4518. // Arguments:
  4519. //
  4520. // Requires:
  4521. //
  4522. // Returns:
  4523. //
  4524. // Notes:
  4525. //
  4526. //
  4527. //--------------------------------------------------------------------------
  4528. SECURITY_STATUS
  4529. NegHandleClientRequest(
  4530. ULONG_PTR dwCreds,
  4531. PNEG_CONTEXT pContext,
  4532. ULONG fContextReq,
  4533. ULONG TargetDataRep,
  4534. PSecBufferDesc pInput,
  4535. PULONG_PTR pdwNewContext,
  4536. PSecBufferDesc pOutput,
  4537. PULONG pfContextAttr,
  4538. PTimeStamp ptsExpiry,
  4539. PBYTE pfMapContext,
  4540. PSecBuffer pContextData )
  4541. {
  4542. PNEG_CREDS Creds ;
  4543. PNEG_CONTEXT Context ;
  4544. SECURITY_STATUS scRet ;
  4545. SECURITY_STATUS MapStatus ;
  4546. NegotiationToken * Request = NULL ;
  4547. InitialNegToken * InitialRequest = NULL;
  4548. NegotiationToken Response = {0};
  4549. ASN1octetstring_t EncodedData ;
  4550. int Result ;
  4551. ULONG Pdu = InitialNegToken_PDU;
  4552. PSecBuffer Buffer ;
  4553. PSecBuffer pToken ;
  4554. PNEG_PACKAGE Package;
  4555. NEG_MATCH DesiredMatch;
  4556. SecBufferDesc AcceptBufferDesc;
  4557. SecBuffer AcceptBuffer;
  4558. SecBufferDesc ResponseBufferDesc;
  4559. SecBuffer ResponseBuffer;
  4560. SecBuffer UserResponseBuffer; // use user buffer for in-place operations if large enough
  4561. struct MechTypeList *MechList = NULL;
  4562. CtxtHandle TempHandle;
  4563. struct _enum1 * Results;
  4564. ULONG_PTR PackageId;
  4565. BOOLEAN CredentialReferenced = FALSE;
  4566. //
  4567. // Initialize stuff:
  4568. //
  4569. ResponseBuffer.pvBuffer = NULL;
  4570. Creds = (PNEG_CREDS) dwCreds ;
  4571. Context = pContext ;
  4572. if ( ( Creds == NULL ) &&
  4573. ( Context != NULL ) )
  4574. {
  4575. Creds = Context->Creds ;
  4576. }
  4577. //
  4578. // First, verify the input buffer contains a Request token, and crack it.
  4579. //
  4580. scRet = NegpParseBuffers( pInput, TRUE, &Buffer, NULL );
  4581. if ( !Buffer )
  4582. {
  4583. return( SEC_E_INVALID_TOKEN );
  4584. }
  4585. if ( !NT_SUCCESS( scRet ) )
  4586. {
  4587. return( scRet );
  4588. }
  4589. //
  4590. // Verify that we have an output buffer
  4591. //
  4592. scRet = NegpParseBuffers( pOutput, TRUE, &pToken, NULL );
  4593. if ( !NT_SUCCESS( scRet ) ||
  4594. ( pToken == NULL ) )
  4595. {
  4596. goto Cleanup ;
  4597. }
  4598. //
  4599. // We need a return token
  4600. //
  4601. if (pToken == NULL)
  4602. {
  4603. DebugLog((DEB_TRACE_NEG,"No output token for NegHandleClientRequest\n"));
  4604. scRet = SEC_E_INVALID_TOKEN;
  4605. goto Cleanup;
  4606. }
  4607. //
  4608. // Compatibility:
  4609. //
  4610. // If we get a zero length blob, and the context has completed,
  4611. // it means we're dealing with old clients
  4612. //
  4613. if ( ( Buffer->cbBuffer == 0 ) &&
  4614. ( Context ) )
  4615. {
  4616. pToken->cbBuffer = 0 ;
  4617. if ( Context->LastStatus != STATUS_SUCCESS )
  4618. {
  4619. return SEC_E_INVALID_TOKEN ;
  4620. }
  4621. #ifndef WIN32_CHICAGO
  4622. if (Context->Mapped)
  4623. {
  4624. *pfMapContext = Context->Mapped;
  4625. *pContextData = Context->MappedBuffer;
  4626. RtlZeroMemory(
  4627. &Context->MappedBuffer,
  4628. sizeof(SecBuffer)
  4629. );
  4630. }
  4631. //
  4632. // Whack the output handle with the one returned from the
  4633. // package.
  4634. //
  4635. LsapChangeHandle( HandleReplace,
  4636. NULL,
  4637. &Context->Handle );
  4638. Context->Handle.dwLower = 0 ;
  4639. Context->Handle.dwUpper = 0 ;
  4640. *ptsExpiry = Context->Expiry ;
  4641. pToken->cbBuffer = 0 ;
  4642. Context = NULL ;
  4643. return STATUS_SUCCESS ;
  4644. #endif
  4645. }
  4646. EncodedData.value = (PUCHAR) Buffer->pvBuffer ;
  4647. EncodedData.length = Buffer->cbBuffer ;
  4648. Request = NULL ;
  4649. Result = SpnegoUnpackData(
  4650. EncodedData.value,
  4651. EncodedData.length,
  4652. Pdu,
  4653. (PVOID *)&InitialRequest);
  4654. //
  4655. // If unable, try it as a second-pass.
  4656. //
  4657. if ( Result != 0 )
  4658. {
  4659. Pdu = NegotiationToken_PDU;
  4660. Result = SpnegoUnpackData(
  4661. EncodedData.value,
  4662. EncodedData.length,
  4663. Pdu,
  4664. (PVOID *)&Request);
  4665. //
  4666. // if the token didn't match either, give up now.
  4667. //
  4668. if (Result != 0)
  4669. {
  4670. #ifndef WIN32_CHICAGO
  4671. NegpReportEvent(
  4672. EVENTLOG_WARNING_TYPE,
  4673. NEGOTIATE_UNKNOWN_PACKET,
  4674. CATEGORY_NEGOTIATE,
  4675. 0,
  4676. 0 );
  4677. #endif
  4678. return(SEC_E_INVALID_TOKEN);
  4679. }
  4680. }
  4681. else
  4682. {
  4683. Request = &InitialRequest->negToken;
  4684. }
  4685. //
  4686. // This function only handles Negotiation tokens. If we ended up with
  4687. // anything else, something is wrong.
  4688. //
  4689. if ( (Pdu != NegotiationToken_PDU) &&
  4690. (Pdu != InitialNegToken_PDU) )
  4691. {
  4692. scRet = SEC_E_INVALID_TOKEN ;
  4693. goto Cleanup ;
  4694. }
  4695. //
  4696. // If this is an initial request, verify the OID
  4697. //
  4698. if (InitialRequest != NULL)
  4699. {
  4700. if (NegpCompareOid(
  4701. NegSpnegoMechOid,
  4702. InitialRequest->spnegoMech
  4703. ))
  4704. {
  4705. scRet = SEC_E_INVALID_TOKEN;
  4706. goto Cleanup;
  4707. }
  4708. }
  4709. //
  4710. // Check to see if we already called Accept once on a package. If so,
  4711. // we want to use the existing context handle.
  4712. //
  4713. if ( Request->choice == negTokenTarg_chosen )
  4714. {
  4715. return(NegHandleSubsequentClientRequest(
  4716. dwCreds,
  4717. pContext,
  4718. fContextReq,
  4719. TargetDataRep,
  4720. Pdu,
  4721. Request,
  4722. pdwNewContext,
  4723. pOutput,
  4724. pfContextAttr,
  4725. ptsExpiry,
  4726. pfMapContext,
  4727. pContextData ) );
  4728. }
  4729. //
  4730. // Ok, we have a request blob. Figure out what they want,
  4731. //
  4732. NegReadLockCreds( Creds );
  4733. scRet = NegpCrackRequest( Creds,
  4734. Request,
  4735. & PackageId,
  4736. & MechList,
  4737. & Package,
  4738. & DesiredMatch );
  4739. if ( !NT_SUCCESS( scRet ) )
  4740. {
  4741. NegUnlockCreds( Creds );
  4742. goto Cleanup ;
  4743. }
  4744. if (DesiredMatch == MatchFailed)
  4745. {
  4746. //
  4747. // There were no common packages, so return an error.
  4748. //
  4749. NegUnlockCreds( Creds );
  4750. #ifndef WIN32_CHICAGO
  4751. NegpReportEvent(
  4752. EVENTLOG_WARNING_TYPE,
  4753. NEGOTIATE_UNKNOWN_PACKAGE,
  4754. CATEGORY_NEGOTIATE,
  4755. 0,
  4756. 0 );
  4757. #endif
  4758. DebugLog(( DEB_TRACE, "No common packages for negotiator\n"));
  4759. scRet = SEC_E_INVALID_TOKEN;
  4760. goto Cleanup;
  4761. }
  4762. DsysAssert( Package != NULL );
  4763. //
  4764. // Found a common package. Was it the first one in the request
  4765. // list? If so, then check for a desired token and pass it down
  4766. // to the other package
  4767. //
  4768. DebugLog(( DEB_TRACE_NEG, "Common Package is %ws\n",
  4769. Package->LsaPackage->Name.Buffer ));
  4770. Response.choice = negTokenTarg_chosen ;
  4771. Response.u.negTokenTarg.supportedMech = Package->ObjectId ;
  4772. Response.u.negTokenTarg.bit_mask |= supportedMech_present | negResult_present;
  4773. if ( !Context )
  4774. {
  4775. Context = NegpCreateContext();
  4776. if ( !Context )
  4777. {
  4778. NegUnlockCreds( Creds );
  4779. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  4780. goto Cleanup ;
  4781. }
  4782. }
  4783. //
  4784. // Save away the mechlist for the mic at the end
  4785. //
  4786. if ( Context->SupportedMechs )
  4787. {
  4788. if ((Context->Flags & NEG_CONTEXT_FREE_EACH_MECH))
  4789. {
  4790. NegpFreeMechList(Context->SupportedMechs);
  4791. }
  4792. else
  4793. {
  4794. LsapFreeLsaHeap(Context->SupportedMechs);
  4795. }
  4796. }
  4797. Context->SupportedMechs = NegpCopyMechList(MechList);
  4798. if (Context->SupportedMechs == NULL)
  4799. {
  4800. NegUnlockCreds(Creds);
  4801. scRet = SEC_E_INSUFFICIENT_MEMORY;
  4802. goto Cleanup ;
  4803. }
  4804. Context->Flags |= NEG_CONTEXT_FREE_EACH_MECH;
  4805. DebugLog(( DEB_TRACE_NEG, "Adding mech list for %p\n", Context));
  4806. //
  4807. // Reference the credentials so they don't go away before we
  4808. // finish with the context.
  4809. //
  4810. if (Context->Creds == NULL)
  4811. {
  4812. Context->Creds = Creds ;
  4813. NegUnlockCreds(Creds);
  4814. NegWriteLockCreds(Creds);
  4815. Creds->RefCount++;
  4816. NegUnlockCreds(Creds);
  4817. NegReadLockCreds(Creds);
  4818. }
  4819. Context->CredIndex = PackageId ;
  4820. if ( ( DesiredMatch == PreferredSucceed ) &&
  4821. ( Request->u.negTokenInit.bit_mask & NegTokenInit_mechToken_present ) )
  4822. {
  4823. CredHandle TempCredHandle;
  4824. #ifndef WIN32_CHICAGO
  4825. NegpReportEvent(
  4826. EVENTLOG_INFORMATION_TYPE,
  4827. NEGOTIATE_MESSAGE_DECODED,
  4828. CATEGORY_NEGOTIATE,
  4829. 0,
  4830. 1,
  4831. &Package->LsaPackage->Name
  4832. );
  4833. #endif
  4834. DebugLog(( DEB_TRACE_NEG, "Desired Package match with token!\n"));
  4835. TempHandle = Context->Handle ;
  4836. PackageId = GetCurrentPackageId();
  4837. TempCredHandle = Creds->Creds[ Context->CredIndex ].Handle;
  4838. //
  4839. // Unlock the credentials while we make the call
  4840. //
  4841. NegUnlockCreds(Creds);
  4842. //
  4843. // Build up a buffer for accept
  4844. //
  4845. AcceptBuffer.pvBuffer = Request->u.negTokenInit.mechToken.value;
  4846. AcceptBuffer.cbBuffer = Request->u.negTokenInit.mechToken.length;
  4847. AcceptBuffer.BufferType = SECBUFFER_READONLY | SECBUFFER_TOKEN ;
  4848. AcceptBufferDesc.ulVersion = SECBUFFER_VERSION ;
  4849. AcceptBufferDesc.cBuffers = 1;
  4850. AcceptBufferDesc.pBuffers = &AcceptBuffer ;
  4851. ResponseBufferDesc.ulVersion = SECBUFFER_VERSION ;
  4852. ResponseBufferDesc.cBuffers = 1;
  4853. if( pToken->cbBuffer >= Package->LsaPackage->TokenSize )
  4854. {
  4855. UserResponseBuffer.cbBuffer = pToken->cbBuffer;
  4856. UserResponseBuffer.BufferType = SECBUFFER_TOKEN ;
  4857. UserResponseBuffer.pvBuffer = pToken->pvBuffer;
  4858. ResponseBufferDesc.pBuffers = &UserResponseBuffer ;
  4859. } else {
  4860. ResponseBuffer.cbBuffer = Package->LsaPackage->TokenSize ;
  4861. ResponseBuffer.BufferType = SECBUFFER_TOKEN ;
  4862. ResponseBuffer.pvBuffer = LsapAllocateLsaHeap(
  4863. ResponseBuffer.cbBuffer );
  4864. if ( ResponseBuffer.pvBuffer == NULL )
  4865. {
  4866. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  4867. goto Cleanup ;
  4868. }
  4869. ResponseBufferDesc.pBuffers = &ResponseBuffer ;
  4870. }
  4871. #ifndef WIN32_CHICAGO
  4872. scRet = WLsaAcceptContext(
  4873. &TempCredHandle,
  4874. &TempHandle,
  4875. &AcceptBufferDesc,
  4876. (fContextReq & (~(ASC_REQ_ALLOCATE_MEMORY))),
  4877. SECURITY_NATIVE_DREP,
  4878. &Context->Handle,
  4879. &ResponseBufferDesc,
  4880. &Context->Attributes,
  4881. &Context->Expiry,
  4882. &Context->Mapped,
  4883. &Context->MappedBuffer );
  4884. #else
  4885. scRet = AcceptSecurityContext(
  4886. &TempCredHandle,
  4887. &TempHandle,
  4888. &AcceptBufferDesc,
  4889. (fContextReq & (~(ASC_REQ_ALLOCATE_MEMORY))),
  4890. SECURITY_NATIVE_DREP,
  4891. &Context->Handle,
  4892. &ResponseBufferDesc,
  4893. &Context->Attributes,
  4894. &Context->Expiry
  4895. );
  4896. #endif // WIN32_CHICAGO
  4897. SetCurrentPackageId( PackageId );
  4898. Context->CallCount++ ;
  4899. DebugLog(( DEB_TRACE_NEG, "WLsaAcceptContext( %ws ) returned %x\n",
  4900. Creds->Creds[ Context->CredIndex ].Package->LsaPackage->Name.Buffer,
  4901. scRet ));
  4902. if ( !NT_SUCCESS( scRet ) )
  4903. {
  4904. DebugLog((DEB_TRACE, "Neg Failure from package %ws, %#x\n",
  4905. Package->LsaPackage->Name.Buffer, scRet ));
  4906. if( ResponseBuffer.pvBuffer )
  4907. {
  4908. LsapFreeLsaHeap( ResponseBuffer.pvBuffer );
  4909. }
  4910. goto Cleanup ;
  4911. }
  4912. NegReadLockCreds(Creds);
  4913. if ( NT_SUCCESS( scRet ) &&
  4914. (Context->Attributes & ASC_RET_EXTENDED_ERROR ) )
  4915. {
  4916. if ( (Creds->Flags & (NEGCRED_MULTI | NEGCRED_MULTI_PART)) != 0 )
  4917. {
  4918. scRet = SEC_E_LOGON_DENIED ;
  4919. DebugLog(( DEB_TRACE, "Multi-cred failure, no return message\n" ));
  4920. NegUnlockCreds( Creds );
  4921. if( ResponseBuffer.pvBuffer )
  4922. {
  4923. LsapFreeLsaHeap( ResponseBuffer.pvBuffer );
  4924. }
  4925. goto Cleanup ;
  4926. }
  4927. }
  4928. //
  4929. // Now: push that info back out to our caller,
  4930. //
  4931. Context->LastStatus = scRet ;
  4932. //
  4933. // Mark the context to indicate that we already called
  4934. // AcceptSecurityContext once.
  4935. //
  4936. Context->Flags |= NEG_CONTEXT_PACKAGE_CALLED;
  4937. //
  4938. // Set the response pointers up so they get folded in to the
  4939. // response packet
  4940. //
  4941. Response.u.negTokenTarg.responseToken.length = ResponseBufferDesc.pBuffers[0].cbBuffer ;
  4942. Response.u.negTokenTarg.responseToken.value = (PUCHAR) ResponseBufferDesc.pBuffers[0].pvBuffer ;
  4943. Response.u.negTokenTarg.bit_mask |= responseToken_present ;
  4944. *ptsExpiry = Context->Expiry;
  4945. *pfContextAttr = Context->Attributes;
  4946. if (scRet == STATUS_SUCCESS)
  4947. {
  4948. Response.u.negTokenTarg.negResult = accept_completed;
  4949. //
  4950. // Generate a MIC here
  4951. //
  4952. //
  4953. // Get rid of the mech list now, since
  4954. // it has been mic'd. As it were.
  4955. //
  4956. if ( Context->SupportedMechs )
  4957. {
  4958. DebugLog(( DEB_TRACE_NEG, "Freeing mech list for %p\n", Context ));
  4959. NegpFreeMechList( Context->SupportedMechs );
  4960. Context->SupportedMechs = NULL ;
  4961. }
  4962. // scRet = SEC_I_CONTINUE_NEEDED ;
  4963. }
  4964. else
  4965. {
  4966. DsysAssert((scRet == SEC_I_CONTINUE_NEEDED) ||
  4967. (scRet == SEC_I_COMPLETE_NEEDED) ||
  4968. (scRet == SEC_I_COMPLETE_AND_CONTINUE))
  4969. Response.u.negTokenTarg.negResult = accept_incomplete;
  4970. }
  4971. //
  4972. // Fall through to rest of handling
  4973. //
  4974. }
  4975. else
  4976. {
  4977. //
  4978. // We have a common package, but either there is no desired token
  4979. // present, or the common package was not the desired one. The
  4980. // selected package is in the structure already, so we don't have
  4981. // to do anything here.
  4982. //
  4983. #ifndef WIN32_CHICAGO
  4984. NegpReportEvent(
  4985. EVENTLOG_INFORMATION_TYPE,
  4986. NEGOTIATE_MESSAGE_DECODED_NO_TOKEN,
  4987. CATEGORY_NEGOTIATE,
  4988. 0,
  4989. 1,
  4990. &Package->LsaPackage->Name
  4991. );
  4992. #endif
  4993. scRet = SEC_I_CONTINUE_NEEDED;
  4994. DebugLog(( DEB_TRACE_NEG, "Common package has no token\n"));
  4995. Response.u.negTokenTarg.negResult = accept_incomplete;
  4996. }
  4997. NegUnlockCreds( Creds );
  4998. //
  4999. // Assemble reply token:
  5000. //
  5001. EncodedData.value = 0 ;
  5002. EncodedData.length = 0 ;
  5003. Result = SpnegoPackData(
  5004. &Response,
  5005. NegotiationToken_PDU,
  5006. &(EncodedData.length),
  5007. &(EncodedData.value));
  5008. //
  5009. // Clean up:
  5010. //
  5011. if ( ResponseBuffer.pvBuffer )
  5012. {
  5013. LsapFreeLsaHeap( ResponseBuffer.pvBuffer );
  5014. ResponseBuffer.pvBuffer = NULL ;
  5015. }
  5016. if (InitialRequest != NULL)
  5017. {
  5018. SpnegoFreeData( Pdu, InitialRequest );
  5019. InitialRequest = NULL;
  5020. Request = NULL;
  5021. }
  5022. else if ( Request )
  5023. {
  5024. SpnegoFreeData( Pdu, Request );
  5025. Request = NULL;
  5026. }
  5027. if ( Result )
  5028. {
  5029. DebugLog((DEB_ERROR, "Failed to encode data: %d\n", Result ));
  5030. scRet = SEC_E_INVALID_TOKEN ;
  5031. goto Cleanup ;
  5032. }
  5033. else
  5034. {
  5035. if ( fContextReq & ASC_REQ_ALLOCATE_MEMORY )
  5036. {
  5037. pToken->pvBuffer = EncodedData.value ;
  5038. *pfContextAttr |= ASC_RET_ALLOCATED_MEMORY ;
  5039. EncodedData.value = NULL ;
  5040. pToken->cbBuffer = EncodedData.length ;
  5041. }
  5042. else
  5043. {
  5044. if ( pToken->cbBuffer >= (ULONG) EncodedData.length )
  5045. {
  5046. RtlCopyMemory( pToken->pvBuffer,
  5047. EncodedData.value,
  5048. EncodedData.length );
  5049. pToken->cbBuffer = EncodedData.length ;
  5050. }
  5051. else if ( ( ( fContextReq & ASC_REQ_FRAGMENT_TO_FIT ) != 0 ) &&
  5052. ( pToken->cbBuffer >= SPNEGO_MINIMUM_BUFFER ) )
  5053. {
  5054. //
  5055. // Ok, we need to whack the context to indicate that we are
  5056. // fragmenting, and return only what the caller can handle.
  5057. //
  5058. Context->Message = EncodedData.value ;
  5059. Context->TotalSize = EncodedData.length ;
  5060. Context->Flags |= NEG_CONTEXT_FRAGMENTING ;
  5061. //
  5062. // set this to NULL so it doesn't get freed later
  5063. //
  5064. EncodedData.value = NULL ;
  5065. RtlCopyMemory(
  5066. pToken->pvBuffer,
  5067. Context->Message,
  5068. pToken->cbBuffer );
  5069. Context->CurrentSize = pToken->cbBuffer ;
  5070. }
  5071. else
  5072. {
  5073. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  5074. goto Cleanup ;
  5075. }
  5076. }
  5077. //
  5078. // If the context has been mapped by the underlying package,
  5079. // get out of the way:
  5080. //
  5081. #ifndef WIN32_CHICAGO
  5082. if ( scRet == SEC_E_OK )
  5083. {
  5084. if ( Context->Mapped )
  5085. {
  5086. *pfContextAttr = Context->Attributes ;
  5087. if ( fContextReq & ASC_REQ_ALLOCATE_MEMORY )
  5088. {
  5089. *pfContextAttr |= ASC_RET_ALLOCATED_MEMORY ;
  5090. }
  5091. *ptsExpiry = Context->Expiry ;
  5092. *pfMapContext = Context->Mapped ;
  5093. *pContextData = Context->MappedBuffer ;
  5094. //
  5095. // Set this to NULL so we don't later try
  5096. // to free it.
  5097. //
  5098. Context->MappedBuffer.pvBuffer = NULL ;
  5099. }
  5100. LsapChangeHandle( HandleReplace,
  5101. NULL,
  5102. &Context->Handle );
  5103. Context->Handle.dwLower = 0 ;
  5104. Context->Handle.dwUpper = 0 ;
  5105. if ( !pContext )
  5106. {
  5107. //
  5108. // If we created this context during this call, get
  5109. // rid of it now
  5110. //
  5111. NegpDeleteContext( Context );
  5112. }
  5113. Context = NULL ;
  5114. }
  5115. else
  5116. #endif // WIN32_CHICAGO
  5117. {
  5118. *pdwNewContext = (DWORD_PTR) Context ;
  5119. }
  5120. }
  5121. if ( EncodedData.value )
  5122. {
  5123. LsapFreeLsaHeap( EncodedData.value );
  5124. }
  5125. return( scRet );
  5126. Cleanup:
  5127. if (InitialRequest != NULL)
  5128. {
  5129. SpnegoFreeData( Pdu, InitialRequest );
  5130. }
  5131. else if ( Request )
  5132. {
  5133. SpnegoFreeData( Pdu, Request );
  5134. }
  5135. if ( Context )
  5136. {
  5137. if ( Context->Handle.dwLower )
  5138. {
  5139. #ifndef WIN32_CHICAGO
  5140. WLsaDeleteContext( &Context->Handle );
  5141. #else
  5142. DeleteSecurityContext( &Context->Handle );
  5143. #endif // WIN32_CHICAGO
  5144. Context->Handle.dwLower = 0;
  5145. }
  5146. if ( pContext == NULL )
  5147. {
  5148. NegpDeleteContext( Context );
  5149. }
  5150. }
  5151. return( scRet );
  5152. }
  5153. //+-------------------------------------------------------------------------
  5154. //
  5155. // Function: NegHandleServerReply
  5156. //
  5157. // Synopsis: Handles a subsequent call to InitializeSecurityContext
  5158. //
  5159. // Effects:
  5160. //
  5161. // Arguments:
  5162. //
  5163. // Requires:
  5164. //
  5165. // Returns:
  5166. //
  5167. // Notes:
  5168. //
  5169. //
  5170. //--------------------------------------------------------------------------
  5171. SECURITY_STATUS
  5172. NegHandleServerReply(
  5173. ULONG_PTR dwCreds,
  5174. PNEG_CONTEXT pContext,
  5175. PSECURITY_STRING Target,
  5176. ULONG fContextReq,
  5177. ULONG TargetDataRep,
  5178. PSecBufferDesc pInput,
  5179. PULONG_PTR pdwNewContext,
  5180. PSecBufferDesc pOutput,
  5181. PULONG pfContextAttr,
  5182. PTimeStamp ptsExpiry,
  5183. PBYTE pfMapContext,
  5184. PSecBuffer pContextData)
  5185. {
  5186. SECURITY_STATUS scRet;
  5187. NegotiationToken * Reply = NULL ;
  5188. NegotiationToken Request;
  5189. ASN1octetstring_t EncodedData = {0};
  5190. int Result;
  5191. ULONG Pdu = NegotiationToken_PDU;
  5192. PSecBuffer Buffer;
  5193. struct MechTypeList *pMechs;
  5194. PNEG_CREDS Creds;
  5195. PNEG_CONTEXT Context ;
  5196. ULONG_PTR PackageIndex ;
  5197. PNEG_PACKAGE Package ;
  5198. SecBuffer InitBuffer ;
  5199. SecBufferDesc InitBufferDesc ;
  5200. ULONG_PTR PackageId ;
  5201. PCtxtHandle pInitHandle ;
  5202. CtxtHandle TempHandle = { 0, 0 };
  5203. ULONG LocalContextReq = fContextReq;
  5204. ULONG LocalContextAttr = 0 ;
  5205. BOOLEAN ClientFinished = FALSE;
  5206. BOOLEAN ServerFinished = FALSE;
  5207. SecBuffer OutputToken = {0};
  5208. SecBufferDesc OutputDescription ;
  5209. PSecBuffer OutputBuffer = NULL;
  5210. CredHandle TempCredHandle ;
  5211. RtlZeroMemory(
  5212. &Request,
  5213. sizeof(NegotiationToken)
  5214. );
  5215. RtlZeroMemory(
  5216. &OutputToken,
  5217. sizeof(SecBuffer)
  5218. );
  5219. //
  5220. // Find the token buffer:
  5221. //
  5222. scRet = NegpParseBuffers( pInput, TRUE, &Buffer, NULL );
  5223. if ( !NT_SUCCESS( scRet ) )
  5224. {
  5225. return( scRet );
  5226. }
  5227. if ( !Buffer )
  5228. {
  5229. return( SEC_E_INVALID_TOKEN );
  5230. }
  5231. scRet = NegpParseBuffers( pOutput, TRUE, &OutputBuffer, NULL );
  5232. if (!NT_SUCCESS(scRet))
  5233. {
  5234. goto HSR_ErrorReturn;
  5235. }
  5236. //
  5237. // Get the credential handle. If it wasn't passed in, use the one from
  5238. // the context.
  5239. //
  5240. if (dwCreds != 0)
  5241. {
  5242. Creds = (PNEG_CREDS) dwCreds ;
  5243. }
  5244. else
  5245. {
  5246. Creds = pContext->Creds;
  5247. }
  5248. Context = pContext ;
  5249. NegpValidContext( Context );
  5250. //
  5251. // Decode the reply token:
  5252. //
  5253. EncodedData.value = (PUCHAR) Buffer->pvBuffer ;
  5254. EncodedData.length = Buffer->cbBuffer ;
  5255. Reply = NULL ;
  5256. Result = SpnegoUnpackData(
  5257. EncodedData.value,
  5258. EncodedData.length,
  5259. Pdu,
  5260. (PVOID *)&Reply);
  5261. //
  5262. // Reset the encoded data value so we don't free it accidentally
  5263. //
  5264. EncodedData.value = NULL;
  5265. if ( Result != 0 )
  5266. {
  5267. DebugLog(( DEB_TRACE_NEG, "Unknown token from server: %d\n", Result ));
  5268. scRet = SEC_E_INVALID_TOKEN ;
  5269. goto HSR_ErrorReturn ;
  5270. }
  5271. if ( Reply->choice != negTokenTarg_chosen )
  5272. {
  5273. DebugLog(( DEB_TRACE_NEG, "Found Request token, expecting Reply token\n" ));
  5274. scRet = SEC_E_INVALID_TOKEN ;
  5275. goto HSR_ErrorReturn ;
  5276. }
  5277. if ((Reply->u.negTokenTarg.bit_mask & negResult_present) != 0)
  5278. {
  5279. if (Reply->u.negTokenTarg.negResult == reject)
  5280. {
  5281. DebugLog((DEB_TRACE_NEG,"Server rejected\n"));
  5282. scRet = SEC_E_LOGON_DENIED;
  5283. goto HSR_ErrorReturn;
  5284. }
  5285. if (Reply->u.negTokenTarg.negResult == accept_completed)
  5286. {
  5287. ServerFinished = TRUE;
  5288. }
  5289. }
  5290. //
  5291. // Ok, see what the server sent us. In an ideal world, the server will send
  5292. // us a preferred, chosen token.
  5293. //
  5294. InitBuffer.pvBuffer = NULL ;
  5295. InitBuffer.cbBuffer = 0 ;
  5296. InitBuffer.BufferType = SECBUFFER_TOKEN ;
  5297. InitBufferDesc.ulVersion = SECBUFFER_VERSION ;
  5298. InitBufferDesc.cBuffers = 1 ;
  5299. InitBufferDesc.pBuffers = &InitBuffer ;
  5300. if ( Reply->u.negTokenTarg.bit_mask & supportedMech_present )
  5301. {
  5302. NegReadLockCreds( Creds );
  5303. PackageIndex = NegpFindPackageForOid( Creds,
  5304. Reply->u.negTokenTarg.supportedMech );
  5305. if ( PackageIndex == NEG_INVALID_PACKAGE )
  5306. {
  5307. NegUnlockCreds( Creds );
  5308. NegDumpOid( "Invalid OID returned by server",
  5309. Reply->u.negTokenTarg.supportedMech );
  5310. scRet = SEC_E_INVALID_TOKEN ;
  5311. goto HSR_ErrorReturn ;
  5312. }
  5313. Package = Creds->Creds[ PackageIndex ].Package ;
  5314. NegUnlockCreds( Creds );
  5315. DebugLog(( DEB_TRACE_NEG, "Server supports %ws!\n",
  5316. Package->LsaPackage->Name.Buffer ));
  5317. if ( Reply->u.negTokenTarg.bit_mask & responseToken_present )
  5318. {
  5319. //
  5320. // Oh boy! A Token too!
  5321. //
  5322. InitBuffer.pvBuffer = Reply->u.negTokenTarg.responseToken.value ;
  5323. InitBuffer.cbBuffer = (ULONG) Reply->u.negTokenTarg.responseToken.length ;
  5324. Context->Flags |= NEG_CONTEXT_UPLEVEL ;
  5325. }
  5326. else if ( Reply->u.negTokenTarg.bit_mask & NegTokenTarg_mechListMIC_present )
  5327. {
  5328. InitBuffer.pvBuffer = Reply->u.negTokenTarg.mechListMIC.value ;
  5329. InitBuffer.cbBuffer = Reply->u.negTokenTarg.mechListMIC.length ;
  5330. }
  5331. }
  5332. else
  5333. {
  5334. //
  5335. // If we haven't settled on a package yet, we need a mechanism.
  5336. //
  5337. if ((Context->Flags & NEG_CONTEXT_PACKAGE_CALLED ) == 0)
  5338. {
  5339. //
  5340. // No token specified, nor preferred mechanism. Find the first
  5341. // acceptible package in the returned list
  5342. //
  5343. DebugLog((DEB_TRACE_NEG, "No preferred mech from the server?\n"));
  5344. DebugLog(( DEB_TRACE_NEG, "We must drop into GSS only mode for this to work\n"));
  5345. DebugLog(( DEB_ERROR, "No preferred mech from server, not handled yet\n"));
  5346. return( SEC_E_INVALID_TOKEN );
  5347. }
  5348. NegReadLockCreds( Creds );
  5349. Package = Creds->Creds[ Context->CredIndex ].Package ;
  5350. PackageIndex = Context->CredIndex;
  5351. NegUnlockCreds( Creds );
  5352. if ( Reply->u.negTokenTarg.bit_mask & responseToken_present )
  5353. {
  5354. //
  5355. // Oh boy! A Token too!
  5356. //
  5357. InitBuffer.pvBuffer = Reply->u.negTokenTarg.responseToken.value ;
  5358. InitBuffer.cbBuffer = (ULONG) Reply->u.negTokenTarg.responseToken.length ;
  5359. Context->Flags |= NEG_CONTEXT_UPLEVEL ;
  5360. }
  5361. else if ( Reply->u.negTokenTarg.bit_mask & NegTokenTarg_mechListMIC_present )
  5362. {
  5363. InitBuffer.pvBuffer = Reply->u.negTokenTarg.mechListMIC.value ;
  5364. InitBuffer.cbBuffer = Reply->u.negTokenTarg.mechListMIC.length ;
  5365. }
  5366. }
  5367. DebugLog(( DEB_TRACE_NEG, "Calling package %ws\n",
  5368. Package->LsaPackage->Name.Buffer ));
  5369. //
  5370. // Call into the package, possibly again, possibly the first time, and
  5371. // let the package have at it.
  5372. //
  5373. if ( (Context->CredIndex != PackageIndex) &&
  5374. ((Context->Flags & NEG_CONTEXT_PACKAGE_CALLED) != 0) )
  5375. {
  5376. DebugLog(( DEB_TRACE_NEG, "Switched packages, package %ws not selected anymore\n",
  5377. Creds->Creds[Context->CredIndex].Package->LsaPackage->Name.Buffer ));
  5378. //
  5379. // Got to delete the context:
  5380. //
  5381. PackageId = GetCurrentPackageId();
  5382. #ifndef WIN32_CHICAGO
  5383. WLsaDeleteContext( &Context->Handle );
  5384. #else
  5385. DeleteSecurityContext( &Context->Handle );
  5386. #endif // WIN32_CHICAGO
  5387. SetCurrentPackageId( PackageId );
  5388. Context->Flags &= ~NEG_CONTEXT_PACKAGE_CALLED;
  5389. //
  5390. // Clean up the context information in the handle
  5391. //
  5392. if ( Context->MappedBuffer.pvBuffer != NULL)
  5393. {
  5394. LsapFreeLsaHeap(
  5395. Context->MappedBuffer.pvBuffer
  5396. );
  5397. Context->MappedBuffer.pvBuffer = NULL;
  5398. Context->MappedBuffer.cbBuffer = 0;
  5399. }
  5400. Context->Mapped = FALSE;
  5401. //
  5402. // Reset the last status to make sure we call Initailize again.
  5403. //
  5404. Context->LastStatus = SEC_I_CONTINUE_NEEDED;
  5405. //
  5406. // Don't modify TempHandle which is already set to 0,0
  5407. //
  5408. }
  5409. else
  5410. {
  5411. TempHandle = Context->Handle ;
  5412. }
  5413. if ( Context->LastStatus == SEC_I_CONTINUE_NEEDED )
  5414. {
  5415. BOOLEAN LocalContextMapped = FALSE;
  5416. SecBuffer LocalContextData = {0,0,NULL};
  5417. PackageId = GetCurrentPackageId();
  5418. //
  5419. // Client side call. Here, we call down to the desired package,
  5420. // and have it generate a blob to be encoded and sent over to the
  5421. // server.
  5422. //
  5423. #ifndef WIN32_CHICAGO
  5424. OutputToken.pvBuffer = NULL;
  5425. OutputToken.cbBuffer = 0;
  5426. OutputToken.BufferType = SECBUFFER_TOKEN ;
  5427. OutputDescription.ulVersion = SECBUFFER_VERSION ;
  5428. OutputDescription.cBuffers = 1;
  5429. OutputDescription.pBuffers = &OutputToken ;
  5430. LocalContextReq |= ISC_REQ_ALLOCATE_MEMORY ;
  5431. LocalContextAttr = 0;
  5432. #else
  5433. OutputToken.pvBuffer = LocalAlloc(0, Creds->Creds[PackageIndex].Package->LsaPackage->TokenSize);
  5434. OutputToken.cbBuffer = Creds->Creds[PackageIndex].Package->LsaPackage->TokenSize;
  5435. OutputToken.BufferType = SECBUFFER_TOKEN ;
  5436. OutputDescription.ulVersion = SECBUFFER_VERSION ;
  5437. OutputDescription.cBuffers = 1;
  5438. OutputDescription.pBuffers = &OutputToken ;
  5439. LocalContextAttr = 0;
  5440. #endif
  5441. TempCredHandle = Creds->Creds[ PackageIndex ].Handle ;
  5442. #ifndef WIN32_CHICAGO
  5443. scRet = WLsaInitContext(&TempCredHandle,
  5444. &TempHandle,
  5445. &Context->Target,
  5446. LocalContextReq,
  5447. 0,
  5448. TargetDataRep,
  5449. &InitBufferDesc,
  5450. 0,
  5451. &Context->Handle,
  5452. &OutputDescription,
  5453. &LocalContextAttr,
  5454. ptsExpiry,
  5455. &LocalContextMapped,
  5456. &LocalContextData );
  5457. #else
  5458. ANSI_STRING TempAnsiString;
  5459. NTSTATUS TempStatus = RtlUnicodeStringToAnsiString(
  5460. &TempAnsiString,
  5461. &Context->Target,
  5462. TRUE // allocate destination
  5463. );
  5464. scRet = InitializeSecurityContext(
  5465. &TempCredHandle,
  5466. &TempHandle,
  5467. TempAnsiString.Buffer,
  5468. LocalContextReq,
  5469. 0,
  5470. TargetDataRep,
  5471. &InitBufferDesc,
  5472. 0,
  5473. &Context->Handle,
  5474. &OutputDescription,
  5475. &LocalContextAttr,
  5476. ptsExpiry
  5477. );
  5478. #endif // WIN32_CHICAGO
  5479. DebugLog(( DEB_TRACE_NEG, "Subsequent call to WLsaInitContext( %ws ) returned %x\n",
  5480. Creds->Creds[ PackageIndex ].Package->LsaPackage->Name.Buffer,
  5481. scRet ));
  5482. SetCurrentPackageId( PackageId );
  5483. Context->CallCount++ ;
  5484. Context->LastStatus = scRet;
  5485. if (!NT_SUCCESS(scRet))
  5486. {
  5487. goto HSR_ErrorReturn;
  5488. }
  5489. Context->Flags |= NEG_CONTEXT_PACKAGE_CALLED;
  5490. if (NT_SUCCESS(scRet) && LocalContextMapped)
  5491. {
  5492. if (Context->Mapped)
  5493. {
  5494. DebugLog((DEB_ERROR,"Package tried to map a context twice!\n"));
  5495. scRet = SEC_E_INTERNAL_ERROR;
  5496. LsapFreeLsaHeap(LocalContextData.pvBuffer);
  5497. goto HSR_ErrorReturn;
  5498. }
  5499. Context->Mapped = LocalContextMapped;
  5500. Context->MappedBuffer = LocalContextData;
  5501. Context->Expiry = *ptsExpiry ;
  5502. }
  5503. }
  5504. else
  5505. {
  5506. DebugLog(( DEB_TRACE_NEG, "Package did not need to be called again.\n"));
  5507. if (OutputBuffer != NULL )
  5508. {
  5509. OutputBuffer->cbBuffer = 0;
  5510. }
  5511. scRet = STATUS_SUCCESS;
  5512. }
  5513. if ( Reply != NULL )
  5514. {
  5515. SpnegoFreeData( Pdu, Reply );
  5516. Reply = NULL ;
  5517. }
  5518. //
  5519. // Build reply buffer:
  5520. //
  5521. Request.choice = negTokenTarg_chosen;
  5522. Request.u.negTokenTarg.bit_mask = 0 ;
  5523. //
  5524. // If there was an output buffer, package it up to ship back to the server.
  5525. //
  5526. if ((OutputToken.cbBuffer != 0) && (OutputToken.pvBuffer != NULL))
  5527. {
  5528. if (ServerFinished)
  5529. {
  5530. #ifndef WIN32_CHICAGO
  5531. NegpReportEvent(
  5532. EVENTLOG_WARNING_TYPE,
  5533. NEGOTIATE_UNBALANCED_EXCHANGE,
  5534. CATEGORY_NEGOTIATE,
  5535. 0,
  5536. 2,
  5537. Target,
  5538. &Creds->Creds[PackageIndex].Package->LsaPackage->Name
  5539. );
  5540. #endif
  5541. DebugLog((DEB_ERROR,"Server finished but client sending back data\n"));
  5542. scRet = SEC_E_INTERNAL_ERROR;
  5543. goto HSR_ErrorReturn;
  5544. }
  5545. //
  5546. //
  5547. // mechSpecInfo is evil, try to take it out.
  5548. //
  5549. Request.u.negTokenTarg.bit_mask = responseToken_present;
  5550. Request.u.negTokenTarg.responseToken.value = (PUCHAR) OutputToken.pvBuffer;
  5551. Request.u.negTokenTarg.responseToken.length = (int) OutputToken.cbBuffer;
  5552. }
  5553. //
  5554. // Compute the MIC of the mechList, so that the other
  5555. // guy knows we weren't tampered on the wire
  5556. //
  5557. if ( scRet == STATUS_SUCCESS )
  5558. {
  5559. //
  5560. // not yet
  5561. //
  5562. NOTHING ;
  5563. }
  5564. if ( ( OutputToken.cbBuffer != 0 ) )
  5565. {
  5566. //
  5567. // Encode request token:
  5568. //
  5569. EncodedData.value = 0 ;
  5570. EncodedData.length = 0 ;
  5571. Result = SpnegoPackData(
  5572. &Request,
  5573. NegotiationToken_PDU,
  5574. &(EncodedData.length),
  5575. &(EncodedData.value));
  5576. if ( Result )
  5577. {
  5578. DebugLog((DEB_ERROR, "Failed to encode data: %d\n", Result ));
  5579. scRet = SEC_E_INVALID_TOKEN ;
  5580. goto HSR_ErrorReturn ;
  5581. }
  5582. else
  5583. {
  5584. if ( fContextReq & ISC_REQ_ALLOCATE_MEMORY )
  5585. {
  5586. OutputBuffer->pvBuffer = EncodedData.value ;
  5587. OutputBuffer->cbBuffer = EncodedData.length ;
  5588. *pfContextAttr = LocalContextAttr;
  5589. EncodedData.value = NULL ;
  5590. }
  5591. else
  5592. {
  5593. if ( OutputBuffer->cbBuffer >= (ULONG) EncodedData.length )
  5594. {
  5595. RtlCopyMemory( OutputBuffer->pvBuffer,
  5596. EncodedData.value,
  5597. EncodedData.length );
  5598. *pfContextAttr = LocalContextAttr & ~ISC_RET_ALLOCATED_MEMORY;
  5599. OutputBuffer->cbBuffer = EncodedData.length ;
  5600. }
  5601. else if ( ( ( fContextReq & ISC_REQ_FRAGMENT_TO_FIT ) != 0 ) &&
  5602. ( OutputBuffer->cbBuffer >= SPNEGO_MINIMUM_BUFFER ) )
  5603. {
  5604. //
  5605. // Ok, we need to whack the context to indicate that we are
  5606. // fragmenting, and return only what the caller can handle.
  5607. //
  5608. Context->Message = EncodedData.value ;
  5609. Context->TotalSize = EncodedData.length ;
  5610. Context->Flags |= NEG_CONTEXT_FRAGMENTING ;
  5611. //
  5612. // set this to NULL so it doesn't get freed later
  5613. //
  5614. EncodedData.value = NULL ;
  5615. RtlCopyMemory(
  5616. OutputBuffer->pvBuffer,
  5617. Context->Message,
  5618. OutputBuffer->cbBuffer );
  5619. Context->CurrentSize = OutputBuffer->cbBuffer ;
  5620. }
  5621. else
  5622. {
  5623. scRet = SEC_E_INSUFFICIENT_MEMORY ;
  5624. goto HSR_ErrorReturn ;
  5625. }
  5626. }
  5627. }
  5628. }
  5629. else
  5630. {
  5631. if ( OutputBuffer )
  5632. {
  5633. OutputBuffer->cbBuffer = 0 ;
  5634. }
  5635. }
  5636. if ( scRet == STATUS_SUCCESS )
  5637. {
  5638. if ( ( Context->Flags & NEG_CONTEXT_FRAGMENTING ) ||
  5639. ( ServerFinished == FALSE ) )
  5640. {
  5641. scRet = SEC_I_CONTINUE_NEEDED ;
  5642. }
  5643. else
  5644. {
  5645. ClientFinished = TRUE ;
  5646. }
  5647. }
  5648. //
  5649. // On success, we push the handle back to the client. From this point on,
  5650. // the selected package is in charge.
  5651. //
  5652. if ( ClientFinished )
  5653. {
  5654. //
  5655. // If the data was mapped by the package the first time make sure
  5656. // we copy it down now.
  5657. //
  5658. *pfContextAttr = Context->Attributes ;
  5659. *ptsExpiry = Context->Expiry ;
  5660. #ifndef WIN32_CHICAGO
  5661. if (Context->Mapped)
  5662. {
  5663. *pfMapContext = Context->Mapped;
  5664. *pContextData = Context->MappedBuffer;
  5665. //
  5666. // Set these to FALSE & NULL so we don't try to
  5667. // free them later.
  5668. //
  5669. Context->MappedBuffer.pvBuffer = NULL;
  5670. }
  5671. LsapChangeHandle( HandleReplace,
  5672. NULL,
  5673. &Context->Handle );
  5674. Context->Handle.dwLower = 0 ;
  5675. Context->Handle.dwUpper = 0 ;
  5676. if ( pContext == NULL )
  5677. {
  5678. NegpDeleteContext( Context );
  5679. }
  5680. #endif // WIN32_CHICAGO
  5681. // NegpDeleteContext( Context );
  5682. }
  5683. HSR_ErrorReturn:
  5684. if ( OutputToken.pvBuffer )
  5685. {
  5686. LsapFreeLsaHeap( OutputToken.pvBuffer );
  5687. OutputToken.pvBuffer = NULL ;
  5688. }
  5689. if ( EncodedData.value )
  5690. {
  5691. LsapFreeLsaHeap( EncodedData.value );
  5692. }
  5693. if ( Reply )
  5694. {
  5695. SpnegoFreeData( Pdu, Reply );
  5696. }
  5697. return( scRet );
  5698. }
  5699. SECURITY_STATUS
  5700. NegAddFragmentToContext(
  5701. PNEG_CONTEXT Context,
  5702. PSecBuffer Fragment
  5703. )
  5704. {
  5705. if ( Fragment->cbBuffer <= (Context->TotalSize - Context->CurrentSize) )
  5706. {
  5707. RtlCopyMemory(
  5708. Context->Message + Context->CurrentSize,
  5709. Fragment->pvBuffer,
  5710. Fragment->cbBuffer );
  5711. Context->CurrentSize += Fragment->cbBuffer ;
  5712. if ( Context->CurrentSize == Context->TotalSize )
  5713. {
  5714. Context->Flags &= (~(NEG_CONTEXT_FRAGMENTING));
  5715. return STATUS_SUCCESS ;
  5716. }
  5717. return SEC_I_CONTINUE_NEEDED ;
  5718. }
  5719. return SEC_E_INSUFFICIENT_MEMORY ;
  5720. }
  5721. SECURITY_STATUS
  5722. SEC_ENTRY
  5723. NegCreateContextFromFragment(
  5724. LSA_SEC_HANDLE dwCredHandle,
  5725. LSA_SEC_HANDLE dwCtxtHandle,
  5726. PSecBuffer Buffer,
  5727. ULONG fContextReq,
  5728. ULONG TargetDataRep,
  5729. PLSA_SEC_HANDLE pdwNewContext,
  5730. PSecBufferDesc pOutput,
  5731. PULONG pfContextAttr
  5732. )
  5733. {
  5734. NEG_CONTEXT * Context ;
  5735. NEG_CREDS * Creds ;
  5736. LONG ExpectedSize ;
  5737. LONG HeaderSize ;
  5738. PUCHAR Message ;
  5739. LONG MessageSize ;
  5740. SECURITY_STATUS scRet ;
  5741. PSecBuffer OutBuf ;
  5742. ObjectID DecodedOid = NULL;
  5743. NTSTATUS Status;
  5744. Creds = (NEG_CREDS *) dwCredHandle ;
  5745. if ( Buffer->cbBuffer > MAXLONG )
  5746. {
  5747. return SEC_E_INVALID_TOKEN ;
  5748. }
  5749. if ( Buffer->cbBuffer <= 1 )
  5750. {
  5751. return SEC_E_INVALID_TOKEN ;
  5752. }
  5753. Message = (PUCHAR) Buffer->pvBuffer ;
  5754. if ( (*Message != 0xa0 ) &&
  5755. (*Message != 0x60 ) )
  5756. {
  5757. return SEC_E_INVALID_TOKEN ;
  5758. }
  5759. MessageSize = Buffer->cbBuffer ;
  5760. Message++ ;
  5761. MessageSize -- ;
  5762. ExpectedSize = Neg_der_read_length(
  5763. &Message,
  5764. &MessageSize,
  5765. &HeaderSize );
  5766. if ( ExpectedSize > 0 )
  5767. {
  5768. //
  5769. // Header size + 1 since we already incremented above
  5770. //
  5771. ExpectedSize += HeaderSize + 1;
  5772. }
  5773. if ( ExpectedSize < 0 )
  5774. {
  5775. return SEC_E_INVALID_TOKEN ;
  5776. }
  5777. if ( (ULONG) ExpectedSize < Buffer->cbBuffer )
  5778. {
  5779. return SEC_E_INVALID_TOKEN ;
  5780. }
  5781. //
  5782. // Get the OID from the token, if possible, to see if it is for SPNEGO
  5783. //
  5784. Status = NegpGetTokenOid(
  5785. (PUCHAR) Buffer->pvBuffer,
  5786. Buffer->cbBuffer,
  5787. &DecodedOid
  5788. );
  5789. if (!NT_SUCCESS(Status))
  5790. {
  5791. return(Status);
  5792. }
  5793. //
  5794. // Check for spnego
  5795. //
  5796. if (NegpCompareOid(
  5797. DecodedOid,
  5798. NegSpnegoMechOid
  5799. ) != 0)
  5800. {
  5801. NegpFreeObjectId(DecodedOid);
  5802. return(SEC_E_INVALID_TOKEN);
  5803. }
  5804. NegpFreeObjectId(DecodedOid);
  5805. if ( (ULONG) ExpectedSize == Buffer->cbBuffer )
  5806. {
  5807. *pdwNewContext = 0 ;
  5808. return SEC_E_OK ;
  5809. }
  5810. Context = NegpCreateContext();
  5811. if ( !Context )
  5812. {
  5813. return SEC_E_INSUFFICIENT_MEMORY ;
  5814. }
  5815. Context->Flags = NEG_CONTEXT_FRAGMENTING ;
  5816. Context->Message = (PUCHAR) LsapAllocateLsaHeap( ExpectedSize ) ;
  5817. if ( !Context->Message )
  5818. {
  5819. NegpDeleteContext( Context );
  5820. return SEC_E_INSUFFICIENT_MEMORY ;
  5821. }
  5822. Context->CurrentSize = 0 ;
  5823. Context->TotalSize = ExpectedSize ;
  5824. scRet = NegAddFragmentToContext(
  5825. Context,
  5826. Buffer );
  5827. if ( !NT_SUCCESS( scRet ) )
  5828. {
  5829. NegpDeleteContext( Context );
  5830. }
  5831. else
  5832. {
  5833. *pdwNewContext = (LSA_SEC_HANDLE) Context ;
  5834. DsysAssert( scRet != SEC_E_OK );
  5835. NegpParseBuffers( pOutput, FALSE, &OutBuf, NULL );
  5836. if ( OutBuf )
  5837. {
  5838. OutBuf->cbBuffer = 0 ;
  5839. }
  5840. Context->Creds = Creds ;
  5841. //
  5842. // Reference the credentials so they don't go away unexpectedly
  5843. //
  5844. NegWriteLockCreds(Creds);
  5845. Creds->RefCount++;
  5846. NegUnlockCreds(Creds);
  5847. }
  5848. return scRet ;
  5849. }
  5850. //+---------------------------------------------------------------------------
  5851. //
  5852. // Function: NegInitLsaModeContext
  5853. //
  5854. // Synopsis: Initialize a client side context
  5855. //
  5856. // Arguments: [dwCredHandle] --
  5857. // [dwCtxtHandle] --
  5858. // [pszTargetName] --
  5859. // [fContextReq] --
  5860. // [TargetDataRep] --
  5861. // [pInput] --
  5862. // [pdwNewContext] --
  5863. // [pOutput] --
  5864. // [pfContextAttr] --
  5865. // [ptsExpiry] --
  5866. // [pfMapContext] --
  5867. // [pContextData] --
  5868. //
  5869. // History: 7-26-96 RichardW Created
  5870. //
  5871. // Notes:
  5872. //
  5873. //----------------------------------------------------------------------------
  5874. SECURITY_STATUS SEC_ENTRY
  5875. NegInitLsaModeContext(
  5876. LSA_SEC_HANDLE dwCredHandle,
  5877. LSA_SEC_HANDLE dwCtxtHandle,
  5878. PSECURITY_STRING pszTargetName,
  5879. ULONG fContextReq,
  5880. ULONG TargetDataRep,
  5881. PSecBufferDesc pInput,
  5882. PLSA_SEC_HANDLE pdwNewContext,
  5883. PSecBufferDesc pOutput,
  5884. PULONG pfContextAttr,
  5885. PTimeStamp ptsExpiry,
  5886. PBYTE pfMapContext,
  5887. PSecBuffer pContextData)
  5888. {
  5889. SECURITY_STATUS scRet = SEC_E_OK;
  5890. PSecBuffer Buffer = NULL;
  5891. SecBuffer LocalBuffer = {0};
  5892. PSecBuffer OutBuf = NULL;
  5893. PNEG_CONTEXT Context = NULL;
  5894. ULONG PackageIndex ;
  5895. ULONG CallState ;
  5896. CallState = 0 ;
  5897. if ( dwCtxtHandle )
  5898. {
  5899. CallState |= LATER_CALL_BIT ;
  5900. }
  5901. scRet = NegpParseBuffers( pInput, FALSE, &Buffer, NULL );
  5902. if ( !NT_SUCCESS( scRet ) )
  5903. {
  5904. DebugLog(( DEB_ERROR, "NegInitLsaModeContext failed to map input buffers, %x\n", scRet ));
  5905. return scRet ;
  5906. }
  5907. if ( ( Buffer != NULL ) &&
  5908. ( Buffer->cbBuffer != 0 ) )
  5909. {
  5910. CallState |= BUFFER_PRESENT_BIT ;
  5911. }
  5912. if ( fContextReq & ISC_REQ_DATAGRAM )
  5913. {
  5914. return SEC_E_UNSUPPORTED_FUNCTION ;
  5915. }
  5916. switch ( CallState )
  5917. {
  5918. case FIRST_CALL_WITH_INPUT:
  5919. //
  5920. // Initial case: Server initiated blob, may be
  5921. // fragmented
  5922. //
  5923. scRet = NegCreateContextFromFragment(
  5924. dwCredHandle,
  5925. dwCtxtHandle,
  5926. Buffer,
  5927. fContextReq,
  5928. TargetDataRep,
  5929. pdwNewContext,
  5930. pOutput,
  5931. pfContextAttr );
  5932. if ( scRet == SEC_E_OK )
  5933. {
  5934. Context = (PNEG_CONTEXT) *pdwNewContext ;
  5935. if ( Context )
  5936. {
  5937. //
  5938. // final
  5939. //
  5940. *pdwNewContext = 0 ;
  5941. LocalBuffer.BufferType = SECBUFFER_TOKEN ;
  5942. LocalBuffer.cbBuffer = Context->TotalSize ;
  5943. LocalBuffer.pvBuffer = Context->Message ;
  5944. //
  5945. // Reset frag buffer to NULL - this will be
  5946. // freed when the call completes by the LSA wrappers.
  5947. // hence the ChangeBuffer call below:
  5948. //
  5949. Context->Message = NULL ;
  5950. LsapChangeBuffer( Buffer, &LocalBuffer );
  5951. //
  5952. // Get rid of the context - we have the whole
  5953. // message
  5954. //
  5955. NegpDeleteContext( Context );
  5956. }
  5957. }
  5958. else if ( NT_SUCCESS( scRet ) )
  5959. {
  5960. //
  5961. // building a context, so return now
  5962. //
  5963. break;
  5964. }
  5965. if ( !NT_SUCCESS( scRet ) )
  5966. {
  5967. //
  5968. // Check the package in use. It is possible that we are being
  5969. // sent the context token from a totally separate package and
  5970. // are being asked to dispatch to the appropriate package.
  5971. //
  5972. scRet = NegpDetermineTokenPackage(
  5973. dwCredHandle,
  5974. Buffer,
  5975. &PackageIndex
  5976. );
  5977. }
  5978. else
  5979. {
  5980. PackageIndex = (ULONG) -1 ;
  5981. }
  5982. if ( PackageIndex != (ULONG) -1 )
  5983. {
  5984. CtxtHandle TempCtxtHandle = {0};
  5985. CtxtHandle TempInputCtxtHandle = {0};
  5986. CredHandle TempCredHandle;
  5987. PNEG_CREDS Creds = (PNEG_CREDS) dwCredHandle;
  5988. #ifndef WIN32_CHICAGO
  5989. NegpReportEvent(
  5990. EVENTLOG_INFORMATION_TYPE,
  5991. NEGOTIATE_RAW_PACKET,
  5992. CATEGORY_NEGOTIATE,
  5993. 0,
  5994. 1,
  5995. &Creds->Creds[PackageIndex].Package->LsaPackage->Name
  5996. );
  5997. #endif
  5998. //
  5999. // Call into another package to do the accept
  6000. //
  6001. NegReadLockCreds(Creds);
  6002. TempCredHandle = Creds->Creds[PackageIndex].Handle;
  6003. NegUnlockCreds(Creds);
  6004. DebugLog(( DEB_TRACE_NEG, "Got a blob directly for package %x\n",
  6005. TempCredHandle.dwLower ));
  6006. #ifndef WIN32_CHICAGO
  6007. scRet = WLsaInitContext(
  6008. &TempCredHandle,
  6009. &TempInputCtxtHandle,
  6010. pszTargetName,
  6011. fContextReq,
  6012. 0,
  6013. TargetDataRep,
  6014. pInput,
  6015. 0,
  6016. &TempCtxtHandle,
  6017. pOutput,
  6018. pfContextAttr,
  6019. ptsExpiry,
  6020. pfMapContext,
  6021. pContextData
  6022. );
  6023. #else
  6024. {
  6025. ANSI_STRING TempAnsiString;
  6026. NTSTATUS TempStatus = RtlUnicodeStringToAnsiString(
  6027. &TempAnsiString,
  6028. pszTargetName,
  6029. TRUE // allocate destination
  6030. );
  6031. scRet = InitializeSecurityContext(
  6032. &TempCredHandle,
  6033. &TempInputCtxtHandle,
  6034. TempAnsiString.Buffer,
  6035. fContextReq,
  6036. 0,
  6037. TargetDataRep,
  6038. pInput,
  6039. 0,
  6040. &TempCtxtHandle,
  6041. pOutput,
  6042. pfContextAttr,
  6043. ptsExpiry
  6044. );
  6045. RtlFreeAnsiString( &TempAnsiString );
  6046. }
  6047. Context->CallCount++ ;
  6048. #endif // WIN32_CHICAGO
  6049. if (NT_SUCCESS(scRet))
  6050. {
  6051. #ifndef WIN32_CHICAGO
  6052. LsapChangeHandle(
  6053. HandleReplace,
  6054. NULL,
  6055. &TempCtxtHandle
  6056. );
  6057. #endif // WIN32_CHICAGO
  6058. }
  6059. }
  6060. else
  6061. {
  6062. scRet = NegCrackServerRequestAndReply(
  6063. dwCredHandle,
  6064. pszTargetName,
  6065. fContextReq | ISC_REQ_MUTUAL_AUTH,
  6066. TargetDataRep,
  6067. pInput,
  6068. pdwNewContext,
  6069. pOutput,
  6070. pfContextAttr,
  6071. ptsExpiry,
  6072. pfMapContext,
  6073. pContextData );
  6074. }
  6075. //
  6076. // if we couldn't parse it, try to go without the hint:
  6077. //
  6078. if ( scRet != SEC_E_INVALID_TOKEN )
  6079. {
  6080. break;
  6081. }
  6082. DebugLog(( DEB_TRACE_NEG, "Unidentified token, trying without it\n" ));
  6083. case FIRST_CALL_NO_INPUT:
  6084. //
  6085. // First call, but server has provided some hints as to
  6086. // what to do.
  6087. //
  6088. scRet = NegGenerateInitialToken(
  6089. dwCredHandle,
  6090. pszTargetName,
  6091. fContextReq,
  6092. TargetDataRep,
  6093. pInput,
  6094. pdwNewContext,
  6095. pOutput,
  6096. pfContextAttr,
  6097. ptsExpiry,
  6098. pfMapContext,
  6099. pContextData);
  6100. DebugLog(( DEB_TRACE_NEG, "NegGenerateInitialToken returned %x\n", scRet ));
  6101. break;
  6102. case LATER_CALL_WITH_INPUT:
  6103. //
  6104. // Subsequent call, with a context working and
  6105. // a blob from the server. May be fragmented
  6106. //
  6107. if ( NegpIsValidContext( dwCtxtHandle ) )
  6108. {
  6109. //
  6110. // See if we're doing fragment reassembly:
  6111. //
  6112. Context = (PNEG_CONTEXT) dwCtxtHandle ;
  6113. if ( Context->Flags & NEG_CONTEXT_FRAGMENTING )
  6114. {
  6115. scRet = NegAddFragmentToContext(
  6116. Context,
  6117. Buffer );
  6118. //
  6119. // More trips needed to construct the fragments.
  6120. //
  6121. if (scRet == SEC_I_CONTINUE_NEEDED)
  6122. {
  6123. NegpParseBuffers( pOutput, FALSE, &OutBuf, NULL );
  6124. if ( OutBuf )
  6125. {
  6126. OutBuf->cbBuffer = 0 ;
  6127. }
  6128. return scRet;
  6129. }
  6130. else if ( scRet != SEC_E_OK )
  6131. {
  6132. return scRet ;
  6133. }
  6134. //
  6135. // That was the final blob. Reset the message
  6136. // to be the whole thing
  6137. //
  6138. LocalBuffer.BufferType = SECBUFFER_TOKEN ;
  6139. LocalBuffer.cbBuffer = Context->TotalSize ;
  6140. LocalBuffer.pvBuffer = Context->Message ;
  6141. //
  6142. // Reset frag buffer to NULL - this will be
  6143. // freed when the call completes by the LSA wrappers.
  6144. // hence the ChangeBuffer call below:
  6145. //
  6146. Context->Message = NULL ;
  6147. scRet = LsapChangeBuffer( Buffer, &LocalBuffer );
  6148. if ( !NT_SUCCESS( scRet ) )
  6149. {
  6150. return scRet ;
  6151. }
  6152. //
  6153. // Fall through to the normal processing
  6154. //
  6155. }
  6156. }
  6157. else
  6158. {
  6159. return SEC_E_INVALID_HANDLE;
  6160. }
  6161. if (NegpIsValidContext(dwCtxtHandle))
  6162. {
  6163. scRet = NegHandleServerReply(
  6164. dwCredHandle,
  6165. (PNEG_CONTEXT) dwCtxtHandle,
  6166. pszTargetName,
  6167. fContextReq,
  6168. TargetDataRep,
  6169. pInput,
  6170. pdwNewContext,
  6171. pOutput,
  6172. pfContextAttr,
  6173. ptsExpiry,
  6174. pfMapContext,
  6175. pContextData );
  6176. }
  6177. else
  6178. {
  6179. scRet = SEC_E_INVALID_HANDLE ;
  6180. }
  6181. break;
  6182. case LATER_CALL_NO_INPUT:
  6183. //
  6184. // No data from the server,
  6185. if ( NegpIsValidContext( dwCtxtHandle ) )
  6186. {
  6187. //
  6188. // See if we're doing fragment reassembly:
  6189. //
  6190. Context = (PNEG_CONTEXT) dwCtxtHandle ;
  6191. if ( ( Context->Flags & NEG_CONTEXT_FRAGMENTING ) &&
  6192. ( fContextReq & ISC_REQ_FRAGMENT_TO_FIT ) )
  6193. {
  6194. //
  6195. // Pull the next chunk off the stored context:
  6196. //
  6197. scRet = NegpParseBuffers( pOutput, FALSE, &Buffer, NULL );
  6198. if ( ( Buffer != NULL ) &&
  6199. ( NT_SUCCESS( scRet ) ) )
  6200. {
  6201. Buffer->cbBuffer = min( Buffer->cbBuffer,
  6202. (Context->TotalSize - Context->CurrentSize) );
  6203. RtlCopyMemory(
  6204. Buffer->pvBuffer,
  6205. Context->Message + Context->CurrentSize,
  6206. Buffer->cbBuffer );
  6207. Context->CurrentSize += Buffer->cbBuffer ;
  6208. if ( Context->CurrentSize == Context->TotalSize )
  6209. {
  6210. //
  6211. // Sent the whole thing
  6212. //
  6213. Context->Flags &= (~(NEG_CONTEXT_FRAGMENTING) );
  6214. Context->TotalSize = 0 ;
  6215. Context->CurrentSize = 0 ;
  6216. LsapFreeLsaHeap( Context->Message );
  6217. Context->Message = NULL ;
  6218. scRet = Context->LastStatus ;
  6219. if ( scRet == SEC_E_OK )
  6220. {
  6221. *pfMapContext = Context->Mapped;
  6222. *pContextData = Context->MappedBuffer;
  6223. *pfContextAttr = Context->Attributes ;
  6224. RtlZeroMemory(
  6225. &Context->MappedBuffer,
  6226. sizeof(SecBuffer)
  6227. );
  6228. #ifndef WIN32_CHICAGO
  6229. LsapChangeHandle( HandleReplace,
  6230. NULL,
  6231. &Context->Handle );
  6232. Context->Handle.dwLower = 0xFFFFFFFF ;
  6233. #endif
  6234. }
  6235. }
  6236. else
  6237. {
  6238. scRet = SEC_I_CONTINUE_NEEDED ;
  6239. }
  6240. }
  6241. else
  6242. {
  6243. DebugLog((DEB_TRACE_NEG, "NegInitLsaModeContext: No buffer found (1)\n" ));
  6244. scRet = SEC_E_INVALID_TOKEN ;
  6245. }
  6246. }
  6247. else
  6248. {
  6249. //
  6250. // Last round trip for signed blobs:
  6251. //
  6252. if ( Context->LastStatus == SEC_E_OK )
  6253. {
  6254. *pfMapContext = Context->Mapped;
  6255. *pContextData = Context->MappedBuffer;
  6256. *pfContextAttr = Context->Attributes ;
  6257. RtlZeroMemory(
  6258. &Context->MappedBuffer,
  6259. sizeof(SecBuffer)
  6260. );
  6261. scRet = NegpParseBuffers( pOutput, FALSE, &Buffer, NULL );
  6262. if ( Buffer &&
  6263. NT_SUCCESS( scRet ) )
  6264. {
  6265. Buffer->cbBuffer = 0 ;
  6266. }
  6267. scRet = SEC_E_OK ;
  6268. #ifndef WIN32_CHICAGO
  6269. LsapChangeHandle( HandleReplace,
  6270. NULL,
  6271. &Context->Handle );
  6272. Context->Handle.dwLower = 0xFFFFFFFF ;
  6273. #endif
  6274. }
  6275. else
  6276. {
  6277. DebugLog(( DEB_TRACE_NEG, "NegInitLsaModeContext: Signed exchange not ok\n" ));
  6278. scRet = SEC_E_INVALID_TOKEN ;
  6279. }
  6280. }
  6281. }
  6282. else
  6283. {
  6284. scRet = SEC_E_INVALID_TOKEN ;
  6285. }
  6286. break;
  6287. default:
  6288. DsysAssert( FALSE );
  6289. scRet = SEC_E_INTERNAL_ERROR ;
  6290. }
  6291. return scRet ;
  6292. }
  6293. SECURITY_STATUS SEC_ENTRY
  6294. NegMoveContextToUser(
  6295. LSA_SEC_HANDLE dwCtxtHandle,
  6296. PSecBuffer pContextBuffer
  6297. )
  6298. {
  6299. return( SEC_E_UNSUPPORTED_FUNCTION );
  6300. }
  6301. //+---------------------------------------------------------------------------
  6302. //
  6303. // Function: NegDeleteLsaModeContext
  6304. //
  6305. // Synopsis: Deletes the LSA portion of the context
  6306. //
  6307. // Arguments: [dwCtxtHandle] --
  6308. //
  6309. // History: 9-24-96 RichardW Created
  6310. //
  6311. // Notes:
  6312. //
  6313. //----------------------------------------------------------------------------
  6314. SECURITY_STATUS
  6315. SEC_ENTRY
  6316. NegDeleteLsaModeContext( LSA_SEC_HANDLE dwCtxtHandle)
  6317. {
  6318. SECURITY_STATUS scRet = SEC_E_INVALID_HANDLE;
  6319. PNEG_CONTEXT Context;
  6320. #ifndef WIN32_CHICAGO
  6321. PSession pSession = GetCurrentSession();
  6322. #endif
  6323. Context = (PNEG_CONTEXT) dwCtxtHandle ;
  6324. __try
  6325. {
  6326. if (NegpIsValidContext( Context ))
  6327. {
  6328. #ifndef WIN32_CHICAGO
  6329. //
  6330. // If the session is being run down, don't call WLsaDeleteContext,
  6331. // it will complicate things (that entry may already have been
  6332. // deleted.
  6333. //
  6334. if ( pSession->fSession & SESFLAG_CLEANUP )
  6335. {
  6336. Context->Handle.dwLower = 0 ;
  6337. Context->Handle.dwUpper = 0 ;
  6338. }
  6339. NegpDeleteContext( Context );
  6340. scRet = SEC_E_OK ;
  6341. #endif
  6342. }
  6343. }
  6344. __except( EXCEPTION_EXECUTE_HANDLER ) {}
  6345. return( scRet );
  6346. }
  6347. SECURITY_STATUS SEC_ENTRY
  6348. NegApplyControlToken( LSA_SEC_HANDLE dwCtxtHandle,
  6349. PSecBufferDesc pInput)
  6350. {
  6351. return(SEC_E_UNSUPPORTED_FUNCTION);
  6352. }
  6353. VOID
  6354. SEC_ENTRY
  6355. NegLogoffNotify(
  6356. PLUID pLogonId
  6357. )
  6358. {
  6359. #ifndef WIN32_CHICAGO
  6360. NegpDerefLogonSessionById( pLogonId );
  6361. #endif
  6362. }
  6363. #define TOKEN_MATCHES(_buf_,_oid_,_oidlen_) \
  6364. (((_buf_)->cbBuffer >= (_oidlen_)) && \
  6365. RtlEqualMemory( \
  6366. (_buf_)->pvBuffer, \
  6367. (_oid_), \
  6368. (_oidlen_) \
  6369. ))
  6370. //+-------------------------------------------------------------------------
  6371. //
  6372. // Function:
  6373. //
  6374. // Synopsis:
  6375. //
  6376. // Effects:
  6377. //
  6378. // Arguments:
  6379. //
  6380. // Requires:
  6381. //
  6382. // Returns:
  6383. //
  6384. // Notes:
  6385. //
  6386. //
  6387. //--------------------------------------------------------------------------
  6388. /*
  6389. * Copyright 1993 by OpenVision Technologies, Inc.
  6390. *
  6391. * Permission to use, copy, modify, distribute, and sell this software
  6392. * and its documentation for any purpose is hereby granted without fee,
  6393. * provided that the above copyright notice appears in all copies and
  6394. * that both that copyright notice and this permission notice appear in
  6395. * supporting documentation, and that the name of OpenVision not be used
  6396. * in advertising or publicity pertaining to distribution of the software
  6397. * without specific, written prior permission. OpenVision makes no
  6398. * representations about the suitability of this software for any
  6399. * purpose. It is provided "as is" without express or implied warranty.
  6400. *
  6401. * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  6402. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  6403. * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  6404. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  6405. * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  6406. * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  6407. * PERFORMANCE OF THIS SOFTWARE.
  6408. */
  6409. NTSTATUS
  6410. NegpGetTokenOid(
  6411. IN PUCHAR Buf,
  6412. OUT ULONG BufSize,
  6413. OUT ObjectID * ObjectId
  6414. )
  6415. {
  6416. UCHAR sf;
  6417. ULONG TokenSize;
  6418. ULONG OidLength;
  6419. //
  6420. // Check for the encoding indicator
  6421. //
  6422. if (BufSize < 2)
  6423. {
  6424. return SEC_E_INVALID_TOKEN;
  6425. }
  6426. if ( (*Buf == 0x60) ||
  6427. (*Buf == 0xa0) )
  6428. {
  6429. Buf++;
  6430. }
  6431. else
  6432. {
  6433. return SEC_E_INVALID_TOKEN;
  6434. }
  6435. sf = *(Buf)++;
  6436. (BufSize)--;
  6437. if (sf & 0x80)
  6438. {
  6439. if ((sf &= 0x7f) > ((BufSize)-1))
  6440. {
  6441. return(SEC_E_INVALID_TOKEN);
  6442. }
  6443. if (sf > sizeof(ULONG))
  6444. {
  6445. return (SEC_E_INVALID_TOKEN);
  6446. }
  6447. TokenSize = 0;
  6448. for (; sf; sf--)
  6449. {
  6450. TokenSize = (TokenSize<<8) + (*(Buf)++);
  6451. (BufSize)--;
  6452. }
  6453. } else {
  6454. TokenSize = sf;
  6455. }
  6456. if ((--BufSize == 0) || *Buf != 0x06)
  6457. {
  6458. return(SEC_E_INVALID_TOKEN);
  6459. }
  6460. if (--BufSize == 0)
  6461. {
  6462. return(SEC_E_INVALID_TOKEN);
  6463. }
  6464. OidLength = *(Buf+1) + 2; // two extra for OID tag & length field
  6465. //
  6466. // Now buf should point to the encoded oid
  6467. //
  6468. *ObjectId = NegpDecodeObjectId(Buf,OidLength);
  6469. if (ObjectId == NULL)
  6470. {
  6471. return(SEC_E_INVALID_TOKEN);
  6472. }
  6473. return(STATUS_SUCCESS);
  6474. }
  6475. //+-------------------------------------------------------------------------
  6476. //
  6477. // Function: NegpDetermineTokenPackage
  6478. //
  6479. // Synopsis: Determines the package that generated an initial
  6480. // context token
  6481. //
  6482. // Effects:
  6483. //
  6484. // Arguments: CredHandle - handle to the server's credentials
  6485. // InitialToken -Initial context token from client
  6486. // Package - NULL if spnego, otherwise the package
  6487. // that generated the token.
  6488. //
  6489. // Requires:
  6490. //
  6491. // Returns:
  6492. //
  6493. // Notes:
  6494. //
  6495. //
  6496. //--------------------------------------------------------------------------
  6497. NTSTATUS
  6498. NegpDetermineTokenPackage(
  6499. IN ULONG_PTR CredHandle,
  6500. IN PSecBuffer InitialToken,
  6501. OUT PULONG PackageIndex
  6502. )
  6503. {
  6504. NTSTATUS Status = STATUS_SUCCESS;
  6505. ULONG Index;
  6506. PNEG_CREDS Credentials = (PNEG_CREDS) CredHandle;
  6507. ObjectID DecodedOid = NULL;
  6508. int Length ;
  6509. PUCHAR Buffer ;
  6510. LONG Header ;
  6511. LONG Size ;
  6512. ULONG_PTR Package ;
  6513. *PackageIndex = (ULONG) -1;
  6514. //
  6515. // Get the OID from the token, if possible
  6516. //
  6517. Status = NegpGetTokenOid(
  6518. (PUCHAR) InitialToken->pvBuffer,
  6519. InitialToken->cbBuffer,
  6520. &DecodedOid
  6521. );
  6522. if (NT_SUCCESS(Status))
  6523. {
  6524. Status = SEC_E_INVALID_TOKEN;
  6525. //
  6526. // First check for spnego
  6527. //
  6528. if (NegpCompareOid(
  6529. DecodedOid,
  6530. NegSpnegoMechOid
  6531. ) == 0)
  6532. {
  6533. Status = STATUS_SUCCESS;
  6534. }
  6535. else
  6536. {
  6537. //
  6538. // Try the oid for each mech in the credential
  6539. //
  6540. NegReadLockCreds(Credentials);
  6541. Package = NegpFindPackageForOid( Credentials, DecodedOid );
  6542. if ( Package != NEG_INVALID_PACKAGE )
  6543. {
  6544. *PackageIndex = (ULONG) Package ;
  6545. Status = STATUS_SUCCESS ;
  6546. }
  6547. else
  6548. {
  6549. Status = SEC_E_SECPKG_NOT_FOUND ;
  6550. }
  6551. NegUnlockCreds(Credentials);
  6552. }
  6553. NegpFreeObjectId(DecodedOid);
  6554. }
  6555. else
  6556. {
  6557. if (TOKEN_MATCHES(InitialToken,NTLMSSP_SIGNATURE,sizeof(NTLMSSP_SIGNATURE)))
  6558. {
  6559. //
  6560. // Find the NTLM package in the list of packages
  6561. //
  6562. NegReadLockCreds(Credentials);
  6563. for (Index = 0; Index < Credentials->Count ; Index++ )
  6564. {
  6565. if (Credentials->Creds[Index].Package->LsaPackage->dwRPCID == NTLMSP_RPCID)
  6566. {
  6567. *PackageIndex = Index;
  6568. Status = STATUS_SUCCESS;
  6569. break;
  6570. }
  6571. }
  6572. //
  6573. // If we didn't find ntlm, return invalid token.
  6574. //
  6575. NegUnlockCreds(Credentials);
  6576. if ( NT_SUCCESS( Status ) )
  6577. {
  6578. return Status;
  6579. }
  6580. }
  6581. Size = InitialToken->cbBuffer ;
  6582. Buffer = (PUCHAR) InitialToken->pvBuffer ;
  6583. Buffer ++ ;
  6584. Length = Neg_der_read_length(
  6585. &Buffer,
  6586. &Size,
  6587. &Header );
  6588. if ( Length > 0 )
  6589. {
  6590. //
  6591. // Could be kerb, could be snego. Poke a little to find out
  6592. //
  6593. if ( (*Buffer & 0xC0) == 0x40 )
  6594. {
  6595. NegReadLockCreds(Credentials);
  6596. for (Index = 0; Index < Credentials->Count ; Index++ )
  6597. {
  6598. if (Credentials->Creds[Index].Package->LsaPackage->dwRPCID == RPC_C_AUTHN_GSS_KERBEROS)
  6599. {
  6600. *PackageIndex = Index;
  6601. Status = STATUS_SUCCESS;
  6602. break;
  6603. }
  6604. }
  6605. //
  6606. // If we didn't find kerberos, return invalid token.
  6607. //
  6608. NegUnlockCreds(Credentials);
  6609. }
  6610. }
  6611. }
  6612. return(Status);
  6613. }
  6614. SECURITY_STATUS
  6615. SEC_ENTRY
  6616. NegAcceptLsaModeContext(
  6617. LSA_SEC_HANDLE dwCredHandle,
  6618. LSA_SEC_HANDLE dwCtxtHandle,
  6619. PSecBufferDesc pInput,
  6620. ULONG fContextReq,
  6621. ULONG TargetDataRep,
  6622. PLSA_SEC_HANDLE pdwNewContext,
  6623. PSecBufferDesc pOutput,
  6624. PULONG pfContextAttr,
  6625. PTimeStamp ptsExpiry,
  6626. PBYTE pfMapContext,
  6627. PSecBuffer pContextData)
  6628. {
  6629. SECURITY_STATUS scRet = STATUS_SUCCESS;
  6630. ULONG PackageIndex = 0;
  6631. PSecBuffer Buffer;
  6632. SecBufferDesc LocalDesc ;
  6633. SecBuffer LocalBuffer ;
  6634. PSecBuffer OutBuf = NULL;
  6635. PNEG_CONTEXT Context = NULL ;
  6636. PNEG_CREDS Cred ;
  6637. PNEG_CREDS AltCreds ;
  6638. PLIST_ENTRY Scan ;
  6639. BOOL LocalUseSpnego ;
  6640. ULONG CallState ;
  6641. CallState = 0 ;
  6642. if ( dwCtxtHandle )
  6643. {
  6644. CallState |= LATER_CALL_BIT ;
  6645. }
  6646. scRet = NegpParseBuffers( pInput, FALSE, &Buffer, NULL );
  6647. if ( !NT_SUCCESS( scRet ) )
  6648. {
  6649. DebugLog(( DEB_ERROR, "NegAcceptLsaModeContext failed to map input buffers, %x\n", scRet ));
  6650. return scRet ;
  6651. }
  6652. if ( ( Buffer != NULL ) &&
  6653. ( Buffer->cbBuffer != 0 ) )
  6654. {
  6655. CallState |= BUFFER_PRESENT_BIT ;
  6656. }
  6657. ULONG_PTR PackageId = GetCurrentPackageId();
  6658. DebugLog(( DEB_TRACE_NEG, "AcceptLsaModeContext( %x, %x )\n",
  6659. dwCredHandle, dwCtxtHandle ));
  6660. #ifndef WIN32_CHICAGO
  6661. ptsExpiry->QuadPart = (LONGLONG) MAXLONGLONG;
  6662. #else
  6663. *ptsExpiry = (LONGLONG) MAXLONGLONG;
  6664. #endif
  6665. switch ( CallState )
  6666. {
  6667. case FIRST_CALL_NO_INPUT:
  6668. scRet = NegGenerateServerRequest(
  6669. dwCredHandle,
  6670. fContextReq,
  6671. TargetDataRep,
  6672. pInput,
  6673. pdwNewContext,
  6674. pOutput,
  6675. pfContextAttr,
  6676. ptsExpiry,
  6677. pfMapContext,
  6678. pContextData );
  6679. break;
  6680. case FIRST_CALL_WITH_INPUT:
  6681. //
  6682. // Determine if this is a fragment, and if so, is it the
  6683. // last fragment:
  6684. //
  6685. scRet = NegCreateContextFromFragment(
  6686. dwCredHandle,
  6687. dwCtxtHandle,
  6688. Buffer,
  6689. fContextReq,
  6690. TargetDataRep,
  6691. pdwNewContext,
  6692. pOutput,
  6693. pfContextAttr );
  6694. *pfMapContext = FALSE ;
  6695. if ( scRet == SEC_E_OK )
  6696. {
  6697. Context = (PNEG_CONTEXT) *pdwNewContext ;
  6698. if ( Context )
  6699. {
  6700. //
  6701. // final
  6702. //
  6703. *pdwNewContext = 0 ;
  6704. LocalBuffer.BufferType = SECBUFFER_TOKEN ;
  6705. LocalBuffer.cbBuffer = Context->TotalSize ;
  6706. LocalBuffer.pvBuffer = Context->Message ;
  6707. //
  6708. // Reset frag buffer to NULL - this will be
  6709. // freed when the call completes by the LSA wrappers.
  6710. // hence the ChangeBuffer call below:
  6711. //
  6712. Context->Message = NULL ;
  6713. LsapChangeBuffer( Buffer, &LocalBuffer );
  6714. //
  6715. // Get rid of the context - we have the whole
  6716. // message
  6717. //
  6718. NegpDeleteContext( Context );
  6719. }
  6720. }
  6721. else if ( NT_SUCCESS( scRet ) )
  6722. {
  6723. //
  6724. // building a context, so return now
  6725. //
  6726. return scRet ;
  6727. }
  6728. if ( !NT_SUCCESS( scRet ) )
  6729. {
  6730. //
  6731. // Check the package in use. It is possible that we are being
  6732. // sent the context token from a totally separate package and
  6733. // are being asked to dispatch to the appropriate package.
  6734. //
  6735. scRet = NegpDetermineTokenPackage(
  6736. dwCredHandle,
  6737. Buffer,
  6738. &PackageIndex
  6739. );
  6740. }
  6741. else
  6742. {
  6743. PackageIndex = (ULONG) -1 ;
  6744. }
  6745. //
  6746. // Older clients will send data that returns an error
  6747. //
  6748. if (!NT_SUCCESS(scRet) || (PackageIndex == (ULONG) -1))
  6749. {
  6750. scRet = NegHandleClientRequest(
  6751. dwCredHandle,
  6752. NULL,
  6753. fContextReq,
  6754. TargetDataRep,
  6755. pInput,
  6756. pdwNewContext,
  6757. pOutput,
  6758. pfContextAttr,
  6759. ptsExpiry,
  6760. pfMapContext,
  6761. pContextData );
  6762. if ( !NT_SUCCESS( scRet ) ||
  6763. ( NT_SUCCESS( scRet ) && (*pfContextAttr & ASC_RET_EXTENDED_ERROR) ) )
  6764. {
  6765. Cred = (PNEG_CREDS) dwCredHandle ;
  6766. NegReadLockCreds( Cred );
  6767. if ( Cred->Flags & NEGCRED_MULTI )
  6768. {
  6769. //
  6770. // This credential has additional creds hanging off of it.
  6771. //
  6772. DebugLog(( DEB_TRACE_NEG, "Multi credential handle:\n" ));
  6773. Scan = Cred->AdditionalCreds.Flink ;
  6774. while ( Scan != &Cred->AdditionalCreds )
  6775. {
  6776. AltCreds = CONTAINING_RECORD( Scan, NEG_CREDS, List );
  6777. DebugLog(( DEB_TRACE_NEG, "Retrying with credential %p\n", AltCreds ));
  6778. scRet = NegHandleClientRequest(
  6779. (ULONG_PTR) AltCreds,
  6780. NULL,
  6781. fContextReq,
  6782. TargetDataRep,
  6783. pInput,
  6784. pdwNewContext,
  6785. pOutput,
  6786. pfContextAttr,
  6787. ptsExpiry,
  6788. pfMapContext,
  6789. pContextData );
  6790. if ( NT_SUCCESS( scRet ) &&
  6791. ( ( *pfContextAttr & ASC_RET_EXTENDED_ERROR ) == 0 ) )
  6792. {
  6793. break;
  6794. }
  6795. Scan = Scan->Flink ;
  6796. }
  6797. }
  6798. NegUnlockCreds( Cred );
  6799. }
  6800. }
  6801. else
  6802. {
  6803. CtxtHandle TempCtxtHandle = {0};
  6804. CtxtHandle TempInputCtxtHandle = {0};
  6805. CredHandle TempCredHandle;
  6806. PNEG_CREDS Creds = (PNEG_CREDS) dwCredHandle;
  6807. #ifndef WIN32_CHICAGO
  6808. NegpReportEvent(
  6809. EVENTLOG_INFORMATION_TYPE,
  6810. NEGOTIATE_RAW_PACKET,
  6811. CATEGORY_NEGOTIATE,
  6812. 0,
  6813. 1,
  6814. &Creds->Creds[PackageIndex].Package->LsaPackage->Name
  6815. );
  6816. #endif
  6817. //
  6818. // Call into another package to do the accept
  6819. //
  6820. NegReadLockCreds(Creds);
  6821. TempCredHandle = Creds->Creds[PackageIndex].Handle;
  6822. NegUnlockCreds(Creds);
  6823. DebugLog(( DEB_TRACE_NEG, "Got a blob directly for package %x\n",
  6824. TempCredHandle.dwLower ));
  6825. PackageId = GetCurrentPackageId();
  6826. #ifndef WIN32_CHICAGO
  6827. scRet = WLsaAcceptContext(
  6828. &TempCredHandle,
  6829. &TempInputCtxtHandle,
  6830. pInput,
  6831. fContextReq,
  6832. TargetDataRep,
  6833. &TempCtxtHandle,
  6834. pOutput,
  6835. pfContextAttr,
  6836. ptsExpiry,
  6837. pfMapContext,
  6838. pContextData
  6839. );
  6840. #else
  6841. scRet = AcceptSecurityContext(
  6842. &TempCredHandle,
  6843. &TempInputCtxtHandle,
  6844. pInput,
  6845. fContextReq,
  6846. TargetDataRep,
  6847. &TempCtxtHandle,
  6848. pOutput,
  6849. pfContextAttr,
  6850. ptsExpiry
  6851. );
  6852. #endif // WIN32_CHICAGO
  6853. SetCurrentPackageId(PackageId);
  6854. if (Context)
  6855. {
  6856. Context->CallCount++ ;
  6857. }
  6858. if (NT_SUCCESS(scRet))
  6859. {
  6860. #ifndef WIN32_CHICAGO
  6861. LsapChangeHandle(
  6862. HandleReplace,
  6863. NULL,
  6864. &TempCtxtHandle
  6865. );
  6866. #endif // WIN32_CHICAGO
  6867. }
  6868. }
  6869. break;
  6870. case LATER_CALL_NO_INPUT:
  6871. DebugLog(( DEB_TRACE_NEG, "Missing Input Buffer?\n"));
  6872. scRet = SEC_E_INVALID_HANDLE ;
  6873. break;
  6874. case LATER_CALL_WITH_INPUT:
  6875. Context = (PNEG_CONTEXT) dwCtxtHandle ;
  6876. if ( !NegpIsValidContext( dwCtxtHandle ) )
  6877. {
  6878. return SEC_E_INVALID_HANDLE ;
  6879. }
  6880. if ( Context->Flags & NEG_CONTEXT_FRAGMENTING )
  6881. {
  6882. scRet = NegAddFragmentToContext(
  6883. Context,
  6884. Buffer );
  6885. //
  6886. // More trips needed to reconstruct the fragment.
  6887. //
  6888. if (scRet == SEC_I_CONTINUE_NEEDED)
  6889. {
  6890. NegpParseBuffers( pOutput, FALSE, &OutBuf, NULL );
  6891. if ( OutBuf )
  6892. {
  6893. OutBuf->cbBuffer = 0 ;
  6894. }
  6895. return scRet;
  6896. }
  6897. else if ( scRet != SEC_E_OK )
  6898. {
  6899. return scRet ;
  6900. }
  6901. //
  6902. // That was the final blob. Reset the message
  6903. // to be the whole thing
  6904. //
  6905. LocalBuffer.BufferType = SECBUFFER_TOKEN ;
  6906. LocalBuffer.cbBuffer = Context->TotalSize ;
  6907. LocalBuffer.pvBuffer = Context->Message ;
  6908. //
  6909. // Reset frag buffer to NULL - this will be
  6910. // freed when the call completes by the LSA wrappers.
  6911. // hence the ChangeBuffer call below:
  6912. //
  6913. Context->Message = NULL ;
  6914. scRet = LsapChangeBuffer( Buffer, &LocalBuffer );
  6915. if ( !NT_SUCCESS( scRet ) )
  6916. {
  6917. return scRet ;
  6918. }
  6919. //
  6920. // Fall through to the normal processing
  6921. //
  6922. }
  6923. scRet = NegHandleClientRequest(
  6924. dwCredHandle,
  6925. (PNEG_CONTEXT) dwCtxtHandle,
  6926. fContextReq,
  6927. TargetDataRep,
  6928. pInput,
  6929. pdwNewContext,
  6930. pOutput,
  6931. pfContextAttr,
  6932. ptsExpiry,
  6933. pfMapContext,
  6934. pContextData );
  6935. break;
  6936. default:
  6937. DsysAssert(FALSE);
  6938. scRet = SEC_E_INTERNAL_ERROR ;
  6939. break;
  6940. }
  6941. return scRet ;
  6942. }
  6943. NTSTATUS
  6944. NegCallPackage(
  6945. IN PLSA_CLIENT_REQUEST ClientRequest,
  6946. IN PVOID ProtocolSubmitBuffer,
  6947. IN PVOID ClientBufferBase,
  6948. IN ULONG SubmitBufferLength,
  6949. OUT PVOID *ProtocolReturnBuffer,
  6950. OUT PULONG ReturnBufferLength,
  6951. OUT PNTSTATUS ProtocolStatus
  6952. )
  6953. {
  6954. #ifdef WIN32_CHICAGO
  6955. return SEC_E_UNSUPPORTED_FUNCTION ;
  6956. #else
  6957. PULONG_PTR MessageTypePtr ;
  6958. NEGOTIATE_MESSAGES Messages ;
  6959. if ( SubmitBufferLength < sizeof( ULONG_PTR ) )
  6960. {
  6961. return STATUS_INVALID_PARAMETER ;
  6962. }
  6963. MessageTypePtr = (PULONG_PTR) ProtocolSubmitBuffer ;
  6964. if ( *MessageTypePtr >= NegCallPackageMax )
  6965. {
  6966. return STATUS_INVALID_PARAMETER ;
  6967. }
  6968. switch ( *MessageTypePtr )
  6969. {
  6970. case NegEnumPackagePrefixes:
  6971. return NegEnumPackagePrefixesCall(
  6972. ClientRequest,
  6973. ProtocolSubmitBuffer,
  6974. ClientBufferBase,
  6975. SubmitBufferLength,
  6976. ProtocolReturnBuffer,
  6977. ReturnBufferLength,
  6978. ProtocolStatus );
  6979. break;
  6980. case NegGetCallerName:
  6981. return NegGetCallerNameCall(
  6982. ClientRequest,
  6983. ProtocolSubmitBuffer,
  6984. ClientBufferBase,
  6985. SubmitBufferLength,
  6986. ProtocolReturnBuffer,
  6987. ReturnBufferLength,
  6988. ProtocolStatus );
  6989. break;
  6990. default:
  6991. DsysAssert( FALSE );
  6992. return STATUS_NOT_IMPLEMENTED ;
  6993. }
  6994. #endif
  6995. }
  6996. NTSTATUS
  6997. NegCallPackageUntrusted(
  6998. IN PLSA_CLIENT_REQUEST ClientRequest,
  6999. IN PVOID ProtocolSubmitBuffer,
  7000. IN PVOID ClientBufferBase,
  7001. IN ULONG SubmitBufferLength,
  7002. OUT PVOID *ProtocolReturnBuffer,
  7003. OUT PULONG ReturnBufferLength,
  7004. OUT PNTSTATUS ProtocolStatus
  7005. )
  7006. {
  7007. return( SEC_E_UNSUPPORTED_FUNCTION );
  7008. }
  7009. NTSTATUS
  7010. NegCallPackagePassthrough(
  7011. IN PLSA_CLIENT_REQUEST ClientRequest,
  7012. IN PVOID ProtocolSubmitBuffer,
  7013. IN PVOID ClientBufferBase,
  7014. IN ULONG SubmitBufferLength,
  7015. OUT PVOID *ProtocolReturnBuffer,
  7016. OUT PULONG ReturnBufferLength,
  7017. OUT PNTSTATUS ProtocolStatus
  7018. )
  7019. {
  7020. return( SEC_E_UNSUPPORTED_FUNCTION );
  7021. }
  7022. SECURITY_STATUS SEC_ENTRY
  7023. NegShutdown(void)
  7024. {
  7025. return(SEC_E_UNSUPPORTED_FUNCTION);
  7026. }
  7027. SECURITY_STATUS SEC_ENTRY
  7028. NegSystemLogon( PSECURITY_STRING pName,
  7029. DWORD cbKey,
  7030. PBYTE pbKey,
  7031. DWORD * pdwHandle,
  7032. PTimeStamp ptsExpiry)
  7033. {
  7034. return(SEC_E_UNSUPPORTED_FUNCTION);
  7035. }
  7036. SECURITY_STATUS SEC_ENTRY
  7037. NegGetUserInfo( PLUID pLogonId,
  7038. ULONG fFlags,
  7039. PSecurityUserData * ppUserInfo)
  7040. {
  7041. return(SEC_E_UNSUPPORTED_FUNCTION);
  7042. }
  7043. //+---------------------------------------------------------------------------
  7044. //
  7045. // Function: NegSaveCredentials
  7046. //
  7047. // Synopsis: Store credentials (not supported)
  7048. //
  7049. // Arguments: [dwCredHandle] --
  7050. // [CredType] --
  7051. // [pCredentials] --
  7052. //
  7053. //
  7054. // History: 7-26-96 RichardW Created
  7055. //
  7056. // Notes:
  7057. //
  7058. //----------------------------------------------------------------------------
  7059. SECURITY_STATUS SEC_ENTRY
  7060. NegSaveCredentials( LSA_SEC_HANDLE dwCredHandle,
  7061. PSecBuffer pCredentials)
  7062. {
  7063. return(SEC_E_UNSUPPORTED_FUNCTION);
  7064. }
  7065. //+---------------------------------------------------------------------------
  7066. //
  7067. // Function: NegGetCredentials
  7068. //
  7069. // Synopsis: Get Credentials (not supported)
  7070. //
  7071. // Arguments: [dwCredHandle] --
  7072. // [CredType] --
  7073. // [pCredentials] --
  7074. //
  7075. // History: 7-26-96 RichardW Created
  7076. //
  7077. // Notes:
  7078. //
  7079. //----------------------------------------------------------------------------
  7080. SECURITY_STATUS SEC_ENTRY
  7081. NegGetCredentials( LSA_SEC_HANDLE dwCredHandle,
  7082. PSecBuffer pCredentials)
  7083. {
  7084. return(SEC_E_UNSUPPORTED_FUNCTION);
  7085. }
  7086. //+---------------------------------------------------------------------------
  7087. //
  7088. // Function: NegDeleteCredentials
  7089. //
  7090. // Synopsis: Delete stored creds (not supported)
  7091. //
  7092. // Arguments: [dwCredHandle] --
  7093. // [CredType] --
  7094. // [pKey] --
  7095. //
  7096. // History: 7-26-96 RichardW Created
  7097. //
  7098. // Notes:
  7099. //
  7100. //----------------------------------------------------------------------------
  7101. SECURITY_STATUS SEC_ENTRY
  7102. NegDeleteCredentials( LSA_SEC_HANDLE dwCredHandle,
  7103. PSecBuffer pKey)
  7104. {
  7105. return(SEC_E_UNSUPPORTED_FUNCTION);
  7106. }
  7107. SECURITY_STATUS SEC_ENTRY
  7108. NegAddCredentials(
  7109. IN LSA_SEC_HANDLE CredentialHandle,
  7110. IN OPTIONAL PUNICODE_STRING PrincipalName,
  7111. IN PUNICODE_STRING Package,
  7112. IN ULONG CredentialUseFlags,
  7113. IN PVOID AuthorizationData,
  7114. IN PVOID GetKeyFunction,
  7115. IN PVOID GetKeyArgument,
  7116. OUT PTimeStamp ExpirationTime
  7117. )
  7118. {
  7119. PNEG_CREDS Cred ;
  7120. PNEG_CREDS NewCred ;
  7121. NTSTATUS Status ;
  7122. TimeStamp Expiration ;
  7123. PLIST_ENTRY Prev ;
  7124. PNEG_CREDS PreviousCreds ;
  7125. Cred = (PNEG_CREDS) CredentialHandle ;
  7126. Status = NegpAcquireCredHandle(
  7127. PrincipalName,
  7128. CredentialUseFlags | NEG_CRED_DONT_LINK,
  7129. &Cred->ClientLogonId,
  7130. AuthorizationData,
  7131. GetKeyFunction,
  7132. GetKeyArgument,
  7133. (PULONG_PTR) &NewCred,
  7134. &Expiration );
  7135. if ( !NT_SUCCESS( Status ) )
  7136. {
  7137. return Status ;
  7138. }
  7139. NegWriteLockCreds( Cred );
  7140. Prev = Cred->AdditionalCreds.Blink ;
  7141. if ( Prev != &Cred->AdditionalCreds )
  7142. {
  7143. //
  7144. // If there are other creds, make sure they are marked
  7145. //
  7146. PreviousCreds = CONTAINING_RECORD( Prev, NEG_CREDS, List );
  7147. PreviousCreds->Flags |= NEGCRED_MULTI_PART ;
  7148. }
  7149. InsertTailList( &Cred->AdditionalCreds, &NewCred->List );
  7150. Cred->Flags |= NEGCRED_MULTI ;
  7151. NegUnlockCreds( Cred );
  7152. return Status ;
  7153. }
  7154. NTSTATUS
  7155. NegGetExtendedInformation(
  7156. IN SECPKG_EXTENDED_INFORMATION_CLASS Class,
  7157. OUT PSECPKG_EXTENDED_INFORMATION * ppInformation
  7158. )
  7159. {
  7160. PSECPKG_EXTENDED_INFORMATION Thunks ;
  7161. NTSTATUS Status ;
  7162. switch ( Class )
  7163. {
  7164. case SecpkgContextThunks:
  7165. Thunks = (PSECPKG_EXTENDED_INFORMATION) LsapAllocateLsaHeap( sizeof( SECPKG_EXTENDED_INFORMATION ) + sizeof( DWORD ));
  7166. if ( Thunks )
  7167. {
  7168. Thunks->Class = SecpkgContextThunks;
  7169. Thunks->Info.ContextThunks.InfoLevelCount = 2 ;
  7170. Thunks->Info.ContextThunks.Levels[0] = SECPKG_ATTR_PACKAGE_INFO;
  7171. Thunks->Info.ContextThunks.Levels[1] = SECPKG_ATTR_SIZES ;
  7172. Status = STATUS_SUCCESS ;
  7173. }
  7174. else
  7175. {
  7176. Status = STATUS_NO_MEMORY ;
  7177. }
  7178. *ppInformation = Thunks ;
  7179. break;
  7180. default:
  7181. *ppInformation = NULL ;
  7182. Status = STATUS_INVALID_INFO_CLASS ;
  7183. break;
  7184. }
  7185. return Status ;
  7186. }
  7187. //+---------------------------------------------------------------------------
  7188. //
  7189. // Function: NegQueryContextAttributes
  7190. //
  7191. // Synopsis:
  7192. //
  7193. // Arguments: [ContextHandle] --
  7194. // [ContextAttribute] --
  7195. // [Buffer] --
  7196. //
  7197. // Returns:
  7198. //
  7199. // Notes:
  7200. //
  7201. //----------------------------------------------------------------------------
  7202. NTSTATUS
  7203. NegQueryContextAttributes(
  7204. IN LSA_SEC_HANDLE ContextHandle,
  7205. IN ULONG ContextAttribute,
  7206. IN OUT PVOID Buffer)
  7207. {
  7208. SecPkgContext_NegotiationInfoW NegInfo = {0};
  7209. SecPkgContext_Sizes Sizes ;
  7210. NTSTATUS Status = STATUS_SUCCESS;
  7211. PNEG_CONTEXT Context = (PNEG_CONTEXT) ContextHandle ;
  7212. SECPKG_CALL_INFO CallInfo ;
  7213. SecPkgInfoW PackageInfo ;
  7214. #ifndef WIN32_CHICAGO
  7215. LsapGetCallInfo( &CallInfo );
  7216. switch ( ContextAttribute )
  7217. {
  7218. case SECPKG_ATTR_NEGOTIATION_INFO :
  7219. if ( CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE )
  7220. {
  7221. Status = LsapCopyFromClient(
  7222. Buffer,
  7223. &NegInfo,
  7224. sizeof( NegInfo ) );
  7225. }
  7226. if ( (Context->Flags & NEG_CONTEXT_NEGOTIATING) != 0 )
  7227. {
  7228. NegInfo.NegotiationState = SECPKG_NEGOTIATION_IN_PROGRESS ;
  7229. }
  7230. else
  7231. {
  7232. NegInfo.NegotiationState = SECPKG_NEGOTIATION_OPTIMISTIC ;
  7233. }
  7234. if ( NegInfo.NegotiationState == SECPKG_NEGOTIATION_OPTIMISTIC )
  7235. {
  7236. if ( ( CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) == 0 )
  7237. {
  7238. Status = WLsaQueryPackageInfo(
  7239. &Context->Creds->Creds[ Context->CredIndex ].Package->LsaPackage->Name,
  7240. &NegInfo.PackageInfo
  7241. );
  7242. }
  7243. else
  7244. {
  7245. //
  7246. // For kernel mode callers, we can't return the package info
  7247. // this way due to VM risks. So, we just put the package ID
  7248. // into the pointer, and ksec looks it up in kernel space.
  7249. //
  7250. PackageInfo.wRPCID = (WORD) Context->Creds->Creds[ Context->CredIndex ].Package->LsaPackage->dwRPCID;
  7251. PackageInfo.fCapabilities = Context->Creds->Creds[ Context->CredIndex ].Package->LsaPackage->fCapabilities ;
  7252. PackageInfo.cbMaxToken = Context->Creds->Creds[ Context->CredIndex ].Package->LsaPackage->TokenSize ;
  7253. Status = LsapCopyToClient(
  7254. &PackageInfo,
  7255. NegInfo.PackageInfo,
  7256. sizeof( PackageInfo ) );
  7257. }
  7258. }
  7259. if (NT_SUCCESS(Status))
  7260. {
  7261. Status = LsapCopyToClient( &NegInfo, Buffer, sizeof( NegInfo ) );
  7262. if (!NT_SUCCESS(Status))
  7263. {
  7264. if (( NegInfo.PackageInfo != NULL ) &&
  7265. ( ( CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) == 0 ) )
  7266. {
  7267. LsapClientFree(NegInfo.PackageInfo);
  7268. }
  7269. }
  7270. }
  7271. return Status ;
  7272. case SECPKG_ATTR_SIZES:
  7273. Sizes.cbMaxToken = NegLsaPackage->TokenSize ;
  7274. Sizes.cbMaxSignature = 64 ;
  7275. Sizes.cbBlockSize = 8 ;
  7276. Sizes.cbSecurityTrailer = 64 ;
  7277. Status = LsapCopyToClient( &Sizes, Buffer, sizeof( Sizes ) );
  7278. return Status ;
  7279. default:
  7280. return SEC_E_UNSUPPORTED_FUNCTION ;
  7281. }
  7282. #endif
  7283. return SEC_E_UNSUPPORTED_FUNCTION ;
  7284. }