Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3664 lines
94 KiB

  1. /*--
  2. Copyright (c) 1994-1997 Microsoft Corporation
  3. Module Name:
  4. secpkg.c
  5. Abstract:
  6. Security package used for Netlogon's secure channel between two netlogon
  7. processes.
  8. Author:
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 05-Mar-1994 (MikeSw)
  15. Created as user mode example SSPI
  16. 02-Nov-1997 (CliffV)
  17. Converted to be the Netlogon security package.
  18. --*/
  19. //
  20. // Common include files.
  21. //
  22. #include "logonsrv.h" // Include files common to entire service
  23. #pragma hdrstop
  24. //
  25. // Include files specific to this .c file
  26. //
  27. #include <spseal.h>
  28. //
  29. // Authentication Data for the Netlogon Authentication Package.
  30. //
  31. // This is the auth data to pass to RpcBindingSetAuthInfo for the
  32. // Netlogon authentication package.
  33. //
  34. typedef struct _NL_AUTH_DATA {
  35. //
  36. // Signature to identify that this is really AUTH Data
  37. //
  38. ULONG Signature;
  39. #define NL_AUTH_DATA_SIGNATURE 0x29120227
  40. //
  41. // Size of this structure (in bytes)
  42. //
  43. ULONG Size;
  44. //
  45. // Information describing the session between the client and server.
  46. //
  47. SESSION_INFO SessionInfo;
  48. //
  49. // Domain name of the domain we're connecting to.
  50. //
  51. ULONG OemNetbiosDomainNameOffset;
  52. ULONG OemNetbiosDomainNameLength;
  53. ULONG Utf8DnsDomainNameOffset;
  54. //
  55. // Computer name of this machine
  56. //
  57. ULONG OemComputerNameOffset;
  58. ULONG OemComputerNameLength;
  59. ULONG Utf8ComputerNameOffset;
  60. ULONG Utf8ComputerNameLength;
  61. ULONG Utf8DnsHostNameOffset;
  62. } NL_AUTH_DATA, *PNL_AUTH_DATA;
  63. //
  64. // A single credential
  65. // Only the outbound side has a credential allocated. The inbound side simply
  66. // returns a constant handle to the caller.
  67. #define NL_AUTH_SERVER_CRED 0xfefefefe
  68. typedef struct _NL_AUTH_CREDENTIAL {
  69. //
  70. // Handle identifying the credential
  71. //
  72. CredHandle CredentialHandle;
  73. //
  74. // Global list of all credentials
  75. //
  76. struct _NL_AUTH_CREDENTIAL *Next;
  77. //
  78. // Reference count
  79. //
  80. ULONG ReferenceCount;
  81. //
  82. // For a client side (outbound) credential,
  83. // this is a pointer to the information from the client session structure
  84. // representing the secure channel to the server.
  85. //
  86. PNL_AUTH_DATA ClientAuthData;
  87. } NL_AUTH_CREDENTIAL, *PNL_AUTH_CREDENTIAL;
  88. //
  89. // A single context.
  90. //
  91. typedef struct _NL_AUTH_CONTEXT {
  92. //
  93. // Handle identifying the context
  94. //
  95. CtxtHandle ContextHandle;
  96. //
  97. // Global list of all contexts
  98. //
  99. struct _NL_AUTH_CONTEXT * Next;
  100. LARGE_INTEGER Nonce;
  101. ULONG ContextFlags;
  102. //
  103. // Information describing the session between the client and server.
  104. //
  105. SESSION_INFO SessionInfo;
  106. enum {
  107. Idle,
  108. FirstInit,
  109. FirstAccept,
  110. SecondInit
  111. } State;
  112. //
  113. // Flags
  114. //
  115. BOOLEAN Inbound;
  116. } NL_AUTH_CONTEXT, *PNL_AUTH_CONTEXT;
  117. #define BUFFERTYPE(_x_) ((_x_).BufferType & ~SECBUFFER_ATTRMASK)
  118. //
  119. // On the wire message transmitted from client to server during the bind.
  120. //
  121. typedef enum {
  122. Negotiate,
  123. NegotiateResponse
  124. } NL_AUTH_MESSAGE_TYPE;
  125. typedef struct _NL_AUTH_MESSAGE {
  126. NL_AUTH_MESSAGE_TYPE MessageType;
  127. ULONG Flags;
  128. #define NL_AUTH_NETBIOS_DOMAIN_NAME 0x0001 // Netbios Domain name exists in buffer
  129. #define NL_AUTH_NETBIOS_COMPUTER_NAME 0x0002 // Netbios Computer name exists in buffer
  130. #define NL_AUTH_DNS_DOMAIN_NAME 0x0004 // DNS Domain name exists in buffer
  131. #define NL_AUTH_DNS_HOST_NAME 0x0008 // DNS Host name exists in buffer
  132. #define NL_AUTH_UTF8_NETBIOS_COMPUTER_NAME 0x0010 // UTF-8 Netbios Computer name exists in buffer
  133. UCHAR Buffer[1];
  134. } NL_AUTH_MESSAGE, *PNL_AUTH_MESSAGE;
  135. //
  136. // Signature for signed and sealed messages
  137. //
  138. #define NL_AUTH_ETYPE KERB_ETYPE_RC4_PLAIN_OLD // Encryption algorithm to use
  139. #define NL_AUTH_CHECKSUM KERB_CHECKSUM_MD5_HMAC // Checksum algorithm to use
  140. typedef struct _NL_AUTH_SIGNATURE {
  141. BYTE SignatureAlgorithm[2]; // see below table for values
  142. union {
  143. BYTE SignFiller[4]; // filler, must be ff ff ff ff
  144. struct {
  145. BYTE SealAlgorithm[2];
  146. BYTE SealFiller[2];
  147. };
  148. };
  149. BYTE Flags[2];
  150. #define NL_AUTH_SIGNED_BYTES 8 // Number of bytes in signature before SequenceNumber
  151. #define NL_AUTH_SEQUENCE_SIZE 8
  152. BYTE SequenceNumber[NL_AUTH_SEQUENCE_SIZE];
  153. BYTE Checksum[8];
  154. // Confounder must be the last field in the structure since it isn't sent on
  155. // the wire if we're only signing the message.
  156. #define NL_AUTH_CONFOUNDER_SIZE 8
  157. BYTE Confounder[NL_AUTH_CONFOUNDER_SIZE];
  158. } NL_AUTH_SIGNATURE, *PNL_AUTH_SIGNATURE;
  159. #define PACKAGE_NAME NL_PACKAGE_NAME
  160. #define PACKAGE_COMMENT L"Package for securing Netlogon's Secure Channel"
  161. #define PACAKGE_CAPABILITIES (SECPKG_FLAG_TOKEN_ONLY | \
  162. SECPKG_FLAG_MULTI_REQUIRED | \
  163. SECPKG_FLAG_CONNECTION | \
  164. SECPKG_FLAG_INTEGRITY | \
  165. SECPKG_FLAG_PRIVACY)
  166. #define PACKAGE_VERSION 1
  167. #define PACKAGE_RPCID RPC_C_AUTHN_NETLOGON
  168. #define PACKAGE_MAXTOKEN (sizeof(NL_AUTH_MESSAGE) + DNLEN + 1 + CNLEN + 1 + 2*(NL_MAX_DNS_LENGTH+1) )
  169. #define PACKAGE_SIGNATURE_SIZE sizeof(NL_AUTH_SIGNATURE)
  170. SecurityFunctionTableW SecTableW = {SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
  171. EnumerateSecurityPackagesW,
  172. NULL,
  173. AcquireCredentialsHandleW,
  174. FreeCredentialsHandle,
  175. NULL, // LogonUser
  176. InitializeSecurityContextW,
  177. AcceptSecurityContext,
  178. NULL,
  179. DeleteSecurityContext,
  180. NULL,
  181. QueryContextAttributesW,
  182. ImpersonateSecurityContext,
  183. RevertSecurityContext,
  184. MakeSignature,
  185. VerifySignature,
  186. FreeContextBuffer,
  187. QuerySecurityPackageInfoW,
  188. SealMessage,
  189. UnsealMessage,
  190. };
  191. PNL_AUTH_CONTEXT ContextList;
  192. PNL_AUTH_CREDENTIAL CredentialList;
  193. //
  194. // Id's to identify a context or credential.
  195. // Access serialized by NlGlobalSecPkgCritSect
  196. //
  197. LARGE_INTEGER NextId = {0,0};
  198. TimeStamp Forever = {0x7fffffff,0xfffffff};
  199. TimeStamp Never = {0,0};
  200. PVOID
  201. NlBuildAuthData(
  202. PCLIENT_SESSION ClientSession
  203. )
  204. /*++
  205. Routine Description:
  206. Allocate an authentication data structure suitable for passing to
  207. RpcBindingSetAuthInfo
  208. On Entry,
  209. The caller must be a writer of the trust list entry.
  210. The trust list entry must be authenticated.
  211. Arguments:
  212. ClientSession - Authenticated session describing the secure channel to a
  213. DC.
  214. Return Value:
  215. Pointer to the AUTH_DATA. (Buffer should be freed by calling I_NetLogonFree.)
  216. NULL: memory could not be allocated
  217. --*/
  218. {
  219. ULONG Size;
  220. PNL_AUTH_DATA ClientAuthData;
  221. LPBYTE Where;
  222. ULONG DnsDomainNameSize;
  223. ULONG DnsHostNameSize;
  224. NlAssert( ClientSession->CsReferenceCount > 0 );
  225. NlAssert( ClientSession->CsFlags & CS_WRITER );
  226. NlAssert( ClientSession->CsState == CS_AUTHENTICATED );
  227. //
  228. // Determine the size of the entry
  229. //
  230. DnsDomainNameSize =
  231. (ClientSession->CsUtf8DnsDomainName != NULL ?
  232. (strlen( ClientSession->CsUtf8DnsDomainName ) + 1) :
  233. 0);
  234. #ifdef notdef
  235. DnsHostNameSize =
  236. (ClientSession->CsDomainInfo->DomUtf8DnsHostName != NULL ?
  237. (strlen( ClientSession->CsDomainInfo->DomUtf8DnsHostName ) + 1) :
  238. 0);
  239. #else // notdef
  240. DnsHostNameSize = 0;
  241. #endif // notdef
  242. Size = sizeof(NL_AUTH_DATA) +
  243. ClientSession->CsOemNetbiosDomainNameLength + 1 +
  244. ClientSession->CsDomainInfo->DomOemComputerNameLength + 1 +
  245. ClientSession->CsDomainInfo->DomUtf8ComputerNameLength + 1 +
  246. DnsDomainNameSize +
  247. DnsHostNameSize;
  248. //
  249. // Allocate the entry
  250. //
  251. ClientAuthData = NetpMemoryAllocate( Size );
  252. if ( ClientAuthData == NULL ) {
  253. return NULL;
  254. }
  255. Where = (LPBYTE) (ClientAuthData + 1);
  256. RtlZeroMemory( ClientAuthData, sizeof(NL_AUTH_DATA) );
  257. //
  258. // Fill in the fixed length fields.
  259. //
  260. ClientAuthData->Signature = NL_AUTH_DATA_SIGNATURE;
  261. ClientAuthData->Size = Size;
  262. ClientAuthData->SessionInfo.SessionKey = ClientSession->CsSessionKey;
  263. ClientAuthData->SessionInfo.NegotiatedFlags = ClientSession->CsNegotiatedFlags;
  264. //
  265. // Copy the Netbios domain name of the domain hosted by the DC into the buffer
  266. //
  267. if ( ClientSession->CsOemNetbiosDomainNameLength != 0 ) {
  268. ClientAuthData->OemNetbiosDomainNameOffset = (ULONG) (Where-(LPBYTE)ClientAuthData);
  269. ClientAuthData->OemNetbiosDomainNameLength =
  270. ClientSession->CsOemNetbiosDomainNameLength;
  271. RtlCopyMemory( Where,
  272. ClientSession->CsOemNetbiosDomainName,
  273. ClientSession->CsOemNetbiosDomainNameLength + 1 );
  274. Where += ClientAuthData->OemNetbiosDomainNameLength + 1;
  275. }
  276. //
  277. // Copy the OEM Netbios computer name of this machine into the buffer.
  278. //
  279. // ???: Only copy the Netbios computername or DNS host name. Copy the
  280. // one that was passed to the server on the NetServerReqChallenge.
  281. //
  282. if ( ClientSession->CsDomainInfo->DomOemComputerNameLength != 0 ) {
  283. ClientAuthData->OemComputerNameOffset = (ULONG) (Where-(LPBYTE)ClientAuthData);
  284. ClientAuthData->OemComputerNameLength =
  285. ClientSession->CsDomainInfo->DomOemComputerNameLength;
  286. RtlCopyMemory( Where,
  287. ClientSession->CsDomainInfo->DomOemComputerName,
  288. ClientSession->CsDomainInfo->DomOemComputerNameLength + 1);
  289. Where += ClientAuthData->OemComputerNameLength + 1;
  290. }
  291. //
  292. // Copy the UTF-8 Netbios computer name of this machine into the buffer.
  293. //
  294. if ( ClientSession->CsDomainInfo->DomUtf8ComputerNameLength != 0 ) {
  295. ClientAuthData->Utf8ComputerNameOffset = (ULONG) (Where-(LPBYTE)ClientAuthData);
  296. ClientAuthData->Utf8ComputerNameLength =
  297. ClientSession->CsDomainInfo->DomUtf8ComputerNameLength;
  298. RtlCopyMemory( Where,
  299. ClientSession->CsDomainInfo->DomUtf8ComputerName,
  300. ClientSession->CsDomainInfo->DomUtf8ComputerNameLength +1 );
  301. Where += ClientAuthData->Utf8ComputerNameLength + 1;
  302. }
  303. //
  304. // Copy the DNS domain name of the domain hosted by the DC into the buffer.
  305. //
  306. if ( ClientSession->CsUtf8DnsDomainName != NULL ) {
  307. ClientAuthData->Utf8DnsDomainNameOffset = (ULONG) (Where-(LPBYTE)ClientAuthData);
  308. RtlCopyMemory( Where, ClientSession->CsUtf8DnsDomainName, DnsDomainNameSize );
  309. Where += DnsDomainNameSize;
  310. }
  311. //
  312. // Copy the DNS host name name of this machine into the buffer.
  313. //
  314. // ???: Only copy the Netbios computername or DNS host name. Copy the
  315. // one that was passed to the server on the NetServerReqChallenge.
  316. //
  317. #ifdef notdef
  318. if ( ClientSession->CsDomainInfo->DomUtf8DnsHostName != NULL ) {
  319. ClientAuthData->Utf8DnsHostNameOffset = (ULONG) (Where-(LPBYTE)ClientAuthData);
  320. RtlCopyMemory( Where, ClientSession->CsDomainInfo->DomUtf8DnsHostName, DnsHostNameSize );
  321. Where += DnsHostNameSize;
  322. }
  323. #endif // notdef
  324. return ClientAuthData;
  325. }
  326. BOOL
  327. NlStartNetlogonCall(
  328. VOID
  329. )
  330. /*++
  331. Routine Description:
  332. Start a procedure call from outside the Netlogon service into the
  333. Netlogon Service.
  334. Arguments:
  335. None.
  336. Return Value:
  337. TRUE - Call is OK. (Caller must call NlEndNetlogonCall())
  338. FALSE - Netlogon is not started.
  339. --*/
  340. {
  341. //
  342. // If caller is calling when the netlogon service isn't running,
  343. // tell it so.
  344. //
  345. EnterCriticalSection( &NlGlobalMsvCritSect );
  346. if ( !NlGlobalMsvEnabled ) {
  347. LeaveCriticalSection( &NlGlobalMsvCritSect );
  348. return FALSE;
  349. }
  350. NlGlobalMsvThreadCount ++;
  351. LeaveCriticalSection( &NlGlobalMsvCritSect );
  352. return TRUE;
  353. }
  354. VOID
  355. NlEndNetlogonCall(
  356. VOID
  357. )
  358. /*++
  359. Routine Description:
  360. End a procedure call from outside the Netlogon service into the
  361. Netlogon Service.
  362. Arguments:
  363. None.
  364. Return Value:
  365. None.
  366. --*/
  367. {
  368. //
  369. // Indicate that the calling thread has left netlogon.dll
  370. //
  371. EnterCriticalSection( &NlGlobalMsvCritSect );
  372. NlGlobalMsvThreadCount --;
  373. if ( NlGlobalMsvThreadCount == 0 && !NlGlobalMsvEnabled ) {
  374. if ( !SetEvent( NlGlobalMsvTerminateEvent ) ) {
  375. NlPrint((NL_CRITICAL, "Cannot set MSV termination event: %lu\n",
  376. GetLastError() ));
  377. }
  378. }
  379. LeaveCriticalSection( &NlGlobalMsvCritSect );
  380. }
  381. PNL_AUTH_CREDENTIAL
  382. LocateCredential(
  383. PCredHandle CredentialHandle
  384. )
  385. /*++
  386. Routine Description:
  387. Find a credential given its handle
  388. Arguments:
  389. CredentialHandle - Handle to the credential to locate
  390. Return Value:
  391. Pointer to the credential
  392. --*/
  393. {
  394. PNL_AUTH_CREDENTIAL TestCredential;
  395. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  396. for ( TestCredential = CredentialList;
  397. TestCredential != NULL;
  398. TestCredential = TestCredential->Next ) {
  399. if ( TestCredential->CredentialHandle.dwUpper == CredentialHandle->dwUpper &&
  400. TestCredential->CredentialHandle.dwLower == CredentialHandle->dwLower ) {
  401. break;
  402. }
  403. }
  404. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  405. return(TestCredential);
  406. }
  407. BOOLEAN
  408. DeleteCredential(
  409. PCtxtHandle CredentialHandle
  410. )
  411. /*++
  412. Routine Description:
  413. Delete a credential given its handle
  414. Arguments:
  415. CredentialHandle - Handle to the credential to locate
  416. Return Value:
  417. TRUE: if credential existed.
  418. --*/
  419. {
  420. PNL_AUTH_CREDENTIAL TestCredential, LastCredential;
  421. //
  422. // Find the credential.
  423. //
  424. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  425. LastCredential = NULL;
  426. for ( TestCredential = CredentialList;
  427. TestCredential != NULL ;
  428. TestCredential = TestCredential->Next ) {
  429. if ( TestCredential->CredentialHandle.dwUpper == CredentialHandle->dwUpper &&
  430. TestCredential->CredentialHandle.dwLower == CredentialHandle->dwLower ) {
  431. break;
  432. }
  433. LastCredential = TestCredential;
  434. }
  435. //
  436. // If we found it,
  437. // Dereference it.
  438. //
  439. if ( TestCredential != NULL ) {
  440. TestCredential->ReferenceCount --;
  441. //
  442. // If this is the last dereference,
  443. // delink it and delete it.
  444. //
  445. if ( TestCredential->ReferenceCount == 0 ) {
  446. if (LastCredential != NULL) {
  447. LastCredential->Next = TestCredential->Next;
  448. } else {
  449. NlAssert(CredentialList == TestCredential);
  450. CredentialList = TestCredential->Next;
  451. }
  452. NlPrint(( NL_SESSION_MORE,
  453. "DeleteCredential: %lx.%lx: credential freed\n",
  454. CredentialHandle->dwUpper, CredentialHandle->dwLower ));
  455. LocalFree(TestCredential);
  456. } else {
  457. NlPrint(( NL_SESSION_MORE,
  458. "DeleteCredential: %lx.%lx: credential dereferenced: %ld\n",
  459. CredentialHandle->dwUpper, CredentialHandle->dwLower,
  460. TestCredential->ReferenceCount ));
  461. }
  462. } else {
  463. NlPrint(( NL_SESSION_MORE,
  464. "DeleteCredential: %lx.%lx: credential handle not found\n",
  465. CredentialHandle->dwUpper, CredentialHandle->dwLower ));
  466. }
  467. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  468. return( TestCredential == NULL ? FALSE : TRUE );
  469. }
  470. PNL_AUTH_CREDENTIAL
  471. AllocateCredential(
  472. IN PNL_AUTH_DATA ClientAuthData
  473. )
  474. /*++
  475. Routine Description:
  476. Allocate and initialize a credential (Client or server side)
  477. Arguments:
  478. ClientAuthData - The client auth data to capture.
  479. Return Value:
  480. Allocated credential. Delete this credential by DeleteCredential( Credential->CredentialHandle );
  481. NULL if credential cannot be allocated.
  482. --*/
  483. {
  484. PNL_AUTH_CREDENTIAL Credential;
  485. //
  486. // Determine if we already have a credential
  487. //
  488. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  489. for ( Credential = CredentialList;
  490. Credential != NULL;
  491. Credential = Credential->Next ) {
  492. if ( ClientAuthData->Size == Credential->ClientAuthData->Size &&
  493. RtlEqualMemory( ClientAuthData,
  494. Credential->ClientAuthData,
  495. ClientAuthData->Size ) ) {
  496. //
  497. // Return the existing credential to the caller.
  498. //
  499. Credential->ReferenceCount ++;
  500. NlPrint(( NL_SESSION_MORE,
  501. "AllocateCredential: %lx.%lx: credential referenced: %ld\n",
  502. Credential->CredentialHandle.dwUpper,
  503. Credential->CredentialHandle.dwLower,
  504. Credential->ReferenceCount ));
  505. goto Cleanup;
  506. }
  507. }
  508. //
  509. // Allocate a credential block.
  510. //
  511. Credential = (PNL_AUTH_CREDENTIAL)
  512. LocalAlloc( LMEM_ZEROINIT,
  513. sizeof(NL_AUTH_CREDENTIAL) +
  514. ClientAuthData->Size );
  515. if (Credential == NULL) {
  516. goto Cleanup;
  517. }
  518. //
  519. // Initialize the credential.
  520. //
  521. NextId.QuadPart ++;
  522. Credential->CredentialHandle.dwUpper = NextId.HighPart;
  523. Credential->CredentialHandle.dwLower = NextId.LowPart;
  524. Credential->ReferenceCount = 1;
  525. Credential->Next = CredentialList;
  526. CredentialList = Credential;
  527. //
  528. // Capture a local copy of the credential
  529. // The caller might free the one passed in to us.
  530. //
  531. Credential->ClientAuthData = (PNL_AUTH_DATA)
  532. (((LPBYTE)Credential) + sizeof(NL_AUTH_CREDENTIAL));
  533. RtlCopyMemory( Credential->ClientAuthData,
  534. ClientAuthData,
  535. ClientAuthData->Size );
  536. NlPrint(( NL_SESSION_MORE,
  537. "AllocateCredential: %lx.%lx: credential allocated\n",
  538. Credential->CredentialHandle.dwUpper,
  539. Credential->CredentialHandle.dwLower ));
  540. Cleanup:
  541. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  542. return Credential;
  543. }
  544. PNL_AUTH_CONTEXT
  545. LocateContext(
  546. PCtxtHandle ContextHandle
  547. )
  548. /*++
  549. Routine Description:
  550. Find a context given its handle
  551. Arguments:
  552. ContextHandle - Handle to the context to locate
  553. Return Value:
  554. Pointer to the context
  555. --*/
  556. {
  557. PNL_AUTH_CONTEXT TestContext;
  558. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  559. for ( TestContext = ContextList;
  560. TestContext != NULL;
  561. TestContext = TestContext->Next ) {
  562. if ( TestContext->ContextHandle.dwUpper == ContextHandle->dwUpper &&
  563. TestContext->ContextHandle.dwLower == ContextHandle->dwLower ) {
  564. break;
  565. }
  566. }
  567. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  568. return(TestContext);
  569. }
  570. BOOLEAN
  571. DeleteContext(
  572. PCtxtHandle ContextHandle
  573. )
  574. /*++
  575. Routine Description:
  576. Delete a context given its handle
  577. Arguments:
  578. ContextHandle - Handle to the context to locate
  579. Return Value:
  580. TRUE: Context existed
  581. --*/
  582. {
  583. PNL_AUTH_CONTEXT TestContext, LastContext;
  584. //
  585. // Find the context.
  586. //
  587. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  588. LastContext = NULL;
  589. for ( TestContext = ContextList;
  590. TestContext != NULL ;
  591. TestContext = TestContext->Next ) {
  592. if ( TestContext->ContextHandle.dwUpper == ContextHandle->dwUpper &&
  593. TestContext->ContextHandle.dwLower == ContextHandle->dwLower ) {
  594. break;
  595. }
  596. LastContext = TestContext;
  597. }
  598. //
  599. // If we found it,
  600. // and it is no longer needed as a context or a credential,
  601. // delink it and delete it.
  602. //
  603. if ( TestContext != NULL ) {
  604. if (LastContext != NULL) {
  605. LastContext->Next = TestContext->Next;
  606. } else {
  607. NlAssert(ContextList == TestContext);
  608. ContextList = TestContext->Next;
  609. }
  610. NlPrint(( NL_SESSION_MORE,
  611. "DeleteContext: %lx.%lx: context freed\n",
  612. ContextHandle->dwUpper, ContextHandle->dwLower ));
  613. LocalFree(TestContext);
  614. } else {
  615. NlPrint(( NL_SESSION_MORE,
  616. "DeleteContext: %lx.%lx: context handle not found\n",
  617. ContextHandle->dwUpper, ContextHandle->dwLower ));
  618. }
  619. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  620. return( TestContext == NULL ? FALSE : TRUE );
  621. }
  622. PNL_AUTH_CONTEXT
  623. AllocateContext(
  624. IN ULONG fContextReq
  625. )
  626. /*++
  627. Routine Description:
  628. Allocate and initialize a context (Client or server side)
  629. Arguments:
  630. fContextReq - Context request flags
  631. Return Value:
  632. Allocated context. Delete this context by DeleteContext( Context->ContextHandle, FALSE );
  633. NULL if context cannot be allocated.
  634. --*/
  635. {
  636. PNL_AUTH_CONTEXT Context;
  637. //
  638. // Allocate a context block.
  639. //
  640. Context = (PNL_AUTH_CONTEXT) LocalAlloc( LMEM_ZEROINIT, sizeof(NL_AUTH_CONTEXT) );
  641. if (Context == NULL) {
  642. return NULL;
  643. }
  644. //
  645. // Initialize the context.
  646. //
  647. Context->State = Idle;
  648. Context->ContextFlags = fContextReq;
  649. RtlEnterCriticalSection(&NlGlobalSecPkgCritSect);
  650. NextId.QuadPart ++;
  651. Context->ContextHandle.dwUpper = NextId.HighPart;
  652. Context->ContextHandle.dwLower = NextId.LowPart;
  653. Context->Next = ContextList;
  654. ContextList = Context;
  655. RtlLeaveCriticalSection(&NlGlobalSecPkgCritSect);
  656. return Context;
  657. }
  658. PSecBuffer
  659. LocateBuffer(PSecBufferDesc Buffer, ULONG MinimumSize)
  660. /*++
  661. Routine Description:
  662. Arguments:
  663. Standard.
  664. Return Value:
  665. --*/
  666. {
  667. ULONG Index;
  668. if (Buffer == NULL) {
  669. return(NULL);
  670. }
  671. for (Index = 0; Index < Buffer->cBuffers ; Index++) {
  672. if ( BUFFERTYPE(Buffer->pBuffers[Index]) == SECBUFFER_TOKEN) {
  673. //
  674. // Do size checking
  675. //
  676. if (Buffer->pBuffers[Index].cbBuffer < MinimumSize) {
  677. return(NULL);
  678. }
  679. return(&Buffer->pBuffers[Index]);
  680. }
  681. }
  682. return(NULL);
  683. }
  684. PSecBuffer
  685. LocateSecBuffer(PSecBufferDesc Buffer)
  686. /*++
  687. Routine Description:
  688. Locate a buffer suitable for authentication
  689. Arguments:
  690. Standard.
  691. Return Value:
  692. --*/
  693. {
  694. return(LocateBuffer(Buffer, sizeof(NL_AUTH_MESSAGE)));
  695. }
  696. PSecBuffer
  697. LocateSigBuffer(PSecBufferDesc Buffer)
  698. /*++
  699. Routine Description:
  700. Locate a buffer suitable for a signature
  701. Arguments:
  702. Standard.
  703. Return Value:
  704. --*/
  705. {
  706. return(LocateBuffer(Buffer, PACKAGE_SIGNATURE_SIZE - NL_AUTH_CONFOUNDER_SIZE ));
  707. }
  708. PSecurityFunctionTableW SEC_ENTRY
  709. InitSecurityInterfaceW(VOID)
  710. /*++
  711. Routine Description:
  712. Initialization routine called by RPC to get pointers to all other routines.
  713. Arguments:
  714. None.
  715. Return Value:
  716. Pointer to function table.
  717. --*/
  718. {
  719. NlPrint(( NL_SESSION_MORE,
  720. "InitSecurityInterfaceW: called\n" ));
  721. return(&SecTableW);
  722. }
  723. SECURITY_STATUS SEC_ENTRY
  724. AcquireCredentialsHandleW(
  725. LPWSTR pszPrincipal, // Name of principal
  726. LPWSTR pszPackageName, // Name of package
  727. unsigned long fCredentialUse, // Flags indicating use
  728. void SEC_FAR * pvLogonId, // Pointer to logon ID
  729. void SEC_FAR * pAuthData, // Package specific data
  730. SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func
  731. void SEC_FAR * pvGetKeyArgument, // Value to pass to GetKey()
  732. PCredHandle phCredential, // (out) Cred Handle
  733. PTimeStamp ptsExpiry // (out) Lifetime (optional)
  734. )
  735. /*++
  736. Routine Description:
  737. Client and Server side routine to grab a credential handle.
  738. Arguments:
  739. Standard.
  740. Return Value:
  741. --*/
  742. {
  743. SECURITY_STATUS SecStatus;
  744. PNL_AUTH_CREDENTIAL Credential = NULL;
  745. NlPrint(( NL_SESSION_MORE,
  746. "AcquireCredentialsHandleW: called\n" ));
  747. //
  748. // If caller is calling when the netlogon service isn't running,
  749. // tell it so.
  750. //
  751. if ( !NlStartNetlogonCall() ) {
  752. return SEC_E_SECPKG_NOT_FOUND;
  753. }
  754. //
  755. // Validate the input parameters
  756. //
  757. if ((fCredentialUse & (SECPKG_CRED_BOTH)) == 0) {
  758. NlPrint(( NL_CRITICAL,
  759. "AcquireCredentialHandle: Bad Credential Use 0x%lx.\n", fCredentialUse ));
  760. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  761. goto Cleanup;
  762. }
  763. if ((fCredentialUse & (SECPKG_CRED_BOTH)) == SECPKG_CRED_BOTH) {
  764. NlPrint(( NL_CRITICAL,
  765. "AcquireCredentialHandle: Bad Credential Use 0x%lx.\n", fCredentialUse ));
  766. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  767. goto Cleanup;
  768. }
  769. //
  770. // Handle a client credential
  771. //
  772. if ((fCredentialUse & (SECPKG_CRED_BOTH)) == SECPKG_CRED_OUTBOUND) {
  773. //
  774. // Sanity check the client session
  775. //
  776. if ( pAuthData == NULL ) {
  777. NlPrint(( NL_CRITICAL,
  778. "AcquireCredentialHandle: NULL auth data\n" ));
  779. SecStatus = SEC_E_INVALID_TOKEN;
  780. goto Cleanup;
  781. }
  782. if ( ((PNL_AUTH_DATA)pAuthData)->Signature != NL_AUTH_DATA_SIGNATURE ) {
  783. NlPrint(( NL_CRITICAL,
  784. "AcquireCredentialHandle: Invalid Signature on auth data\n" ));
  785. SecStatus = SEC_E_INVALID_TOKEN;
  786. goto Cleanup;
  787. }
  788. //
  789. // Allocate a credential to remember the AuthData (ClientSession) in.
  790. //
  791. Credential = AllocateCredential( (PNL_AUTH_DATA)pAuthData );
  792. if (Credential == NULL) {
  793. NlPrint(( NL_CRITICAL,
  794. "AcquireCredentialHandle: Cannot allocate context\n" ));
  795. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  796. goto Cleanup;
  797. }
  798. //
  799. // Return to the caller.
  800. //
  801. *phCredential = Credential->CredentialHandle;
  802. *ptsExpiry = Forever;
  803. SecStatus = SEC_E_OK;
  804. //
  805. // Handle a server credential
  806. //
  807. // We don't need a credential on the server side.
  808. // Silently succeed.
  809. //
  810. } else {
  811. phCredential->dwUpper = NL_AUTH_SERVER_CRED; // Just return a constant
  812. phCredential->dwLower = 0;
  813. *ptsExpiry = Forever;
  814. SecStatus = SEC_E_OK;
  815. goto Cleanup;
  816. }
  817. Cleanup:
  818. NlPrint(( NL_SESSION_MORE,
  819. "AcquireCredentialsHandleW: %lx.%lx: returns 0x%lx\n",
  820. phCredential->dwUpper, phCredential->dwLower,
  821. SecStatus ));
  822. // Let netlogon service exit.
  823. NlEndNetlogonCall();
  824. return SecStatus;
  825. UNREFERENCED_PARAMETER( pvGetKeyArgument );
  826. UNREFERENCED_PARAMETER( pGetKeyFn );
  827. UNREFERENCED_PARAMETER( pAuthData );
  828. UNREFERENCED_PARAMETER( pvLogonId );
  829. UNREFERENCED_PARAMETER( pszPackageName );
  830. UNREFERENCED_PARAMETER( pszPrincipal );
  831. }
  832. SECURITY_STATUS SEC_ENTRY
  833. FreeCredentialsHandle(
  834. PCredHandle phCredential // Handle to free
  835. )
  836. /*++
  837. Routine Description:
  838. Arguments:
  839. Standard.
  840. Return Value:
  841. --*/
  842. {
  843. NlPrint(( NL_SESSION_MORE,
  844. "FreeCredentialsHandle: %lx.%lx: called\n",
  845. phCredential->dwUpper, phCredential->dwLower ));
  846. //
  847. // Don't require that Netlogon be running. Some credential handles are
  848. // deleted as Netlogon is shutting down.
  849. //
  850. //
  851. // Ignore server side credentials.
  852. //
  853. if ( phCredential->dwUpper == NL_AUTH_SERVER_CRED &&
  854. phCredential->dwLower == 0 ) {
  855. return(SEC_E_OK);
  856. }
  857. //
  858. // For the Client side,
  859. // Delete the credential.
  860. //
  861. if ( DeleteCredential( phCredential ) ) {
  862. return(SEC_E_OK);
  863. } else {
  864. return(SEC_E_UNKNOWN_CREDENTIALS);
  865. }
  866. }
  867. SECURITY_STATUS SEC_ENTRY
  868. InitializeSecurityContextW(
  869. PCredHandle phCredential, // Cred to base context
  870. PCtxtHandle phContext, // Existing context (OPT)
  871. LPWSTR pszTargetName, // Name of target
  872. unsigned long fContextReq, // Context Requirements
  873. unsigned long Reserved1, // Reserved, MBZ
  874. unsigned long TargetDataRep, // Data rep of target
  875. PSecBufferDesc pInput, // Input Buffers
  876. unsigned long Reserved2, // Reserved, MBZ
  877. PCtxtHandle phNewContext, // (out) New Context handle
  878. PSecBufferDesc pOutput, // (inout) Output Buffers
  879. unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs
  880. PTimeStamp ptsExpiry // (out) Life span (OPT)
  881. )
  882. /*++
  883. Routine Description:
  884. Client side routine to define a security context.
  885. Arguments:
  886. Standard.
  887. Return Value:
  888. --*/
  889. {
  890. SECURITY_STATUS SecStatus;
  891. NET_API_STATUS NetStatus;
  892. PNL_AUTH_CONTEXT Context = NULL;
  893. PNL_AUTH_CREDENTIAL Credential = NULL;
  894. NL_AUTH_MESSAGE UNALIGNED *Message = NULL;
  895. PSecBuffer OutputBuffer;
  896. PSecBuffer InputBuffer;
  897. WORD CompressOffset[10];
  898. CHAR *CompressUtf8String[10];
  899. ULONG CompressCount = 0;
  900. ULONG Utf8StringSize;
  901. LPBYTE Where;
  902. NlPrint(( NL_SESSION_MORE,
  903. "InitializeSecurityContext: %ws: called\n", pszTargetName ));
  904. //
  905. // If caller is calling when the netlogon service isn't running,
  906. // tell it so.
  907. //
  908. if ( !NlStartNetlogonCall() ) {
  909. return SEC_E_SECPKG_NOT_FOUND;
  910. }
  911. if (fContextReq & ISC_REQ_ALLOCATE_MEMORY) {
  912. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  913. goto Cleanup;
  914. }
  915. OutputBuffer = LocateSecBuffer(pOutput);
  916. if (OutputBuffer == NULL) {
  917. SecStatus = SEC_E_INVALID_TOKEN;
  918. goto Cleanup;
  919. }
  920. //
  921. // Handle the first init call,
  922. //
  923. if (phContext == NULL) {
  924. PNL_AUTH_DATA ClientAuthData;
  925. //
  926. // Find the credential and ensure it is outbound
  927. //
  928. if ( phCredential == NULL ) {
  929. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  930. goto Cleanup;
  931. }
  932. NlPrint(( NL_SESSION_MORE,
  933. "InitializeSecurityContext: %lx.%lx: %ws: called with cred handle\n",
  934. phCredential->dwUpper, phCredential->dwLower,
  935. pszTargetName ));
  936. //
  937. // Locate the credential and make sure this is a client side call.
  938. //
  939. Credential = LocateCredential( phCredential );
  940. if (Credential == NULL) {
  941. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  942. goto Cleanup;
  943. }
  944. ClientAuthData = Credential->ClientAuthData;
  945. if ( ClientAuthData == NULL ) {
  946. SecStatus = SEC_E_INVALID_TOKEN;
  947. goto Cleanup;
  948. }
  949. NlAssert( ClientAuthData->Signature == NL_AUTH_DATA_SIGNATURE );
  950. //
  951. // Build an output token.
  952. //
  953. // This token simply tells the server side of the authentication
  954. // package our computer name.
  955. //
  956. Message = (PNL_AUTH_MESSAGE) OutputBuffer->pvBuffer;
  957. SmbPutUlong( &Message->MessageType, Negotiate );
  958. Message->Flags = 0;
  959. Where = &Message->Buffer[0];
  960. //
  961. // Copy the Netbios domain name of the domain hosted by the DC into the buffer
  962. //
  963. // OEM on the wire is bad. Luckily, if the DC is in a different locale,
  964. // that DC also has a DNS domain name and we'll use that to find the
  965. // hosted domain.
  966. //
  967. if ( ClientAuthData->OemNetbiosDomainNameLength != 0 ) {
  968. strcpy( Where,
  969. ((LPBYTE)ClientAuthData) +
  970. ClientAuthData->OemNetbiosDomainNameOffset );
  971. Where += ClientAuthData->OemNetbiosDomainNameLength + 1;
  972. Message->Flags |= NL_AUTH_NETBIOS_DOMAIN_NAME;
  973. }
  974. //
  975. // Copy the computer name of this machine into the buffer.
  976. //
  977. // ???: Only copy the Netbios computername or DNS host name. Copy the
  978. // one that was passed to the server on the NetServerReqChallenge.
  979. //
  980. // OEM on the wire is bad. So pass the UTF-8 version, too.
  981. //
  982. if ( ClientAuthData->OemComputerNameLength != 0 ) {
  983. strcpy( Where,
  984. ((LPBYTE)ClientAuthData) +
  985. ClientAuthData->OemComputerNameOffset );
  986. Where += ClientAuthData->OemComputerNameLength + 1;
  987. Message->Flags |= NL_AUTH_NETBIOS_COMPUTER_NAME;
  988. }
  989. //
  990. // Copy the DNS domain name of the domain hosted by the DC into the buffer.
  991. //
  992. Utf8StringSize = 2*(NL_MAX_DNS_LENGTH+1);
  993. CompressCount = 0; // No strings compressed yet.
  994. if ( ClientAuthData->Utf8DnsDomainNameOffset != 0 ) {
  995. NetStatus = NlpUtf8ToCutf8(
  996. (LPBYTE)Message,
  997. ((LPBYTE)ClientAuthData) +
  998. ClientAuthData->Utf8DnsDomainNameOffset,
  999. FALSE,
  1000. &Where,
  1001. &Utf8StringSize,
  1002. &CompressCount,
  1003. CompressOffset,
  1004. CompressUtf8String );
  1005. if ( NetStatus != NO_ERROR ) {
  1006. NlPrint((NL_CRITICAL,
  1007. "Cannot pack DomainName into message %ld\n",
  1008. NetStatus ));
  1009. SecStatus = SEC_E_INVALID_TOKEN;
  1010. goto Cleanup;
  1011. }
  1012. Message->Flags |= NL_AUTH_DNS_DOMAIN_NAME;
  1013. }
  1014. //
  1015. // Copy the DNS host name name of this machine into the buffer.
  1016. //
  1017. // ???: Only copy the Netbios computername or DNS host name. Copy the
  1018. // one that was passed to the server on the NetServerReqChallenge.
  1019. //
  1020. if ( ClientAuthData->Utf8DnsHostNameOffset != 0 ) {
  1021. NetStatus = NlpUtf8ToCutf8(
  1022. (LPBYTE)Message,
  1023. ((LPBYTE)ClientAuthData) +
  1024. ClientAuthData->Utf8DnsHostNameOffset,
  1025. FALSE,
  1026. &Where,
  1027. &Utf8StringSize,
  1028. &CompressCount,
  1029. CompressOffset,
  1030. CompressUtf8String );
  1031. if ( NetStatus != NO_ERROR ) {
  1032. NlPrint((NL_CRITICAL,
  1033. "Cannot pack dns host name into message %ld\n",
  1034. NetStatus ));
  1035. SecStatus = SEC_E_INVALID_TOKEN;
  1036. goto Cleanup;
  1037. }
  1038. Message->Flags |= NL_AUTH_DNS_HOST_NAME;
  1039. }
  1040. //
  1041. // Copy the UTF-8 netbios computer name of this machine into the buffer.
  1042. //
  1043. // ???: Only copy the Netbios computername or DNS host name. Copy the
  1044. // one that was passed to the server on the NetServerReqChallenge.
  1045. //
  1046. // OEM on the wire is bad. So pass the UTF-8 version, too.
  1047. //
  1048. if ( ClientAuthData->Utf8ComputerNameLength != 0 ) {
  1049. NetStatus = NlpUtf8ToCutf8(
  1050. (LPBYTE)Message,
  1051. ((LPBYTE)ClientAuthData) +
  1052. ClientAuthData->Utf8ComputerNameOffset,
  1053. TRUE,
  1054. &Where,
  1055. &Utf8StringSize,
  1056. &CompressCount,
  1057. CompressOffset,
  1058. CompressUtf8String );
  1059. if ( NetStatus != NO_ERROR ) {
  1060. NlPrint((NL_CRITICAL,
  1061. "Cannot pack UTF-8 netbios computer name into message %ld\n",
  1062. NetStatus ));
  1063. SecStatus = SEC_E_INVALID_TOKEN;
  1064. goto Cleanup;
  1065. }
  1066. Message->Flags |= NL_AUTH_UTF8_NETBIOS_COMPUTER_NAME;
  1067. }
  1068. //
  1069. // Allocate a context.
  1070. //
  1071. Context = AllocateContext( fContextReq );
  1072. if ( Context == NULL) {
  1073. NlPrint(( NL_CRITICAL,
  1074. "InitializeSecurityContext: Cannot allocate context\n" ));
  1075. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1076. goto Cleanup;
  1077. }
  1078. //
  1079. // Mark the context to indicate what state we're in.
  1080. //
  1081. Context->State = FirstInit;
  1082. Context->Inbound = FALSE;
  1083. //
  1084. // Grab the session key
  1085. //
  1086. Context->SessionInfo = ClientAuthData->SessionInfo;
  1087. //
  1088. // Ask the caller to call us back
  1089. //
  1090. OutputBuffer->cbBuffer = (DWORD)(Where - (LPBYTE)Message);
  1091. *phNewContext = Context->ContextHandle;
  1092. *pfContextAttr = fContextReq;
  1093. *ptsExpiry = Forever;
  1094. SecStatus = SEC_I_CONTINUE_NEEDED;
  1095. //
  1096. // Handle the second call
  1097. //
  1098. } else {
  1099. NlPrint(( NL_SESSION_MORE,
  1100. "InitializeSecurityContext: %lx.%lx: %ws: called with context handle\n",
  1101. phContext->dwUpper, phContext->dwLower,
  1102. pszTargetName ));
  1103. //
  1104. // This is the second call. Lookup the old context.
  1105. //
  1106. // Locate the context and make sure this is a client side call.
  1107. //
  1108. Context = LocateContext( phContext );
  1109. if (Context == NULL) {
  1110. SecStatus = SEC_E_INVALID_HANDLE;
  1111. goto Cleanup;
  1112. }
  1113. //
  1114. // Ensure we're in the right state.
  1115. //
  1116. if ( Context->State != FirstInit ) {
  1117. SecStatus = SEC_E_INVALID_HANDLE;
  1118. goto Cleanup;
  1119. }
  1120. //
  1121. // Check that the input message is what we expected.
  1122. //
  1123. InputBuffer = LocateSecBuffer(pInput);
  1124. if (InputBuffer == NULL) {
  1125. SecStatus = SEC_E_INVALID_TOKEN;
  1126. goto Cleanup;
  1127. }
  1128. Message = (PNL_AUTH_MESSAGE) InputBuffer->pvBuffer;
  1129. if ( InputBuffer->cbBuffer < sizeof(NL_AUTH_MESSAGE) ) {
  1130. SecStatus = SEC_E_INVALID_TOKEN;
  1131. goto Cleanup;
  1132. }
  1133. if ( Message->MessageType != NegotiateResponse ) {
  1134. SecStatus = SEC_E_INVALID_TOKEN;
  1135. goto Cleanup;
  1136. }
  1137. Context->State = SecondInit;
  1138. Context->Nonce.QuadPart = 0;
  1139. //
  1140. // Return to the caller.
  1141. //
  1142. OutputBuffer->cbBuffer = 0;
  1143. *pfContextAttr = fContextReq;
  1144. *ptsExpiry = Forever;
  1145. SecStatus = SEC_E_OK;
  1146. }
  1147. Cleanup:
  1148. NlPrint(( NL_SESSION_MORE,
  1149. "InitializeSecurityContext: returns 0x%lx\n", SecStatus ));
  1150. // Let netlogon service exit.
  1151. NlEndNetlogonCall();
  1152. return SecStatus;
  1153. UNREFERENCED_PARAMETER( Reserved2 );
  1154. UNREFERENCED_PARAMETER( TargetDataRep );
  1155. UNREFERENCED_PARAMETER( Reserved1 );
  1156. UNREFERENCED_PARAMETER( pszTargetName );
  1157. UNREFERENCED_PARAMETER( pInput );
  1158. }
  1159. SECURITY_STATUS SEC_ENTRY
  1160. AcceptSecurityContext(
  1161. PCredHandle phCredential, // Cred to base context
  1162. PCtxtHandle phContext, // Existing context (OPT)
  1163. PSecBufferDesc pInput, // Input buffer
  1164. unsigned long fContextReq, // Context Requirements
  1165. unsigned long TargetDataRep, // Target Data Rep
  1166. PCtxtHandle phNewContext, // (out) New context handle
  1167. PSecBufferDesc pOutput, // (inout) Output buffers
  1168. unsigned long SEC_FAR * pfContextAttr, // (out) Context attributes
  1169. PTimeStamp ptsExpiry // (out) Life span (OPT)
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. Servert side routine to define a security context.
  1174. Arguments:
  1175. Standard.
  1176. Return Value:
  1177. --*/
  1178. {
  1179. SECURITY_STATUS SecStatus;
  1180. PNL_AUTH_CONTEXT Context = NULL;
  1181. NL_AUTH_MESSAGE UNALIGNED *Message = NULL;
  1182. PSecBuffer OutputBuffer = NULL;
  1183. PSecBuffer InputBuffer;
  1184. LPBYTE Where;
  1185. LPSTR DnsDomainName = NULL;
  1186. LPSTR DnsHostName = NULL;
  1187. LPSTR Utf8ComputerName = NULL;
  1188. LPSTR OemDomainName = NULL;
  1189. LPWSTR UnicodeDomainName = NULL;
  1190. LPSTR OemComputerName = NULL;
  1191. LPWSTR UnicodeComputerName = NULL;
  1192. PDOMAIN_INFO DomainInfo = NULL;
  1193. PSERVER_SESSION ServerSession;
  1194. SESSION_INFO SessionInfo;
  1195. SecHandle CurrentHandle = {0};
  1196. NlPrint(( NL_SESSION_MORE,
  1197. "AcceptSecurityContext: called\n" ));
  1198. //
  1199. // If caller is calling when the netlogon service isn't running,
  1200. // tell it so.
  1201. //
  1202. if ( !NlStartNetlogonCall() ) {
  1203. return SEC_E_SECPKG_NOT_FOUND;
  1204. }
  1205. if (fContextReq & ISC_REQ_ALLOCATE_MEMORY) {
  1206. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1207. goto Cleanup;
  1208. }
  1209. InputBuffer = LocateSecBuffer(pInput);
  1210. if (InputBuffer == NULL) {
  1211. SecStatus = SEC_E_INVALID_TOKEN;
  1212. goto Cleanup;
  1213. }
  1214. //
  1215. // Make sure the output buffer exists.
  1216. //
  1217. OutputBuffer = LocateSecBuffer(pOutput);
  1218. if (OutputBuffer == NULL) {
  1219. SecStatus = SEC_E_INVALID_TOKEN;
  1220. goto Cleanup;
  1221. }
  1222. //
  1223. // Handle the first server side call.
  1224. //
  1225. if (phContext == NULL) {
  1226. //
  1227. // Validate the credential handle.
  1228. //
  1229. if ( phCredential == NULL ||
  1230. phCredential->dwUpper != NL_AUTH_SERVER_CRED ||
  1231. phCredential->dwLower != 0 ) {
  1232. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  1233. goto Cleanup;
  1234. }
  1235. CurrentHandle = *phCredential;
  1236. //
  1237. // Check that the input message is what we expected.
  1238. //
  1239. Message = (PNL_AUTH_MESSAGE) InputBuffer->pvBuffer;
  1240. if ( InputBuffer->cbBuffer < sizeof(NL_AUTH_MESSAGE) ) {
  1241. SecStatus = SEC_E_INVALID_TOKEN;
  1242. goto Cleanup;
  1243. }
  1244. if ( Message->MessageType != Negotiate ) {
  1245. SecStatus = SEC_E_INVALID_TOKEN;
  1246. goto Cleanup;
  1247. }
  1248. Where = &Message->Buffer[0];
  1249. //
  1250. // Get Netbios hosted domain name from the buffer
  1251. //
  1252. if ( Message->Flags & NL_AUTH_NETBIOS_DOMAIN_NAME ) {
  1253. if ( !NetpLogonGetOemString(
  1254. Message,
  1255. InputBuffer->cbBuffer,
  1256. &Where,
  1257. DNLEN+1,
  1258. &OemDomainName ) ) {
  1259. NlPrint((NL_CRITICAL,
  1260. "AcceptSecurityContext: %lx.%lx: cannot get netbios domain name\n",
  1261. CurrentHandle.dwUpper, CurrentHandle.dwLower ));
  1262. SecStatus = SEC_E_INVALID_TOKEN;
  1263. goto Cleanup;
  1264. }
  1265. }
  1266. //
  1267. // Get the Netbios client computer name from the message.
  1268. //
  1269. if ( Message->Flags & NL_AUTH_NETBIOS_COMPUTER_NAME ) {
  1270. //
  1271. // Get the computer name of the
  1272. if ( !NetpLogonGetOemString(
  1273. Message,
  1274. InputBuffer->cbBuffer,
  1275. &Where,
  1276. CNLEN+1,
  1277. &OemComputerName ) ) {
  1278. NlPrint((NL_CRITICAL,
  1279. "AcceptSecurityContext: %lx.%lx: Cannot parse computer name\n",
  1280. CurrentHandle.dwUpper, CurrentHandle.dwLower ));
  1281. SecStatus = SEC_E_INVALID_TOKEN;
  1282. goto Cleanup;
  1283. }
  1284. }
  1285. //
  1286. // Get the domain name of the hosted domain from the message.
  1287. //
  1288. // Either get a utf-8 DNS domain name or an OEM netbios domain name
  1289. //
  1290. if ( Message->Flags & NL_AUTH_DNS_DOMAIN_NAME ) {
  1291. if ( !NetpLogonGetCutf8String(
  1292. Message,
  1293. InputBuffer->cbBuffer,
  1294. &Where,
  1295. &DnsDomainName ) ) {
  1296. NlPrint(( NL_CRITICAL,
  1297. "AcceptSecurityContext: %lx.%lx: DNS domain bad.\n",
  1298. CurrentHandle.dwUpper, CurrentHandle.dwLower ));
  1299. SecStatus = SEC_E_INVALID_TOKEN;
  1300. goto Cleanup;
  1301. }
  1302. }
  1303. //
  1304. // Get the DNS client computer name from the message.
  1305. //
  1306. //
  1307. if ( Message->Flags & NL_AUTH_DNS_HOST_NAME ) {
  1308. if ( !NetpLogonGetCutf8String(
  1309. Message,
  1310. InputBuffer->cbBuffer,
  1311. &Where,
  1312. &DnsHostName ) ) {
  1313. NlPrint(( NL_CRITICAL,
  1314. "AcceptSecurityContext: %lx.%lx: DNS hostname bad.\n",
  1315. CurrentHandle.dwUpper, CurrentHandle.dwLower
  1316. ));
  1317. SecStatus = SEC_E_INVALID_TOKEN;
  1318. goto Cleanup;
  1319. }
  1320. //
  1321. // Ensure Netbios name isn't also present
  1322. //
  1323. if ( Message->Flags & NL_AUTH_NETBIOS_COMPUTER_NAME ) {
  1324. NlPrint((NL_CRITICAL,
  1325. "AcceptSecurityContext: %lx.%lx: both DNS '%s' and Netbios '%s' client name specified\n",
  1326. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1327. DnsHostName,
  1328. OemComputerName ));
  1329. /* This isn't fatal */
  1330. }
  1331. }
  1332. //
  1333. // Get the UTF8 netbios computer name
  1334. //
  1335. if ( Message->Flags & NL_AUTH_UTF8_NETBIOS_COMPUTER_NAME ) {
  1336. if ( !NetpLogonGetCutf8String(
  1337. Message,
  1338. InputBuffer->cbBuffer,
  1339. &Where,
  1340. &Utf8ComputerName ) ) {
  1341. NlPrint(( NL_CRITICAL,
  1342. "AcceptSecurityContext: %lx.%lx: UTF8 computer name bad.\n",
  1343. CurrentHandle.dwUpper, CurrentHandle.dwLower
  1344. ));
  1345. SecStatus = SEC_E_INVALID_TOKEN;
  1346. goto Cleanup;
  1347. }
  1348. }
  1349. //
  1350. // Try to find the hosted domain using DNS
  1351. //
  1352. if ( DnsDomainName != NULL ) {
  1353. DomainInfo = NlFindDnsDomain( DnsDomainName,
  1354. NULL,
  1355. FALSE, // don't lookup NDNCs
  1356. TRUE, // check alias names
  1357. NULL ); // don't care if alias name matched
  1358. if ( DomainInfo == NULL ) {
  1359. NlPrint((NL_CRITICAL,
  1360. "AcceptSecurityContext: %lx.%lx: Cannot find domain %s\n",
  1361. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1362. DnsDomainName ));
  1363. SecStatus = SEC_E_INVALID_TOKEN;
  1364. goto Cleanup;
  1365. }
  1366. //
  1367. // Try to find hosted domain name using netbios.
  1368. //
  1369. } else {
  1370. //
  1371. // Make sure we were passed one.
  1372. //
  1373. if ( OemDomainName == NULL) {
  1374. NlPrint((NL_CRITICAL,
  1375. "AcceptSecurityContext: %lx.%lx: Neither DNS or netbios domain name specified (fatal)\n",
  1376. CurrentHandle.dwUpper, CurrentHandle.dwLower ));
  1377. SecStatus = SEC_E_INVALID_TOKEN;
  1378. goto Cleanup;
  1379. }
  1380. //
  1381. // Convert to unicode
  1382. // Note: this is bogus since the clients OEM code page may be different
  1383. // than ours.
  1384. //
  1385. UnicodeDomainName = NetpAllocWStrFromStr( OemDomainName );
  1386. if ( UnicodeDomainName == NULL ) {
  1387. NlPrint((NL_CRITICAL,
  1388. "AcceptSecurityContext: %lx.%lx: Cannot alloc domain name %s\n",
  1389. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1390. OemDomainName ));
  1391. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1392. goto Cleanup;
  1393. }
  1394. //
  1395. // Look the name up.
  1396. //
  1397. DomainInfo = NlFindNetbiosDomain( UnicodeDomainName, FALSE );
  1398. if ( DomainInfo == NULL ) {
  1399. NlPrint((NL_CRITICAL,
  1400. "AcceptSecurityContext: %lx.%lx: Cannot find domain %ws (fatal)\n",
  1401. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1402. UnicodeDomainName ));
  1403. SecStatus = SEC_E_INVALID_TOKEN;
  1404. goto Cleanup;
  1405. }
  1406. }
  1407. //
  1408. // Get the name of the client machine.
  1409. //
  1410. // If the client computer passed us its DnsHostName,
  1411. // use that.
  1412. //
  1413. if ( DnsHostName != NULL ) {
  1414. UnicodeComputerName = NetpAllocWStrFromUtf8Str( DnsHostName );
  1415. if ( UnicodeComputerName == NULL ) {
  1416. NlPrint((NL_CRITICAL,
  1417. "AcceptSecurityContext: %lx.%lx: Cannot alloc DNS computer name %s\n",
  1418. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1419. DnsHostName ));
  1420. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1421. goto Cleanup;
  1422. }
  1423. //
  1424. // If the client computer passed us its Netbios name in UTF-8,
  1425. // use that.
  1426. //
  1427. } else if ( Utf8ComputerName != NULL ) {
  1428. UnicodeComputerName = NetpAllocWStrFromUtf8Str( Utf8ComputerName );
  1429. if ( UnicodeComputerName == NULL ) {
  1430. NlPrint((NL_CRITICAL,
  1431. "AcceptSecurityContext: %lx.%lx: Cannot alloc utf8 computer name %s\n",
  1432. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1433. Utf8ComputerName ));
  1434. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1435. goto Cleanup;
  1436. }
  1437. //
  1438. // If the client computer passed us its Netbios name in OEM,
  1439. // use that.
  1440. // OEM is bad since the clients code page might be different than ours.
  1441. //
  1442. } else if ( OemComputerName != NULL ) {
  1443. UnicodeComputerName = NetpAllocWStrFromStr( OemComputerName );
  1444. if ( UnicodeComputerName == NULL ) {
  1445. NlPrint((NL_CRITICAL,
  1446. "AcceptSecurityContext: %lx.%lx: Cannot alloc oem computer name %s\n",
  1447. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1448. OemComputerName ));
  1449. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1450. goto Cleanup;
  1451. }
  1452. //
  1453. // At this point it is fatal if we don't know the client computer name
  1454. //
  1455. } else {
  1456. NlPrint((NL_CRITICAL,
  1457. "AcceptSecurityContext: %lx.%lx: Don't know client computer name.\n",
  1458. CurrentHandle.dwUpper, CurrentHandle.dwLower ));
  1459. SecStatus = SEC_E_INVALID_TOKEN;
  1460. goto Cleanup;
  1461. }
  1462. //
  1463. // Find the server session containing the session key
  1464. // and make a copy of it.
  1465. //
  1466. NlPrint((NL_SESSION_MORE,
  1467. "AcceptSecurityContext: %lx.%lx: from %ws\n",
  1468. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1469. UnicodeComputerName ));
  1470. LOCK_SERVER_SESSION_TABLE( DomainInfo );
  1471. ServerSession = NlFindNamedServerSession( DomainInfo, UnicodeComputerName );
  1472. if (ServerSession == NULL) {
  1473. UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
  1474. NlPrint((NL_CRITICAL,
  1475. "AcceptSecurityContext: %lx.%lx: Can't NlFindNamedServerSession for %ws\n",
  1476. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1477. UnicodeComputerName ));
  1478. SecStatus = SEC_E_INVALID_TOKEN;
  1479. goto Cleanup;
  1480. }
  1481. SessionInfo.SessionKey = ServerSession->SsSessionKey;
  1482. SessionInfo.NegotiatedFlags = ServerSession->SsNegotiatedFlags;
  1483. UNLOCK_SERVER_SESSION_TABLE( DomainInfo );
  1484. //
  1485. // Build a new context.
  1486. //
  1487. Context = AllocateContext( fContextReq );
  1488. if (Context == NULL) {
  1489. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1490. goto Cleanup;
  1491. }
  1492. Context->State = FirstAccept;
  1493. Context->Inbound = TRUE;
  1494. Context->SessionInfo = SessionInfo;
  1495. //
  1496. // Build an output token.
  1497. //
  1498. Message = (PNL_AUTH_MESSAGE) OutputBuffer->pvBuffer;
  1499. Message->MessageType = NegotiateResponse;
  1500. Message->Flags = 0;
  1501. Message->Buffer[0] = '\0';
  1502. OutputBuffer->cbBuffer = sizeof(NL_AUTH_MESSAGE);
  1503. //
  1504. // Tell the caller he need not call us back.
  1505. //
  1506. *phNewContext = Context->ContextHandle;
  1507. CurrentHandle = *phNewContext;
  1508. *pfContextAttr = fContextReq;
  1509. *ptsExpiry = Forever;
  1510. SecStatus = SEC_E_OK;
  1511. //
  1512. // We asked the caller to not call us back.
  1513. //
  1514. } else {
  1515. NlAssert( FALSE );
  1516. NlPrint((NL_CRITICAL,
  1517. "AcceptSecurityContext: Second accept called.\n" ));
  1518. SecStatus = SEC_E_INVALID_TOKEN;
  1519. goto Cleanup;
  1520. }
  1521. Cleanup:
  1522. if ( DnsDomainName != NULL ) {
  1523. NetpMemoryFree( DnsDomainName );
  1524. }
  1525. if ( DnsHostName != NULL ) {
  1526. NetpMemoryFree( DnsHostName );
  1527. }
  1528. if ( Utf8ComputerName != NULL ) {
  1529. NetpMemoryFree( Utf8ComputerName );
  1530. }
  1531. if ( UnicodeComputerName != NULL ) {
  1532. NetApiBufferFree( UnicodeComputerName );
  1533. }
  1534. if ( UnicodeDomainName != NULL ) {
  1535. NetApiBufferFree( UnicodeDomainName );
  1536. }
  1537. if ( DomainInfo != NULL ) {
  1538. NlDereferenceDomain( DomainInfo );
  1539. }
  1540. NlPrint(( NL_SESSION_MORE,
  1541. "AcceptSecurityContext: %lx.%lx: returns 0x%lx\n",
  1542. CurrentHandle.dwUpper, CurrentHandle.dwLower,
  1543. SecStatus ));
  1544. // Let netlogon service exit.
  1545. NlEndNetlogonCall();
  1546. return SecStatus;
  1547. UNREFERENCED_PARAMETER( TargetDataRep );
  1548. UNREFERENCED_PARAMETER( pOutput );
  1549. }
  1550. SECURITY_STATUS SEC_ENTRY
  1551. DeleteSecurityContext(
  1552. PCtxtHandle phContext // Context to delete
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. Routine to delete client or server side security context.
  1557. Arguments:
  1558. Standard.
  1559. Return Value:
  1560. --*/
  1561. {
  1562. NlPrint(( NL_SESSION_MORE,
  1563. "DeleteSecurityContext: %lx.%lx: called\n",
  1564. phContext->dwUpper, phContext->dwLower ));
  1565. //
  1566. // Don't require that Netlogon be running. Some security contexts are
  1567. // deleted as Netlogon is shutting down.
  1568. //
  1569. if ( DeleteContext( phContext )) {
  1570. return(SEC_E_OK);
  1571. } else {
  1572. return(SEC_E_INVALID_HANDLE);
  1573. }
  1574. }
  1575. SECURITY_STATUS SEC_ENTRY
  1576. EnumerateSecurityPackagesW(
  1577. unsigned long SEC_FAR * pcPackages, // Receives num. packages
  1578. PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives array of info
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. Routine to return a description of all the security packages implemented
  1583. by this DLL.
  1584. Arguments:
  1585. Standard.
  1586. Return Value:
  1587. --*/
  1588. {
  1589. SECURITY_STATUS SecStatus;
  1590. SecStatus = QuerySecurityPackageInfoW(
  1591. PACKAGE_NAME,
  1592. ppPackageInfo
  1593. );
  1594. if (SecStatus == SEC_E_OK) {
  1595. *pcPackages = 1;
  1596. }
  1597. return(SecStatus);
  1598. }
  1599. SECURITY_STATUS SEC_ENTRY
  1600. QuerySecurityPackageInfoW(
  1601. LPWSTR pszPackageName, // Name of package
  1602. PSecPkgInfoW SEC_FAR * ppPackageInfo // Receives package info
  1603. )
  1604. /*++
  1605. Routine Description:
  1606. Routine to return the description of the named security package.
  1607. Arguments:
  1608. Standard.
  1609. Return Value:
  1610. --*/
  1611. {
  1612. SECURITY_STATUS SecStatus;
  1613. PSecPkgInfoW PackageInfo;
  1614. ULONG PackageInfoSize;
  1615. PUCHAR Where;
  1616. if (_wcsicmp(pszPackageName, PACKAGE_NAME)) {
  1617. SecStatus = SEC_E_SECPKG_NOT_FOUND;
  1618. goto Cleanup;
  1619. }
  1620. PackageInfoSize = sizeof(SecPkgInfoW) +
  1621. (wcslen(PACKAGE_NAME) + 1 +
  1622. wcslen(PACKAGE_COMMENT) + 1) * sizeof(WCHAR);
  1623. PackageInfo = (PSecPkgInfoW) LocalAlloc(0,PackageInfoSize);
  1624. if (PackageInfo == NULL) {
  1625. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1626. goto Cleanup;
  1627. }
  1628. PackageInfo->fCapabilities = PACAKGE_CAPABILITIES;
  1629. PackageInfo->wVersion = PACKAGE_VERSION;
  1630. PackageInfo->wRPCID = PACKAGE_RPCID;
  1631. PackageInfo->cbMaxToken = PACKAGE_MAXTOKEN;
  1632. Where = (PUCHAR) (PackageInfo + 1);
  1633. PackageInfo->Name = (LPWSTR) Where;
  1634. Where += (wcslen(PACKAGE_NAME) + 1) * sizeof(WCHAR);
  1635. wcscpy(PackageInfo->Name, PACKAGE_NAME);
  1636. PackageInfo->Comment = (LPWSTR) Where;
  1637. Where += (wcslen(PACKAGE_COMMENT) + 1) * sizeof(WCHAR);
  1638. wcscpy(PackageInfo->Comment, PACKAGE_COMMENT);
  1639. NlAssert((Where - (PBYTE) PackageInfo) == (LONG) PackageInfoSize);
  1640. *ppPackageInfo = PackageInfo;
  1641. SecStatus = SEC_E_OK;
  1642. Cleanup:
  1643. NlPrint(( NL_SESSION_MORE,
  1644. "QuerySecurityPackageInfo: returns 0x%lx\n", SecStatus ));
  1645. return SecStatus;
  1646. }
  1647. SECURITY_STATUS SEC_ENTRY
  1648. FreeContextBuffer(
  1649. void SEC_FAR * pvContextBuffer
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. Routine to free a context buffer.
  1654. Arguments:
  1655. Standard.
  1656. Return Value:
  1657. --*/
  1658. {
  1659. LocalFree(pvContextBuffer);
  1660. return(SEC_E_OK);
  1661. }
  1662. SECURITY_STATUS SEC_ENTRY
  1663. ImpersonateSecurityContext(
  1664. PCtxtHandle phContext // Context to impersonate
  1665. )
  1666. /*++
  1667. Routine Description:
  1668. Server side routine to impersonate an authenticated user.
  1669. Arguments:
  1670. Standard.
  1671. Return Value:
  1672. --*/
  1673. {
  1674. NTSTATUS Status;
  1675. Status = RtlImpersonateSelf(SecurityImpersonation);
  1676. if (NT_SUCCESS(Status)) {
  1677. return(SEC_E_OK);
  1678. } else {
  1679. return(SEC_E_NO_IMPERSONATION);
  1680. }
  1681. UNREFERENCED_PARAMETER( phContext );
  1682. }
  1683. SECURITY_STATUS SEC_ENTRY
  1684. RevertSecurityContext(
  1685. PCtxtHandle phContext // Context from which to re
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. Server side routine to undo a previous imperonation.
  1690. Arguments:
  1691. Standard.
  1692. Return Value:
  1693. --*/
  1694. {
  1695. RevertToSelf();
  1696. return(SEC_E_OK);
  1697. UNREFERENCED_PARAMETER( phContext );
  1698. }
  1699. SECURITY_STATUS SEC_ENTRY
  1700. QueryContextAttributesW(
  1701. PCtxtHandle phContext, // Context to query
  1702. unsigned long ulAttribute, // Attribute to query
  1703. void SEC_FAR * pBuffer // Buffer for attributes
  1704. )
  1705. /*++
  1706. Routine Description:
  1707. Routine to return information about a context.
  1708. Arguments:
  1709. Standard.
  1710. Return Value:
  1711. --*/
  1712. {
  1713. SECURITY_STATUS SecStatus;
  1714. PNL_AUTH_CONTEXT Context;
  1715. PSecPkgContext_Sizes ContextSizes;
  1716. PSecPkgContext_NamesW ContextNames;
  1717. PSecPkgContext_Lifespan ContextLifespan;
  1718. PSecPkgContext_DceInfo ContextDceInfo;
  1719. //
  1720. // If caller is calling when the netlogon service isn't running,
  1721. // tell it so.
  1722. //
  1723. if ( !NlStartNetlogonCall() ) {
  1724. return SEC_E_SECPKG_NOT_FOUND;
  1725. }
  1726. //
  1727. // Locate the context and make sure this is a client side call.
  1728. //
  1729. Context = LocateContext( phContext );
  1730. if (Context == NULL) {
  1731. SecStatus = SEC_E_INVALID_HANDLE;
  1732. goto Cleanup;
  1733. }
  1734. //
  1735. //
  1736. //
  1737. switch(ulAttribute) {
  1738. case SECPKG_ATTR_SIZES:
  1739. ContextSizes = (PSecPkgContext_Sizes) pBuffer;
  1740. ContextSizes->cbMaxSignature = PACKAGE_SIGNATURE_SIZE;
  1741. if ((Context->ContextFlags & ISC_REQ_CONFIDENTIALITY) != 0) {
  1742. ContextSizes->cbSecurityTrailer = PACKAGE_SIGNATURE_SIZE;
  1743. ContextSizes->cbBlockSize = 1;
  1744. } else {
  1745. ContextSizes->cbSecurityTrailer = 0;
  1746. ContextSizes->cbBlockSize = 0;
  1747. }
  1748. ContextSizes->cbMaxToken = PACKAGE_MAXTOKEN;
  1749. break;
  1750. #ifdef notdef // Only support the ones RPC uses
  1751. case SECPKG_ATTR_NAMES:
  1752. ContextNames = (PSecPkgContext_Names) pBuffer;
  1753. ContextNames->sUserName = (LPWSTR) LocalAlloc(0,sizeof(L"dummy user"));
  1754. if (ContextNames->sUserName == NULL) {
  1755. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1756. goto Cleanup;
  1757. }
  1758. wcscpy(ContextNames->sUserName, L"dummy user");
  1759. break;
  1760. case SECPKG_ATTR_LIFESPAN:
  1761. ContextLifespan = (PSecPkgContext_Lifespan) pBuffer;
  1762. ContextLifespan->tsStart = Never;
  1763. ContextLifespan->tsExpiry = Forever;
  1764. break;
  1765. case SECPKG_ATTR_DCE_INFO:
  1766. ContextDceInfo = (PSecPkgContext_DceInfo) pBuffer;
  1767. ContextDceInfo->AuthzSvc = 0;
  1768. ContextDceInfo->pPac = (PVOID) LocalAlloc(0,sizeof(L"dummy user"));
  1769. if (ContextDceInfo->pPac == NULL) {
  1770. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1771. goto Cleanup;
  1772. }
  1773. wcscpy((LPWSTR) ContextDceInfo->pPac, L"dummy user");
  1774. break;
  1775. #endif // notdef // Only support the ones RPC uses
  1776. default:
  1777. SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
  1778. goto Cleanup;
  1779. }
  1780. SecStatus = SEC_E_OK;
  1781. Cleanup:
  1782. NlPrint(( NL_SESSION_MORE,
  1783. "QueryContextAttributes: %lx.%lx: %ld returns 0x%lx\n",
  1784. phContext->dwUpper, phContext->dwLower,
  1785. ulAttribute,
  1786. SecStatus ));
  1787. // Let netlogon service exit.
  1788. NlEndNetlogonCall();
  1789. return SecStatus;
  1790. UNREFERENCED_PARAMETER( pBuffer );
  1791. }
  1792. SECURITY_STATUS
  1793. KerbMapNtStatusToSecStatus(
  1794. IN NTSTATUS Status
  1795. )
  1796. {
  1797. SECURITY_STATUS SecStatus;
  1798. //
  1799. // Check for security status and let them through
  1800. //
  1801. if (HRESULT_FACILITY(Status) == FACILITY_SECURITY )
  1802. {
  1803. return(Status);
  1804. }
  1805. switch(Status) {
  1806. case STATUS_SUCCESS:
  1807. SecStatus = SEC_E_OK;
  1808. break;
  1809. case STATUS_INSUFFICIENT_RESOURCES:
  1810. case STATUS_NO_MEMORY:
  1811. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1812. break;
  1813. case STATUS_NETLOGON_NOT_STARTED:
  1814. case STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
  1815. case STATUS_NO_LOGON_SERVERS:
  1816. case STATUS_NO_SUCH_DOMAIN:
  1817. SecStatus = SEC_E_NO_AUTHENTICATING_AUTHORITY;
  1818. break;
  1819. case STATUS_NO_SUCH_LOGON_SESSION:
  1820. SecStatus = SEC_E_UNKNOWN_CREDENTIALS;
  1821. break;
  1822. case STATUS_INVALID_PARAMETER:
  1823. SecStatus = SEC_E_INVALID_TOKEN;
  1824. break;
  1825. case STATUS_PRIVILEGE_NOT_HELD:
  1826. SecStatus = SEC_E_NOT_OWNER;
  1827. break;
  1828. case STATUS_INVALID_HANDLE:
  1829. SecStatus = SEC_E_INVALID_HANDLE;
  1830. break;
  1831. case STATUS_BUFFER_TOO_SMALL:
  1832. // ???: there should be a better code
  1833. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1834. break;
  1835. case STATUS_NOT_SUPPORTED:
  1836. SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
  1837. break;
  1838. case STATUS_OBJECT_NAME_NOT_FOUND:
  1839. SecStatus = SEC_E_TARGET_UNKNOWN;
  1840. break;
  1841. case STATUS_LOGON_FAILURE:
  1842. case STATUS_NO_SUCH_USER:
  1843. case STATUS_ACCOUNT_DISABLED:
  1844. case STATUS_ACCOUNT_RESTRICTION:
  1845. case STATUS_ACCOUNT_LOCKED_OUT:
  1846. case STATUS_WRONG_PASSWORD:
  1847. case STATUS_ACCOUNT_EXPIRED:
  1848. case STATUS_PASSWORD_EXPIRED:
  1849. SecStatus = SEC_E_LOGON_DENIED;
  1850. break;
  1851. case STATUS_NO_TRUST_SAM_ACCOUNT:
  1852. SecStatus = SEC_E_TARGET_UNKNOWN;
  1853. break;
  1854. case STATUS_BAD_NETWORK_PATH:
  1855. case STATUS_TRUST_FAILURE:
  1856. case STATUS_TRUSTED_RELATIONSHIP_FAILURE:
  1857. // ???: what should this be?
  1858. SecStatus = SEC_E_NO_AUTHENTICATING_AUTHORITY;
  1859. break;
  1860. case STATUS_NAME_TOO_LONG:
  1861. case STATUS_ILL_FORMED_PASSWORD:
  1862. // ???: what should this be?
  1863. SecStatus = SEC_E_INVALID_TOKEN;
  1864. break;
  1865. case STATUS_INTERNAL_ERROR:
  1866. SecStatus = SEC_E_INTERNAL_ERROR;
  1867. break;
  1868. default:
  1869. NlPrint(( NL_CRITICAL, "\n\n\n Unable to map error code 0x%x\n\n\n\n",Status));
  1870. SecStatus = SEC_E_INTERNAL_ERROR;
  1871. }
  1872. return(SecStatus);
  1873. }
  1874. SECURITY_STATUS
  1875. NlpSignOrSeal(
  1876. IN PCtxtHandle phContext,
  1877. IN ULONG fQOP,
  1878. IN OUT PSecBufferDesc MessageBuffers,
  1879. IN ULONG MessageSeqNo,
  1880. IN BOOLEAN SealIt
  1881. )
  1882. /*++
  1883. Routine Description:
  1884. Common routine to sign or seal a message (Client or server side)
  1885. Arguments:
  1886. Standard.
  1887. SealIt - True to seal the message.
  1888. FALSE to sign the message.
  1889. Return Value:
  1890. --*/
  1891. {
  1892. SECURITY_STATUS SecStatus = SEC_E_OK;
  1893. NTSTATUS Status = STATUS_SUCCESS;
  1894. PCHECKSUM_FUNCTION Check;
  1895. PCRYPTO_SYSTEM CryptSystem;
  1896. PCHECKSUM_BUFFER CheckBuffer = NULL;
  1897. PCRYPT_STATE_BUFFER CryptBuffer = NULL;
  1898. ULONG Index;
  1899. PSecBuffer SignatureBuffer = NULL;
  1900. PNL_AUTH_SIGNATURE Signature;
  1901. UCHAR LocalChecksum[24]; // ??? need better constant
  1902. NETLOGON_SESSION_KEY EncryptionSessionKey;
  1903. ULONG OutputSize;
  1904. PNL_AUTH_CONTEXT Context;
  1905. //
  1906. // Locate the context.
  1907. //
  1908. Context = LocateContext( phContext );
  1909. if (Context == NULL) {
  1910. NlPrint(( NL_CRITICAL,
  1911. "NlpSignOrSeal: %lx.%lx: Cannot LocateContext\n",
  1912. phContext->dwUpper, phContext->dwLower ));
  1913. SecStatus = SEC_E_INVALID_HANDLE;
  1914. goto Cleanup;
  1915. }
  1916. //
  1917. // Find a buffer to put the signature in.
  1918. //
  1919. SignatureBuffer = LocateSigBuffer( MessageBuffers );
  1920. if (SignatureBuffer == NULL) {
  1921. NlPrint(( NL_CRITICAL,
  1922. "NlpSignOrSeal: %lx.%lx: No signature buffer found\n",
  1923. phContext->dwUpper, phContext->dwLower ));
  1924. SecStatus = SEC_E_INVALID_TOKEN;
  1925. goto Cleanup;
  1926. }
  1927. if ( SealIt ) {
  1928. if ( SignatureBuffer->cbBuffer < sizeof(PACKAGE_SIGNATURE_SIZE) ) {
  1929. NlPrint(( NL_CRITICAL,
  1930. "NlpVerifyOrUnseal: %lx.%lx: buffer too small for sealing\n",
  1931. phContext->dwUpper, phContext->dwLower ));
  1932. SecStatus = SEC_E_MESSAGE_ALTERED;
  1933. goto Cleanup;
  1934. }
  1935. }
  1936. //
  1937. // Build the signature.
  1938. Signature = (PNL_AUTH_SIGNATURE) SignatureBuffer->pvBuffer;
  1939. Signature->SignatureAlgorithm[0] = (UCHAR) NL_AUTH_CHECKSUM;
  1940. Signature->SignatureAlgorithm[1] = 0;
  1941. if ( SealIt ) {
  1942. Signature->SealAlgorithm[0] = (UCHAR) NL_AUTH_ETYPE;
  1943. Signature->SealAlgorithm[1] = 0;
  1944. memset(Signature->SealFiller, 0xff, sizeof(Signature->SealFiller));
  1945. NlGenerateRandomBits( Signature->Confounder, NL_AUTH_CONFOUNDER_SIZE );
  1946. SignatureBuffer->cbBuffer = PACKAGE_SIGNATURE_SIZE;
  1947. } else {
  1948. memset(Signature->SignFiller, 0xff, sizeof(Signature->SignFiller));
  1949. SignatureBuffer->cbBuffer = PACKAGE_SIGNATURE_SIZE - NL_AUTH_CONFOUNDER_SIZE;
  1950. }
  1951. Signature->Flags[0] = 0;
  1952. Signature->Flags[1] = 0;
  1953. Signature->SequenceNumber[0] = (UCHAR) ((Context->Nonce.LowPart & 0xff000000) >> 24);
  1954. Signature->SequenceNumber[1] = (UCHAR) ((Context->Nonce.LowPart & 0x00ff0000) >> 16);
  1955. Signature->SequenceNumber[2] = (UCHAR) ((Context->Nonce.LowPart & 0x0000ff00) >> 8);
  1956. Signature->SequenceNumber[3] = (UCHAR) (Context->Nonce.LowPart & 0x000000ff);
  1957. Signature->SequenceNumber[4] = (UCHAR) ((Context->Nonce.HighPart & 0xff000000) >> 24);
  1958. Signature->SequenceNumber[5] = (UCHAR) ((Context->Nonce.HighPart & 0x00ff0000) >> 16);
  1959. Signature->SequenceNumber[6] = (UCHAR) ((Context->Nonce.HighPart & 0x0000ff00) >> 8);
  1960. Signature->SequenceNumber[7] = (UCHAR) (Context->Nonce.HighPart & 0x000000ff);
  1961. if ( !Context->Inbound ) {
  1962. Signature->SequenceNumber[4] |= 0x80; // Discriminate between inbound and outbound messages
  1963. }
  1964. Context->Nonce.QuadPart ++;
  1965. //
  1966. // Initialize the checksum routines.
  1967. //
  1968. Status = CDLocateCheckSum( (ULONG)NL_AUTH_CHECKSUM, &Check);
  1969. if (!NT_SUCCESS(Status)) {
  1970. NlPrint(( NL_CRITICAL,
  1971. "NlpSignOrSeal: %lx.%lx: Failed to load checksum routines: 0x%x\n",
  1972. phContext->dwUpper, phContext->dwLower,
  1973. Status));
  1974. goto Cleanup;
  1975. }
  1976. NlAssert(Check->CheckSumSize <= sizeof(LocalChecksum));
  1977. NlPrint(( NL_ENCRYPT,
  1978. "NlpSignOrSeal: %lx.%lx: Session Key: ",
  1979. phContext->dwUpper, phContext->dwLower ));
  1980. NlpDumpBuffer(NL_ENCRYPT, &Context->SessionInfo.SessionKey, sizeof( Context->SessionInfo.SessionKey) );
  1981. Status = Check->InitializeEx(
  1982. (LPBYTE)&Context->SessionInfo.SessionKey,
  1983. sizeof( Context->SessionInfo.SessionKey),
  1984. 0, // no message type
  1985. &CheckBuffer );
  1986. if (!NT_SUCCESS(Status)) {
  1987. NlPrint(( NL_CRITICAL,
  1988. "NlpSignOrSeal: %lx.%lx: Failed to initialize checksum routines: 0x%x\n",
  1989. phContext->dwUpper, phContext->dwLower,
  1990. Status));
  1991. goto Cleanup;
  1992. }
  1993. //
  1994. // Locate the encryption routines.
  1995. //
  1996. Status = CDLocateCSystem( (ULONG)NL_AUTH_ETYPE, &CryptSystem);
  1997. if (!NT_SUCCESS(Status)) {
  1998. NlPrint(( NL_CRITICAL,
  1999. "NlpSignOrSeal: %lx.%lx: Failed to load crypt system: 0x%x\n",
  2000. phContext->dwUpper, phContext->dwLower,
  2001. Status));
  2002. goto Cleanup;
  2003. }
  2004. //
  2005. // Sum first several bytes of the signature
  2006. //
  2007. Check->Sum( CheckBuffer,
  2008. NL_AUTH_SIGNED_BYTES,
  2009. (PUCHAR)Signature );
  2010. //
  2011. // Sum and encrypt the confounder
  2012. //
  2013. if ( SealIt ) {
  2014. //
  2015. // Sum the confounder
  2016. //
  2017. Check->Sum(
  2018. CheckBuffer,
  2019. NL_AUTH_CONFOUNDER_SIZE,
  2020. Signature->Confounder );
  2021. //
  2022. // Create the encryption key by xoring the session key with 0xf0f0f0f0
  2023. //
  2024. for ( Index=0; Index < sizeof(EncryptionSessionKey); Index++ ) {
  2025. ((LPBYTE)(&EncryptionSessionKey))[Index] =
  2026. ((LPBYTE)(&Context->SessionInfo.SessionKey))[Index] ^0xf0f0f0f0;
  2027. }
  2028. //
  2029. // Pass the key to the encryption routines.
  2030. //
  2031. Status = CryptSystem->Initialize(
  2032. (LPBYTE)&EncryptionSessionKey,
  2033. sizeof( EncryptionSessionKey ),
  2034. 0, // no message type
  2035. &CryptBuffer );
  2036. if (!NT_SUCCESS(Status)) {
  2037. NlPrint(( NL_CRITICAL,
  2038. "NlpSignOrSeal: %lx.%lx: Failed to initialize crypt routines: 0x%x\n",
  2039. phContext->dwUpper, phContext->dwLower,
  2040. Status));
  2041. goto Cleanup;
  2042. }
  2043. //
  2044. // Set the initial vector to ensure the key is different for each message
  2045. //
  2046. Status = CryptSystem->Control(
  2047. CRYPT_CONTROL_SET_INIT_VECT,
  2048. CryptBuffer,
  2049. Signature->SequenceNumber,
  2050. sizeof(Signature->SequenceNumber) );
  2051. if (!NT_SUCCESS(Status)) {
  2052. NlPrint(( NL_CRITICAL,
  2053. "NlpSignOrSeal: %lx.%lx: Failed to set IV: 0x%x\n",
  2054. phContext->dwUpper, phContext->dwLower,
  2055. Status));
  2056. goto Cleanup;
  2057. }
  2058. //
  2059. // Encrypt the confounder
  2060. //
  2061. Status = CryptSystem->Encrypt(
  2062. CryptBuffer,
  2063. Signature->Confounder,
  2064. NL_AUTH_CONFOUNDER_SIZE,
  2065. Signature->Confounder,
  2066. &OutputSize );
  2067. if (!NT_SUCCESS(Status)) {
  2068. NlPrint(( NL_CRITICAL,
  2069. "NlpSignOrSeal: %lx.%lx: Failed to encrypt confounder: 0x%x\n",
  2070. phContext->dwUpper, phContext->dwLower,
  2071. Status));
  2072. goto Cleanup;
  2073. }
  2074. NlAssert( OutputSize == NL_AUTH_CONFOUNDER_SIZE );
  2075. }
  2076. //
  2077. // Sum and encrypt the caller's message.
  2078. //
  2079. for (Index = 0; Index < MessageBuffers->cBuffers; Index++ ) {
  2080. if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  2081. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)) &&
  2082. (MessageBuffers->pBuffers[Index].cbBuffer != 0)) {
  2083. Check->Sum(
  2084. CheckBuffer,
  2085. MessageBuffers->pBuffers[Index].cbBuffer,
  2086. (PBYTE) MessageBuffers->pBuffers[Index].pvBuffer );
  2087. //
  2088. // Now encrypt the buffer
  2089. //
  2090. if ( SealIt ) {
  2091. Status = CryptSystem->Encrypt(
  2092. CryptBuffer,
  2093. (PUCHAR) MessageBuffers->pBuffers[Index].pvBuffer,
  2094. MessageBuffers->pBuffers[Index].cbBuffer,
  2095. (PUCHAR) MessageBuffers->pBuffers[Index].pvBuffer,
  2096. &OutputSize );
  2097. if (!NT_SUCCESS(Status)) {
  2098. NlPrint(( NL_CRITICAL,
  2099. "NlpSignOrSeal: %lx.%lx: Failed to encrypt buffer: 0x%x\n",
  2100. phContext->dwUpper, phContext->dwLower,
  2101. Status));
  2102. goto Cleanup;
  2103. }
  2104. NlAssert(OutputSize == MessageBuffers->pBuffers[Index].cbBuffer);
  2105. }
  2106. }
  2107. }
  2108. //
  2109. // Finish the checksum
  2110. //
  2111. (void) Check->Finalize(CheckBuffer, LocalChecksum);
  2112. #ifdef notdef
  2113. Status = Check->Finish(&CheckBuffer);
  2114. if (!NT_SUCCESS(Status)) {
  2115. NlPrint(( NL_CRITICAL,"NlpSignOrSeal: Failed to finish checksum: 0x%x\n", Status));
  2116. goto Cleanup;
  2117. }
  2118. CheckBuffer = NULL;
  2119. #endif // notdef
  2120. //
  2121. // Copy the checksum into the message.
  2122. //
  2123. NlAssert( sizeof(LocalChecksum) >= sizeof(Signature->Checksum) );
  2124. RtlCopyMemory( Signature->Checksum, LocalChecksum, sizeof(Signature->Checksum) );
  2125. //
  2126. // Always encrypt the sequence number, using the checksum as the IV
  2127. //
  2128. if ( SealIt ) {
  2129. CryptSystem->Discard( &CryptBuffer );
  2130. CryptBuffer = NULL;
  2131. }
  2132. Status = CryptSystem->Initialize(
  2133. (LPBYTE)&Context->SessionInfo.SessionKey,
  2134. sizeof( Context->SessionInfo.SessionKey),
  2135. 0, // no message type
  2136. &CryptBuffer );
  2137. if (!NT_SUCCESS(Status)) {
  2138. NlPrint(( NL_CRITICAL,
  2139. "NlpSignOrSeal: %lx.%lx: Failed initialize crypt routines: 0x%x\n",
  2140. phContext->dwUpper, phContext->dwLower,
  2141. Status));
  2142. goto Cleanup;
  2143. }
  2144. //
  2145. // Set the initial vector
  2146. //
  2147. NlPrint(( NL_ENCRYPT,
  2148. "NlpSignOrSeal: %lx.%lx: IV: ",
  2149. phContext->dwUpper, phContext->dwLower ));
  2150. NlpDumpBuffer(NL_ENCRYPT, Signature->Checksum, sizeof(Signature->Checksum) );
  2151. Status = CryptSystem->Control(
  2152. CRYPT_CONTROL_SET_INIT_VECT,
  2153. CryptBuffer,
  2154. Signature->Checksum,
  2155. sizeof(Signature->Checksum) );
  2156. if (!NT_SUCCESS(Status)) {
  2157. NlPrint(( NL_CRITICAL,
  2158. "NlpSignOrSeal: %lx.%lx: Failed to set IV: 0x%x\n",
  2159. phContext->dwUpper, phContext->dwLower,
  2160. Status));
  2161. goto Cleanup;
  2162. }
  2163. //
  2164. // Now encrypt the sequence number
  2165. //
  2166. NlPrint(( NL_ENCRYPT,
  2167. "NlpSignOrSeal: %lx.%lx: Clear Seq: ",
  2168. phContext->dwUpper, phContext->dwLower ));
  2169. NlpDumpBuffer(NL_ENCRYPT, Signature->SequenceNumber, sizeof(Signature->SequenceNumber) );
  2170. Status = CryptSystem->Encrypt(
  2171. CryptBuffer,
  2172. Signature->SequenceNumber,
  2173. sizeof(Signature->SequenceNumber),
  2174. Signature->SequenceNumber,
  2175. &OutputSize
  2176. );
  2177. if (!NT_SUCCESS(Status)) {
  2178. NlPrint(( NL_CRITICAL,
  2179. "NlpSignOrSeal: %lx.%lx: Failed to encrypt sequence number: 0x%x\n",
  2180. phContext->dwUpper, phContext->dwLower,
  2181. Status));
  2182. goto Cleanup;
  2183. }
  2184. NlPrint(( NL_ENCRYPT,
  2185. "NlpSignOrSeal: %lx.%lx: Encrypted Seq: ",
  2186. phContext->dwUpper, phContext->dwLower ));
  2187. NlpDumpBuffer(NL_ENCRYPT, Signature->SequenceNumber, sizeof(Signature->SequenceNumber) );
  2188. NlAssert(OutputSize == sizeof(Signature->SequenceNumber));
  2189. Cleanup:
  2190. if (CryptBuffer != NULL) {
  2191. CryptSystem->Discard(&CryptBuffer);
  2192. }
  2193. if (CheckBuffer != NULL) {
  2194. Check->Finish(&CheckBuffer);
  2195. }
  2196. if ( SecStatus == SEC_E_OK ) {
  2197. SecStatus = KerbMapNtStatusToSecStatus(Status);
  2198. }
  2199. return SecStatus;
  2200. UNREFERENCED_PARAMETER( MessageSeqNo );
  2201. UNREFERENCED_PARAMETER( fQOP );
  2202. }
  2203. SECURITY_STATUS
  2204. NlpVerifyOrUnseal(
  2205. IN PCtxtHandle phContext,
  2206. IN PSecBufferDesc MessageBuffers,
  2207. IN ULONG MessageSequenceNumber,
  2208. OUT PULONG QualityOfProtection,
  2209. IN BOOLEAN UnsealIt
  2210. )
  2211. /*++
  2212. Routine Description:
  2213. Common routine to verify or unseal a message (Client or server side)
  2214. Arguments:
  2215. Standard.
  2216. UnSealIt - True to unseal the message.
  2217. FALSE to verify the message.
  2218. Return Value:
  2219. --*/
  2220. {
  2221. SECURITY_STATUS SecStatus = SEC_E_OK;
  2222. NTSTATUS Status = STATUS_SUCCESS;
  2223. PCHECKSUM_FUNCTION Check;
  2224. PCRYPTO_SYSTEM CryptSystem;
  2225. PCHECKSUM_BUFFER CheckBuffer = NULL;
  2226. PCRYPT_STATE_BUFFER CryptBuffer = NULL;
  2227. ULONG Index;
  2228. PSecBuffer SignatureBuffer = NULL;
  2229. PNL_AUTH_SIGNATURE Signature;
  2230. UCHAR LocalChecksum[24]; // ??? need better constant
  2231. BYTE LocalNonce[ NL_AUTH_SEQUENCE_SIZE ];
  2232. NETLOGON_SESSION_KEY EncryptionSessionKey;
  2233. ULONG OutputSize;
  2234. PNL_AUTH_CONTEXT Context;
  2235. //
  2236. // Locate the context.
  2237. //
  2238. Context = LocateContext( phContext );
  2239. if (Context == NULL) {
  2240. NlPrint(( NL_CRITICAL,
  2241. "NlpVerifyOrUnseal: %lx.%lx: Cannot LocateContext\n",
  2242. phContext->dwUpper, phContext->dwLower ));
  2243. SecStatus = SEC_E_INVALID_HANDLE;
  2244. goto Cleanup;
  2245. }
  2246. //
  2247. // Find a buffer to put the signature in.
  2248. //
  2249. SignatureBuffer = LocateSigBuffer( MessageBuffers );
  2250. if (SignatureBuffer == NULL) {
  2251. NlPrint(( NL_CRITICAL,
  2252. "NlpVerifyOrUnseal: %lx.%lx: No signature buffer found\n",
  2253. phContext->dwUpper, phContext->dwLower ));
  2254. SecStatus = SEC_E_INVALID_TOKEN;
  2255. goto Cleanup;
  2256. }
  2257. //
  2258. // Verify the signature.
  2259. //
  2260. Signature = (PNL_AUTH_SIGNATURE) SignatureBuffer->pvBuffer;
  2261. if ( Signature->SignatureAlgorithm[0] != (BYTE)NL_AUTH_CHECKSUM ||
  2262. Signature->SignatureAlgorithm[1] != 0 ) {
  2263. NlPrint(( NL_CRITICAL,
  2264. "NlpVerifyOrUnseal: %lx.%lx: signature alg different\n",
  2265. phContext->dwUpper, phContext->dwLower ));
  2266. SecStatus = SEC_E_MESSAGE_ALTERED;
  2267. goto Cleanup;
  2268. }
  2269. if ( UnsealIt ) {
  2270. if ( SignatureBuffer->cbBuffer < sizeof(PACKAGE_SIGNATURE_SIZE) ) {
  2271. NlPrint(( NL_CRITICAL,
  2272. "NlpVerifyOrUnseal: %lx.%lx: buffer too small for sealing\n",
  2273. phContext->dwUpper, phContext->dwLower ));
  2274. SecStatus = SEC_E_MESSAGE_ALTERED;
  2275. goto Cleanup;
  2276. }
  2277. if ( Signature->SealAlgorithm[0] != (BYTE)NL_AUTH_ETYPE ||
  2278. Signature->SealAlgorithm[1] != 0 ) {
  2279. NlPrint(( NL_CRITICAL,
  2280. "NlpVerifyOrUnseal: %lx.%lx: seal alg different\n",
  2281. phContext->dwUpper, phContext->dwLower ));
  2282. SecStatus = SEC_E_MESSAGE_ALTERED;
  2283. goto Cleanup;
  2284. }
  2285. if ( *((USHORT UNALIGNED *)Signature->SealFiller) != 0xffff) {
  2286. NlPrint(( NL_CRITICAL,
  2287. "NlpVerifyOrUnseal: %lx.%lx: Filler different\n",
  2288. phContext->dwUpper, phContext->dwLower ));
  2289. SecStatus = SEC_E_MESSAGE_ALTERED;
  2290. goto Cleanup;
  2291. }
  2292. } else {
  2293. if ( *((ULONG UNALIGNED *) Signature->SignFiller) != 0xffffffff) {
  2294. NlPrint(( NL_CRITICAL,
  2295. "NlpVerifyOrUnseal: %lx.%lx: Filler different\n",
  2296. phContext->dwUpper, phContext->dwLower ));
  2297. SecStatus = SEC_E_MESSAGE_ALTERED;
  2298. goto Cleanup;
  2299. }
  2300. }
  2301. //
  2302. // Verify the sequence number.
  2303. //
  2304. // It is sent encrypted using the checksum as the IV, so decrypt it before
  2305. // checking it.
  2306. //
  2307. // Locate the encryption routines.
  2308. //
  2309. Status = CDLocateCSystem( (ULONG)NL_AUTH_ETYPE, &CryptSystem);
  2310. if (!NT_SUCCESS(Status)) {
  2311. NlPrint(( NL_CRITICAL,
  2312. "NlpVerifyOrUnseal: %lx.%lx: Failed to load crypt system: 0x%x\n",
  2313. phContext->dwUpper, phContext->dwLower,
  2314. Status));
  2315. goto Cleanup;
  2316. }
  2317. NlPrint(( NL_ENCRYPT,
  2318. "NlpVerifyOrUnseal: %lx.%lx: Session Key: ",
  2319. phContext->dwUpper, phContext->dwLower ));
  2320. NlpDumpBuffer(NL_ENCRYPT, &Context->SessionInfo.SessionKey, sizeof( Context->SessionInfo.SessionKey) );
  2321. Status = CryptSystem->Initialize(
  2322. (LPBYTE)&Context->SessionInfo.SessionKey,
  2323. sizeof( Context->SessionInfo.SessionKey),
  2324. 0, // no message type
  2325. &CryptBuffer );
  2326. if (!NT_SUCCESS(Status)) {
  2327. NlPrint(( NL_CRITICAL,
  2328. "NlpVerifyOrUnseal: %lx.%lx: Failed initialize crypt routines: 0x%x\n",
  2329. phContext->dwUpper, phContext->dwLower,
  2330. Status));
  2331. goto Cleanup;
  2332. }
  2333. //
  2334. // Set the initial vector
  2335. //
  2336. NlPrint(( NL_ENCRYPT,
  2337. "NlpVerifyOrUnseal: %lx.%lx: IV: ",
  2338. phContext->dwUpper, phContext->dwLower ));
  2339. NlpDumpBuffer(NL_ENCRYPT, Signature->Checksum, sizeof(Signature->Checksum) );
  2340. Status = CryptSystem->Control(
  2341. CRYPT_CONTROL_SET_INIT_VECT,
  2342. CryptBuffer,
  2343. Signature->Checksum,
  2344. sizeof(Signature->Checksum) );
  2345. if (!NT_SUCCESS(Status)) {
  2346. NlPrint(( NL_CRITICAL,
  2347. "NlpVerifyOrUnseal: %lx.%lx: Failed to set IV: 0x%x\n",
  2348. phContext->dwUpper, phContext->dwLower,
  2349. Status));
  2350. goto Cleanup;
  2351. }
  2352. //
  2353. // Now decrypt the sequence number
  2354. //
  2355. NlPrint(( NL_ENCRYPT,
  2356. "NlpVerifyOrUnseal: %lx.%lx: Encrypted Seq: ",
  2357. phContext->dwUpper, phContext->dwLower ));
  2358. NlpDumpBuffer(NL_ENCRYPT, Signature->SequenceNumber, sizeof(Signature->SequenceNumber) );
  2359. Status = CryptSystem->Decrypt(
  2360. CryptBuffer,
  2361. Signature->SequenceNumber,
  2362. sizeof(Signature->SequenceNumber),
  2363. Signature->SequenceNumber,
  2364. &OutputSize );
  2365. if (!NT_SUCCESS(Status)) {
  2366. NlPrint(( NL_CRITICAL,
  2367. "NlpVerifyOrUnseal: %lx.%lx: Cannot decrypt sequence number: 0x%x\n",
  2368. phContext->dwUpper, phContext->dwLower,
  2369. Status));
  2370. goto Cleanup;
  2371. }
  2372. NlPrint(( NL_ENCRYPT,
  2373. "NlpVerifyOrUnseal: %lx.%lx: Clear Seq: ",
  2374. phContext->dwUpper, phContext->dwLower ));
  2375. NlpDumpBuffer(NL_ENCRYPT, Signature->SequenceNumber, sizeof(Signature->SequenceNumber) );
  2376. LocalNonce[0] = (UCHAR) ((Context->Nonce.LowPart & 0xff000000) >> 24);
  2377. LocalNonce[1] = (UCHAR) ((Context->Nonce.LowPart & 0x00ff0000) >> 16);
  2378. LocalNonce[2] = (UCHAR) ((Context->Nonce.LowPart & 0x0000ff00) >> 8);
  2379. LocalNonce[3] = (UCHAR) (Context->Nonce.LowPart & 0x000000ff);
  2380. LocalNonce[4] = (UCHAR) ((Context->Nonce.HighPart & 0xff000000) >> 24);
  2381. LocalNonce[5] = (UCHAR) ((Context->Nonce.HighPart & 0x00ff0000) >> 16);
  2382. LocalNonce[6] = (UCHAR) ((Context->Nonce.HighPart & 0x0000ff00) >> 8);
  2383. LocalNonce[7] = (UCHAR) (Context->Nonce.HighPart & 0x000000ff);
  2384. if ( Context->Inbound ) {
  2385. LocalNonce[4] |= 0x80; // Discriminate between inbound and outbound messages
  2386. }
  2387. if (!RtlEqualMemory( LocalNonce,
  2388. Signature->SequenceNumber,
  2389. NL_AUTH_SEQUENCE_SIZE )) {
  2390. NlPrint(( NL_CRITICAL,
  2391. "NlpVerifyOrUnseal: %lx.%lx: Out of sequence\n",
  2392. phContext->dwUpper, phContext->dwLower ));
  2393. NlPrint(( NL_CRITICAL,"NlpVerifyOrUnseal: Local Sequence: " ));
  2394. NlpDumpBuffer(NL_CRITICAL, LocalNonce, NL_AUTH_SEQUENCE_SIZE );
  2395. NlPrint(( NL_CRITICAL,"NlpVerifyOrUnseal: Remote Sequence: " ));
  2396. NlpDumpBuffer(NL_CRITICAL, Signature->SequenceNumber, NL_AUTH_SEQUENCE_SIZE );
  2397. Status = SEC_E_OUT_OF_SEQUENCE;
  2398. goto Cleanup;
  2399. }
  2400. Context->Nonce.QuadPart ++;
  2401. //
  2402. // Now compute the checksum and verify it
  2403. //
  2404. //
  2405. // Initialize the checksum routines.
  2406. //
  2407. Status = CDLocateCheckSum( (ULONG)NL_AUTH_CHECKSUM, &Check);
  2408. if (!NT_SUCCESS(Status)) {
  2409. NlPrint(( NL_CRITICAL,
  2410. "NlpVerifyOrUnseal: %lx.%lx: Failed to load checksum routines: 0x%x\n",
  2411. phContext->dwUpper, phContext->dwLower,
  2412. Status));
  2413. goto Cleanup;
  2414. }
  2415. NlAssert(Check->CheckSumSize <= sizeof(LocalChecksum));
  2416. Status = Check->InitializeEx(
  2417. (LPBYTE)&Context->SessionInfo.SessionKey,
  2418. sizeof( Context->SessionInfo.SessionKey),
  2419. 0, // no message type
  2420. &CheckBuffer );
  2421. if (!NT_SUCCESS(Status)) {
  2422. NlPrint(( NL_CRITICAL,
  2423. "NlpVerifyOrUnseal: %lx.%lx: Failed to initialize checksum routines: 0x%x\n",
  2424. phContext->dwUpper, phContext->dwLower,
  2425. Status));
  2426. goto Cleanup;
  2427. }
  2428. //
  2429. // Sum first several bytes of the signature
  2430. //
  2431. NlPrint(( NL_ENCRYPT,
  2432. "NlpVerifyOrUnseal: %lx.%lx: First Several of signature: ",
  2433. phContext->dwUpper, phContext->dwLower ));
  2434. NlpDumpBuffer(NL_ENCRYPT, Signature, NL_AUTH_SIGNED_BYTES );
  2435. Check->Sum( CheckBuffer,
  2436. NL_AUTH_SIGNED_BYTES,
  2437. (PUCHAR)Signature );
  2438. //
  2439. // Sum and decrypt the confounder
  2440. //
  2441. if ( UnsealIt ) {
  2442. //
  2443. // Discard the previous CryptBuffer
  2444. //
  2445. CryptSystem->Discard( &CryptBuffer );
  2446. CryptBuffer = NULL;
  2447. //
  2448. // Create the encryption key by xoring the session key with 0xf0f0f0f0
  2449. //
  2450. for ( Index=0; Index < sizeof(EncryptionSessionKey); Index++ ) {
  2451. ((LPBYTE)(&EncryptionSessionKey))[Index] =
  2452. ((LPBYTE)(&Context->SessionInfo.SessionKey))[Index] ^0xf0f0f0f0;
  2453. }
  2454. //
  2455. // Pass the key to the encryption routines.
  2456. //
  2457. Status = CryptSystem->Initialize(
  2458. (LPBYTE)&EncryptionSessionKey,
  2459. sizeof( EncryptionSessionKey ),
  2460. 0, // no message type
  2461. &CryptBuffer );
  2462. if (!NT_SUCCESS(Status)) {
  2463. NlPrint(( NL_CRITICAL,
  2464. "NlpVerifyOrUnseal: %lx.%lx: Failed to initialize crypt routines: 0x%x\n",
  2465. phContext->dwUpper, phContext->dwLower,
  2466. Status));
  2467. goto Cleanup;
  2468. }
  2469. //
  2470. // Set the initial vector to ensure the key is different for each message
  2471. //
  2472. Status = CryptSystem->Control(
  2473. CRYPT_CONTROL_SET_INIT_VECT,
  2474. CryptBuffer,
  2475. Signature->SequenceNumber,
  2476. sizeof(Signature->SequenceNumber) );
  2477. if (!NT_SUCCESS(Status)) {
  2478. NlPrint(( NL_CRITICAL,
  2479. "NlpVerifyOrUnseal: %lx.%lx: Failed to set IV: 0x%x\n",
  2480. phContext->dwUpper, phContext->dwLower,
  2481. Status));
  2482. goto Cleanup;
  2483. }
  2484. //
  2485. // Decrypt the confounder
  2486. //
  2487. Status = CryptSystem->Decrypt(
  2488. CryptBuffer,
  2489. Signature->Confounder,
  2490. NL_AUTH_CONFOUNDER_SIZE,
  2491. Signature->Confounder,
  2492. &OutputSize );
  2493. if (!NT_SUCCESS(Status)) {
  2494. NlPrint(( NL_CRITICAL,
  2495. "NlpVerifyOrUnseal: %lx.%lx: Failed to encrypt confounder: 0x%x\n",
  2496. phContext->dwUpper, phContext->dwLower,
  2497. Status));
  2498. goto Cleanup;
  2499. }
  2500. NlAssert( OutputSize == NL_AUTH_CONFOUNDER_SIZE );
  2501. //
  2502. // Sum the decrypted confounder
  2503. //
  2504. Check->Sum(
  2505. CheckBuffer,
  2506. NL_AUTH_CONFOUNDER_SIZE,
  2507. Signature->Confounder );
  2508. }
  2509. //
  2510. // Sum and decrypt the caller's message.
  2511. //
  2512. for (Index = 0; Index < MessageBuffers->cBuffers; Index++ ) {
  2513. if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  2514. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)) &&
  2515. (MessageBuffers->pBuffers[Index].cbBuffer != 0)) {
  2516. //
  2517. // Now decrypt the buffer
  2518. //
  2519. if ( UnsealIt ) {
  2520. Status = CryptSystem->Decrypt(
  2521. CryptBuffer,
  2522. (PUCHAR) MessageBuffers->pBuffers[Index].pvBuffer,
  2523. MessageBuffers->pBuffers[Index].cbBuffer,
  2524. (PUCHAR) MessageBuffers->pBuffers[Index].pvBuffer,
  2525. &OutputSize );
  2526. if (!NT_SUCCESS(Status)) {
  2527. NlPrint(( NL_CRITICAL,
  2528. "NlpVerifyOrUnseal: %lx.%lx: Failed to encrypt buffer: 0x%x\n",
  2529. phContext->dwUpper, phContext->dwLower,
  2530. Status));
  2531. goto Cleanup;
  2532. }
  2533. NlAssert(OutputSize == MessageBuffers->pBuffers[Index].cbBuffer);
  2534. }
  2535. //
  2536. // Checksum the decrypted buffer.
  2537. //
  2538. Check->Sum(
  2539. CheckBuffer,
  2540. MessageBuffers->pBuffers[Index].cbBuffer,
  2541. (PBYTE) MessageBuffers->pBuffers[Index].pvBuffer );
  2542. }
  2543. }
  2544. //
  2545. // Finish the checksum
  2546. //
  2547. (void) Check->Finalize(CheckBuffer, LocalChecksum);
  2548. if (!RtlEqualMemory(
  2549. LocalChecksum,
  2550. Signature->Checksum,
  2551. sizeof(Signature->Checksum) )) {
  2552. NlPrint(( NL_CRITICAL,
  2553. "NlpVerifyOrUnseal: %lx.%lx: Checksum mismatch\n",
  2554. phContext->dwUpper, phContext->dwLower ));
  2555. Status = SEC_E_MESSAGE_ALTERED;
  2556. goto Cleanup;
  2557. }
  2558. Cleanup:
  2559. if (CheckBuffer != NULL) {
  2560. Check->Finish(&CheckBuffer);
  2561. }
  2562. if (CryptBuffer != NULL) {
  2563. CryptSystem->Discard(&CryptBuffer);
  2564. }
  2565. if ( SecStatus == SEC_E_OK ) {
  2566. SecStatus = KerbMapNtStatusToSecStatus(Status);
  2567. }
  2568. return SecStatus;
  2569. UNREFERENCED_PARAMETER( QualityOfProtection );
  2570. UNREFERENCED_PARAMETER( MessageSequenceNumber );
  2571. }
  2572. SECURITY_STATUS SEC_ENTRY
  2573. MakeSignature( PCtxtHandle phContext,
  2574. ULONG fQOP,
  2575. PSecBufferDesc pMessage,
  2576. ULONG MessageSeqNo)
  2577. /*++
  2578. Routine Description:
  2579. Routine to sign a message (Client or server side)
  2580. Arguments:
  2581. Standard.
  2582. Return Value:
  2583. --*/
  2584. {
  2585. SECURITY_STATUS SecStatus;
  2586. //
  2587. // If caller is calling when the netlogon service isn't running,
  2588. // tell it so.
  2589. //
  2590. if ( !NlStartNetlogonCall() ) {
  2591. return SEC_E_SECPKG_NOT_FOUND;
  2592. }
  2593. SecStatus = NlpSignOrSeal(
  2594. phContext,
  2595. fQOP,
  2596. pMessage,
  2597. MessageSeqNo,
  2598. FALSE ); // Just sign the message
  2599. NlPrint(( NL_SESSION_MORE,
  2600. "MakeSignature: %lx.%lx: returns 0x%lx\n",
  2601. phContext->dwUpper, phContext->dwLower,
  2602. SecStatus ));
  2603. // Let netlogon service exit.
  2604. NlEndNetlogonCall();
  2605. return SecStatus;
  2606. }
  2607. SECURITY_STATUS SEC_ENTRY
  2608. VerifySignature(PCtxtHandle phContext,
  2609. PSecBufferDesc pMessage,
  2610. ULONG MessageSeqNo,
  2611. ULONG * pfQOP)
  2612. /*++
  2613. Routine Description:
  2614. Routine to verify a signed message (Client or server side)
  2615. Arguments:
  2616. Standard.
  2617. Return Value:
  2618. --*/
  2619. {
  2620. SECURITY_STATUS SecStatus;
  2621. //
  2622. // If caller is calling when the netlogon service isn't running,
  2623. // tell it so.
  2624. //
  2625. if ( !NlStartNetlogonCall() ) {
  2626. return SEC_E_SECPKG_NOT_FOUND;
  2627. }
  2628. SecStatus = NlpVerifyOrUnseal(
  2629. phContext,
  2630. pMessage,
  2631. MessageSeqNo,
  2632. pfQOP,
  2633. FALSE ); // Just verify the signature
  2634. NlPrint(( NL_SESSION_MORE,
  2635. "VerifySignature: %lx.%lx: returns 0x%lx\n",
  2636. phContext->dwUpper, phContext->dwLower,
  2637. SecStatus ));
  2638. // Let netlogon service exit.
  2639. NlEndNetlogonCall();
  2640. return SecStatus;
  2641. }
  2642. SECURITY_STATUS SEC_ENTRY
  2643. SealMessage( PCtxtHandle phContext,
  2644. ULONG fQOP,
  2645. PSecBufferDesc pMessage,
  2646. ULONG MessageSeqNo)
  2647. /*++
  2648. Routine Description:
  2649. Routine to encrypt a message (Client or server side)
  2650. Arguments:
  2651. Standard.
  2652. Return Value:
  2653. --*/
  2654. {
  2655. SECURITY_STATUS SecStatus;
  2656. //
  2657. // If caller is calling when the netlogon service isn't running,
  2658. // tell it so.
  2659. //
  2660. if ( !NlStartNetlogonCall() ) {
  2661. return SEC_E_SECPKG_NOT_FOUND;
  2662. }
  2663. SecStatus = NlpSignOrSeal(
  2664. phContext,
  2665. fQOP,
  2666. pMessage,
  2667. MessageSeqNo,
  2668. TRUE ); // Seal the message
  2669. NlPrint(( NL_SESSION_MORE,
  2670. "SealMessage: %lx.%lx: returns 0x%lx\n",
  2671. phContext->dwUpper, phContext->dwLower,
  2672. SecStatus ));
  2673. // Let netlogon service exit.
  2674. NlEndNetlogonCall();
  2675. return SecStatus;
  2676. }
  2677. SECURITY_STATUS SEC_ENTRY
  2678. UnsealMessage( PCtxtHandle phContext,
  2679. PSecBufferDesc pMessage,
  2680. ULONG MessageSeqNo,
  2681. ULONG * pfQOP)
  2682. /*++
  2683. Routine Description:
  2684. Routine to un-encrypt a message (client or server side)
  2685. Arguments:
  2686. Standard.
  2687. Return Value:
  2688. --*/
  2689. {
  2690. SECURITY_STATUS SecStatus;
  2691. //
  2692. // If caller is calling when the netlogon service isn't running,
  2693. // tell it so.
  2694. //
  2695. if ( !NlStartNetlogonCall() ) {
  2696. return SEC_E_SECPKG_NOT_FOUND;
  2697. }
  2698. SecStatus = NlpVerifyOrUnseal(
  2699. phContext,
  2700. pMessage,
  2701. MessageSeqNo,
  2702. pfQOP,
  2703. TRUE ); // unseal the message
  2704. NlPrint(( NL_SESSION_MORE,
  2705. "UnsealMessage: %lx.%lx: returns 0x%lx\n",
  2706. phContext->dwUpper, phContext->dwLower,
  2707. SecStatus ));
  2708. // Let netlogon service exit.
  2709. NlEndNetlogonCall();
  2710. return SecStatus;
  2711. }