1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlsnames.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,511 @@
1.4 +/*
1.5 +* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <wtlsnames.h>
1.23 +#include "wtlsdec.h"
1.24 +#include <x500dn.h>
1.25 +#include <utf.h>
1.26 +
1.27 +_LIT(KWTLSStructuredTextFieldSeparator, ";");
1.28 +_LIT(KWTLSStructuredTextAssignmentCharacter, "=");
1.29 +const TInt KWTLSTextHeaderLength = 3;
1.30 +
1.31 +EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData)
1.32 + {
1.33 + TInt pos = 0;
1.34 + return CWTLSName::NewL(aBinaryData, pos);
1.35 + }
1.36 +
1.37 +EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData)
1.38 + {
1.39 + TInt pos = 0;
1.40 + return CWTLSName::NewLC(aBinaryData, pos);
1.41 + }
1.42 +
1.43 +EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData, TInt& aPos)
1.44 + {
1.45 + CWTLSName* self = CWTLSName::NewLC(aBinaryData, aPos);
1.46 + CleanupStack::Pop();
1.47 + return self;
1.48 + }
1.49 +
1.50 +EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData, TInt& aPos)
1.51 + {
1.52 + CWTLSName* self = new(ELeave) CWTLSName;
1.53 + CleanupStack::PushL(self);
1.54 + self->ConstructL(aBinaryData, aPos);
1.55 + return self;
1.56 + }
1.57 +
1.58 +EXPORT_C CWTLSName* CWTLSName::NewL(const CWTLSName& aName)
1.59 + {
1.60 + CWTLSName* self = CWTLSName::NewLC(aName);
1.61 + CleanupStack::Pop();
1.62 + return self;
1.63 + }
1.64 +
1.65 +EXPORT_C CWTLSName* CWTLSName::NewLC(const CWTLSName& aName)
1.66 + {
1.67 + CWTLSName* self = new(ELeave) CWTLSName;
1.68 + CleanupStack::PushL(self);
1.69 + self->ConstructL(aName);
1.70 + return self;
1.71 + }
1.72 +
1.73 +CWTLSName::CWTLSName()
1.74 + {
1.75 + }
1.76 +
1.77 +void CWTLSName::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
1.78 + {
1.79 + if ((aBinaryData.Length() - aPos) < 1)
1.80 + {
1.81 + User::Leave(KErrArgument);
1.82 + }
1.83 + iNameType = aBinaryData[aPos];
1.84 + aPos++;
1.85 + switch(iNameType)
1.86 + {
1.87 + case EWTLSText:
1.88 + {
1.89 + AllocTextDataL(aBinaryData, aPos);
1.90 + break;
1.91 + }
1.92 + case EWTLSX500DN:
1.93 + {
1.94 + AllocNameDataL(aBinaryData, aPos);
1.95 + break;
1.96 + }
1.97 + default:
1.98 + {
1.99 + User::Leave(KErrNotSupported);
1.100 + }
1.101 + }
1.102 + }
1.103 +
1.104 +void CWTLSName::ConstructL(const CWTLSName& aName)
1.105 + {
1.106 + iNameType = aName.iNameType;
1.107 + iNameData = aName.iNameData->AllocL();
1.108 + }
1.109 +
1.110 +EXPORT_C CWTLSName::~CWTLSName()
1.111 + {
1.112 + delete iNameData;
1.113 + }
1.114 +
1.115 +void CWTLSName::AllocTextDataL(const TDesC8& aBinaryData, TInt& aPos)
1.116 + {
1.117 + if ((aBinaryData.Length() - aPos) < KWTLSTextHeaderLength)
1.118 + {
1.119 + User::Leave(KErrArgument);
1.120 + }
1.121 + TInt nameLength = (aBinaryData[aPos+2] + KWTLSTextHeaderLength);
1.122 + if ((aBinaryData.Length() ) < (aPos+nameLength))
1.123 + {
1.124 + User::Leave(KErrArgument);
1.125 + }
1.126 + iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
1.127 + aPos += nameLength;
1.128 + }
1.129 +
1.130 +void CWTLSName::AllocNameDataL(const TDesC8& aBinaryData, TInt& aPos)
1.131 + {
1.132 + if ((aBinaryData.Length() - aPos) < 1)
1.133 + {
1.134 + User::Leave(KErrArgument);
1.135 + }
1.136 + TUint8 nameLength = aBinaryData[aPos];
1.137 + aPos++;
1.138 + if (aBinaryData.Length() - (aPos + nameLength) < 0)
1.139 + {
1.140 + User::Leave(KErrArgument);
1.141 + }
1.142 + iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
1.143 + aPos += nameLength;
1.144 + }
1.145 +
1.146 +EXPORT_C TBool CWTLSName::ExactMatchL(const CWTLSName& aName) const
1.147 + {
1.148 +//hmmm, in the absence of any matching rules, just match the bytes...
1.149 + return (*(iNameData) == *(aName.iNameData));
1.150 + }
1.151 +
1.152 +EXPORT_C TWTLSNameType CWTLSName::NameType() const
1.153 + {
1.154 + return iNameType;
1.155 + }
1.156 +
1.157 +EXPORT_C TPtrC8 CWTLSName::NameData() const
1.158 + {
1.159 + return *iNameData;
1.160 + }
1.161 +
1.162 +EXPORT_C HBufC* CWTLSName::DisplayNameL() const
1.163 + {
1.164 + switch (iNameType)
1.165 + {
1.166 + case EWTLSText:
1.167 + {
1.168 + CWTLSStructuredText* sText = NULL;
1.169 + TRAPD(err, sText = CWTLSStructuredText::NewL(*iNameData));
1.170 + if (err != KErrNone)
1.171 + {
1.172 + if (err != KErrArgument)
1.173 + {
1.174 + User::Leave(err);
1.175 + }
1.176 + else
1.177 + {
1.178 + CWTLSText* text = CWTLSText::NewLC(*iNameData);
1.179 + HBufC* res = text->Name().AllocL();
1.180 + CleanupStack::PopAndDestroy();//text
1.181 + return res;
1.182 + }
1.183 + }
1.184 + else
1.185 + {
1.186 + CleanupStack::PushL(sText);
1.187 + HBufC* res = sText->DisplayNameL();
1.188 + CleanupStack::PopAndDestroy();//sText
1.189 + return res;
1.190 + }
1.191 + }
1.192 + case EWTLSX500DN:
1.193 + {
1.194 + CX500DistinguishedName* dN = CX500DistinguishedName::NewLC(*iNameData);
1.195 + HBufC* res = dN->DisplayNameL();
1.196 + CleanupStack::PopAndDestroy();//dN
1.197 + return res;
1.198 + }
1.199 + default:
1.200 + {
1.201 + User::Leave(KErrNotSupported);
1.202 + return NULL;//never gets to here...
1.203 + }
1.204 + }
1.205 + }
1.206 +
1.207 +//************************************************************************//
1.208 +//text name
1.209 +EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData)
1.210 + {
1.211 + TInt pos = 0;
1.212 + return CWTLSText::NewL(aBinaryData, pos);
1.213 + }
1.214 +
1.215 +EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData)
1.216 + {
1.217 + TInt pos = 0;
1.218 + return CWTLSText::NewLC(aBinaryData, pos);
1.219 + }
1.220 +
1.221 +EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData, TInt& aPos)
1.222 + {
1.223 + CWTLSText* self = CWTLSText::NewLC(aBinaryData, aPos);
1.224 + CleanupStack::Pop();
1.225 + return self;
1.226 + }
1.227 +
1.228 +EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
1.229 + {
1.230 + CWTLSText* self = new(ELeave) CWTLSText;
1.231 + CleanupStack::PushL(self);
1.232 + self->ConstructL(aBinaryData, aPos);
1.233 + return self;
1.234 + }
1.235 +
1.236 +EXPORT_C CWTLSText::~CWTLSText()
1.237 + {
1.238 + delete iName;
1.239 + }
1.240 +
1.241 +EXPORT_C TBool CWTLSText::ExactMatchL(const CWTLSText& aName) const
1.242 + {
1.243 +//subtle difference between this byte-match and
1.244 +//CWTLSName::ExactMatchL(...) is that this should successfully match 2 names that
1.245 +//are the same which were encoded using different character sets...
1.246 + return (*iName == *(aName.iName));
1.247 + }
1.248 +
1.249 +EXPORT_C TPtrC CWTLSText::Name() const
1.250 + {
1.251 + return *iName;
1.252 + }
1.253 +
1.254 +EXPORT_C TWTLSCharSet CWTLSText::CharacterSet() const
1.255 + {
1.256 + return iCharacterSet;
1.257 + }
1.258 +
1.259 +CWTLSText::CWTLSText()
1.260 + {
1.261 + }
1.262 +
1.263 +void CWTLSText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
1.264 + {
1.265 + if ((aBinaryData.Length() - aPos) < 3)
1.266 + {
1.267 + User::Leave(KErrArgument);
1.268 + }
1.269 + TWTLSDecUnsignedInteger decInt;
1.270 + iCharacterSet = decInt.DecodeShortL(aBinaryData, aPos, 2);
1.271 + TUint8 nameLength = aBinaryData[aPos];
1.272 + aPos++;
1.273 + if (aBinaryData.Length() < (aPos + nameLength))
1.274 + {
1.275 + User::Leave(KErrArgument);
1.276 + }
1.277 + TPtrC8 ptr = aBinaryData.Mid(aPos, nameLength);
1.278 + //only works for latin-1 here...
1.279 + iName = HBufC::NewL(ptr.Length());
1.280 + switch (iCharacterSet)
1.281 + {
1.282 + case KWTLSLatin1CharSet://=latin-1
1.283 + {
1.284 + TPtr pRes = iName->Des();
1.285 + pRes.Copy(ptr);
1.286 + aPos+=nameLength;
1.287 + break;
1.288 + }
1.289 + case KWTLSUTF8CharSet:
1.290 + {
1.291 + TPtr pRes = iName->Des();
1.292 + User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(pRes, ptr));
1.293 + break;
1.294 + }
1.295 + default:
1.296 + {
1.297 + User::Leave(KErrNotSupported);
1.298 + }
1.299 + }
1.300 + }
1.301 +
1.302 +TWTLSStructuredTextField::TWTLSStructuredTextField(const TDesC& aType, const TDesC& aValue)
1.303 + :iType(aType), iValue(aValue)
1.304 + {
1.305 + }
1.306 +
1.307 +EXPORT_C TPtrC TWTLSStructuredTextField::Type() const
1.308 + {
1.309 + return iType;
1.310 + }
1.311 +
1.312 +EXPORT_C TPtrC TWTLSStructuredTextField::Value() const
1.313 + {
1.314 + return iValue;
1.315 + }
1.316 +
1.317 +//Structured text class
1.318 +EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData)
1.319 + {
1.320 + TInt pos = 0;
1.321 + return CWTLSStructuredText::NewL(aBinaryData, pos);
1.322 + }
1.323 +
1.324 +EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData)
1.325 + {
1.326 + TInt pos = 0;
1.327 + return CWTLSStructuredText::NewLC(aBinaryData, pos);
1.328 + }
1.329 +
1.330 +EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData, TInt& aPos)
1.331 + {
1.332 + CWTLSStructuredText* self = CWTLSStructuredText::NewLC(aBinaryData, aPos);
1.333 + CleanupStack::Pop();
1.334 + return self;
1.335 + }
1.336 +
1.337 +EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
1.338 + {
1.339 + CWTLSStructuredText* self = new(ELeave) CWTLSStructuredText;
1.340 + CleanupStack::PushL(self);
1.341 + self->ConstructL(aBinaryData, aPos);
1.342 + return self;
1.343 + }
1.344 +
1.345 +EXPORT_C CWTLSStructuredText::~CWTLSStructuredText()
1.346 + {
1.347 + delete iFields;
1.348 + }
1.349 +
1.350 +EXPORT_C HBufC* CWTLSStructuredText::DisplayNameL() const
1.351 + {
1.352 + if (iFields->Count() > 3)
1.353 + {
1.354 + return iFields->At(3).Value().AllocL();
1.355 + }
1.356 + else
1.357 + {
1.358 + return iFields->At(1).Value().AllocL();
1.359 + }
1.360 + }
1.361 +
1.362 + //accessors for defined fields
1.363 +EXPORT_C TPtrC CWTLSStructuredText::ServiceName() const
1.364 + {
1.365 + //construction ensures iFields must have at least 3 elements
1.366 + return iFields->At(0).Value();
1.367 + }
1.368 +
1.369 +EXPORT_C TPtrC CWTLSStructuredText::Organization() const
1.370 + {
1.371 + //construction ensures iFields must have at least 3 elements
1.372 + return iFields->At(1).Value();
1.373 + }
1.374 +
1.375 +EXPORT_C TPtrC CWTLSStructuredText::Country() const
1.376 + {
1.377 + //construction ensures iFields must have at least 3 elements
1.378 + return iFields->At(2).Value();
1.379 + }
1.380 +
1.381 +EXPORT_C TInt CWTLSStructuredText::Count() const
1.382 + {
1.383 + return iFields->Count();
1.384 + }
1.385 +
1.386 +EXPORT_C const TWTLSStructuredTextField* CWTLSStructuredText::FieldByName(const TDesC& aType) const
1.387 + {
1.388 + TInt count = iFields->Count();
1.389 + for (TInt i = 0; i < count; i++)
1.390 + {
1.391 + TWTLSStructuredTextField* field = &(iFields->At(i));
1.392 + if (field->Type() == aType)
1.393 + {
1.394 + return field;
1.395 + }
1.396 + }
1.397 + return NULL;
1.398 + }
1.399 +
1.400 +EXPORT_C const TWTLSStructuredTextField& CWTLSStructuredText::FieldByIndex(TInt aIndex) const
1.401 + {
1.402 + return iFields->At(aIndex);
1.403 + }
1.404 +
1.405 +CWTLSStructuredText::CWTLSStructuredText()
1.406 + {
1.407 + }
1.408 +
1.409 +void CWTLSStructuredText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
1.410 + {
1.411 + CWTLSText::ConstructL(aBinaryData, aPos);
1.412 + iFields = new(ELeave) CArrayFixFlat<TWTLSStructuredTextField> (4);
1.413 + TInt pos = 0;
1.414 + TInt end = iName->Length();
1.415 + AddFieldValueL(KWTLSServiceName, pos);
1.416 + AddFieldValueL(KWTLSOrganizationName, pos);
1.417 + AddFieldValueL(KWTLSCountryName, pos);
1.418 + if (pos < end)
1.419 + {
1.420 + AddFieldValueL(KWTLSCommonName, pos);
1.421 + }
1.422 + while (pos < end)
1.423 + {
1.424 + AddFieldL(pos);
1.425 + }
1.426 + }
1.427 +
1.428 +void CWTLSStructuredText::AddFieldValueL(const TDesC& aFieldName, TInt& aPos)
1.429 + {
1.430 + TPtrC startOfData = iName->Right(iName->Length() - aPos);
1.431 + TPtrC value = GetFieldL(startOfData, aPos);
1.432 + TWTLSStructuredTextField field(aFieldName, value);
1.433 + iFields->AppendL(field);
1.434 + }
1.435 +
1.436 +void CWTLSStructuredText::AddFieldL(TInt& aPos)
1.437 + {
1.438 + TPtrC startOfData = iName->Right(iName->Length() - aPos);
1.439 + TPtrC fieldData = GetFieldL(startOfData, aPos);
1.440 + TInt fieldLength = fieldData.Length();
1.441 + TInt endType = fieldData.FindF(KWTLSStructuredTextAssignmentCharacter);
1.442 + if ((endType == KErrNotFound) || ((endType+1) == fieldLength))
1.443 + {
1.444 + User::Leave(KErrArgument);
1.445 + }
1.446 + TPtrC type = fieldData.Left(endType);
1.447 + TPtrC value = fieldData.Right( fieldLength - (endType+1) );
1.448 + TWTLSStructuredTextField field(type, value);
1.449 + iFields->AppendL(field);
1.450 + }
1.451 +
1.452 +TPtrC CWTLSStructuredText::GetFieldL(TDesC& aString, TInt& aPos)
1.453 + {
1.454 +//aString = where we've got up to
1.455 +//aPos = start of this chunk of name data
1.456 + TInt length = 0;
1.457 + TBool done = GetSubFieldL(aString, length);
1.458 + while (!done)
1.459 + {
1.460 + TPtrC remainder = aString.Right(aString.Length() - (length));
1.461 + TInt increment = 0;
1.462 + done = GetSubFieldL(remainder, increment);
1.463 + length += increment;
1.464 + }
1.465 + if (length == 0)
1.466 + {
1.467 + //disallow zero-length field values
1.468 + User::Leave(KErrArgument);
1.469 + }
1.470 + aPos += length;
1.471 + if (length < aString.Length())
1.472 + {
1.473 + //if we're not on the last field, skip the ';' character
1.474 + aPos++;
1.475 + }
1.476 + return aString.Left(length);
1.477 + }
1.478 +
1.479 +TBool CWTLSStructuredText::GetSubFieldL(TDesC& aString, TInt& aPos)
1.480 + {
1.481 +//fields in structured text are separated by ';'. If this character appears
1.482 +//in the field text it's represented by ';;'. so, the string 'symbian;systems' would
1.483 +//be encoded as 'symbian;;systems'.
1.484 +
1.485 +//starting at the start of aString, this function sets 'aPos' to the position after the
1.486 +//first occurrence of ';' in aString. If the character following ';' is also ';' it returns
1.487 +//EFalse (meaning, this sub-field isn't a whole field), otherwise it returns ETrue.
1.488 +
1.489 + aPos = aString.FindF(KWTLSStructuredTextFieldSeparator);
1.490 + if (aPos == KErrNotFound)
1.491 + {
1.492 + aPos = aString.Length();
1.493 + }
1.494 + else
1.495 + {
1.496 + //separator char mustn't be last char
1.497 + if (aPos == (aString.Length() -1))
1.498 + {
1.499 + User::Leave(KErrArgument);
1.500 + }
1.501 + else
1.502 + {
1.503 + //if the next char is ';', skip it and return EFalse
1.504 + TPtrC next = aString.Mid(aPos + 1, 1);
1.505 + if (next == KWTLSStructuredTextFieldSeparator)
1.506 + {
1.507 + aPos++;
1.508 + return EFalse;
1.509 + }
1.510 + //if it isn't, that's the end of the field
1.511 + }
1.512 + }
1.513 + return ETrue;
1.514 + }