CACCertificate.cpp

Go to the documentation of this file.
00001 
00009 #include "Certificate.h"
00010 #include "AlgorithmIdentifier.h"
00011 #include "Name.h"
00012 #include "Validity.h"
00013 #include "SubjectPublicKeyInfo.h"
00014 #include "PKIFCryptUtils.h"
00015 
00016 #include "PKIFX509Extensions2.h"
00017 #include "IPKIFCryptoRaw.h"
00018 #include "ExtensionsMatch.h"
00019 #include "PKIFException.h"
00020 #include "ASN1Helper.h"
00021 #include "Buffer.h"
00022 #include "PKIFTime.h"
00023 #include "PKIFCommonErrors.h"
00024 #include "PKIFBase64.h"
00025 #include "BasicConstraints.h"
00026 
00027 #include "PKIX1Explicit88.h"
00028 #include "PKIX1Implicit88.h"
00029 
00030 #include <vector>
00031 using namespace std;
00032 
00034 struct CPKIFCertificateImpl
00035 {
00043     CPKIFCertificateImpl ();
00044   void populateExtensionsVector();
00045   
00046   // added 2/24/2005
00047   void ClearContent();
00048   
00049   CPKIFBufferPtr m_rawCert;
00050   CPKIFASNWrapper<CACX509V3Certificate> m_signedCert;
00051   CPKIFAlgorithmIdentifierPtr m_signatureAlgFromSignedMacro;
00052   std::vector<CPKIFX509ExtensionPtr> m_exts;
00053   
00054   // non-primitive cert members
00055   CPKIFAlgorithmIdentifierPtr m_signatureAlg;
00056   CPKIFNamePtr m_issuer;
00057   CPKIFValidityPtr m_validity;
00058   CPKIFNamePtr m_subject;
00059   CPKIFSubjectPublicKeyInfoPtr m_subjectPublicKeyInfo;
00060   
00061   // added these 8/27/2004
00062   bool m_bSelfSigned;
00063   bool m_bSelfSignedSet;
00064   bool m_bSelfIssued;
00065   bool m_bSelfIssuedSet;
00066 
00067   // pointer back to the certificate class
00068   CPKIFCertificate * m_this;
00069 };
00077 CPKIFCertificateImpl::CPKIFCertificateImpl ()
00078 : m_signedCert(BEREncCACX509V3Certificate, BERDecCACX509V3Certificate)
00079 {
00080 }
00081 
00094 void CPKIFCertificateImpl::populateExtensionsVector()
00095 {
00096     if(NULL == m_signedCert.data())
00097         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00098 
00099     //if we've already populated the extensions vector then return
00100     if(!m_exts.empty())
00101         return;
00102 
00103     //if there are no extensions then return
00104     if(0 == m_signedCert->tbsCertificate.m.extensionsPresent)
00105     {
00106         m_exts.clear();
00107         return;
00108     }
00109 
00110     // get the one and only extension mediator, with any additions an app might
00111     // have made
00112     CPKIFX509ExtensionMediator2 * mediator = CPKIFX509ExtensionMediator2::GetInstance();
00113     m_this->IPKIFHasExtensions::GetExtensions (mediator, m_exts);
00114 }
00115 
00116 //added 2/24/2005
00124 void CPKIFCertificateImpl::ClearContent()
00125 {
00126     CPKIFBufferPtr tmpBuf;
00127     m_rawCert = tmpBuf;
00128     
00129     m_exts.clear();
00130 
00131     CPKIFAlgorithmIdentifierPtr tmpAlg;
00132     m_signatureAlg = tmpAlg;
00133 
00134     CPKIFNamePtr tmpIss;
00135     m_issuer = tmpIss;
00136     CPKIFValidityPtr tmpVal;
00137     m_validity = tmpVal;
00138     CPKIFNamePtr tmpSub;
00139     m_subject = tmpSub;
00140     CPKIFSubjectPublicKeyInfoPtr tmpSPKI;
00141     m_subjectPublicKeyInfo = tmpSPKI;
00142 
00143     m_bSelfSigned = false;
00144     m_bSelfSignedSet = false;
00145     m_bSelfIssued = false;
00146     m_bSelfIssuedSet = false;
00147 }
00148 
00150 
00151 //void CPKIFCertificate::GetExtensions (vector<CPKIFX509ExtensionPtr>& ext) 
00152 //{
00153 //  m_impl->populateExtensionsVector();
00154 //  ext = m_impl->m_exts;
00155 //}
00156 
00164 CPKIFCertificate::CPKIFCertificate(void)
00165   :m_impl (new CPKIFCertificateImpl)
00166 {
00167   //m_impl->m_signedCert(BEREncCACX509V3Certificate, BERDecCACX509V3Certificate);
00168   m_impl->m_bSelfSigned = false; //has no meaning unless set = true
00169   m_impl->m_bSelfSignedSet = false;
00170   m_impl->m_bSelfIssued = false;//has no meaning unless set = true
00171   m_impl->m_bSelfIssuedSet = false;
00172   m_impl->m_this = this;
00173 }
00181 CPKIFCertificate::~CPKIFCertificate(void)
00182 {
00183     if(m_impl)
00184     {   
00185         delete m_impl;
00186         m_impl = 0;
00187     }
00188 }
00197 bool CPKIFCertificate::IsSelfIssued() const
00198 {
00199     if(!m_impl->m_bSelfIssuedSet)
00200     {
00201         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00202         nonConstCert->m_impl->m_bSelfIssuedSet = true;
00203         nonConstCert->m_impl->m_bSelfIssued = (*Subject() == *Issuer());
00204     }
00205 
00206     return m_impl->m_bSelfIssued;
00207 }
00216 bool CPKIFCertificate::IsSelfSigned() const
00217 {
00218     if(!m_impl->m_bSelfSignedSet)
00219     {
00220         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00221         nonConstCert->m_impl->m_bSelfSignedSet = true;
00222         IPKIFCryptoRaw* raw = GetPlatformCryptoRaw();
00223         if(raw)
00224         {
00225             nonConstCert->m_impl->m_bSelfSigned = raw->VerifyCertificate(*this, *this);
00226         }
00227     }
00228 
00229     return m_impl->m_bSelfSigned;
00230 }
00241 CPKIFBufferPtr CPKIFCertificate::Encoded() const 
00242 {
00243     return m_impl->m_rawCert;
00244 }
00245 
00261 void CPKIFCertificate::Decode(
00263     const unsigned char* cert, 
00265     int certLen)
00266 {
00267     try 
00268     {
00269         m_impl->ClearContent();
00270         CPKIFBufferPtr tmp(new CPKIFBuffer(cert, certLen));
00271         m_impl->m_rawCert = tmp;
00272         m_impl->m_signedCert.Decode(m_impl->m_rawCert->GetBuffer(), m_impl->m_rawCert->GetLength());
00273 
00274     } 
00275     catch ( ... ) 
00276     {
00277 
00278         m_impl->ClearContent();
00279         unsigned char * decoded = NULL;
00280         unsigned long decodedLen;
00281         bool b = PEMDecode_l((char *)cert, certLen, &decoded, &decodedLen);
00282         if(b)
00283         {
00284             try
00285             {
00286                 m_impl->ClearContent();
00287                 CPKIFBufferPtr tmp2(new CPKIFBuffer(decoded, decodedLen));
00288                 m_impl->m_rawCert = tmp2;
00289                 m_impl->m_signedCert.InitContext();
00290                 m_impl->m_signedCert.Decode(m_impl->m_rawCert->GetBuffer(), m_impl->m_rawCert->GetLength());
00291 
00292                 if(NULL != decoded)
00293                     delete[] decoded;
00294 
00295             }catch(...)
00296             {
00297                 if(NULL != decoded)
00298                     delete[] decoded;
00299                 m_impl->ClearContent();
00300                 throw;
00301             }
00302         }
00303         else
00304         {
00305             if(NULL != decoded)
00306                 delete[] decoded;
00307             m_impl->ClearContent();
00308             throw;
00309         }
00310     }
00311 
00312     //Added a call to Version() to make sure certificae contains an acceptable version
00313     Version();
00314 }
00325 int CPKIFCertificate::Version() const
00326 {
00327     if(NULL == m_impl->m_signedCert.data())
00328         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00329 
00330     if(!m_impl->m_signedCert->tbsCertificate.m.versionPresent)
00331         return 1;
00332 
00333     switch( m_impl->m_signedCert->tbsCertificate.version ) 
00334     {
00335         case CACX509V3AFv1:
00336             return 1;
00337             break;
00338         case CACX509V3AFv2:
00339             return 2;
00340             break;
00341         case CACX509V3AFv3:
00342             return 3;
00343             break;
00344         default:
00345             throw CPKIFException(TOOLKIT_ASN, COMMON_UNSUPPORTED_VERSION, "Unsupported certificate version");
00346         break;
00347     }
00348 }
00361 const char* CPKIFCertificate::SerialNumber() const
00362 {
00363     if(NULL == m_impl->m_signedCert.data())
00364         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00365 
00366     return m_impl->m_signedCert->tbsCertificate.serialNumber; 
00367 }
00378 CPKIFAlgorithmIdentifierPtr CPKIFCertificate::TBSSignatureAlgorithm() const
00379 {
00380     if(NULL == m_impl->m_signedCert.data())
00381         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00382 
00383     if(m_impl->m_signatureAlg == (CPKIFAlgorithmIdentifier*)NULL)
00384     {
00385 
00386         CPKIFOIDPtr algOID(new CPKIFOID(m_impl->m_signedCert->tbsCertificate.signature.algorithm.subid,
00387                                     m_impl->m_signedCert->tbsCertificate.signature.algorithm.numids));
00388         
00389         CPKIFBufferPtr paramBuf;
00390         if(m_impl->m_signedCert->tbsCertificate.signature.m.parametersPresent)
00391         {
00392             paramBuf = CPKIFBufferPtr(new CPKIFBuffer(m_impl->m_signedCert->tbsCertificate.signature.parameters.data,
00393                                 m_impl->m_signedCert->tbsCertificate.signature.parameters.numocts));
00394         
00395         
00396         }
00397         
00398         CPKIFAlgorithmIdentifierPtr tmpRef(new CPKIFAlgorithmIdentifier(algOID, paramBuf)); 
00399 
00400         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00401         nonConstCert->m_impl->m_signatureAlg = tmpRef;
00402     }
00403 
00404     return m_impl->m_signatureAlg;
00405 }
00406 CPKIFAlgorithmIdentifierPtr CPKIFCertificate::SignatureAlgorithm( ) const
00407 {
00408     if(NULL == m_impl->m_signedCert.data())
00409         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00410 
00411     if(m_impl->m_signatureAlgFromSignedMacro == (CPKIFAlgorithmIdentifier*)NULL)
00412     {
00413 
00414         CPKIFOIDPtr algOID(new CPKIFOID(m_impl->m_signedCert->signatureAlgorithm.algorithm.subid,
00415                                     m_impl->m_signedCert->signatureAlgorithm.algorithm.numids));
00416         
00417         CPKIFBufferPtr paramBuf;
00418         if(m_impl->m_signedCert->signatureAlgorithm.m.parametersPresent)
00419         {
00420             paramBuf = CPKIFBufferPtr(new CPKIFBuffer(m_impl->m_signedCert->signatureAlgorithm.parameters.data,
00421                                 m_impl->m_signedCert->signatureAlgorithm.parameters.numocts));
00422         
00423         
00424         }
00425         
00426         CPKIFAlgorithmIdentifierPtr tmpRef(new CPKIFAlgorithmIdentifier(algOID, paramBuf)); 
00427 
00428         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00429         nonConstCert->m_impl->m_signatureAlgFromSignedMacro = tmpRef;
00430     }
00431 
00432     return m_impl->m_signatureAlgFromSignedMacro;
00433 }
00446 CPKIFSubjectPublicKeyInfoPtr CPKIFCertificate::SubjectPublicKeyInfo( ) const
00447 {
00448     if(NULL == m_impl->m_signedCert.data())
00449         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00450 
00451     if(m_impl->m_subjectPublicKeyInfo == (CPKIFSubjectPublicKeyInfo*)NULL)
00452     {
00453         
00454         CPKIFOIDPtr algOID(new CPKIFOID(m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.subid,
00455                                     m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.numids));
00456         
00457         CPKIFBufferPtr paramBuf;
00458         if(m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.algorithm.m.parametersPresent)
00459         {
00460             paramBuf = CPKIFBufferPtr(new CPKIFBuffer(m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.algorithm.parameters.data,
00461                                 m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.algorithm.parameters.numocts));
00462         
00463         
00464         }
00465         
00466         CPKIFAlgorithmIdentifierPtr tmpAlgID(new CPKIFAlgorithmIdentifier(algOID, paramBuf));
00467 
00468         CPKIFBufferPtr tempBuffer(new CPKIFBuffer(m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data,
00469                             m_impl->m_signedCert->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.numbits/8));
00470 
00471         CPKIFSubjectPublicKeyInfo* tmpSPKI = new CPKIFSubjectPublicKeyInfo(tmpAlgID, tempBuffer);
00472         CPKIFSubjectPublicKeyInfoPtr tmpRef(tmpSPKI); 
00473 
00474         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00475         nonConstCert->m_impl->m_subjectPublicKeyInfo = tmpRef;
00476     }
00477 
00478     return m_impl->m_subjectPublicKeyInfo;
00479 }
00489 CPKIFNamePtr CPKIFCertificate::Issuer( ) const
00490 {
00491     if(NULL == m_impl->m_signedCert.data())
00492         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00493 
00494     if(m_impl->m_issuer == (CPKIFName*)NULL)
00495     {
00496         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU2);
00497         ASN1OpenType* data1 = objPDU2.Encode(&(m_impl->m_signedCert->tbsCertificate.issuer));
00498         CPKIFBufferPtr tmpBuf;
00499         if (data1 != NULL)
00500         {
00501              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
00502             delete data1;
00503         }
00504         //CPKIFName* tmpName = new CPKIFName(m_impl->m_signedCert->tbsCertificate.issuer);
00505         CPKIFName* tmpName = new CPKIFName(tmpBuf);
00506         CPKIFNamePtr tmpRef(tmpName); 
00507 
00508         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00509         nonConstCert->m_impl->m_issuer = tmpRef;
00510     }
00511 
00512     return m_impl->m_issuer;
00513 }
00523 CPKIFNamePtr CPKIFCertificate::Subject( ) const
00524 {
00525     if(NULL == m_impl->m_signedCert.data())
00526         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00527 
00528     if(m_impl->m_subject == (CPKIFName*)NULL)
00529     {
00530         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU2);
00531         ASN1OpenType* data1 = objPDU2.Encode(&(m_impl->m_signedCert->tbsCertificate.subject));
00532         CPKIFBufferPtr tmpBuf;
00533         if (data1 != NULL)
00534         {   
00535              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
00536             delete data1;
00537         }
00538         //CPKIFName* tmpName = new CPKIFName(m_impl->m_signedCert->tbsCertificate.subject);
00539         CPKIFName* tmpName = new CPKIFName(tmpBuf);
00540         CPKIFNamePtr tmpRef(tmpName); 
00541 
00542         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00543         nonConstCert->m_impl->m_subject = tmpRef;
00544     }
00545 
00546     return m_impl->m_subject;
00547 }
00557 CPKIFValidityPtr CPKIFCertificate::Validity( ) const
00558 {
00559     if(NULL == m_impl->m_signedCert.data())
00560         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT, "Attempted to read data from a certificate object prior to parsing a certificate.");
00561 
00562     if(m_impl->m_validity == (CPKIFValidity*)NULL)
00563     {
00564         CPKIFTimePtr notBefore;
00565         if(m_impl->m_signedCert->tbsCertificate.validity.notBefore.t == T_CACX509V3Time_utcTime)
00566         {
00567             notBefore = CPKIFTimePtr(new CPKIFTime(m_impl->m_signedCert->tbsCertificate.validity.notBefore.u.utcTime,
00568                             UTCTIME));
00569         }
00570         else
00571         {
00572             notBefore = CPKIFTimePtr(new CPKIFTime(m_impl->m_signedCert->tbsCertificate.validity.notBefore.u.generalTime,
00573                             GENERALIZEDTIME));
00574         }
00575 
00576         CPKIFTimePtr notAfter;
00577         if(m_impl->m_signedCert->tbsCertificate.validity.notAfter.t == T_CACX509V3Time_utcTime)
00578         {
00579             notAfter = CPKIFTimePtr(new CPKIFTime(m_impl->m_signedCert->tbsCertificate.validity.notAfter.u.utcTime,
00580                             UTCTIME));
00581         }
00582         else
00583         {
00584             notAfter = CPKIFTimePtr(new CPKIFTime(m_impl->m_signedCert->tbsCertificate.validity.notAfter.u.generalTime,
00585                             GENERALIZEDTIME));
00586         }
00587         
00588             
00589         CPKIFValidity* tmpName = new CPKIFValidity(notBefore, notAfter);
00590         CPKIFValidityPtr tmpRef(tmpName); 
00591 
00592         CPKIFCertificate* nonConstCert = const_cast<CPKIFCertificate*>(this);
00593         nonConstCert->m_impl->m_validity = tmpRef;
00594     }
00595 
00596     return m_impl->m_validity;
00597 }
00598 
00599 
00600 //this function is for use when retrieving an extension for which no proper class exists
00611 void CPKIFCertificate::GetExtensionByOID(
00613     const CPKIFOID& oid,
00615     CPKIFX509ExtensionPtr& ref)
00616 {
00617     if(m_impl->m_exts.empty() && (NULL != m_impl->m_signedCert.data() && m_impl->m_signedCert->tbsCertificate.m.extensionsPresent && 0 != m_impl->m_signedCert->tbsCertificate.extensions.count))
00618         m_impl->populateExtensionsVector();
00619 
00620     vector<CPKIFX509ExtensionPtr>::iterator pos;
00621     vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00622     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00623     {
00624         if(oid == (*pos)->oid())
00625         {
00626             ref = *pos;
00627             return;
00628         }
00629     }       
00630 }
00641 bool CPKIFCertificate::AreThereAnyUnprocessedCriticalExtensions(
00643     std::vector<CPKIFX509ExtensionPtr>& processedExts)
00644 {
00645     // XXX TODO: commenting this out for the moment; we really need to make it true.
00646     /*if(processedExts.size() > m_impl->m_exts.size())
00647     {
00648         throw CPKIFException(TOOLKIT_X509_ASN, COMMON_INVALID_INPUT,
00649             "More extensions were processed than are present in the certificate.");
00650     }*/
00651     std::vector<CPKIFX509ExtensionPtr>::iterator pos;
00652     std::vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00653     std::vector<CPKIFX509ExtensionPtr>::iterator processedEnd = processedExts.end();
00654     ExtensionsMatch em;
00655     size_t count = processedExts.size();
00656     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00657     {
00658         em.SetRHS(*pos);
00659         if((*pos)->isCritical() && processedEnd == find_if(processedExts.begin(), processedExts.end(), em))
00660             return true;
00661     }
00662 
00663     return false;
00664 }
00672 bool CPKIFCertificate::operator==(
00674     const CPKIFCertificate& rhs) const
00675 {
00676     if(*m_impl->m_rawCert == *rhs.Encoded())
00677         return true;
00678     else
00679     {
00680         const char* lhsSN = SerialNumber();
00681         const char* rhsSN = rhs.SerialNumber();
00682         //reviewed 4/24 - added strlen check
00683         if(strlen(lhsSN) != strlen(rhsSN) || 0 != stricmp(lhsSN, rhsSN))
00684             return false;
00685         else
00686             return *Issuer() == *rhs.Issuer();
00687     }
00688 }
00696 CPKIFBufferPtr CPKIFCertificate::Signature() const
00697 {
00698     CPKIFBufferPtr tmp(new CPKIFBuffer(m_impl->m_signedCert->signature.data, m_impl->m_signedCert->signature.numbits/8));
00699     return tmp;
00700 }
00701 
00709 void CPKIFCertificate::GetEncodedExtensions (
00711     CPKIFBufferPtr& buf) 
00712 {
00713     try 
00714     {
00715         if (m_impl->m_signedCert->tbsCertificate.m.extensionsPresent)
00716         {
00717             CACASNWRAPPER_CREATE(CACX509V3Extensions, extsWrapper);
00718             ASN1OpenType *data = extsWrapper.Encode (&m_impl->m_signedCert->tbsCertificate.extensions);
00719             CPKIFBufferPtr tmp(new CPKIFBuffer(data->data, data->numocts));
00720             buf = tmp;
00721             delete data;
00722             return;
00723         }
00724     }
00725     catch (... /*CPKIFException& e*/)
00726     {
00727         // How do we want to handle the exception?
00728     }
00729 
00730     CPKIFBufferPtr nullExt;
00731     buf = nullExt;
00732 }
00740 CPKIFNamePtr CPKIFCertificate::GetSubjectName() const
00741 {
00742     return Subject();
00743 }
00751 CPKIFBufferPtr CPKIFCertificate::GetKey() const
00752 {
00753     CPKIFSubjectPublicKeyInfoPtr spki = SubjectPublicKeyInfo();
00754     if(spki != (CPKIFSubjectPublicKeyInfo*)NULL)
00755         return spki->rawKey();
00756     else
00757     {
00758         CPKIFBufferPtr bp;
00759         return bp;
00760     }
00761 }
00769 CPKIFNamePtr CPKIFCertificate::GetIssuerName() const
00770 {
00771     return Issuer();
00772 }
00780 CPKIFSubjectPublicKeyInfoPtr CPKIFCertificate::GetSubjectPublicKeyInfo() const
00781 {
00782     return SubjectPublicKeyInfo();
00783 }
00784 
00785 bool CAC_API IsCaCertificate(CPKIFCertificatePtr& cert)
00786 {
00787     if(cert)
00788     {
00789         try
00790         {
00791             CPKIFBasicConstraintsPtr bc = cert->GetExtension<CPKIFBasicConstraints>();
00792             if(bc && bc->isCA())
00793                 return true;
00794         }
00795         catch(...)
00796         {
00797         }
00798     }
00799 
00800     return false;
00801 }

Generated on Mon Nov 15 11:15:46 2010 for PublicKeyInfrastructureFramework(PKIF) by  doxygen 1.5.6