427 lines
13 KiB
C++
427 lines
13 KiB
C++
|
// AddCert.cpp : implementation file
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "certmap.h"
|
||
|
|
||
|
// persistence and mapping includes
|
||
|
#include "WrapMaps.h"
|
||
|
#include "wrapmb.h"
|
||
|
|
||
|
#include "ListRow.h"
|
||
|
#include "ChkLstCt.h"
|
||
|
|
||
|
// mapping page includes
|
||
|
#include "brwsdlg.h"
|
||
|
#include "EdtOne11.h"
|
||
|
#include "Ed11Maps.h"
|
||
|
#include "Map11Pge.h"
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
#include <wincrypt.h>
|
||
|
#include <sslsp.h>
|
||
|
}
|
||
|
|
||
|
#include <iismap.hxx>
|
||
|
#include <iiscmr.hxx>
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define COL_NUM_NAME 0
|
||
|
#define COL_NUM_NTACCOUNT 1
|
||
|
|
||
|
#define CERT_HEADER "-----BEGIN CERTIFICATE-----"
|
||
|
|
||
|
|
||
|
|
||
|
// the code that reads the certificate file is pretty much lifted from the
|
||
|
// keyring application. Which pretty much lifted it from the setkey application
|
||
|
|
||
|
// defines taken from the old KeyGen utility
|
||
|
#define MESSAGE_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----\r\n"
|
||
|
#define MESSAGE_TRAILER "-----END NEW CERTIFICATE REQUEST-----\r\n"
|
||
|
#define MIME_TYPE "Content-Type: application/x-pkcs10\r\n"
|
||
|
#define MIME_ENCODING "Content-Transfer-Encoding: base64\r\n\r\n"
|
||
|
|
||
|
void uudecode_cert(char *bufcoded, DWORD *pcbDecoded );
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// originally from keyring - modified to fit
|
||
|
BOOL CMap11Page::FAddCertificateFile( CString szFile )
|
||
|
{
|
||
|
CFile cfile;
|
||
|
PVOID pData = NULL;
|
||
|
BOOL fSuccess =FALSE;;
|
||
|
|
||
|
// open the file
|
||
|
if ( !cfile.Open( szFile, CFile::modeRead | CFile::shareDenyNone ) )
|
||
|
return FALSE;
|
||
|
|
||
|
// how big is the file - add one so we can zero terminate the buffer
|
||
|
DWORD cbCertificate = cfile.GetLength() + 1;
|
||
|
|
||
|
// make sure the file has some size
|
||
|
if ( !cbCertificate )
|
||
|
{
|
||
|
AfxMessageBox( IDS_ERR_INVALID_CERTIFICATE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// put the rest of the operation in a try/catch
|
||
|
try
|
||
|
{
|
||
|
PCCERT_CONTEXT pCertContext=NULL; //used to determine whether cert file is binary DER encoded
|
||
|
// allocate space for the data
|
||
|
pData = GlobalAlloc( GPTR, cbCertificate );
|
||
|
if ( !pData ) AfxThrowMemoryException();
|
||
|
|
||
|
// copy in the data from the file to the pointer - will throw and exception
|
||
|
DWORD cbRead = cfile.Read( pData, cbCertificate );
|
||
|
|
||
|
// zero terminate for decoding
|
||
|
((BYTE*)pData)[cbRead] = 0;
|
||
|
|
||
|
// close the file
|
||
|
cfile.Close();
|
||
|
|
||
|
//certificate file may be either be binary DER file or BASE64 encoded file
|
||
|
|
||
|
// try binary DER encoded first
|
||
|
pCertContext= CertCreateCertificateContext(X509_ASN_ENCODING, (const BYTE *)pData, cbRead);
|
||
|
if(pCertContext != NULL)
|
||
|
{
|
||
|
// we created certificate context only to verify that file is binary DER encoded
|
||
|
// free it now
|
||
|
CertFreeCertificateContext(pCertContext);
|
||
|
pCertContext=NULL;
|
||
|
}
|
||
|
else // now try BASE64 encoded
|
||
|
{
|
||
|
// we don't care about header ----BEGIN CERTIFICATE----- or trailer-----END CERTIFICATE-----,
|
||
|
// uudecode will take care of that
|
||
|
uudecode_cert( (PCHAR)pData, &cbRead );
|
||
|
}
|
||
|
// we now have a pointer to a certificate. Lets keep it clean looking
|
||
|
// call another subroutine to finish the job.
|
||
|
fSuccess = FAddCertificate( (PUCHAR)pData, cbRead );
|
||
|
|
||
|
}catch( CException e )
|
||
|
{
|
||
|
// return failure
|
||
|
fSuccess = FALSE;
|
||
|
|
||
|
// if the pointer was allocated, deallocate it
|
||
|
if ( pData )
|
||
|
{
|
||
|
GlobalFree( pData );
|
||
|
pData = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// return success
|
||
|
return fSuccess;
|
||
|
}
|
||
|
|
||
|
#define CERT_HEADER_LEN 17
|
||
|
CHAR CertTag[ 13 ] = { 0x04, 0x0b, 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e' };
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// we are passed in a complete certificate. We need to parse out the subject
|
||
|
// and the issuer fields so we can add the mapping. Then add the mapping.
|
||
|
BOOL CMap11Page::FAddCertificate( PUCHAR pCertificate, DWORD cbCertificate )
|
||
|
{
|
||
|
BOOL fSuccess = FALSE;
|
||
|
|
||
|
// thankfully, the certificate is already in the correct format.
|
||
|
// this means that, for now at least, we don't have to do anything
|
||
|
// special to it to store it. However, we should crack it once just
|
||
|
// to see that we can to prove that it is a valid cert.
|
||
|
|
||
|
ASSERT( pCertificate );
|
||
|
if ( !pCertificate ) return FALSE;
|
||
|
|
||
|
// crack the certificate to prove that we can
|
||
|
PX509Certificate p509 = NULL;
|
||
|
fSuccess = SslCrackCertificate( pCertificate, cbCertificate, CF_CERT_FROM_FILE, &p509 );
|
||
|
if ( fSuccess )
|
||
|
{
|
||
|
SslFreeCertificate( p509 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we were not able to crack the certificate. Alert the user and fail
|
||
|
AfxMessageBox( IDS_ERR_INVALID_CERTIFICATE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// by this point we know we have a valid certificate, make the new mapping and fill it in
|
||
|
// make the new mapping object
|
||
|
C11Mapping* pMapping = PNewMapping();
|
||
|
ASSERT( pMapping );
|
||
|
if( !pMapping )
|
||
|
{
|
||
|
AfxThrowMemoryException(); // seems fairly appropriate
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
// one more thing before we add the certificate. Skip the header if it is there
|
||
|
PUCHAR pCert = pCertificate;
|
||
|
DWORD cbCert = cbCertificate;
|
||
|
if ( memcmp( pCert + 4, CertTag, sizeof( CertTag ) ) == 0 )
|
||
|
{
|
||
|
pCert += CERT_HEADER_LEN;
|
||
|
cbCert -= CERT_HEADER_LEN;
|
||
|
}
|
||
|
|
||
|
|
||
|
// install the certificate into the mapping
|
||
|
fSuccess &= pMapping->SetCertificate( pCert, cbCert );
|
||
|
|
||
|
// by default, the mapping is enabled
|
||
|
fSuccess &= pMapping->SetMapEnabled( TRUE );
|
||
|
|
||
|
// install a default name
|
||
|
CString sz;
|
||
|
|
||
|
sz.LoadString( IDS_DEFAULT_11MAP );
|
||
|
|
||
|
fSuccess &= pMapping->SetMapName( sz );
|
||
|
|
||
|
// install a blank mapping
|
||
|
fSuccess &= pMapping->SetNTAccount( "" );
|
||
|
|
||
|
if ( !fSuccess )
|
||
|
AfxThrowMemoryException(); // seems fairly appropriate
|
||
|
|
||
|
|
||
|
// now edit the newly created mapping object. If the user cancels,
|
||
|
// then do not add it to the mapper object nor the list
|
||
|
if ( !EditOneMapping( pMapping) )
|
||
|
{
|
||
|
DeleteMapping( pMapping );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// add the mapping item to the list control
|
||
|
fSuccess = FAddMappingToList( pMapping );
|
||
|
|
||
|
// one more test for success
|
||
|
if ( !fSuccess )
|
||
|
{
|
||
|
DeleteMapping( pMapping );
|
||
|
ASSERT( FALSE );
|
||
|
}
|
||
|
|
||
|
// mark the mapping to be saved
|
||
|
if ( fSuccess )
|
||
|
MarkToSave( pMapping );
|
||
|
|
||
|
// return the answer
|
||
|
return fSuccess;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ==============================================================
|
||
|
// The function 'uudecode_cert' IS THE SAME function that is
|
||
|
// found in file: Addcert.cpp if we make the following code
|
||
|
// have a FALSE for bAddWrapperAroundCert -- surely we can unify
|
||
|
// these 2 functions. Having 2 functions named 'uudecode_cert'
|
||
|
// was causing me LINKING errors. + we have 2 instances of
|
||
|
// the external tables: uudecode_cert and pr2six
|
||
|
//
|
||
|
// Since I am linking both Addcert.cpp and CKey.cpp I choose to
|
||
|
// leave the defintions intact for CKey.cpp [ and have extended
|
||
|
// uudecode_cert by adding conditional code as shown below] Further
|
||
|
// work needs to be done after identification as to why I need both
|
||
|
// Addcert.cpp and CKey.cpp to pass bAddWrapperAroundCert as a
|
||
|
// parameter so that both files can be supported.
|
||
|
// ==============================================================
|
||
|
// BOOL bAddWrapperAroundCert = TRUE;
|
||
|
// if (bAddWrapperAroundCert) {
|
||
|
// //
|
||
|
// // Now we need to add a new wrapper sequence around the certificate
|
||
|
// // indicating this is a certificate
|
||
|
// //
|
||
|
//
|
||
|
// memmove( beginbuf + sizeof(abCertHeader),
|
||
|
// beginbuf,
|
||
|
// nbytesdecoded );
|
||
|
//
|
||
|
// memcpy( beginbuf,
|
||
|
// abCertHeader,
|
||
|
// sizeof(abCertHeader) );
|
||
|
//
|
||
|
// //
|
||
|
// // The beginning record size is the total number of bytes decoded plus
|
||
|
// // the number of bytes in the certificate header
|
||
|
// //
|
||
|
//
|
||
|
// beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
|
||
|
// beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
|
||
|
//
|
||
|
// nbytesdecoded += sizeof(abCertHeader);
|
||
|
// }
|
||
|
|
||
|
// #ifdef WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE
|
||
|
|
||
|
//============================ BASED ON SETKEY
|
||
|
const int pr2six[256]={
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
|
||
|
52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
|
||
|
10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
|
||
|
28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
||
|
64,64,64,64,64,64,64,64,64,64,64,64,64
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// We have to squirt a record into the decoded stream
|
||
|
//
|
||
|
|
||
|
#define CERT_RECORD 13
|
||
|
#define CERT_SIZE_HIBYTE 2 // Index into record of record size
|
||
|
#define CERT_SIZE_LOBYTE 3
|
||
|
|
||
|
unsigned char abCertHeader[] = {0x30, 0x82, // Record
|
||
|
0x00, 0x00, // Size of cert + buff
|
||
|
0x04, 0x0b, 0x63, 0x65,// Cert record data
|
||
|
0x72, 0x74, 0x69, 0x66,
|
||
|
0x69, 0x63, 0x61, 0x74,
|
||
|
0x65 };
|
||
|
|
||
|
void uudecode_cert(char *bufcoded, DWORD *pcbDecoded )
|
||
|
{
|
||
|
int nbytesdecoded;
|
||
|
char *bufin = bufcoded;
|
||
|
unsigned char *bufout = (unsigned char *)bufcoded;
|
||
|
unsigned char *pbuf;
|
||
|
int nprbytes;
|
||
|
char * beginbuf = bufcoded;
|
||
|
|
||
|
ASSERT(bufcoded);
|
||
|
ASSERT(pcbDecoded);
|
||
|
|
||
|
/* Strip leading whitespace. */
|
||
|
|
||
|
while(*bufcoded==' ' ||
|
||
|
*bufcoded == '\t' ||
|
||
|
*bufcoded == '\r' ||
|
||
|
*bufcoded == '\n' )
|
||
|
{
|
||
|
bufcoded++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If there is a beginning '---- ....' then skip the first line
|
||
|
//
|
||
|
|
||
|
if ( bufcoded[0] == '-' && bufcoded[1] == '-' )
|
||
|
{
|
||
|
bufin = strchr( bufcoded, '\n' );
|
||
|
|
||
|
if ( bufin )
|
||
|
{
|
||
|
bufin++;
|
||
|
bufcoded = bufin;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bufin = bufcoded;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bufin = bufcoded;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Strip all cr/lf from the block
|
||
|
//
|
||
|
|
||
|
pbuf = (unsigned char *)bufin;
|
||
|
while ( *pbuf )
|
||
|
{
|
||
|
if ( (*pbuf == ' ') || (*pbuf == '\r') || (*pbuf == '\n') )
|
||
|
{
|
||
|
memmove( (void*)pbuf, pbuf+1, strlen( (char*)pbuf + 1) + 1 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pbuf++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Figure out how many characters are in the input buffer.
|
||
|
* If this would decode into more bytes than would fit into
|
||
|
* the output buffer, adjust the number of input bytes downwards.
|
||
|
*/
|
||
|
|
||
|
while(pr2six[*(bufin++)] <= 63);
|
||
|
nprbytes = DIFF(bufin - bufcoded) - 1;
|
||
|
nbytesdecoded = ((nprbytes+3)/4) * 3;
|
||
|
|
||
|
bufin = bufcoded;
|
||
|
|
||
|
while (nprbytes > 0) {
|
||
|
*(bufout++) =
|
||
|
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||
|
*(bufout++) =
|
||
|
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||
|
*(bufout++) =
|
||
|
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||
|
bufin += 4;
|
||
|
nprbytes -= 4;
|
||
|
}
|
||
|
|
||
|
if(nprbytes & 03) {
|
||
|
if(pr2six[bufin[-2]] > 63)
|
||
|
nbytesdecoded -= 2;
|
||
|
else
|
||
|
nbytesdecoded -= 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
//
|
||
|
// Now we need to add a new wrapper sequence around the certificate
|
||
|
// indicating this is a certificate
|
||
|
//
|
||
|
|
||
|
memmove( beginbuf + sizeof(abCertHeader),
|
||
|
beginbuf,
|
||
|
nbytesdecoded );
|
||
|
|
||
|
memcpy( beginbuf,
|
||
|
abCertHeader,
|
||
|
sizeof(abCertHeader) );
|
||
|
|
||
|
//
|
||
|
// The beginning record size is the total number of bytes decoded plus
|
||
|
// the number of bytes in the certificate header
|
||
|
//
|
||
|
|
||
|
beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
|
||
|
beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
|
||
|
|
||
|
nbytesdecoded += sizeof(abCertHeader);
|
||
|
*/
|
||
|
|
||
|
if ( pcbDecoded )
|
||
|
*pcbDecoded = nbytesdecoded;
|
||
|
}
|
||
|
// ============ END BASED ON SETKEY
|
||
|
|
||
|
//#endif /* WE_ARE_USING_THE_VERSION_IN__CKey_cpp__NOT_THIS_ONE__ITS_JUST_LIKE_THIS_ONE_WITH_1SMALL_CHANGE */
|