windows-nt/Source/XPSP1/NT/com/rpc/runtime/mtrt/dumpcert.cxx
2020-09-26 16:20:57 +08:00

417 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: dumpcert.cxx
//
//--------------------------------------------------------------------------
#include "precomp.hxx"
#include <wincrypt.h>
#include <rpcssl.h>
#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);
}