//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1999 - 1999 // // File: dumpcert.cxx // //-------------------------------------------------------------------------- #include "precomp.hxx" #include #include #if 0 stuff clobbered by Unicode -> ANSI port: wchar_t -> char WCHAR -> char L"" -> "" %S -> %s W suffix-> A suffix wcscmp -> strcmp wmain -> main LPWSTR -> LPSTR #endif #define ByteSwapShort(Value) \ Value = ( (((Value) & 0x00FF) << 8) \ | (((Value) & 0xFF00) >> 8)) #define INITIAL_NAME_LENGTH 100 #define MSSTD_PREFIX_LENGTH 6 const char MSSTD_PREFIX[] = "msstd:"; #define FULLPATH_PREFIX_LENGTH 8 const char FULLPATH_PREFIX[] = "fullsic:"; //------------------------------------------------------------------------ void DumpCertInfo( PCERT_INFO Info ); void RecordErrorAndExit( char * Action, unsigned long Error ); extern "C" { int __cdecl main( int argc, char * argv[], char * envp[] ); } int __cdecl main( int argc, char * argv[], char * envp[] ) { HCERTSTORE Store; PCCERT_CONTEXT Context = 0; unsigned Criterion = CERT_FIND_ANY; void * SearchData = 0; char * StoreName = "My"; int i; char * MatchString = 0; BOOL fMatch = FALSE; BOOL fOutput = FALSE; unsigned long OutputFlags = 0; DWORD StoreFlags = CERT_SYSTEM_STORE_CURRENT_USER; for (i=1; i < argc; ++i) { if (0 == strcmp(argv[i], "-subject")) { Criterion = CERT_FIND_SUBJECT_STR_W; ++i; if (i >= argc) { printf("-subject must be followed by a subject name or substring\n"); return 1; } SearchData = argv[i]; } else if (0 == strcmp(argv[i], "-issuer")) { Criterion = CERT_FIND_ISSUER_STR_W; ++i; if (i >= argc) { printf("-issuer must be followed by an issuer name or substring\n"); return 1; } SearchData = argv[i]; } else if (0 == strcmp(argv[i], "-store")) { ++i; if (i >= argc) { printf("-store must be followed by a store name, such as 'Root' or 'My'\n"); return 1; } StoreName = argv[i]; } else if (0 == strcmp(argv[i], "-location")) { ++i; if (i >= argc) { printf("-location must be followed by 'USER:' or by 'HKLM'\n"); return 1; } if (0 == strcmp(argv[i], "USER:")) { StoreFlags = CERT_SYSTEM_STORE_CURRENT_USER; } else if (0 == strcmp(argv[i], "HKLM")) { StoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE; } else { printf("-location must be followed by 'USER:' or by 'HKLM'\n"); return 1; } } else if (0 == strcmp(argv[i], "-output")) { fOutput = TRUE; ++i; if(i >= argc) { printf("-output must be followed by 'msstd' or by 'fullsic'\n"); return 1; } if (0 == strcmp(argv[i], "fullsic")) { OutputFlags = RPC_C_FULL_CERT_CHAIN; } else if (0 == strcmp(argv[i], "msstd")) { OutputFlags = 0; } else { printf("-output must be followed by 'msstd' or by 'fullsic'\n"); return 1; } } else if (0 == strcmp(argv[i], "-match")) { fMatch = TRUE; ++i; if(i >= argc) { printf("-match must be followed by '@filename', listing the name of the file containing the match string\n"); return 1; } if (argv[i][0] == '@') { DWORD BytesRead; HANDLE hMatchFile; hMatchFile = CreateFileA( argv[i]+1, GENERIC_READ, FILE_SHARE_READ, 0, // no security OPEN_EXISTING, // must already exist FILE_ATTRIBUTE_NORMAL, NULL // no template file ); if (hMatchFile == ULongToHandle(0xffffffff)) { printf("can't open file %s\n", argv[i]+1); return 1; } DWORD Size = GetFileSize( hMatchFile, 0); if (Size == 0xffffffff) { printf("GetFileSize failed with 0x%x\n", GetLastError()); return 1; } if (Size % 2) { printf("the match-string file must be in Unicode.\n"); return 1; } MatchString = new char[ Size/sizeof(char) + sizeof(char) ]; if (!MatchString) { printf("can't allocate memory\n"); return 1; } if (!ReadFile( hMatchFile, MatchString, Size, &BytesRead, 0 // not overlapped ) || BytesRead != Size) { printf("can't read file data: 0x%x\n", GetLastError()); return 1; } MatchString[ Size/sizeof(char) ] = 0; if (MatchString[0] == 0xfeff) { ++MatchString; } else if (MatchString[0] == 0xfffe) { char * pc; for (pc = MatchString; *pc; ++pc) { ByteSwapShort(*pc); } ++MatchString; } } else { MatchString = argv[i]; } printf("string to match is '%s'\n", MatchString); } else if (0 == strcmp(argv[i], "-?") || 0 == strcmp(argv[i], "-help")) { printf("usage:\n" " dumpcert \n" " [-subject subject-substring]\n" " [-issuer issuer-substring]\n" " [-store store-name]\n" " [-output ('fullsic' | 'msstd')\n" " [-location ('HKLM' | 'USER:')\n" " [-match @filename]\n" ); return 1; } else { printf("unknown option '%s'\n", argv[i]); return 1; } } Store = CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, 0, StoreFlags, StoreName ); if (!Store) { RecordErrorAndExit("opening the store", GetLastError()); } for(;;) { Context = CertFindCertificateInStore( Store, X509_ASN_ENCODING, 0, Criterion, SearchData, Context ); if (!Context) { break; } DumpCertInfo( Context->pCertInfo ); if (fOutput) { unsigned char * OutputBuffer = 0; DWORD Status = RpcCertGeneratePrincipalNameA( Context, OutputFlags, &OutputBuffer ); if (Status) { printf("GeneratePrincName returned %d = 0x%x\n", Status, Status); } else { printf(" generated name = '%s'\n", OutputBuffer); } } if (fMatch) { printf("matching is not implemented because RpcCertMatchPrincipalName is not exported\n"); #if 0 DWORD Status = RpcCertMatchPrincipalName( Context, MatchString ); if (Status) { printf("MatchPrincipalName returned %d = 0x%x\n", Status, Status); } else { printf("The names matched.\n"); } #endif } } if (GetLastError() != CRYPT_E_NOT_FOUND) { RecordErrorAndExit("getting certificates", GetLastError()); } return 0; } void DumpCertInfo( PCERT_INFO Info ) { SYSTEMTIME NotBeforeTime; SYSTEMTIME NotAfterTime; char SubjectName[1000]; char IssuerName[1000]; if (!FileTimeToSystemTime( &Info->NotBefore, &NotBeforeTime )) { RecordErrorAndExit("translating not-before time", GetLastError()); } if (!FileTimeToSystemTime( &Info->NotAfter, &NotAfterTime )) { RecordErrorAndExit("translating not-after time", GetLastError()); } if (!CertNameToStrA( X509_ASN_ENCODING, &Info->Subject, CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG, SubjectName, sizeof(SubjectName) )) { RecordErrorAndExit("unpacking subject name", GetLastError()); } if (!CertNameToStrA( X509_ASN_ENCODING, &Info->Issuer, CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG, IssuerName, sizeof(IssuerName) )) { RecordErrorAndExit("unpacking issuer name", GetLastError()); } printf("----------------------------------------------------\n\n"); printf(" subject: %s\n", SubjectName); printf(" issuer: %s\n", IssuerName); printf(" version %d\n", Info->dwVersion ); printf(" valid from %02d:%02d:%02d on %d-%02d-%d\n", NotBeforeTime.wHour, NotBeforeTime.wMinute, NotBeforeTime.wSecond, NotBeforeTime.wMonth, NotBeforeTime.wDay, NotBeforeTime.wYear ); printf(" to %02d:%02d:%02d on %d-%02d-%d\n", NotAfterTime.wHour, NotAfterTime.wMinute, NotAfterTime.wSecond, NotAfterTime.wMonth, NotAfterTime.wDay, NotAfterTime.wYear ); } void RecordErrorAndExit( char * Action, unsigned long Error ) { char * lpMsgBuf = ""; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPSTR) &lpMsgBuf, 0, NULL ); printf("error while %s: %x (%d) \"%s\"", Action, Error, Error, lpMsgBuf); }