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.

859 lines
21 KiB

  1. /*++
  2. Copyright (C) 1995-96 Microsoft Corporation
  3. Module Name:
  4. certify.cxx
  5. Abstract:
  6. This is the command line tool to manipulate certificates on an executable image.
  7. Author: Robert Reichel (robertre) Feb 12, 1996
  8. Revision History:
  9. --*/
  10. //#define UNICODE 1
  11. //#define _UNICODE 1
  12. #include <windows.h>
  13. #include <imagehlp.h>
  14. #include <stdio.h>
  15. #include <malloc.h>
  16. //
  17. // Private prototypes
  18. //
  19. LPWIN_CERTIFICATE
  20. GetCertFromImage(
  21. LPCTSTR ImageName,
  22. DWORD Index
  23. );
  24. SaveCertificate(
  25. LPCTSTR OutputFileName,
  26. LPCTSTR ImageName,
  27. DWORD CertIndex
  28. );
  29. BOOL
  30. RemoveCertificateFromImage(
  31. LPCTSTR ImageName,
  32. DWORD Index
  33. );
  34. BOOL
  35. AddCertificateToImage(
  36. LPCTSTR ImageName,
  37. LPCTSTR CertificateName,
  38. WORD CertificateType,
  39. PDWORD Index
  40. );
  41. VOID
  42. PrintCertificate(
  43. LPWIN_CERTIFICATE Certificate,
  44. DWORD Index
  45. );
  46. BOOL
  47. GetCertHeaderFromImage(
  48. IN LPCTSTR ImageName,
  49. IN DWORD Index,
  50. OUT LPWIN_CERTIFICATE CertificateHeader
  51. );
  52. #define TYPE_X509 TEXT("X509")
  53. #define TYPE_PKCS7 TEXT("PKCS7")
  54. #define TYPE_UNKNOWN TEXT("Unknown")
  55. //
  56. // Globals
  57. //
  58. BOOL fVerbose = FALSE;
  59. void
  60. PrintUsage(
  61. VOID
  62. )
  63. {
  64. fputs("Usage: PESIGMGR [switches] image-name \n"
  65. " [-?] display this message\n"
  66. " [-l] list the certificates in an image\n"
  67. " [-a:<Filename>] add a certificate file to an image\n"
  68. " [-r:<index>] remove certificate <index> from an image\n"
  69. " [-s:<Filename>] used with -r to save the removed certificate\n"
  70. " [-t:<CertType>] used with -a to specify the type of the certificate\n"
  71. " where CertType may be X509 or PKCS7 [default is X509]\n",
  72. stderr
  73. );
  74. exit(-1);
  75. }
  76. #if 0
  77. PWSTR
  78. GetArgAsUnicode(
  79. LPSTR s
  80. )
  81. {
  82. ULONG n;
  83. PWSTR ps;
  84. n = strlen( s );
  85. ps = (PWSTR)HeapAlloc( GetProcessHeap(),
  86. 0,
  87. (n + 1) * sizeof( WCHAR )
  88. );
  89. if (ps == NULL) {
  90. printf( "Out of memory\n" );
  91. }
  92. if (MultiByteToWideChar( CP_ACP,
  93. MB_PRECOMPOSED,
  94. s,
  95. n,
  96. ps,
  97. n
  98. ) != (LONG)n
  99. ) {
  100. printf( "Unable to convert parameter '%s' to Unicode (%u)", (ULONG)s, GetLastError() );
  101. }
  102. ps[ n ] = UNICODE_NULL;
  103. return ps;
  104. }
  105. #endif
  106. int __cdecl
  107. main(
  108. int argc,
  109. char *argv[],
  110. char *envp[]
  111. )
  112. {
  113. BOOL AFlagSeen = FALSE;
  114. BOOL LFlagSeen = FALSE;
  115. BOOL RFlagSeen = FALSE;
  116. BOOL SFlagSeen = FALSE;
  117. BOOL TFlagSeen = FALSE;
  118. BOOL Result;
  119. DWORD Index;
  120. DWORD RFlag_CertIndex;
  121. WORD CertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA; // default
  122. char * CertificateName;
  123. char * ImageName = NULL;
  124. char * SFlag_CertificateFile;
  125. char c, *p;
  126. if (argc < 2) {
  127. PrintUsage();
  128. }
  129. while (--argc) {
  130. p = *++argv;
  131. if (*p == '/' || *p == '-') {
  132. c = *++p;
  133. switch (toupper( c )) {
  134. case '?':
  135. PrintUsage();
  136. break;
  137. case 'A': // Add Certificate to image
  138. c = *++p;
  139. if (c != ':') {
  140. PrintUsage();
  141. } else {
  142. if (AFlagSeen == TRUE) {
  143. PrintUsage();
  144. return( 0 );
  145. }
  146. AFlagSeen = TRUE;
  147. CertificateName = ++p;
  148. }
  149. break;
  150. case 'V':
  151. {
  152. fVerbose = TRUE;
  153. break;
  154. }
  155. case 'T':
  156. {
  157. //
  158. // Specify the Type of the certificate
  159. //
  160. c = *++p;
  161. if (c != ':') {
  162. PrintUsage();
  163. } else {
  164. if (TFlagSeen == TRUE) {
  165. PrintUsage();
  166. return( 0 );
  167. }
  168. TFlagSeen = TRUE;
  169. ++p;
  170. if (_stricmp(p, TYPE_X509) == 0) {
  171. CertificateType = WIN_CERT_TYPE_X509;
  172. if (fVerbose) {
  173. printf("Certificate type = X509\n");
  174. }
  175. } else {
  176. if (_stricmp(p, TYPE_PKCS7) == 0) {
  177. CertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
  178. if (fVerbose) {
  179. printf("Certificate type = PKCS7\n");
  180. }
  181. } else {
  182. if (fVerbose) {
  183. printf("Unrecognized Certificate type %s\n",p);
  184. }
  185. PrintUsage();
  186. return (0);
  187. }
  188. }
  189. }
  190. break;
  191. }
  192. case 'L': // List the certificates in an image.
  193. {
  194. if (LFlagSeen == TRUE) {
  195. PrintUsage();
  196. return( 0 );
  197. }
  198. LFlagSeen = TRUE;
  199. break;
  200. }
  201. case 'R': // Remove certificate from an image
  202. {
  203. c = *++p;
  204. if (c != ':') {
  205. PrintUsage();
  206. } else {
  207. if (RFlagSeen == TRUE) {
  208. PrintUsage();
  209. return( 0 );
  210. }
  211. RFlagSeen = TRUE;
  212. //
  213. // Save the index
  214. //
  215. RFlag_CertIndex = atoi(++p);
  216. }
  217. break;
  218. }
  219. case 'G':
  220. c = *++p;
  221. if (c != ':') {
  222. PrintUsage();
  223. } else {
  224. // Generate a certificate from an image.
  225. }
  226. break;
  227. case 'S': // Save the certificate
  228. c = *++p;
  229. if (c != ':') {
  230. PrintUsage();
  231. } else {
  232. if (SFlagSeen == TRUE) {
  233. PrintUsage();
  234. return( 0 );
  235. }
  236. SFlagSeen = TRUE;
  237. //
  238. // Save the name of the file to put the cert into.
  239. //
  240. SFlag_CertificateFile = ++p;
  241. }
  242. break;
  243. default:
  244. fprintf( stderr, "CERTIFY: Invalid switch - /%c\n", c );
  245. PrintUsage();
  246. break;
  247. }
  248. } else {
  249. //
  250. // Should only be a single image name here
  251. //
  252. if (ImageName != NULL) {
  253. PrintUsage();
  254. return( 0 );
  255. }
  256. ImageName = *argv;
  257. }
  258. }
  259. //
  260. // Finished processing parameters, let's do the work.
  261. //
  262. if (ImageName == NULL) {
  263. if (fVerbose) {
  264. printf("Image name not specified\n");
  265. }
  266. PrintUsage();
  267. return(0);
  268. }
  269. if (LFlagSeen) {
  270. int Index = 0;
  271. WIN_CERTIFICATE Certificate;
  272. if (SFlagSeen || RFlagSeen || AFlagSeen) {
  273. PrintUsage();
  274. return(0);
  275. }
  276. do {
  277. Result = GetCertHeaderFromImage( ImageName, Index, &Certificate );
  278. if (Result) {
  279. PrintCertificate( &Certificate, Index );
  280. }
  281. Index++;
  282. } while ( Result );
  283. return( 1 );
  284. }
  285. if (AFlagSeen) {
  286. //
  287. // 'A' is not used in conjunction with R or S
  288. //
  289. if (SFlagSeen || RFlagSeen) {
  290. PrintUsage();
  291. return( 0 );
  292. }
  293. Result = AddCertificateToImage(
  294. ImageName,
  295. CertificateName,
  296. CertificateType,
  297. &Index
  298. );
  299. if (Result) {
  300. if (fVerbose){
  301. printf("Certificate %d added\n",Index);
  302. }
  303. return( 1 );
  304. } else {
  305. if (fVerbose) {
  306. printf("Unable to add Certificate to %s, error = %d\n",ImageName,GetLastError());
  307. }
  308. return( 0 );
  309. }
  310. }
  311. if (RFlagSeen) {
  312. if (!SFlagSeen) {
  313. if (fVerbose) {
  314. fputs("-R requires -S\n",stderr);
  315. }
  316. PrintUsage();
  317. return(0);
  318. }
  319. //
  320. // Make sure we can save the certificate data before
  321. // we remove it from the image
  322. //
  323. Result = SaveCertificate(
  324. SFlag_CertificateFile,
  325. ImageName,
  326. RFlag_CertIndex
  327. );
  328. if (!Result) {
  329. if (fVerbose) {
  330. printf("Unable to save certificate to file %s, error = %d\n",SFlag_CertificateFile,GetLastError());
  331. }
  332. return(0);
  333. }
  334. //
  335. // Now that the certificate is safe, remove it from the image
  336. //
  337. Result = RemoveCertificateFromImage(
  338. ImageName,
  339. RFlag_CertIndex
  340. );
  341. if (!Result) {
  342. if (fVerbose) {
  343. printf("Unable to remove certificate, error = %d\n",GetLastError());
  344. }
  345. return(0);
  346. }
  347. }
  348. if (SFlagSeen && !RFlagSeen) {
  349. PrintUsage();
  350. return( 0 );
  351. }
  352. return 0;
  353. }
  354. VOID
  355. PrintCertificate(
  356. LPWIN_CERTIFICATE Certificate,
  357. DWORD Index
  358. )
  359. {
  360. char * CertType;
  361. switch (Certificate->wCertificateType) {
  362. case WIN_CERT_TYPE_X509:
  363. {
  364. CertType = TYPE_X509;
  365. break;
  366. }
  367. case WIN_CERT_TYPE_PKCS_SIGNED_DATA:
  368. {
  369. CertType = TYPE_PKCS7;
  370. break;
  371. }
  372. default:
  373. {
  374. CertType = TYPE_UNKNOWN;
  375. break;
  376. }
  377. }
  378. printf("\nCertificate %3d Revision %1d Type %8s",Index,Certificate->wRevision, CertType);
  379. return;
  380. }
  381. BOOL
  382. AddCertificateToImage(
  383. IN LPCTSTR ImageName,
  384. IN LPCTSTR CertificateName,
  385. IN WORD CertificateType,
  386. OUT PDWORD Index
  387. )
  388. /*++
  389. Routine Description:
  390. Adds a certificate to an image, and returns its index.
  391. Arguments:
  392. ImageName - Provides the full name and path to the image to be
  393. modified.
  394. CertificateName - Provides the full name and path to a file containing
  395. the certificate to be added to the image.
  396. CertificateType - Provides the type of the certificate being added.
  397. This type will be placed in the dwType field of the resulting
  398. WIN_CERTIFICATE structure.
  399. Index - Returns the index of the certificate after it is placed in the
  400. image.
  401. Return Value:
  402. TRUE on success, FALSE on failure. More information is available via
  403. GetLastError().
  404. --*/
  405. {
  406. HANDLE CertificateHandle;
  407. DWORD CertificateFileSize;
  408. DWORD CertificateSize;
  409. LPWIN_CERTIFICATE Certificate = NULL;
  410. BOOL Result = FALSE;
  411. HANDLE ImageHandle;
  412. DWORD BytesRead;
  413. //
  414. // Attempt to open the certificate file
  415. //
  416. if ((CertificateHandle = CreateFile(CertificateName,
  417. GENERIC_READ,
  418. 0,
  419. 0,
  420. OPEN_EXISTING,
  421. FILE_ATTRIBUTE_NORMAL,
  422. NULL)) == INVALID_HANDLE_VALUE)
  423. {
  424. if (fVerbose) {
  425. printf("Unable to open %s, error = %d\n",CertificateName,GetLastError());
  426. }
  427. goto ErrorReturn;
  428. }
  429. //
  430. // Read the certificate data into memory
  431. //
  432. CertificateFileSize = GetFileSize( CertificateHandle, NULL );
  433. CertificateSize = CertificateFileSize + (sizeof( WIN_CERTIFICATE ) - sizeof( BYTE ));
  434. //
  435. // Hack to make certs 8 byte aligned
  436. //
  437. // CertificateSize += (8 - (CertificateSize % 8));
  438. Certificate = (LPWIN_CERTIFICATE)malloc( CertificateSize );
  439. if (NULL == Certificate) {
  440. if (fVerbose) {
  441. printf("malloc failed\n");
  442. }
  443. goto ErrorReturn;
  444. }
  445. Certificate->dwLength = CertificateSize;
  446. Certificate->wRevision = WIN_CERT_REVISION_1_0;
  447. Certificate->wCertificateType = CertificateType;
  448. Result = ReadFile( CertificateHandle,
  449. &Certificate->bCertificate,
  450. CertificateFileSize,
  451. &BytesRead,
  452. NULL // Overlapped
  453. );
  454. if (!Result) {
  455. if (fVerbose) {
  456. printf("Unable to read Certificate file, error = %d\n",GetLastError());
  457. }
  458. goto ErrorReturn;
  459. }
  460. ImageHandle = CreateFile( ImageName,
  461. GENERIC_READ | GENERIC_WRITE,
  462. 0,
  463. 0,
  464. OPEN_EXISTING,
  465. FILE_ATTRIBUTE_NORMAL,
  466. NULL
  467. );
  468. if (ImageHandle == INVALID_HANDLE_VALUE) {
  469. if (fVerbose) {
  470. printf("Unable to open image file %s, error = %d\n",ImageName,GetLastError());
  471. }
  472. goto ErrorReturn;
  473. }
  474. Result = ImageAddCertificate( ImageHandle,
  475. Certificate,
  476. Index
  477. );
  478. if (!Result) {
  479. if (fVerbose) {
  480. printf("ImageAddCertificate failed, error = %d\n",GetLastError());
  481. }
  482. goto ErrorReturn;
  483. }
  484. CommonReturn:
  485. if (Certificate)
  486. free(Certificate);
  487. return( Result );
  488. ErrorReturn:
  489. Result = FALSE;
  490. goto CommonReturn;
  491. }
  492. BOOL
  493. GetCertHeaderFromImage(
  494. IN LPCTSTR ImageName,
  495. IN DWORD Index,
  496. OUT LPWIN_CERTIFICATE CertificateHeader
  497. )
  498. {
  499. HANDLE ImageHandle;
  500. BOOL Result;
  501. ImageHandle = CreateFile( ImageName,
  502. GENERIC_READ | GENERIC_WRITE,
  503. 0,
  504. 0,
  505. OPEN_EXISTING,
  506. FILE_ATTRIBUTE_NORMAL,
  507. NULL
  508. );
  509. if (ImageHandle == INVALID_HANDLE_VALUE) {
  510. if (fVerbose) {
  511. printf("Unable to open image file %s\n",ImageName);
  512. }
  513. return( FALSE );
  514. }
  515. Result = ImageGetCertificateHeader(
  516. ImageHandle,
  517. Index,
  518. CertificateHeader
  519. );
  520. CloseHandle( ImageHandle );
  521. if (!Result) {
  522. if (fVerbose) {
  523. printf("\nUnable to retrieve certificate header from %s, index=%d, error = %d\n",ImageName,Index,GetLastError());
  524. }
  525. return( FALSE );
  526. }
  527. return( TRUE );
  528. }
  529. LPWIN_CERTIFICATE
  530. GetCertFromImage(
  531. IN LPCTSTR ImageName,
  532. IN DWORD Index
  533. )
  534. /*++
  535. Routine Description:
  536. Returns a copy of the specified certificate.
  537. Arguments:
  538. ImageName - Provides the full path to the image file containing the
  539. certificate.
  540. Index - Provides the index of the desired certificate in the image.
  541. Return Value:
  542. NULL on failure.
  543. On Success, returns a pointer to a filled in WIN_CERTIFICATE
  544. structure, which may be freed by called free().
  545. --*/
  546. {
  547. HANDLE ImageHandle;
  548. LPWIN_CERTIFICATE Certificate;
  549. DWORD RequiredLength = 0;
  550. BOOL Result;
  551. ImageHandle = CreateFile( ImageName,
  552. GENERIC_READ | GENERIC_WRITE,
  553. 0,
  554. 0,
  555. OPEN_EXISTING,
  556. FILE_ATTRIBUTE_NORMAL,
  557. NULL
  558. );
  559. if (ImageHandle == INVALID_HANDLE_VALUE) {
  560. if (fVerbose) {
  561. printf("Unable to open image file %s\n",ImageName);
  562. }
  563. return( NULL );
  564. }
  565. Result = ImageGetCertificateData(
  566. ImageHandle,
  567. Index,
  568. NULL,
  569. &RequiredLength
  570. );
  571. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  572. if (fVerbose) {
  573. printf("Unable to retrieve certificate data from %s, error = %d\n",ImageName,GetLastError());
  574. }
  575. return(NULL);
  576. }
  577. Certificate = (LPWIN_CERTIFICATE) malloc( RequiredLength );
  578. if (Certificate == NULL) {
  579. if (fVerbose) {
  580. printf("Out of memory in GetCertFromImage\n");
  581. }
  582. return( NULL );
  583. }
  584. Result = ImageGetCertificateData(
  585. ImageHandle,
  586. Index,
  587. Certificate,
  588. &RequiredLength
  589. );
  590. CloseHandle( ImageHandle );
  591. if (!Result) {
  592. if (fVerbose) {
  593. printf("Unable to retrieve certificate from %s, error = %d\n",ImageName,GetLastError());
  594. }
  595. return( NULL );
  596. }
  597. return( Certificate );
  598. }
  599. BOOL
  600. RemoveCertificateFromImage(
  601. LPCTSTR ImageName,
  602. DWORD Index
  603. )
  604. {
  605. HANDLE ImageHandle;
  606. BOOL Result;
  607. if (fVerbose) {
  608. printf("Removing certificate index %d from %s\n",Index,ImageName);
  609. }
  610. ImageHandle = CreateFile( ImageName,
  611. GENERIC_READ | GENERIC_WRITE,
  612. 0,
  613. 0,
  614. OPEN_EXISTING,
  615. FILE_ATTRIBUTE_NORMAL,
  616. NULL
  617. );
  618. if (ImageHandle == INVALID_HANDLE_VALUE) {
  619. printf("Unable to open image file %s\n",ImageName);
  620. return( FALSE );
  621. }
  622. Result = ImageRemoveCertificate(
  623. ImageHandle,
  624. Index
  625. );
  626. if (!Result) {
  627. printf("Unable to remove certificate from %s, error = %d\n",ImageName,GetLastError());
  628. return( FALSE );
  629. }
  630. CloseHandle( ImageHandle );
  631. return( TRUE );
  632. }
  633. BOOL
  634. SaveCertificate(
  635. LPCTSTR OutputFileName,
  636. LPCTSTR ImageName,
  637. DWORD CertIndex
  638. )
  639. {
  640. DWORD Length;
  641. BOOL Result;
  642. DWORD BytesWritten = 0;
  643. LPWIN_CERTIFICATE Certificate;
  644. HANDLE CertificateHandle;
  645. Certificate = GetCertFromImage( ImageName, CertIndex );
  646. if (Certificate == NULL) {
  647. if (fVerbose) {
  648. printf("Unable to retrieve certificate from %s, error = %d\n",ImageName,GetLastError());
  649. }
  650. return( FALSE );
  651. }
  652. Length = Certificate->dwLength - sizeof( WIN_CERTIFICATE ) + sizeof( BYTE );
  653. //
  654. // Attempt to open the certificate file
  655. //
  656. if ((CertificateHandle = CreateFile(OutputFileName,
  657. GENERIC_WRITE,
  658. 0,
  659. 0,
  660. CREATE_ALWAYS,
  661. FILE_ATTRIBUTE_NORMAL,
  662. NULL)) == INVALID_HANDLE_VALUE)
  663. {
  664. printf("Unable to create %s, error = %d\n",OutputFileName,GetLastError());
  665. return( FALSE );
  666. }
  667. Result = WriteFile( CertificateHandle,
  668. &Certificate->bCertificate,
  669. Length,
  670. &BytesWritten,
  671. NULL // Overlapped
  672. );
  673. if (!Result) {
  674. printf("Unable to save certificate to file %s, error = %d\n",OutputFileName,GetLastError());
  675. return( FALSE );
  676. }
  677. CloseHandle( CertificateHandle );
  678. free( Certificate );
  679. return( TRUE );
  680. }