// 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 #include } #include #include #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 */