Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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