pkiutilities/x509certnameparser/src/X509CertNameParser.cpp
changeset 0 164170e6151a
equal deleted inserted replaced
-1:000000000000 0:164170e6151a
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Extracts relevant certificate information to be shown to user.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "X509CertNameParser.h"
       
    21 #include <x509cert.h>       //X509Certificate
       
    22 #include <x500dn.h>         // CX500DistinguishedName
       
    23 #include <pkixcertchain.h>  // OIDS for the extensions
       
    24 #include <escapeutils.h>    // for escape decoding
       
    25 
       
    26 // CONSTANTS
       
    27 _LIT (KX509CertParserSpace, " ");
       
    28 
       
    29 // Max length of array in case of PrimaryAndSecondaryNameL.
       
    30 const TInt KX509CNPPrimAndSecondNameLengh( 3 ); 
       
    31 
       
    32 // ============================ MEMBER FUNCTIONS =============================== 
       
    33                                                                                                                                                                
       
    34 // -----------------------------------------------------------------------------
       
    35 // X509CertNameParser::PrimaryAndSecondaryNameL
       
    36 //
       
    37 // -----------------------------------------------------------------------------
       
    38 EXPORT_C TInt X509CertNameParser::PrimaryAndSecondaryNameL( 
       
    39                                       const CX509Certificate& aCertificate,
       
    40                                       HBufC*& aPrimaryName, 
       
    41                                       HBufC*& aSecondaryName,
       
    42                                       const TDesC& aLabel)
       
    43     {
       
    44     // Get subjectname
       
    45     const CX500DistinguishedName& dName = aCertificate.SubjectName();
       
    46     // Get subject alternative name
       
    47     const CX509CertExtension* extension = 
       
    48         aCertificate.Extension( KSubjectAltName );
       
    49 
       
    50     CDesCArrayFlat* nameArray = new( ELeave ) CDesCArrayFlat(3);
       
    51     CleanupStack::PushL( nameArray );
       
    52     // Append label to array
       
    53     nameArray->AppendL( aLabel );
       
    54     
       
    55     // Get PrimaryName and SecondaryName to nameArray if they exists.
       
    56     GetNamePartsL( dName, extension, *nameArray, EX509CNPPrimAndSecond );
       
    57     
       
    58     // Make sure that these are NULL
       
    59     aPrimaryName = NULL;
       
    60     aSecondaryName = NULL;
       
    61 
       
    62     switch ( nameArray->MdcaCount() )
       
    63         {
       
    64         case 1: //Neither PrimaryName nor SecondaryName found
       
    65             {
       
    66             aPrimaryName = HBufC::NewLC( KNullDesC.iTypeLength );
       
    67             *aPrimaryName = KNullDesC;
       
    68             aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength );
       
    69             *aSecondaryName = KNullDesC;
       
    70             break;
       
    71             }
       
    72         case 2: // Only PrimaryName found
       
    73             {
       
    74             aPrimaryName = HBufC::NewLC(( *nameArray)[1].Length() );
       
    75             *aPrimaryName = ( *nameArray )[1];
       
    76             aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength );
       
    77             *aSecondaryName = KNullDesC;
       
    78             break;
       
    79             }
       
    80         case 3: // Both found
       
    81             {
       
    82             aPrimaryName = HBufC::NewLC(( *nameArray)[1].Length() );
       
    83             *aPrimaryName = ( *nameArray )[1];
       
    84             aSecondaryName = HBufC::NewLC( ( *nameArray )[2].Length() );
       
    85             *aSecondaryName = ( *nameArray )[2];
       
    86             break;
       
    87             }
       
    88         default: // Something went wrong.
       
    89             {
       
    90             aPrimaryName = HBufC::NewLC( KNullDesC.iTypeLength );
       
    91             *aPrimaryName = KNullDesC;
       
    92             aSecondaryName = HBufC::NewLC( KNullDesC.iTypeLength );
       
    93             *aSecondaryName = KNullDesC;
       
    94             break;
       
    95             }
       
    96         }
       
    97 
       
    98     if ( aSecondaryName )
       
    99         {
       
   100         CleanupStack::Pop( aSecondaryName ); // aSecondaryName
       
   101         }
       
   102     if ( aPrimaryName )
       
   103         {
       
   104         CleanupStack::Pop( aPrimaryName ); // aPrimaryName
       
   105         }
       
   106     CleanupStack::PopAndDestroy( nameArray ); //  nameArray
       
   107     return KErrNone;
       
   108     }
       
   109 
       
   110 // -----------------------------------------------------------------------------
       
   111 // X509CertNameParser::SubjectFullNameL
       
   112 // 
       
   113 // -----------------------------------------------------------------------------
       
   114 
       
   115 EXPORT_C TInt X509CertNameParser::SubjectFullNameL(
       
   116                                       const CX509Certificate& aCertificate,
       
   117                                       HBufC*& aSubjectName,
       
   118 									  const TDesC& aLabel )
       
   119     {
       
   120     // Get subjectname
       
   121     const CX500DistinguishedName& dName = aCertificate.SubjectName();
       
   122     // Get subject alternative name
       
   123     const CX509CertExtension* extension = 
       
   124         aCertificate.Extension( KSubjectAltName );
       
   125     
       
   126     return GetFullNameL( dName, extension, aSubjectName, aLabel );
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // X509CertNameParser::IssuerFullNameL
       
   131 //  
       
   132 // -----------------------------------------------------------------------------
       
   133                                                                                 
       
   134 EXPORT_C TInt X509CertNameParser::IssuerFullNameL( 
       
   135                                       const CX509Certificate& aCertificate,
       
   136                                       HBufC*& aIssuerName )
       
   137     {
       
   138     // Get issuerName
       
   139     const CX500DistinguishedName& dName = aCertificate.IssuerName();
       
   140     // Get issuer alternative name
       
   141     const CX509CertExtension* extension = 
       
   142         aCertificate.Extension( KIssuerAltName );
       
   143 
       
   144     return GetFullNameL( dName, extension, aIssuerName );
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // X509CertNameParser::GetFullNameL
       
   149 // 
       
   150 // -----------------------------------------------------------------------------
       
   151 TInt X509CertNameParser::GetFullNameL( 
       
   152                               const CX500DistinguishedName& aDN, 
       
   153                               const CX509CertExtension* aExtension,
       
   154                               HBufC*& aName,
       
   155                               const TDesC& aLabel )
       
   156     {
       
   157     CDesCArrayFlat* nameArray = new( ELeave ) CDesCArrayFlat(3);
       
   158     CleanupStack::PushL( nameArray );
       
   159     // Add label to array. It is used for comparing.
       
   160     nameArray->AppendL( aLabel );
       
   161 
       
   162     // Collect name parts to array
       
   163     GetNamePartsL( aDN, aExtension, *nameArray, EX509CNPFullName);
       
   164     
       
   165     // Count length of the aName.
       
   166     TInt length = 0;
       
   167     TInt i = 1; // Pass label
       
   168     for ( ; i < nameArray->MdcaCount(); i++ )
       
   169         { 
       
   170         length += (*nameArray)[i].Length();
       
   171         length += KX509CNPComma.iTypeLength;
       
   172         }
       
   173     
       
   174     // Add elements of the array to aName.
       
   175     // First element is label, so it is passed.
       
   176     aName = HBufC::NewLC( length );
       
   177     for ( i = 1; i < nameArray->MdcaCount(); i++ )
       
   178         {
       
   179         if ( i != 1 )
       
   180             {
       
   181             aName->Des().Append( KX509CNPComma );
       
   182             }
       
   183         aName->Des().Append( (*nameArray)[i] );   
       
   184         }
       
   185 
       
   186     CleanupStack::Pop( aName ); 
       
   187     CleanupStack::PopAndDestroy( nameArray ); 
       
   188 
       
   189     return KErrNone;
       
   190     }
       
   191 
       
   192 // -----------------------------------------------------------------------------
       
   193 // X509CertNameParser::GetNamePartsL
       
   194 // 
       
   195 // -----------------------------------------------------------------------------
       
   196 
       
   197 TInt X509CertNameParser::GetNamePartsL( 
       
   198                              const CX500DistinguishedName& aDN, 
       
   199                              const CX509CertExtension* aExtension, 
       
   200                              CDesCArray& aNameArray, 
       
   201                              TX509CNPNameType aNameType)
       
   202     {
       
   203     const CX509AltNameExt* altNameExt = NULL;
       
   204     
       
   205     if (aExtension)
       
   206         {
       
   207         altNameExt = CX509AltNameExt::NewLC( aExtension->Data() ); 
       
   208         }
       
   209 
       
   210     TBool notFound = ETrue; 
       
   211     
       
   212     // In case of PrimaryAndSecondaryName loop goes through name elements
       
   213     // until two of them is found.
       
   214     // In case of FullNames loop goes through all supported name element and
       
   215     // adds founded names to array.
       
   216     for( TInt round = 1; notFound; round++ )
       
   217         {
       
   218         switch( round )
       
   219             {
       
   220             case EDNCommonName:
       
   221                 {
       
   222                 GetDNPartL( aDN, KX520CommonName, aNameArray );
       
   223                 break;
       
   224                 }
       
   225             case ECritAltRFC822Name:
       
   226                 {
       
   227                 if (aExtension && aExtension->Critical())
       
   228                     {
       
   229                     GetAltNamePartL( *altNameExt, EX509RFC822Name, aNameArray );
       
   230                     }
       
   231                 break;
       
   232                 }
       
   233             case EDNOrganizationName:
       
   234                 {
       
   235                 GetDNPartL( aDN, KX520OrganizationName, aNameArray);    
       
   236                 break;  
       
   237                 }
       
   238             case EDNOrganizationalUnitName:
       
   239                 {
       
   240                 if ( aNameType == EX509CNPPrimAndSecond )
       
   241                     {
       
   242                     GetDNPartL( aDN, KX520OrganizationalUnitName, aNameArray);    
       
   243                     }
       
   244                 else
       
   245                     {
       
   246                     GetDNPartAllL( aDN, KX520OrganizationalUnitName, aNameArray);    
       
   247                     }
       
   248                 break;
       
   249                 }
       
   250             case ECritAltURI:
       
   251                 {
       
   252                 if (aExtension && aExtension->Critical())
       
   253                     {
       
   254                     GetAltNamePartL( *altNameExt, EX509URI, aNameArray );
       
   255                     }
       
   256                 break;
       
   257                 }
       
   258             case ECritAltDNSName:
       
   259                 {
       
   260                 if (aExtension && aExtension->Critical())
       
   261                     {
       
   262                     GetAltNamePartL( *altNameExt, EX509DNSName, aNameArray);
       
   263                     }
       
   264                 break;
       
   265                 }
       
   266             case ECritAltDirectoryName:
       
   267                 {
       
   268                 if (aExtension && aExtension->Critical())
       
   269                     {
       
   270                     GetAltNamePartL( *altNameExt, EX509DirectoryName, 
       
   271                                      aNameArray );                                   
       
   272                     }
       
   273                 break;
       
   274                 }
       
   275             case ECritAltIPAddress:
       
   276                 {
       
   277                 if (aExtension && aExtension->Critical())
       
   278                     {
       
   279                     GetAltNamePartL( *altNameExt, EX509IPAddress, 
       
   280                                      aNameArray );                                   
       
   281                     }
       
   282                 break;
       
   283                 } 
       
   284             case EAltRFC822Name:
       
   285                 {
       
   286                 if (aExtension)
       
   287                     {
       
   288                     GetAltNamePartL( *altNameExt, EX509RFC822Name, 
       
   289                                       aNameArray );
       
   290                     }
       
   291                 break;
       
   292                 }
       
   293             case EAltURI:
       
   294                 {
       
   295                 if ( aExtension )
       
   296                     {
       
   297                     GetAltNamePartL( *altNameExt, EX509URI, aNameArray );
       
   298                     }
       
   299                 break;
       
   300                 }
       
   301             case EAltDNSName:
       
   302                 {
       
   303                 if ( aExtension )
       
   304                     {
       
   305                     GetAltNamePartL( *altNameExt, EX509DNSName, aNameArray );
       
   306                     }  
       
   307                 break;
       
   308                 }
       
   309             case EDNCountryName:
       
   310                 {
       
   311                 GetDNPartL( aDN, KX520CountryName, aNameArray );
       
   312                 break;
       
   313                 }
       
   314             case EDNStateOrProvinceName:
       
   315                 {
       
   316                 GetDNPartL( aDN, KX520StateOrProvinceName, aNameArray );
       
   317                 break;
       
   318                 }
       
   319             case EDNLocalityName:
       
   320                 {
       
   321                 GetDNPartL( aDN, KX520LocalityName, aNameArray );
       
   322                 break;
       
   323                 }
       
   324             case EAltDirectoryName:
       
   325                 {
       
   326                 if ( aExtension )
       
   327                     {
       
   328                     GetAltNamePartL( *altNameExt, EX509DirectoryName, 
       
   329                                      aNameArray );
       
   330                     }
       
   331                 break;
       
   332                 }
       
   333             case EAltIPAddress:
       
   334                 {
       
   335                 if ( aExtension )
       
   336                     {
       
   337                     GetAltNamePartL( *altNameExt, EX509IPAddress, 
       
   338                                      aNameArray );                                   
       
   339                     }
       
   340                 break;
       
   341                 }    
       
   342             default:
       
   343                 {
       
   344                 // All the names are gone through.
       
   345                 notFound = EFalse;
       
   346                 break;
       
   347                 }
       
   348             } // switch
       
   349 
       
   350         if ( notFound ) 
       
   351             {
       
   352             // If caller is PrimaryAndSecondaryNameL and PrimaryName and
       
   353             // SecondaryName have found then end loop.
       
   354             if ( aNameType == EX509CNPPrimAndSecond &&  
       
   355                ( aNameArray.MdcaCount() >= KX509CNPPrimAndSecondNameLengh ) )
       
   356                 {
       
   357                 notFound = EFalse;    
       
   358                 } // if
       
   359             } // if 
       
   360         } // for
       
   361     
       
   362     if ( aExtension )
       
   363         {
       
   364         CleanupStack::PopAndDestroy(); // altNameExt
       
   365         }
       
   366     return KErrNone;
       
   367     }
       
   368 
       
   369 // -----------------------------------------------------------------------------
       
   370 // X509CertNameParser::GetDNPartAllL
       
   371 // 
       
   372 // -----------------------------------------------------------------------------
       
   373 
       
   374 void X509CertNameParser::GetDNPartAllL(
       
   375                              const CX500DistinguishedName& aDN, 
       
   376                              const TDesC& aSubPartOID, 
       
   377                              CDesCArray& aNameArray )
       
   378     {
       
   379     HBufC* buf = NULL;
       
   380     // Count of the name parts of the DN
       
   381     TInt count = aDN.Count();
       
   382 
       
   383     // This goes through all the nameparts of the DN and appends all the
       
   384     // parts, that OID is aSubPartOID, to the array.
       
   385 	for ( TInt i = 0; i < count; i++ )
       
   386 		{
       
   387 		const CX520AttributeTypeAndValue& ava = aDN.Element( i );
       
   388 		if ( ava.Type() == aSubPartOID )
       
   389 			{
       
   390 			TRAPD( error, buf = ava.ValueL() );
       
   391             HandleErrorL( error );
       
   392             
       
   393             if ( buf )
       
   394                 {
       
   395                 CleanupStack::PushL( buf );
       
   396                 CompareAndAddNameL( *buf, aNameArray );
       
   397                 CleanupStack::PopAndDestroy( buf ); // buf
       
   398                 buf = NULL; 
       
   399                 } // if 
       
   400             } // if
       
   401         } // for
       
   402     }
       
   403 
       
   404 // -----------------------------------------------------------------------------
       
   405 // X509CertNameParser::GetDNPartL
       
   406 // 
       
   407 // -----------------------------------------------------------------------------
       
   408 
       
   409 void X509CertNameParser::GetDNPartL( 
       
   410                              const CX500DistinguishedName& aDN, 
       
   411                              const TDesC& aSubPartOID, 
       
   412                              CDesCArray& aNameArray )
       
   413     {
       
   414     HBufC* buf = NULL;
       
   415     // Extract one DN part
       
   416     TRAPD( error, buf = aDN.ExtractFieldL( aSubPartOID ) );
       
   417     HandleErrorL( error );
       
   418 
       
   419     // Add to array
       
   420     if ( buf )
       
   421         {
       
   422         CleanupStack::PushL( buf );
       
   423         CompareAndAddNameL( *buf, aNameArray );
       
   424         CleanupStack::PopAndDestroy( buf );  // buf
       
   425         }
       
   426     }
       
   427 
       
   428 // -----------------------------------------------------------------------------
       
   429 // X509CertNameParser::GetAltNamePartL
       
   430 // 
       
   431 // -----------------------------------------------------------------------------
       
   432 
       
   433 void X509CertNameParser::GetAltNamePartL( 
       
   434                              const CX509AltNameExt& aAltName, 
       
   435                              const TGNType& aSubPartType, 
       
   436                              CDesCArray& aNameArray )
       
   437     {
       
   438     // Get all parts of the alternative name to the array
       
   439     const CArrayPtrFlat<CX509GeneralName>& subParts = aAltName.AltName();
       
   440     TInt count = subParts.Count();
       
   441     CX509DomainName* domainName = NULL;
       
   442     TInt error = KErrNone;  
       
   443 
       
   444     // This goes through all the nameparts of the DN and appends all the
       
   445     // parts, that OID is aSubPartOID, to the array.
       
   446     for (TInt i = 0; count > i; i++)
       
   447         {
       
   448         if ( subParts[i]->Tag() == aSubPartType )
       
   449             {
       
   450             TPtrC8 data = subParts[i]->Data(); 
       
   451             switch ( aSubPartType )
       
   452                 {
       
   453                 case EX509RFC822Name:
       
   454                     {
       
   455                     TRAP( error, domainName = CX509RFC822Name::NewL( data ) );
       
   456                     CleanupStack::PushL( domainName );
       
   457                     AddAltNameToArrayL( error, domainName, aNameArray );
       
   458                     CleanupStack::PopAndDestroy( domainName );     
       
   459                     break;
       
   460                     }
       
   461                 case EX509DNSName:
       
   462                 case EX509DirectoryName:
       
   463                     {
       
   464                     TRAP( error, domainName = CX509DNSName::NewL( data ) );
       
   465                     CleanupStack::PushL( domainName );
       
   466                     AddAltNameToArrayL( error, domainName, aNameArray );
       
   467                     CleanupStack::PopAndDestroy( domainName );
       
   468                     break;
       
   469                     }
       
   470                 case EX509URI:
       
   471                     {
       
   472                     CX509IPBasedURI* uri = NULL;
       
   473                     HBufC* decodedUri = NULL;
       
   474                     TRAP( error, uri = CX509IPBasedURI::NewL( data ) );
       
   475                     
       
   476                     if ( error == KErrNone )
       
   477                         {
       
   478                         CleanupStack::PushL( uri );
       
   479                         TRAP( error, decodedUri = EscapeUtils::
       
   480                             EscapeDecodeL( uri->Name() ) );
       
   481                         CleanupStack::PopAndDestroy(); //uri
       
   482                         }
       
   483                     
       
   484                     HandleErrorL( error );
       
   485                     if ( error == KErrNone )
       
   486                         {
       
   487                         CleanupStack::PushL( decodedUri );
       
   488                         CompareAndAddNameL( *decodedUri, aNameArray );
       
   489                         CleanupStack::PopAndDestroy(); // decodedUri
       
   490                         }
       
   491                     break;
       
   492                     }
       
   493                 case EX509IPAddress:
       
   494                     {
       
   495                     // Not supported
       
   496                     break;
       
   497                     }
       
   498                 default:
       
   499                     {
       
   500                     break;
       
   501                     }
       
   502                 } // switch
       
   503             } // if 
       
   504         } // for
       
   505     }
       
   506 
       
   507 // -----------------------------------------------------------------------------
       
   508 // X509CertNameParser::AddAltNameToArrayL
       
   509 // 
       
   510 // -----------------------------------------------------------------------------
       
   511 
       
   512 TInt X509CertNameParser::AddAltNameToArrayL( 
       
   513                             TInt aError, 
       
   514                             CX509DomainName* aDomainName, 
       
   515                             CDesCArray& aNameArray )
       
   516     {
       
   517     TInt error = HandleErrorL( aError );
       
   518     
       
   519     if ( error == KErrNone )
       
   520         {
       
   521         const TPtrC name = aDomainName->Name();
       
   522         CompareAndAddNameL( name, aNameArray );
       
   523         }
       
   524 
       
   525     return error;
       
   526     }
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // X509CertNameParser::AddToBufLD
       
   530 // 
       
   531 // -----------------------------------------------------------------------------
       
   532 
       
   533 void X509CertNameParser::AddToBufLD( const TDesC& aName, HBufC*& aBuf )
       
   534     {
       
   535     if (!aBuf)
       
   536         {
       
   537         aBuf = HBufC::NewL( aName.Length() );
       
   538         aBuf->Des().Append( aName );
       
   539         }
       
   540     else
       
   541         {
       
   542         HBufC* helpBuf = HBufC::NewL( aName.Length() + aBuf->Length() + 1);
       
   543         helpBuf->Des().Append( *aBuf );
       
   544         helpBuf->Des().Append( KX509CertParserSpace );
       
   545         helpBuf->Des().Append( aName );
       
   546         CleanupStack::PopAndDestroy( aBuf ); // aBuf
       
   547         aBuf = helpBuf;
       
   548         }
       
   549     }
       
   550 
       
   551 // -----------------------------------------------------------------------------
       
   552 // X509CertNameParser::CompareAndAddNameL
       
   553 // 
       
   554 // -----------------------------------------------------------------------------
       
   555 
       
   556 void X509CertNameParser::CompareAndAddNameL( const TDesC& aProposal, 
       
   557                                              CDesCArray& aNameArray )
       
   558     {
       
   559     TInt pos = 0; // This is needed only for calling Find().
       
   560     // Append to array, if aProposal don't already exist in the array.
       
   561     if ( aNameArray.Find( aProposal, pos, ECmpNormal ) )
       
   562         {
       
   563         aNameArray.AppendL( aProposal );
       
   564         }
       
   565     }
       
   566 
       
   567 
       
   568 
       
   569 // -----------------------------------------------------------------------------
       
   570 // X509CertNameParser::HandleErrorL
       
   571 // 
       
   572 // -----------------------------------------------------------------------------
       
   573 
       
   574 TInt X509CertNameParser::HandleErrorL( TInt aError )
       
   575     {    
       
   576     if ( !( aError == KErrNone || aError == KErrArgument || aError == KErrNotSupported ) )
       
   577         {
       
   578         User::Leave( aError );
       
   579         }       
       
   580     return aError;
       
   581     }
       
   582     
       
   583 //  End of File