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.

416 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: dumpcert.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "precomp.hxx"
  11. #include <wincrypt.h>
  12. #include <rpcssl.h>
  13. #if 0
  14. stuff clobbered by Unicode -> ANSI port:
  15. wchar_t -> char
  16. WCHAR -> char
  17. L"" -> ""
  18. %S -> %s
  19. W suffix-> A suffix
  20. wcscmp -> strcmp
  21. wmain -> main
  22. LPWSTR -> LPSTR
  23. #endif
  24. #define ByteSwapShort(Value) \
  25. Value = ( (((Value) & 0x00FF) << 8) \
  26. | (((Value) & 0xFF00) >> 8))
  27. #define INITIAL_NAME_LENGTH 100
  28. #define MSSTD_PREFIX_LENGTH 6
  29. const char MSSTD_PREFIX[] = "msstd:";
  30. #define FULLPATH_PREFIX_LENGTH 8
  31. const char FULLPATH_PREFIX[] = "fullsic:";
  32. //------------------------------------------------------------------------
  33. void DumpCertInfo( PCERT_INFO Info );
  34. void RecordErrorAndExit( char * Action, unsigned long Error );
  35. extern "C"
  36. {
  37. int __cdecl
  38. main( int argc,
  39. char * argv[],
  40. char * envp[]
  41. );
  42. }
  43. int __cdecl
  44. main( int argc,
  45. char * argv[],
  46. char * envp[]
  47. )
  48. {
  49. HCERTSTORE Store;
  50. PCCERT_CONTEXT Context = 0;
  51. unsigned Criterion = CERT_FIND_ANY;
  52. void * SearchData = 0;
  53. char * StoreName = "My";
  54. int i;
  55. char * MatchString = 0;
  56. BOOL fMatch = FALSE;
  57. BOOL fOutput = FALSE;
  58. unsigned long OutputFlags = 0;
  59. DWORD StoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  60. for (i=1; i < argc; ++i)
  61. {
  62. if (0 == strcmp(argv[i], "-subject"))
  63. {
  64. Criterion = CERT_FIND_SUBJECT_STR_W;
  65. ++i;
  66. if (i >= argc)
  67. {
  68. printf("-subject must be followed by a subject name or substring\n");
  69. return 1;
  70. }
  71. SearchData = argv[i];
  72. }
  73. else if (0 == strcmp(argv[i], "-issuer"))
  74. {
  75. Criterion = CERT_FIND_ISSUER_STR_W;
  76. ++i;
  77. if (i >= argc)
  78. {
  79. printf("-issuer must be followed by an issuer name or substring\n");
  80. return 1;
  81. }
  82. SearchData = argv[i];
  83. }
  84. else if (0 == strcmp(argv[i], "-store"))
  85. {
  86. ++i;
  87. if (i >= argc)
  88. {
  89. printf("-store must be followed by a store name, such as 'Root' or 'My'\n");
  90. return 1;
  91. }
  92. StoreName = argv[i];
  93. }
  94. else if (0 == strcmp(argv[i], "-location"))
  95. {
  96. ++i;
  97. if (i >= argc)
  98. {
  99. printf("-location must be followed by 'USER:' or by 'HKLM'\n");
  100. return 1;
  101. }
  102. if (0 == strcmp(argv[i], "USER:"))
  103. {
  104. StoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  105. }
  106. else if (0 == strcmp(argv[i], "HKLM"))
  107. {
  108. StoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  109. }
  110. else
  111. {
  112. printf("-location must be followed by 'USER:' or by 'HKLM'\n");
  113. return 1;
  114. }
  115. }
  116. else if (0 == strcmp(argv[i], "-output"))
  117. {
  118. fOutput = TRUE;
  119. ++i;
  120. if(i >= argc)
  121. {
  122. printf("-output must be followed by 'msstd' or by 'fullsic'\n");
  123. return 1;
  124. }
  125. if (0 == strcmp(argv[i], "fullsic"))
  126. {
  127. OutputFlags = RPC_C_FULL_CERT_CHAIN;
  128. }
  129. else if (0 == strcmp(argv[i], "msstd"))
  130. {
  131. OutputFlags = 0;
  132. }
  133. else
  134. {
  135. printf("-output must be followed by 'msstd' or by 'fullsic'\n");
  136. return 1;
  137. }
  138. }
  139. else if (0 == strcmp(argv[i], "-match"))
  140. {
  141. fMatch = TRUE;
  142. ++i;
  143. if(i >= argc)
  144. {
  145. printf("-match must be followed by '@filename', listing the name of the file containing the match string\n");
  146. return 1;
  147. }
  148. if (argv[i][0] == '@')
  149. {
  150. DWORD BytesRead;
  151. HANDLE hMatchFile;
  152. hMatchFile = CreateFileA( argv[i]+1,
  153. GENERIC_READ,
  154. FILE_SHARE_READ,
  155. 0, // no security
  156. OPEN_EXISTING, // must already exist
  157. FILE_ATTRIBUTE_NORMAL,
  158. NULL // no template file
  159. );
  160. if (hMatchFile == ULongToHandle(0xffffffff))
  161. {
  162. printf("can't open file %s\n", argv[i]+1);
  163. return 1;
  164. }
  165. DWORD Size = GetFileSize( hMatchFile, 0);
  166. if (Size == 0xffffffff)
  167. {
  168. printf("GetFileSize failed with 0x%x\n", GetLastError());
  169. return 1;
  170. }
  171. if (Size % 2)
  172. {
  173. printf("the match-string file must be in Unicode.\n");
  174. return 1;
  175. }
  176. MatchString = new char[ Size/sizeof(char) + sizeof(char) ];
  177. if (!MatchString)
  178. {
  179. printf("can't allocate memory\n");
  180. return 1;
  181. }
  182. if (!ReadFile( hMatchFile,
  183. MatchString,
  184. Size,
  185. &BytesRead,
  186. 0 // not overlapped
  187. )
  188. || BytesRead != Size)
  189. {
  190. printf("can't read file data: 0x%x\n", GetLastError());
  191. return 1;
  192. }
  193. MatchString[ Size/sizeof(char) ] = 0;
  194. if (MatchString[0] == 0xfeff)
  195. {
  196. ++MatchString;
  197. }
  198. else if (MatchString[0] == 0xfffe)
  199. {
  200. char * pc;
  201. for (pc = MatchString; *pc; ++pc)
  202. {
  203. ByteSwapShort(*pc);
  204. }
  205. ++MatchString;
  206. }
  207. }
  208. else
  209. {
  210. MatchString = argv[i];
  211. }
  212. printf("string to match is '%s'\n", MatchString);
  213. }
  214. else if (0 == strcmp(argv[i], "-?") ||
  215. 0 == strcmp(argv[i], "-help"))
  216. {
  217. printf("usage:\n"
  218. " dumpcert \n"
  219. " [-subject subject-substring]\n"
  220. " [-issuer issuer-substring]\n"
  221. " [-store store-name]\n"
  222. " [-output ('fullsic' | 'msstd')\n"
  223. " [-location ('HKLM' | 'USER:')\n"
  224. " [-match @filename]\n"
  225. );
  226. return 1;
  227. }
  228. else
  229. {
  230. printf("unknown option '%s'\n", argv[i]);
  231. return 1;
  232. }
  233. }
  234. Store = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  235. 0,
  236. 0,
  237. StoreFlags,
  238. StoreName
  239. );
  240. if (!Store)
  241. {
  242. RecordErrorAndExit("opening the store", GetLastError());
  243. }
  244. for(;;)
  245. {
  246. Context = CertFindCertificateInStore( Store,
  247. X509_ASN_ENCODING,
  248. 0,
  249. Criterion,
  250. SearchData,
  251. Context
  252. );
  253. if (!Context)
  254. {
  255. break;
  256. }
  257. DumpCertInfo( Context->pCertInfo );
  258. if (fOutput)
  259. {
  260. unsigned char * OutputBuffer = 0;
  261. DWORD Status = RpcCertGeneratePrincipalNameA( Context, OutputFlags, &OutputBuffer );
  262. if (Status)
  263. {
  264. printf("GeneratePrincName returned %d = 0x%x\n", Status, Status);
  265. }
  266. else
  267. {
  268. printf(" generated name = '%s'\n", OutputBuffer);
  269. }
  270. }
  271. if (fMatch)
  272. {
  273. printf("matching is not implemented because RpcCertMatchPrincipalName is not exported\n");
  274. #if 0
  275. DWORD Status = RpcCertMatchPrincipalName( Context, MatchString );
  276. if (Status)
  277. {
  278. printf("MatchPrincipalName returned %d = 0x%x\n", Status, Status);
  279. }
  280. else
  281. {
  282. printf("The names matched.\n");
  283. }
  284. #endif
  285. }
  286. }
  287. if (GetLastError() != CRYPT_E_NOT_FOUND)
  288. {
  289. RecordErrorAndExit("getting certificates", GetLastError());
  290. }
  291. return 0;
  292. }
  293. void DumpCertInfo( PCERT_INFO Info )
  294. {
  295. SYSTEMTIME NotBeforeTime;
  296. SYSTEMTIME NotAfterTime;
  297. char SubjectName[1000];
  298. char IssuerName[1000];
  299. if (!FileTimeToSystemTime( &Info->NotBefore, &NotBeforeTime ))
  300. {
  301. RecordErrorAndExit("translating not-before time", GetLastError());
  302. }
  303. if (!FileTimeToSystemTime( &Info->NotAfter, &NotAfterTime ))
  304. {
  305. RecordErrorAndExit("translating not-after time", GetLastError());
  306. }
  307. if (!CertNameToStrA( X509_ASN_ENCODING,
  308. &Info->Subject,
  309. CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
  310. SubjectName,
  311. sizeof(SubjectName)
  312. ))
  313. {
  314. RecordErrorAndExit("unpacking subject name", GetLastError());
  315. }
  316. if (!CertNameToStrA( X509_ASN_ENCODING,
  317. &Info->Issuer,
  318. CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
  319. IssuerName,
  320. sizeof(IssuerName)
  321. ))
  322. {
  323. RecordErrorAndExit("unpacking issuer name", GetLastError());
  324. }
  325. printf("----------------------------------------------------\n\n");
  326. printf(" subject: %s\n", SubjectName);
  327. printf(" issuer: %s\n", IssuerName);
  328. printf(" version %d\n", Info->dwVersion );
  329. printf(" valid from %02d:%02d:%02d on %d-%02d-%d\n",
  330. NotBeforeTime.wHour,
  331. NotBeforeTime.wMinute,
  332. NotBeforeTime.wSecond,
  333. NotBeforeTime.wMonth,
  334. NotBeforeTime.wDay,
  335. NotBeforeTime.wYear
  336. );
  337. printf(" to %02d:%02d:%02d on %d-%02d-%d\n",
  338. NotAfterTime.wHour,
  339. NotAfterTime.wMinute,
  340. NotAfterTime.wSecond,
  341. NotAfterTime.wMonth,
  342. NotAfterTime.wDay,
  343. NotAfterTime.wYear
  344. );
  345. }
  346. void RecordErrorAndExit( char * Action, unsigned long Error )
  347. {
  348. char * lpMsgBuf = "";
  349. FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  350. FORMAT_MESSAGE_FROM_SYSTEM |
  351. FORMAT_MESSAGE_IGNORE_INSERTS,
  352. NULL,
  353. Error,
  354. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  355. (LPSTR) &lpMsgBuf,
  356. 0,
  357. NULL
  358. );
  359. printf("error while %s: %x (%d) \"%s\"", Action, Error, Error, lpMsgBuf);
  360. }