00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "SecEngine.h"
00017
00018
00019 const TInt KSendBufferSize = 256;
00020
00021 const TInt KReceiveBufferSize = 256;
00022
00023
00024 _LIT8(KSimpleGet, "GET ");
00025 _LIT8(KNewLine, "\n");
00026
00027
00028 _LIT(KConnnectedMessage, "\nConnecting to %S:%d%S\n");
00029 _LIT(KSecureConnnectingMessage, "\nMaking secure connection");
00030 _LIT(KGettingPageMessage, "\nRequesting web page");
00031 _LIT(KReceivingMessage,"\nReceiving server response");
00032 _LIT(KCipherSuiteInUseMessage,"\nCipher suite in use: %S");
00033 _LIT(KProtocolMessage, "\nProtocol used in connection: %S");
00034 _LIT(KReceivedMessage,"\nReceived server response");
00035 _LIT(KCompleteMessage,"\nTransaction complete: bytes recieved %d");
00036 _LIT(KFileErrorMessage,"\nError in writing data to file");
00037 _LIT(KCancelledMessage,"\nConnection closed");
00038
00039
00040 _LIT( KStateErrESocketConnected, "\nError in state ESocketConnected: %d\n" );
00041 _LIT( KStateErrESettingCiphers, "\nError in state ESettingCiphers: %d\n" );
00042 _LIT( KStateErrSecureConnected, "\nError in state ESecureConnected: %d\n" );
00043 _LIT( KStateErrGetRequestSent, "\nError in state EGetRequestSent: %d\n" );
00044 _LIT( KStateErrEDataReceived, "\nError in state EDataReceived: %d\n" );
00045
00046
00047 _LIT( KSecEnginePanic, "SEC-ENGINE");
00048
00049
00050
00051
00052
00053 CSecEngine* CSecEngine::NewL()
00054 {
00055 CSecEngine* self = new(ELeave) CSecEngine;
00056 CleanupStack::PushL( self );
00057 self->ConstructL();
00058 CleanupStack::Pop();
00059 return self;
00060 }
00061
00062
00063
00064 CSecEngine::CSecEngine()
00065 : CActive(0), iSndBuffer(0,0), iRcvBuffer(0,0)
00066 {
00067 }
00068
00069 CSecEngine::~CSecEngine()
00070 {
00071
00072
00073
00074 ConnectionClosed();
00075
00076 delete iSndBuffer.Ptr();
00077 delete iRcvBuffer.Ptr();
00078 iTimer.Close();
00079 iSocketServ.Close();
00080 }
00081
00082 void CSecEngine::ConstructL()
00083 {
00084 iSndBuffer.Set((TUint8*)User::AllocL(KSendBufferSize),0,KSendBufferSize);
00085 iRcvBuffer.Set((TUint8*)User::AllocL(KReceiveBufferSize),0,KReceiveBufferSize);
00086
00087 User::LeaveIfError( iSocketServ.Connect());
00088
00089 User::LeaveIfError( iTimer.CreateLocal());
00090
00091 iRunState = ESocketConnected;
00092 iInUse = EFalse;
00093
00094 CActiveScheduler::Add( this );
00095 }
00096
00097 void CSecEngine::ConnectL(const TConnectSettings& aConnectSettings)
00098 {
00099 iConnectSettings = &aConnectSettings;
00100
00101
00102 iSuccess = ETrue;
00103 iInUse = ETrue;
00104 iRunState = ESocketConnected;
00105 iSndBuffer.SetLength( 0 );
00106 iRcvBuffer.SetLength( 0 );
00107 iTotalBytesRead = 0;
00108
00109
00110 if (iInetAddr.Input(iConnectSettings->iAddress) != KErrNone)
00111
00112 {
00113
00114 User::LeaveIfError( iHostResolver.Open( iSocketServ, KAfInet, KProtocolInetTcp ));
00115
00116 TNameEntry nameEntry;
00117 User::LeaveIfError (iHostResolver.GetByName( iConnectSettings->iAddress, nameEntry ));
00118 TSockAddr sockAddr = nameEntry().iAddr;
00119 iInetAddr = iInetAddr.Cast( sockAddr );
00120 iHostResolver.Close();
00121 }
00122
00123 iInetAddr.SetPort( iConnectSettings->iPortNum );
00124
00125
00126 User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) );
00127
00128
00129 iSocket.Connect( iInetAddr, iStatus );
00130 SetActive();
00131
00132
00133 iConsole->Printf(KConnnectedMessage,
00134 &iConnectSettings->iAddress,
00135 iConnectSettings->iPortNum,
00136 &iConnectSettings->iPage );
00137 }
00138
00139 void CSecEngine::SetConsole( CConsoleBase& aConsole )
00140 {
00141 iConsole = &aConsole;
00142 }
00143
00144 void CSecEngine::SetOutputFile( RFile& aOutputFile )
00145 {
00146 iOutputFile = &aOutputFile;
00147 }
00148
00149 TBool CSecEngine::InUse()
00150 {
00151 return iInUse;
00152 }
00153
00154 void CSecEngine::RunL()
00155 {
00156 switch ( iRunState )
00157 {
00158 case ESocketConnected:
00159 MakeSecureConnectionL();
00160 break;
00161
00162 case ESecureConnected:
00163 MakePageRequestL();
00164 break;
00165
00166 case EGetRequestSent:
00167 GetServerResponseL();
00168 break;
00169
00170 case EDataReceived:
00171 ReadServerResponseL();
00172 break;
00173
00174 case EConnectionClosed:
00175 ConnectionClosed();
00176 break;
00177
00178 default:
00179 break;
00180 }
00181 }
00182
00183 TInt CSecEngine::RunError( TInt aError )
00184 {
00185
00186 __ASSERT_ALWAYS(iRunState != EConnectionClosed,
00187 User::Panic(KSecEnginePanic,0));
00188
00189
00190 switch (iRunState)
00191 {
00192 case ESocketConnected:
00193 iConsole->Printf(KStateErrESocketConnected, aError );
00194 break;
00195 case ESettingCiphers:
00196 iConsole->Printf(KStateErrESettingCiphers, aError );
00197 break;
00198 case ESecureConnected:
00199 iConsole->Printf(KStateErrSecureConnected, aError);
00200 break;
00201 case EGetRequestSent:
00202 iConsole->Printf(KStateErrGetRequestSent, aError);
00203 break;
00204 case EDataReceived:
00205 iConsole->Printf(KStateErrEDataReceived, aError);
00206 break;
00207 default:
00208 break;
00209 }
00210
00211 iRunState = EConnectionClosed;
00212 iSuccess = EFalse;
00213 iTimer.After( iStatus, 1000000 );
00214 SetActive();
00215
00216 return KErrNone;
00217 }
00218
00219 void CSecEngine::DoCancel()
00220 {
00221 iConsole->Printf(KCancelledMessage);
00222 ConnectionClosed();
00223 }
00224
00225 void CSecEngine::MakeSecureConnectionL()
00226 {
00227 User::LeaveIfError(iStatus.Int());
00228
00229
00230
00231 iConsole->Printf(KSecureConnnectingMessage);
00232 _LIT(KTLS1,"TLS1.0");
00233 iTlsSocket = CSecureSocket::NewL( iSocket, KTLS1 );
00234
00235
00236
00237
00238 iTlsSocket->FlushSessionCache();
00239
00240
00241
00242
00243
00244
00245
00246
00247 iTlsSocket->StartClientHandshake( iStatus );
00248
00249 iRunState = ESecureConnected;
00250 SetActive();
00251 }
00252
00253 void CSecEngine::MakePageRequestL()
00254 {
00255
00256
00257 User::LeaveIfError(iStatus.Int());
00258 iConsole->Printf(KGettingPageMessage);
00259
00260
00261 iSndBuffer+=KSimpleGet;
00262 iSndBuffer+=iConnectSettings->iPage;
00263 iSndBuffer+=KNewLine;
00264
00265
00266 iRunState = EGetRequestSent;
00267 iTlsSocket->Send( iSndBuffer, iStatus, iBytesSent );
00268 SetActive();
00269 }
00270
00271 void CSecEngine::GetServerResponseL()
00272 {
00273
00274 User::LeaveIfError(iStatus.Int());
00275 iConsole->Printf(KReceivingMessage);
00276
00277
00278 TBuf8<2> buf;
00279 User::LeaveIfError(iTlsSocket->CurrentCipherSuite( buf ));
00280 PrintCipherNameL(buf);
00281
00282
00283 TBuf<32> protocol;
00284 User::LeaveIfError(iTlsSocket->Protocol( protocol ));
00285 iConsole->Printf(KProtocolMessage, &protocol );
00286
00287
00288 const CX509Certificate *servCert = iTlsSocket->ServerCert();
00289 if ( servCert ) PrintCertInfo( *servCert );
00290
00291
00292 iRunState = EDataReceived;
00293 iTlsSocket->Recv( iRcvBuffer, iStatus );
00294 SetActive();
00295 }
00296
00297 void CSecEngine::ReadServerResponseL()
00298 {
00299
00300 if (iStatus!=KErrEof) User::LeaveIfError(iStatus.Int());
00301 iConsole->Printf(KReceivedMessage);
00302
00303
00304 iTotalBytesRead += iRcvBuffer.Length();
00305 TInt ret = iOutputFile->Write(iRcvBuffer);
00306 if (ret != KErrNone) iConsole->Printf(KFileErrorMessage);
00307
00308
00309 if ( ( iStatus==KErrEof ) || ( iRcvBuffer.Length() == 0 ) )
00310 {
00311 iConsole->Printf(KCompleteMessage, iTotalBytesRead);
00312
00313 iRunState = EConnectionClosed;
00314 iTimer.After( iStatus, 1000000 );
00315 SetActive();
00316 return;
00317 }
00318
00319
00320 iRcvBuffer.SetLength( 0 );
00321 iRunState = EDataReceived;
00322 iTlsSocket->Recv( iRcvBuffer, iStatus );
00323 SetActive();
00324 }
00325
00326 void CSecEngine::ConnectionClosed()
00327 {
00328 if (!iInUse) return;
00329
00330 iHostResolver.Close();
00331 delete iTlsSocket;
00332 iTlsSocket =0;
00333 iSocket.Close();
00334
00335
00336
00337 User::After( 1000000 );
00338 iInUse = EFalse;
00339 }
00340
00341 void CSecEngine::PrintCipherNameL(const TDes8& aBuf)
00342 {
00343 TLex8 lex(aBuf);
00344 TUint cipherCode=aBuf[1];
00345 if ((cipherCode<1) || (cipherCode > 0x1B))
00346 User::Leave(KErrArgument);
00347 const TText* KCipherNameArray[0x1B] =
00348 {
00349 _S("TLS_RSA_WITH_NULL_MD5"),
00350 _S("TLS_RSA_WITH_NULL_SHA"),
00351 _S("TLS_RSA_EXPORT_WITH_RC4_40_MD5"),
00352 _S("TLS_RSA_WITH_RC4_128_MD5"),
00353 _S("TLS_RSA_WITH_RC4_128_SHA"),
00354 _S("TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"),
00355 _S("TLS_RSA_WITH_IDEA_CBC_SHA"),
00356 _S("TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"),
00357 _S("TLS_RSA_WITH_DES_CBC_SHA"),
00358 _S("TLS_RSA_WITH_3DES_EDE_CBC_SHA"),
00359 _S("TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"),
00360 _S("TLS_DH_DSS_WITH_DES_CBC_SHA"),
00361 _S("TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"),
00362 _S("TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"),
00363 _S("TLS_DH_RSA_WITH_DES_CBC_SHA"),
00364 _S("TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"),
00365 _S("TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"),
00366 _S("TLS_DHE_DSS_WITH_DES_CBC_SHA"),
00367 _S("TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"),
00368 _S("TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"),
00369 _S("TLS_DHE_RSA_WITH_DES_CBC_SHA"),
00370 _S("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"),
00371 _S("TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"),
00372 _S("TLS_DH_anon_WITH_RC4_128_MD5"),
00373 _S("TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"),
00374 _S("TLS_DH_anon_WITH_DES_CBC_SHA"),
00375 _S("TLS_DH_anon_WITH_3DES_EDE_CBC_SHA")
00376 };
00377
00378 TPtrC name(KCipherNameArray[cipherCode-1]);
00379 iConsole->Printf(KCipherSuiteInUseMessage, &name );
00380 }
00381
00382 void CSecEngine::PrintCertInfo(const CX509Certificate& aSource)
00383 {
00384 _LIT(KCertInfoMessage1, "\nCertificate received: \n\tIssuer %S \n\tSubject %S");
00385 _LIT(KCertInfoMessage2, "\n\tValid from %S to %S");
00386 _LIT(KDateString,"%F%/0%M%/1%Y%/2%D%/3");
00387
00388 TRAP_IGNORE(
00389
00390 HBufC* issuer = aSource.IssuerL();
00391 HBufC* subject = aSource.SubjectL();
00392 iConsole->Printf(KCertInfoMessage1, issuer, subject);
00393 delete issuer;
00394 delete subject;
00395
00396
00397 TBuf<20> startTime;
00398 TBuf<20> finishTime;
00399 aSource.ValidityPeriod().Start().FormatL(startTime,KDateString);
00400 aSource.ValidityPeriod().Finish().FormatL(finishTime,KDateString);
00401 iConsole->Printf(KCertInfoMessage2, &startTime, &finishTime);
00402 );
00403 }