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.

552 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. secret.c
  5. Abstract:
  6. This module contains the code to read and write secrets from disk.
  7. Author:
  8. Adam Barr (adamba) 13-June-1997
  9. Revision History:
  10. Adam Barr (adamba) 29-December-1997
  11. Modified from private\ntos\boot\lib\blsecret.c.
  12. --*/
  13. #include <rdrssp.h>
  14. #include <rc4.h>
  15. #include <wcstr.h>
  16. #if defined(REMOTE_BOOT)
  17. #if 0
  18. VOID
  19. RdrpDumpSector(
  20. PUCHAR Sector
  21. )
  22. {
  23. int i, j;
  24. PUCHAR SectorChar = (PUCHAR)Sector;
  25. for (i = 0; i < 512; i+= 16) {
  26. for (j = 0; j < 16; j++) {
  27. DbgPrint("%2.2x ", SectorChar[i + j]);
  28. }
  29. DbgPrint(" ");
  30. for (j = 0; j < 16; j++) {
  31. if ((SectorChar[i+j] >= ' ') && (SectorChar[i+j] < '~')) {
  32. DbgPrint("%c", SectorChar[i+j]);
  33. } else {
  34. DbgPrint(".");
  35. }
  36. }
  37. DbgPrint("\n");
  38. }
  39. }
  40. #endif
  41. NTSTATUS
  42. RdrOpenRawDisk(
  43. PHANDLE Handle
  44. )
  45. /*++
  46. Routine Description:
  47. This routine opens the raw disk for read/write.
  48. Arguments:
  49. Handle - returns the Handle if successful, for use in subsequent calls.
  50. Return Value:
  51. The status return from the ZwOpenFile.
  52. --*/
  53. {
  54. NTSTATUS status;
  55. OBJECT_ATTRIBUTES objectAttributes;
  56. UNICODE_STRING physicalDriveString;
  57. IO_STATUS_BLOCK ioStatus;
  58. RtlInitUnicodeString(&physicalDriveString, L"\\Device\\Harddisk0\\Partition0");
  59. InitializeObjectAttributes(
  60. &objectAttributes,
  61. &physicalDriveString,
  62. OBJ_CASE_INSENSITIVE,
  63. NULL,
  64. NULL);
  65. status = ZwOpenFile(
  66. Handle,
  67. FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
  68. &objectAttributes,
  69. &ioStatus,
  70. FILE_SHARE_READ | FILE_SHARE_WRITE,
  71. FILE_SYNCHRONOUS_IO_NONALERT);
  72. if ((!NT_SUCCESS(status)) || (!NT_SUCCESS(ioStatus.Status))) {
  73. KdPrint(("RdrOpenRawDisk: status on ZwOpenFile: %x, %x\n", status, ioStatus.Status));
  74. if (NT_SUCCESS(status)) {
  75. status = ioStatus.Status;
  76. }
  77. }
  78. return status;
  79. }
  80. NTSTATUS
  81. RdrCloseRawDisk(
  82. HANDLE Handle
  83. )
  84. /*++
  85. Routine Description:
  86. This routine closes the raw disk.
  87. Arguments:
  88. Handle - The Handle returned by RdrOpenRawDisk.
  89. Return Value:
  90. The status return from the ZwClose.
  91. --*/
  92. {
  93. return ZwClose(Handle);
  94. }
  95. NTSTATUS
  96. RdrCheckForFreeSectors (
  97. HANDLE Handle
  98. )
  99. /*++
  100. Routine Description:
  101. This routine makes sure that the MBR looks correct and that there
  102. is nothing installed (OnTrack or EZ-Drive need to detect
  103. NT fault-tolerance also) that would prevent us from using the third
  104. sector for storing the password secret.
  105. Arguments:
  106. Handle - The Handle returned by RdrOpenRawDisk.
  107. Return Value:
  108. ESUCCESS if the disk is OK, or an error.
  109. --*/
  110. {
  111. NTSTATUS status;
  112. USHORT Sector[256];
  113. ULONG BytesRead;
  114. PPARTITION_DESCRIPTOR Partition;
  115. LARGE_INTEGER SeekPosition;
  116. IO_STATUS_BLOCK ioStatus;
  117. SeekPosition.QuadPart = 0;
  118. //
  119. // Read the MBR at the start of the disk.
  120. //
  121. status = ZwReadFile(
  122. Handle,
  123. NULL,
  124. NULL,
  125. NULL,
  126. &ioStatus,
  127. Sector,
  128. 512,
  129. &SeekPosition,
  130. NULL);
  131. if ((!NT_SUCCESS(status)) || (!NT_SUCCESS(ioStatus.Status))) {
  132. KdPrint(("RdrCheckForFreeSectors: status on ZwReadFile: %x, %x\n", status, ioStatus.Status));
  133. if (NT_SUCCESS(status)) {
  134. status = ioStatus.Status;
  135. }
  136. return status;
  137. }
  138. #if 0
  139. RdrpDumpSector((PUCHAR)Sector);
  140. #endif
  141. //
  142. // Make sure the signature is OK, and that the type of partition
  143. // 0 is not 0x54 (OnTrack) or 0x55 (EZ-Drive).
  144. //
  145. if (Sector[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) {
  146. KdPrint(("RdrCheckForFreeSectors: Boot record signature %x not found (%x found)\n",
  147. BOOT_RECORD_SIGNATURE,
  148. Sector[BOOT_SIGNATURE_OFFSET] ));
  149. return STATUS_INVALID_PARAMETER;
  150. }
  151. Partition = (PPARTITION_DESCRIPTOR)&Sector[PARTITION_TABLE_OFFSET];
  152. if ((Partition->PartitionType == 0x54) ||
  153. (Partition->PartitionType == 0x55)) {
  154. KdPrint(("RdrCheckForFreeSectors: First partition has type %x, exiting\n", Partition->PartitionType));
  155. return STATUS_INVALID_PARAMETER;
  156. }
  157. KdPrint(("RdrCheckForFreeSectors: Partition type is %d\n", Partition->PartitionType));
  158. return STATUS_SUCCESS;
  159. }
  160. NTSTATUS
  161. RdrReadSecret(
  162. HANDLE Handle,
  163. PRI_SECRET Secret
  164. )
  165. /*++
  166. Routine Description:
  167. This routine reads the secret from the disk, if present.
  168. Arguments:
  169. Handle - The Handle returned by RdrOpenRawDisk.
  170. Return Value:
  171. ESUCCESS if the secret is OK, an error otherwise.
  172. --*/
  173. {
  174. NTSTATUS status;
  175. ULONG BytesRead;
  176. LARGE_INTEGER SeekPosition;
  177. IO_STATUS_BLOCK ioStatus;
  178. UCHAR Sector[512];
  179. //
  180. // Seek to the third sector.
  181. // DEADISSUE 08/08/2000 -- this is in an #ifdef REMOTE_BOOT block,
  182. // which is dead code, left here in case it is ever resuurected:
  183. // I am pretty sure we can assume that the first disk has 512-byte sectors.
  184. //
  185. SeekPosition.QuadPart = 2 * 512;
  186. //
  187. // Read a full sector. The secret is at the beginning.
  188. //
  189. status = ZwReadFile(
  190. Handle,
  191. NULL,
  192. NULL,
  193. NULL,
  194. &ioStatus,
  195. Sector,
  196. 512,
  197. &SeekPosition,
  198. NULL);
  199. if ((!NT_SUCCESS(status)) || (!NT_SUCCESS(ioStatus.Status))) {
  200. KdPrint(("RdrReadSecret: status on ZwReadFile: %x, %x\n", status, ioStatus.Status));
  201. if (NT_SUCCESS(status)) {
  202. status = ioStatus.Status;
  203. }
  204. return status;
  205. }
  206. RtlMoveMemory(Secret, Sector, sizeof(RI_SECRET));
  207. if (memcmp(Secret->Signature, RI_SECRET_SIGNATURE, 4) != 0) {
  208. KdPrint(("RdrReadSecret: No signature found\n"));
  209. return STATUS_INVALID_PARAMETER;
  210. }
  211. return STATUS_SUCCESS;
  212. }
  213. NTSTATUS
  214. RdrWriteSecret(
  215. HANDLE Handle,
  216. PRI_SECRET Secret
  217. )
  218. /*++
  219. Routine Description:
  220. This routine writes the secret to the disk.
  221. Arguments:
  222. Handle - The Handle returned by RdrOpenRawDisk.
  223. Return Value:
  224. ESUCCESS if the secret is written OK, an error otherwise.
  225. --*/
  226. {
  227. NTSTATUS status;
  228. ULONG BytesWritten;
  229. LARGE_INTEGER SeekPosition;
  230. IO_STATUS_BLOCK ioStatus;
  231. UCHAR Sector[512];
  232. //
  233. // Seek to the third sector.
  234. //
  235. SeekPosition.QuadPart = 2 * 512;
  236. //
  237. // Copy the secret to a full sector since the raw disk requires
  238. // reads/writes in sector multiples.
  239. //
  240. RtlZeroMemory(Sector, sizeof(Sector));
  241. RtlMoveMemory(Sector, Secret, sizeof(RI_SECRET));
  242. //
  243. // Write a secret-sized chunk.
  244. //
  245. status = ZwWriteFile(
  246. Handle,
  247. NULL,
  248. NULL,
  249. NULL,
  250. &ioStatus,
  251. Sector,
  252. 512,
  253. &SeekPosition,
  254. NULL);
  255. if ((!NT_SUCCESS(status)) || (!NT_SUCCESS(ioStatus.Status))) {
  256. KdPrint(("RdrWriteSecret: status on ZwWriteFile: %x, %x\n", status, ioStatus.Status));
  257. if (NT_SUCCESS(status)) {
  258. status = ioStatus.Status;
  259. }
  260. return status;
  261. }
  262. return STATUS_SUCCESS;
  263. }
  264. VOID
  265. RdrInitializeSecret(
  266. IN PUCHAR Domain,
  267. IN PUCHAR User,
  268. IN PUCHAR LmOwfPassword1,
  269. IN PUCHAR NtOwfPassword1,
  270. IN PUCHAR LmOwfPassword2 OPTIONAL,
  271. IN PUCHAR NtOwfPassword2 OPTIONAL,
  272. IN PUCHAR Sid,
  273. IN OUT PRI_SECRET Secret
  274. )
  275. {
  276. int Length;
  277. int i;
  278. struct RC4_KEYSTRUCT Key;
  279. memset(Secret, 0, sizeof(RI_SECRET));
  280. memcpy(Secret->Signature, RI_SECRET_SIGNATURE, 4);
  281. Secret->Version = 1;
  282. Length = strlen(Domain);
  283. memcpy(Secret->Domain, Domain, Length);
  284. Length = strlen(User);
  285. memcpy(Secret->User, User, Length);
  286. memcpy(Secret->Sid, Sid, RI_SECRET_SID_SIZE);
  287. //
  288. // Encrypt the passwords using the user name.
  289. //
  290. #ifdef RDR_USE_LM_PASSWORD
  291. memcpy(Secret->LmEncryptedPassword1, LmOwfPassword1, LM_OWF_PASSWORD_SIZE);
  292. rc4_key(&Key, strlen(User), User);
  293. rc4(&Key, LM_OWF_PASSWORD_SIZE, Secret->LmEncryptedPassword1);
  294. if (LmOwfPassword2 != NULL) {
  295. memcpy(Secret->LmEncryptedPassword2, LmOwfPassword2, LM_OWF_PASSWORD_SIZE);
  296. rc4_key(&Key, strlen(User), User);
  297. rc4(&Key, LM_OWF_PASSWORD_SIZE, Secret->LmEncryptedPassword2);
  298. }
  299. #endif
  300. memcpy(Secret->NtEncryptedPassword1, NtOwfPassword1, NT_OWF_PASSWORD_SIZE);
  301. rc4_key(&Key, strlen(User), User);
  302. rc4(&Key, NT_OWF_PASSWORD_SIZE, Secret->NtEncryptedPassword1);
  303. if (NtOwfPassword2 != NULL) {
  304. memcpy(Secret->NtEncryptedPassword2, NtOwfPassword2, NT_OWF_PASSWORD_SIZE);
  305. rc4_key(&Key, strlen(User), User);
  306. rc4(&Key, NT_OWF_PASSWORD_SIZE, Secret->NtEncryptedPassword2);
  307. }
  308. }
  309. #endif // defined(REMOTE_BOOT)
  310. VOID
  311. RdrParseSecret(
  312. IN OUT PUCHAR Domain,
  313. IN OUT PUCHAR User,
  314. IN OUT PUCHAR LmOwfPassword1,
  315. IN OUT PUCHAR NtOwfPassword1,
  316. #if defined(REMOTE_BOOT)
  317. IN OUT PUCHAR LmOwfPassword2,
  318. IN OUT PUCHAR NtOwfPassword2,
  319. #endif // defined(REMOTE_BOOT)
  320. IN OUT PUCHAR Sid,
  321. IN PRI_SECRET Secret
  322. )
  323. {
  324. struct RC4_KEYSTRUCT Key;
  325. memcpy(Domain, Secret->Domain, RI_SECRET_DOMAIN_SIZE);
  326. Domain[RI_SECRET_DOMAIN_SIZE] = '\0';
  327. memcpy(User, Secret->User, RI_SECRET_USER_SIZE);
  328. User[RI_SECRET_USER_SIZE] = '\0';
  329. memcpy(Sid, Secret->Sid, RI_SECRET_SID_SIZE);
  330. //
  331. // Decrypt the passwords using the user name.
  332. //
  333. #ifdef RDR_USE_LM_PASSWORD
  334. memcpy(LmOwfPassword1, Secret->LmEncryptedPassword1, LM_OWF_PASSWORD_SIZE);
  335. rc4_key(&Key, strlen(User), User);
  336. rc4(&Key, LM_OWF_PASSWORD_SIZE, LmOwfPassword1);
  337. #if defined(REMOTE_BOOT)
  338. memcpy(LmOwfPassword2, Secret->LmEncryptedPassword2, LM_OWF_PASSWORD_SIZE);
  339. rc4_key(&Key, strlen(User), User);
  340. rc4(&Key, LM_OWF_PASSWORD_SIZE, LmOwfPassword2);
  341. #endif // defined(REMOTE_BOOT)
  342. #else
  343. memset(LmOwfPassword1, 0, LM_OWF_PASSWORD_SIZE);
  344. #if defined(REMOTE_BOOT)
  345. memset(LmOwfPassword2, 0, LM_OWF_PASSWORD_SIZE);
  346. #endif // defined(REMOTE_BOOT)
  347. #endif
  348. memcpy(NtOwfPassword1, Secret->NtEncryptedPassword1, NT_OWF_PASSWORD_SIZE);
  349. rc4_key(&Key, strlen(User), User);
  350. rc4(&Key, NT_OWF_PASSWORD_SIZE, NtOwfPassword1);
  351. #if defined(REMOTE_BOOT)
  352. memcpy(NtOwfPassword2, Secret->NtEncryptedPassword2, NT_OWF_PASSWORD_SIZE);
  353. rc4_key(&Key, strlen(User), User);
  354. rc4(&Key, NT_OWF_PASSWORD_SIZE, NtOwfPassword2);
  355. #endif // defined(REMOTE_BOOT)
  356. }
  357. #if defined(REMOTE_BOOT)
  358. VOID
  359. RdrOwfPassword(
  360. IN PUNICODE_STRING Password,
  361. IN OUT PUCHAR LmOwfPassword,
  362. IN OUT PUCHAR NtOwfPassword
  363. )
  364. {
  365. char TmpText[CLEAR_BLOCK_LENGTH*2];
  366. char TmpChar;
  367. int Length;
  368. int i;
  369. #ifdef RDR_USE_LM_PASSWORD
  370. Length = Password.Length / sizeof(WCHAR);
  371. //
  372. // Convert the password to an upper-case ANSI buffer.
  373. //
  374. if (Length == 0) {
  375. TmpText[0] = '\0';
  376. } else {
  377. for (i = 0; i <= Length; i++) {
  378. wctomb(&TmpChar, Password.Buffer[i]);
  379. TmpText[i] = toupper(TmpChar);
  380. }
  381. }
  382. RtlCalculateLmOwfPassword((PLM_PASSWORD)TmpText, (PLM_OWF_PASSWORD)LmOwfPassword);
  383. #else
  384. memset(LmOwfPassword, 0, LM_OWF_PASSWORD_SIZE);
  385. #endif
  386. RtlCalculateNtOwfPassword(Password, (PNT_OWF_PASSWORD)NtOwfPassword);
  387. RtlSecureZeroMemory(TmpText, sizeof(TmpText));
  388. }
  389. #endif // defined(REMOTE_BOOT)