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

/*++
Copyright (C) 1995-96 Microsoft Corporation
Module Name:
certify.cxx
Abstract:
This is the command line tool to manipulate certificates on an executable image.
Author: Robert Reichel (robertre) Feb 12, 1996
Revision History:
--*/
//#define UNICODE 1
//#define _UNICODE 1
#include <windows.h>
#include <imagehlp.h>
#include <stdio.h>
#include <malloc.h>
//
// Private prototypes
//
LPWIN_CERTIFICATE
GetCertFromImage(
LPCTSTR ImageName,
DWORD Index
);
SaveCertificate(
LPCTSTR OutputFileName,
LPCTSTR ImageName,
DWORD CertIndex
);
BOOL
RemoveCertificateFromImage(
LPCTSTR ImageName,
DWORD Index
);
BOOL
AddCertificateToImage(
LPCTSTR ImageName,
LPCTSTR CertificateName,
WORD CertificateType,
PDWORD Index
);
VOID
PrintCertificate(
LPWIN_CERTIFICATE Certificate,
DWORD Index
);
BOOL
GetCertHeaderFromImage(
IN LPCTSTR ImageName,
IN DWORD Index,
OUT LPWIN_CERTIFICATE CertificateHeader
);
#define TYPE_X509 TEXT("X509")
#define TYPE_PKCS7 TEXT("PKCS7")
#define TYPE_UNKNOWN TEXT("Unknown")
//
// Globals
//
BOOL fVerbose = FALSE;
void
PrintUsage(
VOID
)
{
fputs("Usage: PESIGMGR [switches] image-name \n"
" [-?] display this message\n"
" [-l] list the certificates in an image\n"
" [-a:<Filename>] add a certificate file to an image\n"
" [-r:<index>] remove certificate <index> from an image\n"
" [-s:<Filename>] used with -r to save the removed certificate\n"
" [-t:<CertType>] used with -a to specify the type of the certificate\n"
" where CertType may be X509 or PKCS7 [default is X509]\n",
stderr
);
exit(-1);
}
#if 0
PWSTR
GetArgAsUnicode(
LPSTR s
)
{
ULONG n;
PWSTR ps;
n = strlen( s );
ps = (PWSTR)HeapAlloc( GetProcessHeap(),
0,
(n + 1) * sizeof( WCHAR )
);
if (ps == NULL) {
printf( "Out of memory\n" );
}
if (MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
s,
n,
ps,
n
) != (LONG)n
) {
printf( "Unable to convert parameter '%s' to Unicode (%u)", (ULONG)s, GetLastError() );
}
ps[ n ] = UNICODE_NULL;
return ps;
}
#endif
int __cdecl
main(
int argc,
char *argv[],
char *envp[]
)
{
BOOL AFlagSeen = FALSE;
BOOL LFlagSeen = FALSE;
BOOL RFlagSeen = FALSE;
BOOL SFlagSeen = FALSE;
BOOL TFlagSeen = FALSE;
BOOL Result;
DWORD Index;
DWORD RFlag_CertIndex;
WORD CertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA; // default
char * CertificateName;
char * ImageName = NULL;
char * SFlag_CertificateFile;
char c, *p;
if (argc < 2) {
PrintUsage();
}
while (--argc) {
p = *++argv;
if (*p == '/' || *p == '-') {
c = *++p;
switch (toupper( c )) {
case '?':
PrintUsage();
break;
case 'A': // Add Certificate to image
c = *++p;
if (c != ':') {
PrintUsage();
} else {
if (AFlagSeen == TRUE) {
PrintUsage();
return( 0 );
}
AFlagSeen = TRUE;
CertificateName = ++p;
}
break;
case 'V':
{
fVerbose = TRUE;
break;
}
case 'T':
{
//
// Specify the Type of the certificate
//
c = *++p;
if (c != ':') {
PrintUsage();
} else {
if (TFlagSeen == TRUE) {
PrintUsage();
return( 0 );
}
TFlagSeen = TRUE;
++p;
if (_stricmp(p, TYPE_X509) == 0) {
CertificateType = WIN_CERT_TYPE_X509;
if (fVerbose) {
printf("Certificate type = X509\n");
}
} else {
if (_stricmp(p, TYPE_PKCS7) == 0) {
CertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
if (fVerbose) {
printf("Certificate type = PKCS7\n");
}
} else {
if (fVerbose) {
printf("Unrecognized Certificate type %s\n",p);
}
PrintUsage();
return (0);
}
}
}
break;
}
case 'L': // List the certificates in an image.
{
if (LFlagSeen == TRUE) {
PrintUsage();
return( 0 );
}
LFlagSeen = TRUE;
break;
}
case 'R': // Remove certificate from an image
{
c = *++p;
if (c != ':') {
PrintUsage();
} else {
if (RFlagSeen == TRUE) {
PrintUsage();
return( 0 );
}
RFlagSeen = TRUE;
//
// Save the index
//
RFlag_CertIndex = atoi(++p);
}
break;
}
case 'G':
c = *++p;
if (c != ':') {
PrintUsage();
} else {
// Generate a certificate from an image.
}
break;
case 'S': // Save the certificate
c = *++p;
if (c != ':') {
PrintUsage();
} else {
if (SFlagSeen == TRUE) {
PrintUsage();
return( 0 );
}
SFlagSeen = TRUE;
//
// Save the name of the file to put the cert into.
//
SFlag_CertificateFile = ++p;
}
break;
default:
fprintf( stderr, "CERTIFY: Invalid switch - /%c\n", c );
PrintUsage();
break;
}
} else {
//
// Should only be a single image name here
//
if (ImageName != NULL) {
PrintUsage();
return( 0 );
}
ImageName = *argv;
}
}
//
// Finished processing parameters, let's do the work.
//
if (ImageName == NULL) {
if (fVerbose) {
printf("Image name not specified\n");
}
PrintUsage();
return(0);
}
if (LFlagSeen) {
int Index = 0;
WIN_CERTIFICATE Certificate;
if (SFlagSeen || RFlagSeen || AFlagSeen) {
PrintUsage();
return(0);
}
do {
Result = GetCertHeaderFromImage( ImageName, Index, &Certificate );
if (Result) {
PrintCertificate( &Certificate, Index );
}
Index++;
} while ( Result );
return( 1 );
}
if (AFlagSeen) {
//
// 'A' is not used in conjunction with R or S
//
if (SFlagSeen || RFlagSeen) {
PrintUsage();
return( 0 );
}
Result = AddCertificateToImage(
ImageName,
CertificateName,
CertificateType,
&Index
);
if (Result) {
if (fVerbose){
printf("Certificate %d added\n",Index);
}
return( 1 );
} else {
if (fVerbose) {
printf("Unable to add Certificate to %s, error = %d\n",ImageName,GetLastError());
}
return( 0 );
}
}
if (RFlagSeen) {
if (!SFlagSeen) {
if (fVerbose) {
fputs("-R requires -S\n",stderr);
}
PrintUsage();
return(0);
}
//
// Make sure we can save the certificate data before
// we remove it from the image
//
Result = SaveCertificate(
SFlag_CertificateFile,
ImageName,
RFlag_CertIndex
);
if (!Result) {
if (fVerbose) {
printf("Unable to save certificate to file %s, error = %d\n",SFlag_CertificateFile,GetLastError());
}
return(0);
}
//
// Now that the certificate is safe, remove it from the image
//
Result = RemoveCertificateFromImage(
ImageName,
RFlag_CertIndex
);
if (!Result) {
if (fVerbose) {
printf("Unable to remove certificate, error = %d\n",GetLastError());
}
return(0);
}
}
if (SFlagSeen && !RFlagSeen) {
PrintUsage();
return( 0 );
}
return 0;
}
VOID
PrintCertificate(
LPWIN_CERTIFICATE Certificate,
DWORD Index
)
{
char * CertType;
switch (Certificate->wCertificateType) {
case WIN_CERT_TYPE_X509:
{
CertType = TYPE_X509;
break;
}
case WIN_CERT_TYPE_PKCS_SIGNED_DATA:
{
CertType = TYPE_PKCS7;
break;
}
default:
{
CertType = TYPE_UNKNOWN;
break;
}
}
printf("\nCertificate %3d Revision %1d Type %8s",Index,Certificate->wRevision, CertType);
return;
}
BOOL
AddCertificateToImage(
IN LPCTSTR ImageName,
IN LPCTSTR CertificateName,
IN WORD CertificateType,
OUT PDWORD Index
)
/*++
Routine Description:
Adds a certificate to an image, and returns its index.
Arguments:
ImageName - Provides the full name and path to the image to be
modified.
CertificateName - Provides the full name and path to a file containing
the certificate to be added to the image.
CertificateType - Provides the type of the certificate being added.
This type will be placed in the dwType field of the resulting
WIN_CERTIFICATE structure.
Index - Returns the index of the certificate after it is placed in the
image.
Return Value:
TRUE on success, FALSE on failure. More information is available via
GetLastError().
--*/
{
HANDLE CertificateHandle;
DWORD CertificateFileSize;
DWORD CertificateSize;
LPWIN_CERTIFICATE Certificate = NULL;
BOOL Result = FALSE;
HANDLE ImageHandle;
DWORD BytesRead;
//
// Attempt to open the certificate file
//
if ((CertificateHandle = CreateFile(CertificateName,
GENERIC_READ,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
if (fVerbose) {
printf("Unable to open %s, error = %d\n",CertificateName,GetLastError());
}
goto ErrorReturn;
}
//
// Read the certificate data into memory
//
CertificateFileSize = GetFileSize( CertificateHandle, NULL );
CertificateSize = CertificateFileSize + (sizeof( WIN_CERTIFICATE ) - sizeof( BYTE ));
//
// Hack to make certs 8 byte aligned
//
// CertificateSize += (8 - (CertificateSize % 8));
Certificate = (LPWIN_CERTIFICATE)malloc( CertificateSize );
if (NULL == Certificate) {
if (fVerbose) {
printf("malloc failed\n");
}
goto ErrorReturn;
}
Certificate->dwLength = CertificateSize;
Certificate->wRevision = WIN_CERT_REVISION_1_0;
Certificate->wCertificateType = CertificateType;
Result = ReadFile( CertificateHandle,
&Certificate->bCertificate,
CertificateFileSize,
&BytesRead,
NULL // Overlapped
);
if (!Result) {
if (fVerbose) {
printf("Unable to read Certificate file, error = %d\n",GetLastError());
}
goto ErrorReturn;
}
ImageHandle = CreateFile( ImageName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (ImageHandle == INVALID_HANDLE_VALUE) {
if (fVerbose) {
printf("Unable to open image file %s, error = %d\n",ImageName,GetLastError());
}
goto ErrorReturn;
}
Result = ImageAddCertificate( ImageHandle,
Certificate,
Index
);
if (!Result) {
if (fVerbose) {
printf("ImageAddCertificate failed, error = %d\n",GetLastError());
}
goto ErrorReturn;
}
CommonReturn:
if (Certificate)
free(Certificate);
return( Result );
ErrorReturn:
Result = FALSE;
goto CommonReturn;
}
BOOL
GetCertHeaderFromImage(
IN LPCTSTR ImageName,
IN DWORD Index,
OUT LPWIN_CERTIFICATE CertificateHeader
)
{
HANDLE ImageHandle;
BOOL Result;
ImageHandle = CreateFile( ImageName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (ImageHandle == INVALID_HANDLE_VALUE) {
if (fVerbose) {
printf("Unable to open image file %s\n",ImageName);
}
return( FALSE );
}
Result = ImageGetCertificateHeader(
ImageHandle,
Index,
CertificateHeader
);
CloseHandle( ImageHandle );
if (!Result) {
if (fVerbose) {
printf("\nUnable to retrieve certificate header from %s, index=%d, error = %d\n",ImageName,Index,GetLastError());
}
return( FALSE );
}
return( TRUE );
}
LPWIN_CERTIFICATE
GetCertFromImage(
IN LPCTSTR ImageName,
IN DWORD Index
)
/*++
Routine Description:
Returns a copy of the specified certificate.
Arguments:
ImageName - Provides the full path to the image file containing the
certificate.
Index - Provides the index of the desired certificate in the image.
Return Value:
NULL on failure.
On Success, returns a pointer to a filled in WIN_CERTIFICATE
structure, which may be freed by called free().
--*/
{
HANDLE ImageHandle;
LPWIN_CERTIFICATE Certificate;
DWORD RequiredLength = 0;
BOOL Result;
ImageHandle = CreateFile( ImageName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (ImageHandle == INVALID_HANDLE_VALUE) {
if (fVerbose) {
printf("Unable to open image file %s\n",ImageName);
}
return( NULL );
}
Result = ImageGetCertificateData(
ImageHandle,
Index,
NULL,
&RequiredLength
);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
if (fVerbose) {
printf("Unable to retrieve certificate data from %s, error = %d\n",ImageName,GetLastError());
}
return(NULL);
}
Certificate = (LPWIN_CERTIFICATE) malloc( RequiredLength );
if (Certificate == NULL) {
if (fVerbose) {
printf("Out of memory in GetCertFromImage\n");
}
return( NULL );
}
Result = ImageGetCertificateData(
ImageHandle,
Index,
Certificate,
&RequiredLength
);
CloseHandle( ImageHandle );
if (!Result) {
if (fVerbose) {
printf("Unable to retrieve certificate from %s, error = %d\n",ImageName,GetLastError());
}
return( NULL );
}
return( Certificate );
}
BOOL
RemoveCertificateFromImage(
LPCTSTR ImageName,
DWORD Index
)
{
HANDLE ImageHandle;
BOOL Result;
if (fVerbose) {
printf("Removing certificate index %d from %s\n",Index,ImageName);
}
ImageHandle = CreateFile( ImageName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (ImageHandle == INVALID_HANDLE_VALUE) {
printf("Unable to open image file %s\n",ImageName);
return( FALSE );
}
Result = ImageRemoveCertificate(
ImageHandle,
Index
);
if (!Result) {
printf("Unable to remove certificate from %s, error = %d\n",ImageName,GetLastError());
return( FALSE );
}
CloseHandle( ImageHandle );
return( TRUE );
}
BOOL
SaveCertificate(
LPCTSTR OutputFileName,
LPCTSTR ImageName,
DWORD CertIndex
)
{
DWORD Length;
BOOL Result;
DWORD BytesWritten = 0;
LPWIN_CERTIFICATE Certificate;
HANDLE CertificateHandle;
Certificate = GetCertFromImage( ImageName, CertIndex );
if (Certificate == NULL) {
if (fVerbose) {
printf("Unable to retrieve certificate from %s, error = %d\n",ImageName,GetLastError());
}
return( FALSE );
}
Length = Certificate->dwLength - sizeof( WIN_CERTIFICATE ) + sizeof( BYTE );
//
// Attempt to open the certificate file
//
if ((CertificateHandle = CreateFile(OutputFileName,
GENERIC_WRITE,
0,
0,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
printf("Unable to create %s, error = %d\n",OutputFileName,GetLastError());
return( FALSE );
}
Result = WriteFile( CertificateHandle,
&Certificate->bCertificate,
Length,
&BytesWritten,
NULL // Overlapped
);
if (!Result) {
printf("Unable to save certificate to file %s, error = %d\n",OutputFileName,GetLastError());
return( FALSE );
}
CloseHandle( CertificateHandle );
free( Certificate );
return( TRUE );
}