os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlsnames.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 1997-2009 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 the License "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: 
    15 *
    16 */
    17 
    18 
    19 #include <wtlsnames.h>
    20 #include "wtlsdec.h"
    21 #include <x500dn.h>
    22 #include <utf.h>
    23 
    24 _LIT(KWTLSStructuredTextFieldSeparator, ";");
    25 _LIT(KWTLSStructuredTextAssignmentCharacter, "=");
    26 const TInt KWTLSTextHeaderLength = 3;
    27 
    28 EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData)
    29 	{
    30 	TInt pos = 0;
    31 	return CWTLSName::NewL(aBinaryData, pos);
    32 	}
    33 
    34 EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData)
    35 	{
    36 	TInt pos = 0;
    37 	return CWTLSName::NewLC(aBinaryData, pos);
    38 	}
    39 
    40 EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData, TInt& aPos)
    41 	{
    42 	CWTLSName* self = CWTLSName::NewLC(aBinaryData, aPos);
    43 	CleanupStack::Pop();
    44 	return self;
    45 	}
    46 
    47 EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData, TInt& aPos)
    48 	{
    49 	CWTLSName* self = new(ELeave) CWTLSName;
    50 	CleanupStack::PushL(self);
    51 	self->ConstructL(aBinaryData, aPos);
    52 	return self;
    53 	}
    54 
    55 EXPORT_C CWTLSName* CWTLSName::NewL(const CWTLSName& aName)
    56 	{
    57 	CWTLSName* self = CWTLSName::NewLC(aName);
    58 	CleanupStack::Pop();
    59 	return self;
    60 	}
    61 
    62 EXPORT_C CWTLSName* CWTLSName::NewLC(const CWTLSName& aName)	
    63 	{
    64 	CWTLSName* self = new(ELeave) CWTLSName;
    65 	CleanupStack::PushL(self);
    66 	self->ConstructL(aName);
    67 	return self;
    68 	}
    69 
    70 CWTLSName::CWTLSName() 	
    71 	{
    72 	}
    73 
    74 void CWTLSName::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
    75 	{
    76 	if ((aBinaryData.Length() - aPos) < 1)
    77 		{
    78 		User::Leave(KErrArgument);
    79 		}
    80 	iNameType = aBinaryData[aPos];
    81 	aPos++;
    82 	switch(iNameType)
    83 		{
    84 		case EWTLSText:
    85 			{
    86 			AllocTextDataL(aBinaryData, aPos);
    87 			break;
    88 			}
    89 		case EWTLSX500DN:
    90 			{
    91 			AllocNameDataL(aBinaryData, aPos);
    92 			break;
    93 			}
    94 		default:
    95 			{
    96 			User::Leave(KErrNotSupported);
    97 			}
    98 		}
    99 	}
   100 
   101 void CWTLSName::ConstructL(const CWTLSName& aName)
   102 	{
   103 	iNameType = aName.iNameType;
   104 	iNameData = aName.iNameData->AllocL();
   105 	}
   106 
   107 EXPORT_C CWTLSName::~CWTLSName() 	
   108 	{
   109 	delete iNameData;
   110 	}
   111 
   112 void CWTLSName::AllocTextDataL(const TDesC8& aBinaryData, TInt& aPos)
   113 	{
   114 	if ((aBinaryData.Length() - aPos) < KWTLSTextHeaderLength)
   115 		{
   116 		User::Leave(KErrArgument);
   117 		}
   118 	TInt nameLength = (aBinaryData[aPos+2] + KWTLSTextHeaderLength);
   119 	if ((aBinaryData.Length() ) < (aPos+nameLength))
   120 		{
   121 		User::Leave(KErrArgument);
   122 		}
   123 	iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
   124 	aPos += nameLength;
   125 	}
   126 
   127 void CWTLSName::AllocNameDataL(const TDesC8& aBinaryData, TInt& aPos)
   128 	{
   129 	if ((aBinaryData.Length() - aPos) < 1)
   130 		{
   131 		User::Leave(KErrArgument);
   132 		}
   133 	TUint8 nameLength = aBinaryData[aPos];
   134 	aPos++;
   135 	if (aBinaryData.Length() - (aPos + nameLength) < 0)
   136 		{
   137 		User::Leave(KErrArgument);
   138 		}
   139 	iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
   140 	aPos += nameLength;
   141 	}
   142 
   143 EXPORT_C TBool CWTLSName::ExactMatchL(const CWTLSName& aName) const	
   144 	{		
   145 //hmmm, in the absence of any matching rules, just match the bytes...
   146  	return (*(iNameData) == *(aName.iNameData));
   147 	}
   148 
   149 EXPORT_C TWTLSNameType CWTLSName::NameType() const
   150 	{
   151 	return iNameType;
   152 	}
   153 
   154 EXPORT_C TPtrC8 CWTLSName::NameData() const
   155 	{
   156 	return *iNameData;
   157 	}
   158 
   159 EXPORT_C HBufC* CWTLSName::DisplayNameL() const
   160 	{
   161 	switch (iNameType)
   162 		{
   163 		case EWTLSText:
   164 			{
   165 			CWTLSStructuredText* sText = NULL;
   166 			TRAPD(err, sText = CWTLSStructuredText::NewL(*iNameData));
   167 			if (err != KErrNone)
   168 				{
   169 				if (err != KErrArgument)
   170 					{
   171 					User::Leave(err);
   172 					}
   173 				else
   174 					{
   175 					CWTLSText* text = CWTLSText::NewLC(*iNameData);
   176 					HBufC* res = text->Name().AllocL();
   177 					CleanupStack::PopAndDestroy();//text
   178 					return res;
   179 					}
   180 				}
   181 			else
   182 				{
   183 				CleanupStack::PushL(sText);
   184 				HBufC* res = sText->DisplayNameL();
   185 				CleanupStack::PopAndDestroy();//sText
   186 				return res;
   187 				}
   188 			}
   189 		case EWTLSX500DN:
   190 			{
   191 			CX500DistinguishedName* dN = CX500DistinguishedName::NewLC(*iNameData);
   192 			HBufC* res = dN->DisplayNameL();
   193 			CleanupStack::PopAndDestroy();//dN
   194 			return res;
   195 			}
   196 		default:
   197 			{
   198 			User::Leave(KErrNotSupported);
   199 			return NULL;//never gets to here...
   200 			}
   201 		}
   202 	}
   203 
   204 //************************************************************************//
   205 //text name
   206 EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData)
   207 	{
   208 	TInt pos = 0;
   209 	return CWTLSText::NewL(aBinaryData, pos);
   210 	}
   211 
   212 EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData)
   213 	{
   214 	TInt pos = 0;
   215 	return CWTLSText::NewLC(aBinaryData, pos);
   216 	}
   217 
   218 EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData, TInt& aPos)
   219 	{
   220 	CWTLSText* self = CWTLSText::NewLC(aBinaryData, aPos);
   221 	CleanupStack::Pop();
   222 	return self;
   223 	}
   224 
   225 EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   226 	{
   227 	CWTLSText* self = new(ELeave) CWTLSText;
   228 	CleanupStack::PushL(self);
   229 	self->ConstructL(aBinaryData, aPos);
   230 	return self;
   231 	}
   232 
   233 EXPORT_C CWTLSText::~CWTLSText() 	
   234 	{
   235 	delete iName;
   236 	}
   237 
   238 EXPORT_C TBool CWTLSText::ExactMatchL(const CWTLSText& aName) const
   239 	{
   240 //subtle difference between this byte-match and 
   241 //CWTLSName::ExactMatchL(...) is that this should successfully match 2 names that 
   242 //are the same which were encoded using different character sets...
   243 	return (*iName == *(aName.iName));
   244 	}
   245 
   246 EXPORT_C TPtrC CWTLSText::Name() const
   247 	{
   248 	return *iName;
   249 	}
   250 
   251 EXPORT_C TWTLSCharSet CWTLSText::CharacterSet() const
   252 	{
   253 	return iCharacterSet;
   254 	}
   255 
   256 CWTLSText::CWTLSText()
   257 	{
   258 	}
   259 
   260 void CWTLSText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   261 	{
   262 	if ((aBinaryData.Length() - aPos) < 3)
   263 		{
   264 		User::Leave(KErrArgument);
   265 		}
   266 	TWTLSDecUnsignedInteger decInt;
   267 	iCharacterSet = decInt.DecodeShortL(aBinaryData, aPos, 2);
   268 	TUint8 nameLength = aBinaryData[aPos];
   269 	aPos++;
   270 	if (aBinaryData.Length() < (aPos + nameLength))
   271 		{
   272 		User::Leave(KErrArgument);
   273 		}
   274 	TPtrC8 ptr = aBinaryData.Mid(aPos, nameLength);
   275 	//only works for latin-1 here...
   276 	iName = HBufC::NewL(ptr.Length());
   277 	switch (iCharacterSet)
   278 		{
   279 		case KWTLSLatin1CharSet://=latin-1
   280 			{
   281 			TPtr pRes = iName->Des();
   282 			pRes.Copy(ptr);
   283 			aPos+=nameLength;
   284 			break;
   285 			}
   286 		case KWTLSUTF8CharSet:
   287 			{
   288 			TPtr pRes = iName->Des();
   289 			User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(pRes, ptr));	
   290 			break;
   291 			}
   292 		default:
   293 			{
   294 			User::Leave(KErrNotSupported);
   295 			}
   296 		}
   297 	}
   298 
   299 TWTLSStructuredTextField::TWTLSStructuredTextField(const TDesC& aType, const TDesC& aValue)
   300 	:iType(aType), iValue(aValue)
   301 	{
   302 	}
   303 
   304 EXPORT_C TPtrC TWTLSStructuredTextField::Type() const
   305 	{
   306 	return iType;
   307 	}
   308 
   309 EXPORT_C TPtrC TWTLSStructuredTextField::Value() const
   310 	{
   311 	return iValue;
   312 	}
   313 
   314 //Structured text class
   315 EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData)
   316 	{
   317 	TInt pos = 0;
   318 	return CWTLSStructuredText::NewL(aBinaryData, pos);
   319 	}
   320 
   321 EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData)
   322 	{
   323 	TInt pos = 0;
   324 	return CWTLSStructuredText::NewLC(aBinaryData, pos);
   325 	}
   326 
   327 EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData, TInt& aPos)
   328 	{
   329 	CWTLSStructuredText* self = CWTLSStructuredText::NewLC(aBinaryData, aPos);
   330 	CleanupStack::Pop();
   331 	return self;
   332 	}
   333 
   334 EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   335 	{
   336 	CWTLSStructuredText* self = new(ELeave) CWTLSStructuredText;
   337 	CleanupStack::PushL(self);
   338 	self->ConstructL(aBinaryData, aPos);
   339 	return self;
   340 	}
   341 
   342 EXPORT_C CWTLSStructuredText::~CWTLSStructuredText()
   343 	{
   344 	delete iFields;
   345 	}
   346 
   347 EXPORT_C HBufC* CWTLSStructuredText::DisplayNameL() const
   348 	{
   349 	if (iFields->Count() > 3)
   350 		{
   351 		return iFields->At(3).Value().AllocL();
   352 		}
   353 	else
   354 		{
   355 		return iFields->At(1).Value().AllocL();
   356 		}
   357 	}
   358 
   359 	//accessors for defined fields
   360 EXPORT_C TPtrC CWTLSStructuredText::ServiceName() const
   361 	{
   362 	//construction ensures iFields must have at least 3 elements
   363 	return iFields->At(0).Value();
   364 	}
   365 
   366 EXPORT_C TPtrC CWTLSStructuredText::Organization() const
   367 	{
   368 	//construction ensures iFields must have at least 3 elements
   369 	return iFields->At(1).Value();
   370 	}
   371 
   372 EXPORT_C TPtrC CWTLSStructuredText::Country() const
   373 	{
   374 	//construction ensures iFields must have at least 3 elements
   375 	return iFields->At(2).Value();
   376 	}
   377 
   378 EXPORT_C TInt CWTLSStructuredText::Count() const
   379 	{
   380 	return iFields->Count();
   381 	}
   382 
   383 EXPORT_C const TWTLSStructuredTextField* CWTLSStructuredText::FieldByName(const TDesC& aType) const
   384 	{
   385 	TInt count = iFields->Count();
   386 	for (TInt i = 0; i < count; i++)
   387 		{
   388 		TWTLSStructuredTextField* field = &(iFields->At(i));
   389 		if (field->Type() == aType)
   390 			{
   391 			return field;
   392 			}
   393 		}
   394 	return NULL;
   395 	}
   396 
   397 EXPORT_C const TWTLSStructuredTextField& CWTLSStructuredText::FieldByIndex(TInt aIndex) const
   398 	{
   399 	return iFields->At(aIndex);
   400 	}
   401 
   402 CWTLSStructuredText::CWTLSStructuredText()
   403 	{
   404 	}
   405 
   406 void CWTLSStructuredText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   407 	{
   408 	CWTLSText::ConstructL(aBinaryData, aPos);
   409 	iFields = new(ELeave) CArrayFixFlat<TWTLSStructuredTextField> (4);
   410 	TInt pos = 0;
   411 	TInt end = iName->Length();
   412 	AddFieldValueL(KWTLSServiceName, pos);
   413 	AddFieldValueL(KWTLSOrganizationName, pos);
   414 	AddFieldValueL(KWTLSCountryName, pos);
   415 	if (pos < end)
   416 		{
   417 		AddFieldValueL(KWTLSCommonName, pos);
   418 		}
   419 	while (pos < end)
   420 		{
   421 		AddFieldL(pos);
   422 		}
   423 	}
   424 
   425 void CWTLSStructuredText::AddFieldValueL(const TDesC& aFieldName, TInt& aPos)
   426 	{
   427 	TPtrC startOfData = iName->Right(iName->Length() - aPos);
   428 	TPtrC value = GetFieldL(startOfData, aPos);
   429 	TWTLSStructuredTextField field(aFieldName, value);
   430 	iFields->AppendL(field);
   431 	}
   432 
   433 void CWTLSStructuredText::AddFieldL(TInt& aPos)
   434 	{
   435 	TPtrC startOfData = iName->Right(iName->Length() - aPos);
   436 	TPtrC fieldData = GetFieldL(startOfData, aPos);
   437 	TInt fieldLength = fieldData.Length();
   438 	TInt endType = fieldData.FindF(KWTLSStructuredTextAssignmentCharacter);
   439 	if ((endType == KErrNotFound) || ((endType+1) == fieldLength))
   440 		{
   441 		User::Leave(KErrArgument);
   442 		}
   443 	TPtrC type = fieldData.Left(endType);
   444 	TPtrC value = fieldData.Right(	fieldLength - (endType+1)	);
   445 	TWTLSStructuredTextField field(type, value);
   446 	iFields->AppendL(field);
   447 	}
   448 
   449 TPtrC CWTLSStructuredText::GetFieldL(TDesC& aString, TInt& aPos)
   450 	{
   451 //aString = where we've got up to
   452 //aPos = start of this chunk of name data
   453 	TInt length = 0;
   454 	TBool done = GetSubFieldL(aString, length);
   455 	while (!done)
   456 		{
   457 		TPtrC remainder = aString.Right(aString.Length() - (length));
   458 		TInt increment = 0;
   459 		done = GetSubFieldL(remainder, increment);
   460 		length += increment;
   461 		}
   462 	if (length == 0)
   463 		{
   464 		//disallow zero-length field values
   465 		User::Leave(KErrArgument);
   466 		}
   467 	aPos += length;
   468 	if (length < aString.Length())
   469 		{
   470 		//if we're not on the last field, skip the ';' character
   471 		aPos++;
   472 		}
   473 	return aString.Left(length);
   474 	}
   475 
   476 TBool CWTLSStructuredText::GetSubFieldL(TDesC& aString, TInt& aPos)
   477 	{
   478 //fields in structured text are separated by ';'. If this character appears 
   479 //in the field text it's represented by ';;'.  so, the string 'symbian;systems' would
   480 //be encoded as 'symbian;;systems'. 
   481 
   482 //starting at the start of aString, this function sets 'aPos' to the position after the 
   483 //first occurrence of ';' in aString. If the character following ';' is also ';' it returns 
   484 //EFalse (meaning, this sub-field isn't a whole field), otherwise it returns ETrue.
   485 
   486 	aPos = aString.FindF(KWTLSStructuredTextFieldSeparator);	
   487 	if (aPos == KErrNotFound)
   488 		{
   489 		aPos = aString.Length();
   490 		}
   491 	else
   492 		{		
   493 		//separator char mustn't be last char
   494 		if (aPos == (aString.Length() -1))
   495 			{
   496 			User::Leave(KErrArgument);
   497 			}
   498 		else
   499 			{
   500 			//if the next char is ';', skip it and return EFalse
   501 			TPtrC next = aString.Mid(aPos + 1, 1);
   502 			if (next == KWTLSStructuredTextFieldSeparator)
   503 				{
   504 				aPos++;
   505 				return EFalse;
   506 				}
   507 			//if it isn't, that's the end of the field
   508 			}
   509 		}
   510 	return ETrue;
   511 	}