diff -r 000000000000 -r 164170e6151a pkiutilities/x509certnameparser/src/X509CertNameParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkiutilities/x509certnameparser/src/X509CertNameParser.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,583 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Extracts relevant certificate information to be shown to user. +* +*/ + + +// INCLUDE FILES +#include "X509CertNameParser.h" +#include //X509Certificate +#include // CX500DistinguishedName +#include // OIDS for the extensions +#include // for escape decoding + +// CONSTANTS +_LIT (KX509CertParserSpace, " "); + +// Max length of array in case of PrimaryAndSecondaryNameL. +const TInt KX509CNPPrimAndSecondNameLengh( 3 ); + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// X509CertNameParser::PrimaryAndSecondaryNameL +// +// ----------------------------------------------------------------------------- +EXPORT_C TInt X509CertNameParser::PrimaryAndSecondaryNameL( + const CX509Certificate& aCertificate, + HBufC*& aPrimaryName, + HBufC*& aSecondaryName, + const TDesC& aLabel) + { + // Get subjectname + const CX500DistinguishedName& dName = aCertificate.SubjectName(); + // Get subject alternative name + const CX509CertExtension* extension = + aCertificate.Extension( KSubjectAltName ); + + CDesCArrayFlat* nameArray = new( ELeave ) CDesCArrayFlat(3); + CleanupStack::PushL( nameArray ); + // Append label to array + nameArray->AppendL( aLabel ); + + // Get PrimaryName and SecondaryName to nameArray if they exists. + GetNamePartsL( dName, extension, *nameArray, EX509CNPPrimAndSecond ); + + // Make sure that these are NULL + aPrimaryName = NULL; + aSecondaryName = NULL; + + switch ( nameArray->MdcaCount() ) + { + case 1: //Neither PrimaryName nor SecondaryName found + { + aPrimaryName = HBufC::NewLC( KNullDesC.iTypeLength ); + *aPrimaryName = KNullDesC; + aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength ); + *aSecondaryName = KNullDesC; + break; + } + case 2: // Only PrimaryName found + { + aPrimaryName = HBufC::NewLC(( *nameArray)[1].Length() ); + *aPrimaryName = ( *nameArray )[1]; + aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength ); + *aSecondaryName = KNullDesC; + break; + } + case 3: // Both found + { + aPrimaryName = HBufC::NewLC(( *nameArray)[1].Length() ); + *aPrimaryName = ( *nameArray )[1]; + aSecondaryName = HBufC::NewLC( ( *nameArray )[2].Length() ); + *aSecondaryName = ( *nameArray )[2]; + break; + } + default: // Something went wrong. + { + aPrimaryName = HBufC::NewLC( KNullDesC.iTypeLength ); + *aPrimaryName = KNullDesC; + aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength ); + *aSecondaryName = KNullDesC; + break; + } + } + + if ( aSecondaryName ) + { + CleanupStack::Pop( aSecondaryName ); // aSecondaryName + } + if ( aPrimaryName ) + { + CleanupStack::Pop( aPrimaryName ); // aPrimaryName + } + CleanupStack::PopAndDestroy( nameArray ); // nameArray + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::SubjectFullNameL +// +// ----------------------------------------------------------------------------- + +EXPORT_C TInt X509CertNameParser::SubjectFullNameL( + const CX509Certificate& aCertificate, + HBufC*& aSubjectName, + const TDesC& aLabel ) + { + // Get subjectname + const CX500DistinguishedName& dName = aCertificate.SubjectName(); + // Get subject alternative name + const CX509CertExtension* extension = + aCertificate.Extension( KSubjectAltName ); + + return GetFullNameL( dName, extension, aSubjectName, aLabel ); + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::IssuerFullNameL +// +// ----------------------------------------------------------------------------- + +EXPORT_C TInt X509CertNameParser::IssuerFullNameL( + const CX509Certificate& aCertificate, + HBufC*& aIssuerName ) + { + // Get issuerName + const CX500DistinguishedName& dName = aCertificate.IssuerName(); + // Get issuer alternative name + const CX509CertExtension* extension = + aCertificate.Extension( KIssuerAltName ); + + return GetFullNameL( dName, extension, aIssuerName ); + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::GetFullNameL +// +// ----------------------------------------------------------------------------- +TInt X509CertNameParser::GetFullNameL( + const CX500DistinguishedName& aDN, + const CX509CertExtension* aExtension, + HBufC*& aName, + const TDesC& aLabel ) + { + CDesCArrayFlat* nameArray = new( ELeave ) CDesCArrayFlat(3); + CleanupStack::PushL( nameArray ); + // Add label to array. It is used for comparing. + nameArray->AppendL( aLabel ); + + // Collect name parts to array + GetNamePartsL( aDN, aExtension, *nameArray, EX509CNPFullName); + + // Count length of the aName. + TInt length = 0; + TInt i = 1; // Pass label + for ( ; i < nameArray->MdcaCount(); i++ ) + { + length += (*nameArray)[i].Length(); + length += KX509CNPComma.iTypeLength; + } + + // Add elements of the array to aName. + // First element is label, so it is passed. + aName = HBufC::NewLC( length ); + for ( i = 1; i < nameArray->MdcaCount(); i++ ) + { + if ( i != 1 ) + { + aName->Des().Append( KX509CNPComma ); + } + aName->Des().Append( (*nameArray)[i] ); + } + + CleanupStack::Pop( aName ); + CleanupStack::PopAndDestroy( nameArray ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::GetNamePartsL +// +// ----------------------------------------------------------------------------- + +TInt X509CertNameParser::GetNamePartsL( + const CX500DistinguishedName& aDN, + const CX509CertExtension* aExtension, + CDesCArray& aNameArray, + TX509CNPNameType aNameType) + { + const CX509AltNameExt* altNameExt = NULL; + + if (aExtension) + { + altNameExt = CX509AltNameExt::NewLC( aExtension->Data() ); + } + + TBool notFound = ETrue; + + // In case of PrimaryAndSecondaryName loop goes through name elements + // until two of them is found. + // In case of FullNames loop goes through all supported name element and + // adds founded names to array. + for( TInt round = 1; notFound; round++ ) + { + switch( round ) + { + case EDNCommonName: + { + GetDNPartL( aDN, KX520CommonName, aNameArray ); + break; + } + case ECritAltRFC822Name: + { + if (aExtension && aExtension->Critical()) + { + GetAltNamePartL( *altNameExt, EX509RFC822Name, aNameArray ); + } + break; + } + case EDNOrganizationName: + { + GetDNPartL( aDN, KX520OrganizationName, aNameArray); + break; + } + case EDNOrganizationalUnitName: + { + if ( aNameType == EX509CNPPrimAndSecond ) + { + GetDNPartL( aDN, KX520OrganizationalUnitName, aNameArray); + } + else + { + GetDNPartAllL( aDN, KX520OrganizationalUnitName, aNameArray); + } + break; + } + case ECritAltURI: + { + if (aExtension && aExtension->Critical()) + { + GetAltNamePartL( *altNameExt, EX509URI, aNameArray ); + } + break; + } + case ECritAltDNSName: + { + if (aExtension && aExtension->Critical()) + { + GetAltNamePartL( *altNameExt, EX509DNSName, aNameArray); + } + break; + } + case ECritAltDirectoryName: + { + if (aExtension && aExtension->Critical()) + { + GetAltNamePartL( *altNameExt, EX509DirectoryName, + aNameArray ); + } + break; + } + case ECritAltIPAddress: + { + if (aExtension && aExtension->Critical()) + { + GetAltNamePartL( *altNameExt, EX509IPAddress, + aNameArray ); + } + break; + } + case EAltRFC822Name: + { + if (aExtension) + { + GetAltNamePartL( *altNameExt, EX509RFC822Name, + aNameArray ); + } + break; + } + case EAltURI: + { + if ( aExtension ) + { + GetAltNamePartL( *altNameExt, EX509URI, aNameArray ); + } + break; + } + case EAltDNSName: + { + if ( aExtension ) + { + GetAltNamePartL( *altNameExt, EX509DNSName, aNameArray ); + } + break; + } + case EDNCountryName: + { + GetDNPartL( aDN, KX520CountryName, aNameArray ); + break; + } + case EDNStateOrProvinceName: + { + GetDNPartL( aDN, KX520StateOrProvinceName, aNameArray ); + break; + } + case EDNLocalityName: + { + GetDNPartL( aDN, KX520LocalityName, aNameArray ); + break; + } + case EAltDirectoryName: + { + if ( aExtension ) + { + GetAltNamePartL( *altNameExt, EX509DirectoryName, + aNameArray ); + } + break; + } + case EAltIPAddress: + { + if ( aExtension ) + { + GetAltNamePartL( *altNameExt, EX509IPAddress, + aNameArray ); + } + break; + } + default: + { + // All the names are gone through. + notFound = EFalse; + break; + } + } // switch + + if ( notFound ) + { + // If caller is PrimaryAndSecondaryNameL and PrimaryName and + // SecondaryName have found then end loop. + if ( aNameType == EX509CNPPrimAndSecond && + ( aNameArray.MdcaCount() >= KX509CNPPrimAndSecondNameLengh ) ) + { + notFound = EFalse; + } // if + } // if + } // for + + if ( aExtension ) + { + CleanupStack::PopAndDestroy(); // altNameExt + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::GetDNPartAllL +// +// ----------------------------------------------------------------------------- + +void X509CertNameParser::GetDNPartAllL( + const CX500DistinguishedName& aDN, + const TDesC& aSubPartOID, + CDesCArray& aNameArray ) + { + HBufC* buf = NULL; + // Count of the name parts of the DN + TInt count = aDN.Count(); + + // This goes through all the nameparts of the DN and appends all the + // parts, that OID is aSubPartOID, to the array. + for ( TInt i = 0; i < count; i++ ) + { + const CX520AttributeTypeAndValue& ava = aDN.Element( i ); + if ( ava.Type() == aSubPartOID ) + { + TRAPD( error, buf = ava.ValueL() ); + HandleErrorL( error ); + + if ( buf ) + { + CleanupStack::PushL( buf ); + CompareAndAddNameL( *buf, aNameArray ); + CleanupStack::PopAndDestroy( buf ); // buf + buf = NULL; + } // if + } // if + } // for + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::GetDNPartL +// +// ----------------------------------------------------------------------------- + +void X509CertNameParser::GetDNPartL( + const CX500DistinguishedName& aDN, + const TDesC& aSubPartOID, + CDesCArray& aNameArray ) + { + HBufC* buf = NULL; + // Extract one DN part + TRAPD( error, buf = aDN.ExtractFieldL( aSubPartOID ) ); + HandleErrorL( error ); + + // Add to array + if ( buf ) + { + CleanupStack::PushL( buf ); + CompareAndAddNameL( *buf, aNameArray ); + CleanupStack::PopAndDestroy( buf ); // buf + } + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::GetAltNamePartL +// +// ----------------------------------------------------------------------------- + +void X509CertNameParser::GetAltNamePartL( + const CX509AltNameExt& aAltName, + const TGNType& aSubPartType, + CDesCArray& aNameArray ) + { + // Get all parts of the alternative name to the array + const CArrayPtrFlat& subParts = aAltName.AltName(); + TInt count = subParts.Count(); + CX509DomainName* domainName = NULL; + TInt error = KErrNone; + + // This goes through all the nameparts of the DN and appends all the + // parts, that OID is aSubPartOID, to the array. + for (TInt i = 0; count > i; i++) + { + if ( subParts[i]->Tag() == aSubPartType ) + { + TPtrC8 data = subParts[i]->Data(); + switch ( aSubPartType ) + { + case EX509RFC822Name: + { + TRAP( error, domainName = CX509RFC822Name::NewL( data ) ); + CleanupStack::PushL( domainName ); + AddAltNameToArrayL( error, domainName, aNameArray ); + CleanupStack::PopAndDestroy( domainName ); + break; + } + case EX509DNSName: + case EX509DirectoryName: + { + TRAP( error, domainName = CX509DNSName::NewL( data ) ); + CleanupStack::PushL( domainName ); + AddAltNameToArrayL( error, domainName, aNameArray ); + CleanupStack::PopAndDestroy( domainName ); + break; + } + case EX509URI: + { + CX509IPBasedURI* uri = NULL; + HBufC* decodedUri = NULL; + TRAP( error, uri = CX509IPBasedURI::NewL( data ) ); + + if ( error == KErrNone ) + { + CleanupStack::PushL( uri ); + TRAP( error, decodedUri = EscapeUtils:: + EscapeDecodeL( uri->Name() ) ); + CleanupStack::PopAndDestroy(); //uri + } + + HandleErrorL( error ); + if ( error == KErrNone ) + { + CleanupStack::PushL( decodedUri ); + CompareAndAddNameL( *decodedUri, aNameArray ); + CleanupStack::PopAndDestroy(); // decodedUri + } + break; + } + case EX509IPAddress: + { + // Not supported + break; + } + default: + { + break; + } + } // switch + } // if + } // for + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::AddAltNameToArrayL +// +// ----------------------------------------------------------------------------- + +TInt X509CertNameParser::AddAltNameToArrayL( + TInt aError, + CX509DomainName* aDomainName, + CDesCArray& aNameArray ) + { + TInt error = HandleErrorL( aError ); + + if ( error == KErrNone ) + { + const TPtrC name = aDomainName->Name(); + CompareAndAddNameL( name, aNameArray ); + } + + return error; + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::AddToBufLD +// +// ----------------------------------------------------------------------------- + +void X509CertNameParser::AddToBufLD( const TDesC& aName, HBufC*& aBuf ) + { + if (!aBuf) + { + aBuf = HBufC::NewL( aName.Length() ); + aBuf->Des().Append( aName ); + } + else + { + HBufC* helpBuf = HBufC::NewL( aName.Length() + aBuf->Length() + 1); + helpBuf->Des().Append( *aBuf ); + helpBuf->Des().Append( KX509CertParserSpace ); + helpBuf->Des().Append( aName ); + CleanupStack::PopAndDestroy( aBuf ); // aBuf + aBuf = helpBuf; + } + } + +// ----------------------------------------------------------------------------- +// X509CertNameParser::CompareAndAddNameL +// +// ----------------------------------------------------------------------------- + +void X509CertNameParser::CompareAndAddNameL( const TDesC& aProposal, + CDesCArray& aNameArray ) + { + TInt pos = 0; // This is needed only for calling Find(). + // Append to array, if aProposal don't already exist in the array. + if ( aNameArray.Find( aProposal, pos, ECmpNormal ) ) + { + aNameArray.AppendL( aProposal ); + } + } + + + +// ----------------------------------------------------------------------------- +// X509CertNameParser::HandleErrorL +// +// ----------------------------------------------------------------------------- + +TInt X509CertNameParser::HandleErrorL( TInt aError ) + { + if ( !( aError == KErrNone || aError == KErrArgument || aError == KErrNotSupported ) ) + { + User::Leave( aError ); + } + return aError; + } + +// End of File