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

913 lines
26 KiB

  1. /*
  2. * macssp.cpp
  3. * MSUAM
  4. *
  5. * Created by mconrad on Sun Sep 30 2001.
  6. * Copyright (c) 2001 Microsoft Corp. All rights reserved.
  7. *
  8. */
  9. #ifdef SSP_TARGET_CARBON
  10. #include <Carbon/Carbon.h>
  11. #endif
  12. #include <descrypt.h>
  13. #include <ntstatus.h>
  14. #include <winerror.h>
  15. #include <ntlmsspv2.h>
  16. #include <ntlmsspi.h>
  17. #include <ntlmssp.h>
  18. #include <macssp.h>
  19. #include <sspdebug.h>
  20. #include <macunicode.h>
  21. // ---------------------------------------------------------------------------
  22. // � MacSspHandleNtlmv2ChallengeMessage()
  23. // ---------------------------------------------------------------------------
  24. // Handles an NTLMv2 challenge message from a server. This function is fairly
  25. // "black box" in that the caller needs to do nothing else other than send
  26. // off the authenticate message generated here to the server.
  27. //
  28. // NOTE: All byte swapping from little to bigendian and back is performed
  29. // here. As a result, the caller should not attempt to access the structures
  30. // after returning or a crash will occur.
  31. //
  32. HRESULT
  33. MacSspHandleNtlmv2ChallengeMessage(
  34. IN PCSTR pszUserName,
  35. IN PCSTR pszDomainName,
  36. IN PCSTR pszWorkstation,
  37. IN PCSTR pszCleartextPassword,
  38. IN ULONG cbChallengeMessage,
  39. IN CHALLENGE_MESSAGE* pChallengeMessage,
  40. IN OUT ULONG* pNegotiateFlags,
  41. OUT ULONG* pcbAuthenticateMessage,
  42. OUT AUTHENTICATE_MESSAGE** ppAuthenticateMessage,
  43. OUT USER_SESSION_KEY* pUserSessionKey
  44. )
  45. {
  46. NTSTATUS Status;
  47. SSP_CREDENTIAL Credential;
  48. USER_SESSION_KEY UserSessionKey;
  49. NT_OWF_PASSWORD NtOwfPassword;
  50. UNICODE_STRING uszCleartextPassword = {0, 0, NULL};
  51. UInt16 unicodeLen = 0;
  52. ULONG cbAuthenticateMessage = 0;
  53. AUTHENTICATE_MESSAGE* pAuthenticateMessage = NULL;
  54. ULONG NegotiateFlags = *pNegotiateFlags;
  55. SspDebugPrint((DBUF, "Handling NTLMv2 Challenge Message..."));
  56. SspDebugPrint((DBUF, "Username: %s", pszUserName));
  57. SspDebugPrint((DBUF, "DomainName: %s", pszDomainName));
  58. SspDebugPrint((DBUF, "Workstation: %s", pszWorkstation));
  59. SspDebugPrint((DBUF, "Password: %s", pszCleartextPassword));
  60. //
  61. //Initialize all the structures, on mac we use memset since not all
  62. //compilers like the {0} initializer.
  63. //
  64. ZeroMemory(&Credential, sizeof(Credential));
  65. ZeroMemory(&UserSessionKey, sizeof(UserSessionKey));
  66. ZeroMemory(&NtOwfPassword, sizeof(NtOwfPassword));
  67. //
  68. //Build a unicode string from the supplied ansi password with which
  69. //we'll use to build an owf password.
  70. //
  71. Status = MacSspCStringToUnicode(
  72. pszCleartextPassword,
  73. &unicodeLen,
  74. (UniCharArrayPtr*)&(uszCleartextPassword.Buffer)
  75. );
  76. if (NT_SUCCESS(Status))
  77. {
  78. uszCleartextPassword.Length = unicodeLen;
  79. uszCleartextPassword.MaximumLength = unicodeLen;
  80. SspSwapUnicodeString(&uszCleartextPassword);
  81. }
  82. else
  83. {
  84. SspDebugPrint((DBUF, "****Unicode conversion failed! Bailing out..."));
  85. return(E_FAIL);
  86. }
  87. //
  88. //Build a credential reference that the Ssp hanlder routine requires.
  89. //
  90. Credential.Username = const_cast<CHAR*>(pszUserName);
  91. Credential.Domain = const_cast<CHAR*>(pszDomainName);
  92. Credential.Workstation = const_cast<CHAR*>(pszWorkstation);
  93. //
  94. //The credenatial requires an NTOwf password.
  95. //
  96. Status = CalculateNtOwfPassword(&uszCleartextPassword, &NtOwfPassword);
  97. if (NT_SUCCESS(Status))
  98. {
  99. Credential.NtPassword = &NtOwfPassword;
  100. //
  101. //The challenge message came from a windows box which means we have
  102. //to swap the byte order to bigendian for Macs.
  103. //
  104. SspSwapChallengeMessageBytes(pChallengeMessage);
  105. //SspDebugPrintNTLMMsg(pChallengeMessage, cbChallengeMessage);
  106. SspDebugPrint((DBUF, "Unicode Password:"));
  107. SspDebugPrintHex(uszCleartextPassword.Buffer, uszCleartextPassword.Length);
  108. SspDebugPrint((DBUF, "Generating Authenticate Message..."));
  109. Status = SsprHandleNtlmv2ChallengeMessage(
  110. &Credential,
  111. cbChallengeMessage,
  112. pChallengeMessage,
  113. &NegotiateFlags,
  114. &cbAuthenticateMessage,
  115. NULL,
  116. &UserSessionKey
  117. );
  118. if (Status == STATUS_BUFFER_TOO_SMALL)
  119. {
  120. pAuthenticateMessage = reinterpret_cast<AUTHENTICATE_MESSAGE*>(new CHAR[cbAuthenticateMessage]);
  121. Status = pAuthenticateMessage ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  122. }
  123. }
  124. if (NT_SUCCESS(Status))
  125. {
  126. Status = SsprHandleNtlmv2ChallengeMessage(
  127. &Credential,
  128. cbChallengeMessage,
  129. pChallengeMessage,
  130. &NegotiateFlags,
  131. &cbAuthenticateMessage,
  132. pAuthenticateMessage,
  133. &UserSessionKey
  134. );
  135. }
  136. if (NT_SUCCESS(Status))
  137. {
  138. *pNegotiateFlags = NegotiateFlags;
  139. *ppAuthenticateMessage = pAuthenticateMessage;
  140. pAuthenticateMessage = NULL;
  141. *pcbAuthenticateMessage = cbAuthenticateMessage;
  142. *pUserSessionKey = UserSessionKey;
  143. //
  144. //Put the authenticate message into Windows byte order.
  145. //
  146. SspSwapAuthenticateMessageBytes(*ppAuthenticateMessage);
  147. SspDebugPrint((DBUF, "******************** Session Key **********************\n"));
  148. SspDebugPrintHex(&UserSessionKey, sizeof(UserSessionKey));
  149. //SspDebugPrintNTLMMsg(*ppAuthenticateMessage, cbAuthenticateMessage);
  150. }
  151. else
  152. {
  153. SspDebugPrint((DBUF, "SsprHandleNtlmv2ChallengeMessage() failed!"));
  154. if (pAuthenticateMessage) {
  155. delete pAuthenticateMessage;
  156. }
  157. }
  158. //
  159. //Release the allocated unicode buffer after zeroing it out.
  160. //
  161. if (uszCleartextPassword.Buffer != NULL)
  162. {
  163. //
  164. //03.01.02 MJC: We need to zero out the buffer before freeing
  165. //otherwise the password may still exist in memory.
  166. //
  167. RtlSecureZeroMemory(
  168. uszCleartextPassword.Buffer,
  169. uszCleartextPassword.Length
  170. );
  171. DisposePtr((Ptr)uszCleartextPassword.Buffer);
  172. }
  173. return NT_SUCCESS(Status) ? S_OK : E_FAIL;
  174. }
  175. // ---------------------------------------------------------------------------
  176. // � MacSspGenerateChallengeMessage()
  177. // ---------------------------------------------------------------------------
  178. // This function creates a "fake" challenge message that can be passed to
  179. // MacSspHandleNtlmv2ChallengeMessage(). Use this function in the case where
  180. // you only want to do NTLMv2 authentication (not session security) and are
  181. // only supplied an 8 byte MSV1_0_CHALLENGE message.
  182. //
  183. // NOTE: This function reverses byte order to align with windows, so don't
  184. // attempt to access elements in the structure upon return from this function!
  185. // The return value should be passed directly to MacSspHandleNtlmv2ChallengeMessage()
  186. // without modification.
  187. //
  188. HRESULT
  189. MacSspGenerateChallengeMessage(
  190. IN CHAR pChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  191. OUT ULONG* pcbChallengeMessage,
  192. OUT CHALLENGE_MESSAGE** ppChallengeMessage
  193. )
  194. {
  195. HRESULT hResult = E_FAIL;
  196. ULONG NegotiateFlags;
  197. //
  198. //Fake the negotiate flags for what we want.
  199. //
  200. NegotiateFlags = NTLMSSP_NEGOTIATE_UNICODE |
  201. NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
  202. NTLMSSP_NEGOTIATE_NTLM2 |
  203. NTLMSSP_NEGOTIATE_128 |
  204. NTLMSSP_TARGET_TYPE_SERVER;
  205. *pcbChallengeMessage = sizeof(CHALLENGE_MESSAGE);
  206. *ppChallengeMessage = (CHALLENGE_MESSAGE*)new char[*pcbChallengeMessage];
  207. hResult = (*ppChallengeMessage) ? S_OK : E_OUTOFMEMORY;
  208. if (SUCCEEDED(hResult))
  209. {
  210. ZeroMemory(*ppChallengeMessage, *pcbChallengeMessage);
  211. StringCbCopy(
  212. (char*)(*ppChallengeMessage)->Signature,
  213. sizeof((*ppChallengeMessage)->Signature),
  214. NTLMSSP_SIGNATURE
  215. );
  216. CopyMemory(
  217. (*ppChallengeMessage)->Challenge,
  218. pChallengeToClient,
  219. MSV1_0_CHALLENGE_LENGTH
  220. );
  221. (*ppChallengeMessage)->MessageType = NtLmChallenge;
  222. (*ppChallengeMessage)->NegotiateFlags = NegotiateFlags;
  223. (*ppChallengeMessage)->TargetInfo.Buffer = *pcbChallengeMessage;
  224. (*ppChallengeMessage)->TargetName.Buffer = *pcbChallengeMessage;
  225. }
  226. //
  227. //Swap the bytes to align with windows system since we assume
  228. //here that the result will be passed directly to the above
  229. //function.
  230. //
  231. SspSwapChallengeMessageBytes(*ppChallengeMessage);
  232. return hResult;
  233. }
  234. // ---------------------------------------------------------------------------
  235. // � MacSspCalculateLmResponse()
  236. // ---------------------------------------------------------------------------
  237. // Wrapper to windows function to calculate LmResponse back to server.
  238. //
  239. BOOL
  240. MacSspCalculateLmResponse(
  241. IN PLM_CHALLENGE LmChallenge,
  242. IN PLM_OWF_PASSWORD LmOwfPassword,
  243. OUT PLM_RESPONSE LmResponse
  244. )
  245. {
  246. return CalculateLmResponse(LmChallenge, LmOwfPassword, LmResponse);
  247. }
  248. // ---------------------------------------------------------------------------
  249. // � MacSspCalculateLmOwfPassword()
  250. // ---------------------------------------------------------------------------
  251. // An LmOwf function that works on a Mac.
  252. //
  253. BOOL
  254. MacSspCalculateLmOwfPassword(
  255. IN PLM_PASSWORD LmPassword,
  256. OUT PLM_OWF_PASSWORD LmOwfPassword
  257. )
  258. {
  259. return CalculateLmOwfPassword(LmPassword, LmOwfPassword);
  260. }
  261. // ---------------------------------------------------------------------------
  262. // � MacSspEncryptBlock()
  263. // ---------------------------------------------------------------------------
  264. // Routine Description:
  265. //
  266. // Takes a block of data and encrypts it with a key producing
  267. // an encrypted block of data.
  268. //
  269. // Arguments:
  270. //
  271. // ClearBlock - The block of data that is to be encrypted.
  272. //
  273. // BlockKey - The key to use to encrypt data
  274. //
  275. // CypherBlock - Encrypted data is returned here
  276. //
  277. // Return Values:
  278. //
  279. // TRUE - The data was encrypted successfully. The encrypted
  280. // data block is in CypherBlock
  281. //
  282. // FALSE - Something failed. The CypherBlock is undefined.
  283. BOOL
  284. MacSspEncryptBlock(
  285. IN PCLEAR_BLOCK ClearBlock,
  286. IN PBLOCK_KEY BlockKey,
  287. OUT PCYPHER_BLOCK CypherBlock
  288. )
  289. {
  290. unsigned Result;
  291. Result = DES_ECB_LM(ENCR_KEY,
  292. (const char *)BlockKey,
  293. (unsigned char *)ClearBlock,
  294. (unsigned char *)CypherBlock
  295. );
  296. if (Result == CRYPT_OK) {
  297. return(TRUE);
  298. } else {
  299. return(FALSE);
  300. }
  301. }
  302. // ---------------------------------------------------------------------------
  303. // � MacSspEncryptLmOwfPwdWithLmOwfPwd()
  304. // ---------------------------------------------------------------------------
  305. // Routine Description:
  306. //
  307. // Encrypts one OwfPassword with another
  308. //
  309. // Arguments:
  310. //
  311. // DataLmOwfPassword - OwfPassword to be encrypted
  312. //
  313. // KeyLmOwfPassword - OwfPassword to be used as a key to the encryption
  314. //
  315. // EncryptedLmOwfPassword - The encrypted OwfPassword is returned here.
  316. //
  317. // Return Values:
  318. //
  319. // TRUE - The function completed successfully. The encrypted
  320. // OwfPassword is in EncryptedLmOwfPassword
  321. //
  322. // FALSE - Something failed. The EncryptedLmOwfPassword is undefined.
  323. BOOL
  324. MacSspEncryptLmOwfPwdWithLmOwfPwd(
  325. IN PLM_OWF_PASSWORD DataLmOwfPassword,
  326. IN PLM_OWF_PASSWORD KeyLmOwfPassword,
  327. OUT PENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword
  328. )
  329. {
  330. Boolean Status;
  331. PBLOCK_KEY pK;
  332. Status = MacSspEncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[0]),
  333. &(((PBLOCK_KEY)(KeyLmOwfPassword->data))[0]),
  334. &(EncryptedLmOwfPassword->data[0]));
  335. if (!Status) {
  336. return(Status);
  337. }
  338. pK = (PBLOCK_KEY)&(KeyLmOwfPassword->data[1]);
  339. //
  340. //Notice the "-1" in the second parameter, this is necessary because the
  341. //compiler aligns on an 8 byte boundary!
  342. //
  343. Status = MacSspEncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[1]),
  344. /*(PBLOCK_KEY)&(KeyLmOwfPassword->data[1]),*/ (PBLOCK_KEY)(((PUCHAR)pK)-1),
  345. &(EncryptedLmOwfPassword->data[1]));
  346. //
  347. //*****************************************
  348. //
  349. return(Status);
  350. }
  351. // ---------------------------------------------------------------------------
  352. // � MacSspEncryptNtOwfPwdWithNtOwfPwd()
  353. // ---------------------------------------------------------------------------
  354. // Routine Description:
  355. //
  356. // Encrypts one OwfPassword with another
  357. BOOL
  358. MacSspEncryptNtOwfPwdWithNtOwfPwd(
  359. IN PNT_OWF_PASSWORD DataNtOwfPassword,
  360. IN PNT_OWF_PASSWORD KeyNtOwfPassword,
  361. OUT PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword
  362. )
  363. {
  364. return( MacSspEncryptLmOwfPwdWithLmOwfPwd(
  365. (PLM_OWF_PASSWORD)DataNtOwfPassword,
  366. (PLM_OWF_PASSWORD)KeyNtOwfPassword,
  367. (PENCRYPTED_LM_OWF_PASSWORD)EncryptedNtOwfPassword));
  368. }
  369. // ---------------------------------------------------------------------------
  370. // � MacSspSampEncryptLmPasswords()
  371. // ---------------------------------------------------------------------------
  372. //Routine Description:
  373. //
  374. // Encrypts the cleartext passwords into the form that is sent over
  375. // the network. Before computing the OWF passwords, the cleartext forms
  376. // are upper cased, then OEMed (the order is significant). The cleartext
  377. // password to be sent is OEMed only.
  378. //
  379. //Arguments:
  380. //
  381. //Return Value:
  382. BOOL
  383. MacSspSampEncryptLmPasswords(
  384. LPSTR OldUpcasePassword,
  385. LPSTR NewUpcasePassword,
  386. LPSTR NewPassword,
  387. PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldLm,
  388. PENCRYPTED_NT_OWF_PASSWORD OldLmOwfEncryptedWithNewLm
  389. )
  390. {
  391. LM_OWF_PASSWORD OldLmOwfPassword;
  392. LM_OWF_PASSWORD NewLmOwfPassword;
  393. PSAMPR_USER_PASSWORD NewLm = (PSAMPR_USER_PASSWORD) NewEncryptedWithOldLm;
  394. struct RC4_KEYSTRUCT Rc4Key;
  395. Boolean Status;
  396. ZeroMemory(&Rc4Key, sizeof(RC4_KEYSTRUCT));
  397. //
  398. // Calculate the LM OWF passwords
  399. //
  400. Status = CalculateLmOwfPassword(
  401. OldUpcasePassword,
  402. &OldLmOwfPassword
  403. );
  404. if (Status)
  405. {
  406. Status = CalculateLmOwfPassword(
  407. NewUpcasePassword,
  408. &NewLmOwfPassword
  409. );
  410. }
  411. //
  412. // Calculate the encrypted old passwords
  413. //
  414. if (Status)
  415. {
  416. Status = MacSspEncryptLmOwfPwdWithLmOwfPwd(
  417. &OldLmOwfPassword,
  418. &NewLmOwfPassword,
  419. OldLmOwfEncryptedWithNewLm
  420. );
  421. }
  422. //
  423. // Calculate the encrypted new passwords
  424. //
  425. if (Status)
  426. {
  427. //
  428. // Compute the encrypted new password with LM key.
  429. //
  430. rc4_key(
  431. &Rc4Key,
  432. (DWORD)LM_OWF_PASSWORD_LENGTH,
  433. (PUCHAR)&OldLmOwfPassword
  434. );
  435. CopyMemory(
  436. ((PUCHAR) NewLm->Buffer) + (SAM_MAX_PASSWORD_LENGTH * sizeof(UInt16)) - strlen(NewPassword),
  437. NewPassword,
  438. strlen(NewPassword)
  439. );
  440. NewLm->Length = strlen(NewPassword);
  441. NewLm->Length = swaplong(NewLm->Length);
  442. rc4(&Rc4Key,
  443. sizeof(SAMPR_USER_PASSWORD),
  444. (PUCHAR) NewLm->Buffer
  445. );
  446. }
  447. return Status;
  448. }
  449. // ---------------------------------------------------------------------------
  450. // � MacSspSamiEncryptPasswords()
  451. // ---------------------------------------------------------------------------
  452. // Produces encrypted old and new passwords.
  453. //
  454. OSStatus
  455. MacSspSamiEncryptPasswords(
  456. IN PUNICODE_STRING oldPassword,
  457. IN PUNICODE_STRING newPassword,
  458. OUT PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldNt,
  459. OUT PENCRYPTED_NT_OWF_PASSWORD OldNtOwfEncryptedWithNewNt
  460. )
  461. {
  462. OSStatus Status;
  463. NT_OWF_PASSWORD OldNtOwfPassword;
  464. NT_OWF_PASSWORD NewNtOwfPassword;
  465. PSAMPR_USER_PASSWORD NewNt = (PSAMPR_USER_PASSWORD)NewEncryptedWithOldNt;
  466. struct RC4_KEYSTRUCT Rc4Key;
  467. SspDebugPrint((DBUF, "Entering MacSfpSamiEncryptPasswords()"));
  468. //
  469. //The struct must be zero filled to start.
  470. //
  471. ZeroMemory(&Rc4Key, sizeof(RC4_KEYSTRUCT));
  472. ZeroMemory(&OldNtOwfPassword, sizeof(OldNtOwfPassword));
  473. ZeroMemory(&NewNtOwfPassword, sizeof(NewNtOwfPassword));
  474. //
  475. //Calculate the NT OWF passwords.
  476. //
  477. Status = CalculateNtOwfPassword(oldPassword, &OldNtOwfPassword);
  478. if (NT_SUCCESS(Status))
  479. {
  480. Status = CalculateNtOwfPassword(newPassword, &NewNtOwfPassword);
  481. }
  482. //
  483. //Compute the encrypted old passwords.
  484. //
  485. if (NT_SUCCESS(Status))
  486. {
  487. Status = MacSspEncryptNtOwfPwdWithNtOwfPwd(
  488. &OldNtOwfPassword,
  489. &NewNtOwfPassword,
  490. OldNtOwfEncryptedWithNewNt
  491. );
  492. }
  493. //
  494. //Calculate the encrypted new passwords.
  495. //
  496. if (NT_SUCCESS(Status))
  497. {
  498. //
  499. //Compute the encrypted new password with NT key.
  500. //
  501. rc4_key(
  502. &Rc4Key,
  503. NT_OWF_PASSWORD_LENGTH,
  504. (PUCHAR)&OldNtOwfPassword
  505. );
  506. CopyMemory(
  507. ((PUCHAR)NewNt->Buffer) + SAM_MAX_PASSWORD_LENGTH * sizeof(WCHAR) - newPassword->Length,
  508. newPassword->Buffer,
  509. newPassword->Length
  510. );
  511. NewNt->Length = newPassword->Length;
  512. NewNt->Length = swaplong(NewNt->Length);
  513. }
  514. if (NT_SUCCESS(Status))
  515. {
  516. rc4(
  517. &Rc4Key,
  518. sizeof(SAMPR_USER_PASSWORD),
  519. (PUCHAR)NewEncryptedWithOldNt
  520. );
  521. }
  522. SspDebugPrint((DBUF, "Leaving MacSfpSamiEncryptPasswords()"));
  523. return(Status);
  524. }
  525. // ---------------------------------------------------------------------------
  526. // � MacSspSamiEncryptPasswordsANSI()
  527. // ---------------------------------------------------------------------------
  528. // Produces encrypted old and new passwords. This routine does not use any
  529. // of the Mac's unicode utilities, therefore, we should not use it. We need
  530. // to leave this here however for possible future use by other parties.
  531. //
  532. OSStatus
  533. MacSspSamiEncryptPasswordsANSI(
  534. IN PCSTR oldPassword,
  535. IN PCSTR newPassword,
  536. OUT PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldNt,
  537. OUT PENCRYPTED_NT_OWF_PASSWORD OldNtOwfEncryptedWithNewNt
  538. )
  539. {
  540. OSStatus Status;
  541. UNICODE_STRING uszOldPassword;
  542. UNICODE_STRING uszNewPassword;
  543. CHAR oldPasswordStorage[(UNLEN + 4) * sizeof(WCHAR)];
  544. CHAR newPasswordStorage[(UNLEN + 4) * sizeof(WCHAR)];
  545. //
  546. //Build a unicode string from the supplied ansi password with which
  547. //we'll use to build a owf password. Note that we swap the strings
  548. //to windows alignment before we calculate passwords.
  549. //
  550. uszOldPassword.Length = 0;
  551. uszOldPassword.MaximumLength = sizeof(oldPasswordStorage);
  552. uszOldPassword.Buffer = (PWSTR)oldPasswordStorage;
  553. SspInitUnicodeStringNoAlloc(oldPassword, (UNICODE_STRING*)&uszOldPassword);
  554. SspSwapUnicodeString(&uszOldPassword);
  555. uszNewPassword.Length = 0;
  556. uszNewPassword.MaximumLength = sizeof(newPasswordStorage);
  557. uszNewPassword.Buffer = (PWSTR)newPasswordStorage;
  558. SspInitUnicodeStringNoAlloc(newPassword, (UNICODE_STRING*)&uszNewPassword);
  559. SspSwapUnicodeString(&uszNewPassword);
  560. Status = MacSspSamiEncryptPasswords(
  561. &uszOldPassword,
  562. &uszNewPassword,
  563. NewEncryptedWithOldNt,
  564. OldNtOwfEncryptedWithNewNt
  565. );
  566. #if 0
  567. SspDebugPrint((DBUF, "NewEncryptedWithOldNt:"));
  568. SspDebugPrintHex(NewEncryptedWithOldNt, sizeof(SAMPR_ENCRYPTED_USER_PASSWORD));
  569. SspDebugPrint((DBUF, "OldNtOwfEncryptedWithNewNt:"));
  570. SspDebugPrintHex(OldNtOwfEncryptedWithNewNt, sizeof(ENCRYPTED_NT_OWF_PASSWORD));
  571. #endif
  572. //
  573. //03.01.02 MJC: We need to zero out the buffers
  574. //otherwise the passwords may still exist in memory.
  575. //
  576. RtlSecureZeroMemory(
  577. uszNewPassword.Buffer,
  578. uszNewPassword.Length
  579. );
  580. RtlSecureZeroMemory(
  581. uszOldPassword.Buffer,
  582. uszOldPassword.Length
  583. );
  584. return(Status);
  585. }
  586. #pragma mark-
  587. // ---------------------------------------------------------------------------
  588. // � MacSspSamiEncryptCStringPasswords()
  589. // ---------------------------------------------------------------------------
  590. // Produces encrypted old and new passwords. This is the C string variant and
  591. // uses the Mac's built in unicode utilities for converting from ASCII to
  592. // unicode strings.
  593. //
  594. OSStatus
  595. MacSspSamiEncryptCStringPasswords(
  596. IN PCSTR oldPassword,
  597. IN PCSTR newPassword,
  598. OUT PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldNt,
  599. OUT PENCRYPTED_NT_OWF_PASSWORD OldNtOwfEncryptedWithNewNt
  600. )
  601. {
  602. OSStatus Status = noErr;
  603. UNICODE_STRING uszOldPassword = {0, 0, NULL};
  604. UNICODE_STRING uszNewPassword = {0, 0, NULL};
  605. //
  606. //Put the converted unicode string into an NT style unicode
  607. //string strucuture format. Get the unicode equivelant string
  608. //of the old password.
  609. //
  610. Status = MacSspCStringToUnicode(
  611. oldPassword,
  612. &uszOldPassword.Length,
  613. &uszOldPassword.Buffer
  614. );
  615. uszOldPassword.MaximumLength = uszOldPassword.Length;
  616. if (NT_SUCCESS(Status))
  617. {
  618. Status = MacSspCStringToUnicode(
  619. newPassword,
  620. &uszNewPassword.Length,
  621. &uszNewPassword.Buffer
  622. );
  623. uszNewPassword.MaximumLength = uszNewPassword.Length;
  624. if (NT_SUCCESS(Status))
  625. {
  626. //
  627. //Swap the unicode strings so they are in Windows byte order.
  628. //
  629. SspSwapUnicodeString(&uszOldPassword);
  630. SspSwapUnicodeString(&uszNewPassword);
  631. //
  632. //Now encrypt everything...
  633. //
  634. Status = MacSspSamiEncryptPasswords(
  635. &uszOldPassword,
  636. &uszNewPassword,
  637. NewEncryptedWithOldNt,
  638. OldNtOwfEncryptedWithNewNt
  639. );
  640. //
  641. //03.01.02 MJC: We need to zero out the buffer before freeing
  642. //otherwise the password may still exist in memory.
  643. //
  644. RtlSecureZeroMemory(
  645. uszNewPassword.Buffer,
  646. uszNewPassword.Length
  647. );
  648. //
  649. //We don't need the unicode string buffer anymore.
  650. //
  651. DisposePtr((Ptr)uszNewPassword.Buffer);
  652. //
  653. //The following debug code helps a lot when debugging but is
  654. //really annoying in most cases.
  655. //
  656. #if 0
  657. SspDebugPrint((DBUF, "NewEncryptedWithOldNt:"));
  658. SspDebugPrintHex(NewEncryptedWithOldNt, sizeof(SAMPR_ENCRYPTED_USER_PASSWORD));
  659. SspDebugPrint((DBUF, "OldNtOwfEncryptedWithNewNt:"));
  660. SspDebugPrintHex(OldNtOwfEncryptedWithNewNt, sizeof(ENCRYPTED_NT_OWF_PASSWORD));
  661. #endif
  662. }
  663. //
  664. //03.01.02 MJC: We need to zero out the buffers before freeing
  665. //otherwise the password may still exist in memory.
  666. //
  667. RtlSecureZeroMemory(
  668. uszOldPassword.Buffer,
  669. uszOldPassword.Length
  670. );
  671. DisposePtr((Ptr)uszOldPassword.Buffer);
  672. }
  673. return(Status);
  674. }
  675. // ---------------------------------------------------------------------------
  676. // � MacSspSamiEncryptPStringPasswords()
  677. // ---------------------------------------------------------------------------
  678. // Produces encrypted old and new passwords. This is the P string variant and
  679. // uses the Mac's built in unicode utilities for converting from ASCII to
  680. // unicode strings.
  681. //
  682. OSStatus
  683. MacSspSamiEncryptPStringPasswords(
  684. IN Str255 oldPassword,
  685. IN Str255 newPassword,
  686. OUT PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldNt,
  687. OUT PENCRYPTED_NT_OWF_PASSWORD OldNtOwfEncryptedWithNewNt
  688. )
  689. {
  690. OSStatus Status = noErr;
  691. UNICODE_STRING uszOldPassword = {0, 0, NULL};
  692. UNICODE_STRING uszNewPassword = {0, 0, NULL};
  693. //
  694. //Put the converted unicode string into an NT style unicode
  695. //string strucuture format. Get the unicode equivelant string
  696. //of the old password.
  697. //
  698. Status = MacSspPStringToUnicode(
  699. oldPassword,
  700. &uszOldPassword.Length,
  701. &uszOldPassword.Buffer
  702. );
  703. uszOldPassword.MaximumLength = uszOldPassword.Length;
  704. if (NT_SUCCESS(Status))
  705. {
  706. Status = MacSspPStringToUnicode(
  707. newPassword,
  708. &uszNewPassword.Length,
  709. &uszNewPassword.Buffer
  710. );
  711. uszNewPassword.MaximumLength = uszNewPassword.Length;
  712. if (NT_SUCCESS(Status))
  713. {
  714. //
  715. //Swap the unicode strings so they are in Windows byte order.
  716. //
  717. SspSwapUnicodeString(&uszOldPassword);
  718. SspSwapUnicodeString(&uszNewPassword);
  719. //
  720. //Now encrypt everything...
  721. //
  722. Status = MacSspSamiEncryptPasswords(
  723. &uszOldPassword,
  724. &uszNewPassword,
  725. NewEncryptedWithOldNt,
  726. OldNtOwfEncryptedWithNewNt
  727. );
  728. //
  729. //03.01.02 MJC: We need to zero out the buffer before freeing
  730. //otherwise the password may still exist in memory.
  731. //
  732. RtlSecureZeroMemory(
  733. uszNewPassword.Buffer,
  734. uszNewPassword.Length
  735. );
  736. //
  737. //We don't need the unicode string buffer anymore.
  738. //
  739. DisposePtr((Ptr)uszNewPassword.Buffer);
  740. }
  741. //
  742. //03.01.02 MJC: We need to zero out the buffers before freeing
  743. //otherwise the password may still exist in memory.
  744. //
  745. RtlSecureZeroMemory(
  746. uszOldPassword.Buffer,
  747. uszOldPassword.Length
  748. );
  749. //
  750. //We don't need the unicode string buffer anymore.
  751. //
  752. DisposePtr((Ptr)uszOldPassword.Buffer);
  753. }
  754. return(Status);
  755. }