webservices/wsoviplugin/src/wsovisecurityhandler.cpp
changeset 0 62f9d29f7211
equal deleted inserted replaced
-1:000000000000 0:62f9d29f7211
       
     1 /*
       
     2 * Copyright (c) 2008 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:       
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 #include <e32std.h>
       
    25 #include "wsovisecurityhandler.h"
       
    26 #include "wsovicons.h"
       
    27 #include "wsovihandlercontext.h"
       
    28 #include "senlogger.h"
       
    29 #include "wsovimessagecontext.h"
       
    30 #include <SenTransportProperties.h>
       
    31 #include <SenHttpTransportProperties.h>
       
    32 
       
    33 #include "wsoviutils.h"
       
    34 #include "sencryptoutils.h"
       
    35 
       
    36 
       
    37 using namespace OAuth;
       
    38 namespace
       
    39     {
       
    40     const TInt KSHA1OutputSize = 20;// see http://en.wikipedia.org/wiki/SHA_hash_functions
       
    41     }
       
    42 // Create instance of concrete ECOM interface implementation
       
    43 CWSOviSecurityHandler* CWSOviSecurityHandler::NewL(
       
    44         MSenHandlerContext* aHandlerCtx)
       
    45     {
       
    46     
       
    47     CWSOviSecurityHandler* self =
       
    48             new (ELeave) CWSOviSecurityHandler(*aHandlerCtx);
       
    49     return self;
       
    50     }
       
    51 
       
    52 // Constructor
       
    53 CWSOviSecurityHandler::CWSOviSecurityHandler(MSenHandlerContext& aCtx):
       
    54         CSenMessageHandler(aCtx), iDiff(0)
       
    55     {
       
    56     }
       
    57 
       
    58 // Destructor
       
    59 CWSOviSecurityHandler::~CWSOviSecurityHandler()
       
    60     {
       
    61         TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::~CWSOviSecurityHandler()")));
       
    62     }
       
    63 
       
    64 TInt CWSOviSecurityHandler::InvokeL(MSenMessageContext& aCtx)
       
    65     {
       
    66     TInt error(KErrNone);
       
    67     TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::InvokeL(MSenMessageContext& aCtx)")));
       
    68     CSenTransportProperties* tp = ((CWSOviMessageContext&)aCtx).TP();
       
    69     const TInt* servertime = ((CWSOviMessageContext&)aCtx).GetIntL(WSOviContextKeys::KRetryNeeded);
       
    70     const TDesC8* bodyMessage = ((CWSOviMessageContext&)aCtx).GetDesC8L(WSOviContextKeys::KMessageBody);
       
    71     
       
    72     
       
    73     TPtrC8 oldValue;
       
    74     if (!tp) return KErrNotFound;
       
    75     error = tp->PropertyL(KAuthHttpHeader, oldValue);
       
    76     if (error) return error;//device handler missed
       
    77     
       
    78     
       
    79     TPtrC8 consumerKey;
       
    80     error = tp->PropertyL(KNCIMConsumerKeyId, consumerKey);
       
    81         
       
    82     TPtrC8 consumerSecret;
       
    83     error = tp->PropertyL(KNCIMConsumerSecret, consumerSecret);
       
    84     
       
    85     TBool needSecurity(ETrue);
       
    86     error = tp->BoolPropertyL(KNeedSecurity,needSecurity);
       
    87     
       
    88     
       
    89     const TDesC8* endpoint = ((CWSOviMessageContext&)aCtx).GetDesC8L(KEndpointKey);
       
    90     if (!endpoint)
       
    91         {
       
    92         endpoint = &KParValRealm();
       
    93         }
       
    94     
       
    95     CSenHttpTransportProperties::TSenHttpMethod httpMethod;
       
    96     error = ((CSenHttpTransportProperties*)tp)->HttpMethodL(httpMethod);
       
    97     if (error)
       
    98         {
       
    99         httpMethod = CSenHttpTransportProperties::ESenHttpPost;
       
   100         }
       
   101 //====================NAuth message encoding + signing (algorithm)
       
   102 
       
   103 //____1____ generate random(NONCE)
       
   104 
       
   105     HBufC8* nonce(SenCryptoUtils::GetRandomNonceL());
       
   106     TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,_L("CWSOviSecurityHandler::   ____1____ generate random(NONCE %S)"), nonce));
       
   107     
       
   108     
       
   109 //____2____ generate timestamp
       
   110     TTime time;
       
   111     time.UniversalTime();
       
   112     if (servertime && *servertime > 0/*&& iDiff==0*/)
       
   113         {
       
   114         TTimeIntervalMinutes minutes(*servertime);
       
   115         iDiff = time-minutes;
       
   116         ((CWSOviMessageContext&)aCtx).Update(WSOviContextKeys::KRetryNeeded, 0);
       
   117         }
       
   118     time -= TTimeIntervalMicroSeconds(iDiff.Int64());
       
   119     HBufC8* timestamp = SenCryptoUtils::GetTimestampL(time);
       
   120     
       
   121         
       
   122     
       
   123     
       
   124     
       
   125     
       
   126     TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,_L("CWSOviSecurityHandler::   ____2____ generate (timestamp %S)"), timestamp));
       
   127 
       
   128 //____3____ create request without signature
       
   129 
       
   130     const TDesC8* token = aCtx.GetDesC8L(WSOviContextKeys::KToken());
       
   131     TPtrC8 clearToken = KNullDesC8();
       
   132     TInt tokenLength(0);
       
   133     if (token && needSecurity)
       
   134         {
       
   135         TInt left = token->Locate('>') + 1;
       
   136         TInt right = token->LocateReverse('<');
       
   137         clearToken.Set(token->Mid(left, right - left));
       
   138         tokenLength = clearToken.Length();
       
   139         tokenLength += KParToken().Length();
       
   140         tokenLength += KEqual().Length() + KQtMark().Length() +                    
       
   141                     KQtMark().Length() + KComma().Length();
       
   142         }
       
   143     
       
   144     RBuf8 newValue;
       
   145     newValue.Create(oldValue.Length() +
       
   146                     KComma().Length() +
       
   147                    
       
   148                     KParSignMethod().Length() +
       
   149                     KEqual().Length() + KQtMark().Length() +
       
   150                     KParValHMACSHA().Length() +
       
   151                     KQtMark().Length() + KComma().Length() +
       
   152 
       
   153                     KParTimestamp().Length() +
       
   154                     KEqual().Length() + KQtMark().Length() +
       
   155                     timestamp->Length() +
       
   156                     KQtMark().Length() + KComma().Length() +
       
   157 
       
   158                     KParNonce().Length() +
       
   159                     KEqual().Length() + KQtMark().Length() +
       
   160                     nonce->Length() +
       
   161                     KQtMark().Length() + KComma().Length() +
       
   162 
       
   163                     tokenLength +
       
   164                     
       
   165                     KParSignature().Length() +
       
   166                     KEqual().Length() + KQtMark().Length() +
       
   167                     KSHA1OutputSize*3  +
       
   168                     KParSignature().Length()
       
   169 
       
   170                     );
       
   171     CleanupClosePushL(newValue);
       
   172   
       
   173     TPtrC8 country;
       
   174     tp->PropertyL(KNCIMCountry(), country);
       
   175     
       
   176   	RMapDescriptors& headerProperties = ((CWSOviMessageContext&)aCtx).OAuthProperies();
       
   177     HBufC8* property = KParValHMACSHA().AllocL();
       
   178     headerProperties.Insert(&KParSignMethod, property);
       
   179     headerProperties.Insert(&KParTimestamp, timestamp);
       
   180     headerProperties.Insert(&KParNonce, nonce);
       
   181     if (country.Length())
       
   182         {
       
   183         headerProperties.Insert(&KNCIMCountry, country.AllocL());
       
   184         }
       
   185     headerProperties.Insert(&KParConsumerKey, consumerKey.AllocL());
       
   186     if (token && needSecurity)
       
   187     	{
       
   188     	headerProperties.Insert(&KParToken, clearToken.AllocL());
       
   189     	}
       
   190 
       
   191     newValue.Append(oldValue);
       
   192     newValue.Append(KComma());
       
   193     
       
   194    
       
   195 
       
   196     newValue.Append(KParSignMethod());
       
   197     newValue.Append(KEqual());
       
   198     newValue.Append(KQtMark());
       
   199     newValue.Append(KParValHMACSHA);
       
   200     newValue.Append(KQtMark());
       
   201     newValue.Append(KComma());
       
   202 
       
   203 
       
   204     newValue.Append(KParTimestamp());
       
   205     newValue.Append(KEqual());
       
   206     newValue.Append(KQtMark());
       
   207     newValue.Append(*timestamp);
       
   208     newValue.Append(KQtMark());
       
   209     newValue.Append(KComma());
       
   210 
       
   211 
       
   212     newValue.Append(KParNonce());
       
   213     newValue.Append(KEqual());
       
   214     newValue.Append(KQtMark());
       
   215     newValue.Append(*nonce);
       
   216     newValue.Append(KQtMark());
       
   217     newValue.Append(KComma());
       
   218     
       
   219     if (token && needSecurity)
       
   220         {
       
   221         newValue.Append(KParToken());
       
   222         newValue.Append(KEqual());
       
   223         newValue.Append(KQtMark());
       
   224         newValue.Append(clearToken);
       
   225         newValue.Append(KQtMark());
       
   226         newValue.Append(KComma());
       
   227         }
       
   228     
       
   229     TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::   ____3____ create request without signature")));
       
   230 
       
   231 //____4____ normalize request
       
   232 
       
   233     HBufC8* body = NULL;
       
   234     if (bodyMessage)
       
   235         {
       
   236         HBufC8* bodyEncoded = CWSOviUtils::EncodeCharsLC(*bodyMessage);
       
   237         body = HBufC8::NewL(OAuth::KXmlContentEqual().Length()+bodyEncoded->Length());
       
   238         body->Des().Append(OAuth::KXmlContentEqual());
       
   239         body->Des().Append(*bodyEncoded);
       
   240         CleanupStack::PopAndDestroy(bodyEncoded);
       
   241         CleanupStack::PushL(body);
       
   242         }
       
   243     
       
   244 	TInt length=0;
       
   245 	if (body)
       
   246 	    {
       
   247 	    length+=body->Length();
       
   248 	    length+=KAmpMark().Length();
       
   249 	    }
       
   250 	for(TInt i=0; i<headerProperties.Count(); i++)
       
   251 	{
       
   252 		length+=(*headerProperties.KeyAt(i)).Length();
       
   253 		length+=(*headerProperties.ValueAt(i)).Length();
       
   254 		length+=KEqual().Length();
       
   255 		if(i)
       
   256 		length+=KAmpMark().Length();
       
   257 	}
       
   258 
       
   259 	RBuf8 headerToNormalize;
       
   260 	CleanupClosePushL(headerToNormalize);
       
   261 	headerToNormalize.Create(length);
       
   262 	if (body)
       
   263 	    {
       
   264 	    headerToNormalize.Append(*body);
       
   265 	    headerToNormalize.Append(KAmpMark());
       
   266 	    }
       
   267 	for(TInt i=0; i<headerProperties.Count(); i++)
       
   268 	{
       
   269 		headerToNormalize.Append(*headerProperties.KeyAt(i));
       
   270 		headerToNormalize.Append(KEqual());
       
   271 		headerToNormalize.Append(*headerProperties.ValueAt(i));
       
   272 		if(i<headerProperties.Count()-1)
       
   273 		headerToNormalize.Append(KAmpMark());
       
   274 	}
       
   275     TLSLOG_ALL(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel, headerToNormalize);
       
   276 
       
   277 	HBufC8* strToSign = NULL;
       
   278 	if (httpMethod == CSenHttpTransportProperties::ESenHttpPost)
       
   279 	    {
       
   280 	    strToSign = CWSOviUtils::NormalizeStringLC( KParHttpMethodPost, *endpoint/*KParValRealm*/, headerToNormalize );
       
   281 	    }
       
   282 	else if (httpMethod == CSenHttpTransportProperties::ESenHttpGet)
       
   283 	    {
       
   284         strToSign = CWSOviUtils::NormalizeStringLC( KParHttpMethodGet, *endpoint/*KParValRealm*/, headerToNormalize );
       
   285 	    }
       
   286 	else if(httpMethod == CSenHttpTransportProperties::ESenHttpPut)
       
   287 		{
       
   288 		strToSign = CWSOviUtils::NormalizeStringLC( KParHttpMethodPut, *endpoint/*KParValRealm*/, headerToNormalize );
       
   289 		}
       
   290     else if(httpMethod == CSenHttpTransportProperties::ESenHttpDelete)
       
   291         {
       
   292         strToSign = CWSOviUtils::NormalizeStringLC( KParHttpMethodDelete, *endpoint/*KParValRealm*/, headerToNormalize );
       
   293         }
       
   294 #ifdef _SENDEBUG
       
   295 
       
   296     TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::   ____4____ normalize request")));
       
   297 	if(strToSign)
       
   298 		{
       
   299 			TLSLOG_ALL(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel, *strToSign);
       
   300 		}
       
   301 #endif // _SENDEBUG
       
   302     
       
   303 //____5____ calculate hash
       
   304 
       
   305     CSHA1* sha1 = CSHA1::NewL();    
       
   306     CleanupStack::PushL(sha1);
       
   307     
       
   308     TBuf8<KSHA1OutputSize> hash; 
       
   309     hash.Copy(sha1->Final(*strToSign));
       
   310 
       
   311     TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::   ____5____ calculate hash & Key")));
       
   312     TLSLOG_ALL(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel, hash);
       
   313 
       
   314 //____6____ sign (with HC client secret)
       
   315 
       
   316 
       
   317     /*
       
   318     See http://oauth.net/core/1.0/#anchor16
       
   319     "...key is the concatenated values (each first encoded per Parameter Encoding (Parameter Encoding)) 
       
   320     of the Consumer Secret and Token Secret, separated by an ‘&’ character (ASCII code 38) even if empty..."
       
   321     */
       
   322     
       
   323     const TDesC8* tokenSecretCtx = aCtx.GetDesC8L(WSOviContextKeys::KTokenSecret());
       
   324     HBufC8* tokenSecret = NULL;
       
   325     if (tokenSecretCtx && needSecurity)
       
   326     	{
       
   327         tokenSecret = CWSOviUtils::EncodeCharsLC(*tokenSecretCtx);
       
   328     	}
       
   329     HBufC8* encodedConsumerSecret = CWSOviUtils::EncodeCharsLC(consumerSecret); 
       
   330     RBuf8 key;
       
   331     CleanupClosePushL(key);
       
   332     if (tokenSecret && needSecurity)
       
   333         {
       
   334         key.Create(KAmpMark().Length() +
       
   335         		encodedConsumerSecret->Length() +
       
   336                tokenSecret->Length()    );
       
   337         }
       
   338     else
       
   339         {
       
   340         key.Create(KAmpMark().Length() +
       
   341         		encodedConsumerSecret->Length());
       
   342         }
       
   343     
       
   344     key.Append(*encodedConsumerSecret);
       
   345     key.Append(KAmpMark());
       
   346     if (tokenSecret && needSecurity)
       
   347         {
       
   348         key.Append(*tokenSecret);
       
   349         }
       
   350     TLSLOG_ALL(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel, key);        
       
   351     //CleanupStack::PopAndDestroy(encodedSignatureSecret);
       
   352     CHMAC* hmac = CHMAC::NewL(key, sha1);//sha1 is consumed
       
   353 
       
   354     CleanupStack::PopAndDestroy(&key);
       
   355     CleanupStack::PopAndDestroy(encodedConsumerSecret);
       
   356     if (tokenSecretCtx && needSecurity)
       
   357     	{
       
   358     	CleanupStack::PopAndDestroy(tokenSecret);
       
   359     	}
       
   360     CleanupStack::Pop(sha1);
       
   361     CleanupStack::PushL(hmac);    
       
   362     TPtrC8 signatureValue = hmac->Final(*strToSign); //(hash);
       
   363 
       
   364     
       
   365     
       
   366     TLSLOG_FORMAT((KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,_L("CWSOviSecurityHandler::   ____6____ sign (with HC client secret %S)"), &signatureValue));    
       
   367 //____7____ append signature to http header
       
   368 
       
   369     newValue.Append(KParSignature());
       
   370     newValue.Append(KEqual());
       
   371     newValue.Append(KQtMark());
       
   372     HBufC8* base64Signature = SenCryptoUtils::EncodeBase64L(signatureValue);
       
   373     CleanupStack::PopAndDestroy(hmac);      
       
   374     CleanupStack::PushL(base64Signature);
       
   375     
       
   376 //____8____  URL-encoded 
       
   377     HBufC8* encodedSignature = CWSOviUtils::EncodeCharsLC(*base64Signature);
       
   378     
       
   379     newValue.Append(*encodedSignature);
       
   380     newValue.Append(KQtMark());        
       
   381         
       
   382         
       
   383         
       
   384     tp->SetPropertyL(KAuthHttpHeader, newValue, KHttpHeaderType);
       
   385     
       
   386     
       
   387     CleanupStack::PopAndDestroy(encodedSignature);
       
   388     CleanupStack::PopAndDestroy(base64Signature);
       
   389     CleanupStack::PopAndDestroy(strToSign);
       
   390     CleanupStack::PopAndDestroy(&headerToNormalize);
       
   391     if (body)
       
   392         {
       
   393         CleanupStack::PopAndDestroy(body);
       
   394         }
       
   395     CleanupStack::PopAndDestroy(&newValue);
       
   396     TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::   ____7____ append signature to http header")));
       
   397     
       
   398     //msg context keeps same tp, so we dont have to update msg context
       
   399     return KErrNone;
       
   400     }
       
   401 
       
   402     
       
   403 SenHandler::THandlerDirection CWSOviSecurityHandler::Direction() const
       
   404     {
       
   405         TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::Direction()")));
       
   406         return SenHandler::EOutgoing;
       
   407     };
       
   408 SenHandler::THandlerPhase CWSOviSecurityHandler::Phase()
       
   409     {
       
   410         TLSLOG(KSenCoreServiceManagerLogChannelBase  , KMinLogLevel,(_L("CWSOviSecurityHandler::Phase()")));
       
   411         return SenHandler::EMessage;
       
   412     };    
       
   413 TInt CWSOviSecurityHandler::InitL(MSenHandlerContext& /*aCtx*/)
       
   414     {
       
   415     return KErrNone;
       
   416     }
       
   417 // END OF FILE
       
   418