diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_sec_engine_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_sec_engine_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ - -
-00001 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). -00002 // All rights reserved. -00003 // This component and the accompanying materials are made available -00004 // under the terms of "Eclipse Public License v1.0" -00005 // which accompanies this distribution, and is available -00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". -00007 // -00008 // Initial Contributors: -00009 // Nokia Corporation - initial contribution. -00010 // -00011 // Contributors: -00012 // -00013 // Description: -00014 // -00015 -00016 #include "SecEngine.h" -00017 -00018 // Send buffer size -00019 const TInt KSendBufferSize = 256; -00020 // Receive buffer size -00021 const TInt KReceiveBufferSize = 256; -00022 -00023 // HTTP messages -00024 _LIT8(KSimpleGet, "GET "); -00025 _LIT8(KNewLine, "\n"); -00026 -00027 // Progress messages -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 // State reporting messages -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 // Panic code -00047 _LIT( KSecEnginePanic, "SEC-ENGINE"); -00048 -00049 // -00050 // CSecEngine -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 // Constructor should also call the parent constructor to set the priority -00063 // of the active object. -00064 CSecEngine::CSecEngine() -00065 : CActive(0), iSndBuffer(0,0), iRcvBuffer(0,0) -00066 { -00067 } -00068 -00069 CSecEngine::~CSecEngine() -00070 { -00071 // Cancel any outstanding request- this cleans up -00072 // resources created during a connection -00073 //Cancel(); -00074 ConnectionClosed(); -00075 // Clean up engine's permanent resources -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 // Connect the socket server -00087 User::LeaveIfError( iSocketServ.Connect()); -00088 // Create a local timer -00089 User::LeaveIfError( iTimer.CreateLocal()); -00090 // Set initial state -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 // Set initial values for flags & buffers -00102 iSuccess = ETrue; -00103 iInUse = ETrue; -00104 iRunState = ESocketConnected; -00105 iSndBuffer.SetLength( 0 ); -00106 iRcvBuffer.SetLength( 0 ); -00107 iTotalBytesRead = 0; -00108 -00109 // Interpret server address -00110 if (iInetAddr.Input(iConnectSettings->iAddress) != KErrNone) -00111 // Success if already in dotted-decimal format -00112 { -00113 // Connect to a host resolver (for DNS resolution) - happens sychronously -00114 User::LeaveIfError( iHostResolver.Open( iSocketServ, KAfInet, KProtocolInetTcp )); -00115 // Try to resolve symbolic name -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 // Store other connection parameters -00123 iInetAddr.SetPort( iConnectSettings->iPortNum ); -00124 -00125 // Open a TCP socket -00126 User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) ); -00127 -00128 // Connect to the server, asynchronously -00129 iSocket.Connect( iInetAddr, iStatus ); -00130 SetActive(); -00131 -00132 // Print status -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 } // end switch -00181 } -00182 -00183 TInt CSecEngine::RunError( TInt aError ) -00184 { -00185 // Panic prevents looping -00186 __ASSERT_ALWAYS(iRunState != EConnectionClosed, -00187 User::Panic(KSecEnginePanic,0)); -00188 -00189 // do a switch on the state to get the right err message -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()); // errors caught by RunError() -00228 -00229 // Construct the TLS socket, to use the TLS1.0 protocol. -00230 // Specifying SSL3.0 would also use the same implementation -00231 iConsole->Printf(KSecureConnnectingMessage); -00232 _LIT(KTLS1,"TLS1.0"); -00233 iTlsSocket = CSecureSocket::NewL( iSocket, KTLS1 ); -00234 -00235 // Set any options before the handshake starts -00236 -00237 // Clears any previous options -00238 iTlsSocket->FlushSessionCache(); -00239 -00240 /* Note: You could here set the available ciphers with code such as the following: -00241 TBuf8<2> buf; -00242 buf.SetLength(2); -00243 buf[0]=0; buf[1]=10; -00244 iTlsSocket->SetAvailableCipherSuites( buf ); */ -00245 -00246 // start the handshake -00247 iTlsSocket->StartClientHandshake( iStatus ); -00248 -00249 iRunState = ESecureConnected; -00250 SetActive(); -00251 } -00252 -00253 void CSecEngine::MakePageRequestL() -00254 { -00255 // The secure connection has now been made. -00256 // Send a get request for the page. -00257 User::LeaveIfError(iStatus.Int()); -00258 iConsole->Printf(KGettingPageMessage); -00259 -00260 // Create a GET request -00261 iSndBuffer+=KSimpleGet; -00262 iSndBuffer+=iConnectSettings->iPage; -00263 iSndBuffer+=KNewLine; -00264 -00265 // Send the request -00266 iRunState = EGetRequestSent; -00267 iTlsSocket->Send( iSndBuffer, iStatus, iBytesSent ); -00268 SetActive(); -00269 } -00270 -00271 void CSecEngine::GetServerResponseL() -00272 { -00273 // The get request has been sent, can now try and receive the data -00274 User::LeaveIfError(iStatus.Int()); -00275 iConsole->Printf(KReceivingMessage); -00276 -00277 // Print the cipher suite that has been negotiated. -00278 TBuf8<2> buf; -00279 User::LeaveIfError(iTlsSocket->CurrentCipherSuite( buf )); -00280 PrintCipherNameL(buf); -00281 -00282 // Print the protocol version string -00283 TBuf<32> protocol; -00284 User::LeaveIfError(iTlsSocket->Protocol( protocol )); -00285 iConsole->Printf(KProtocolMessage, &protocol ); -00286 -00287 // Print info about the server's certificate -00288 const CX509Certificate *servCert = iTlsSocket->ServerCert(); -00289 if ( servCert ) PrintCertInfo( *servCert ); -00290 -00291 // Read asynchonously-returns when buffer full -00292 iRunState = EDataReceived; -00293 iTlsSocket->Recv( iRcvBuffer, iStatus ); -00294 SetActive(); -00295 } -00296 -00297 void CSecEngine::ReadServerResponseL() -00298 { -00299 // Any error other than KErrEof means the test is a failure -00300 if (iStatus!=KErrEof) User::LeaveIfError(iStatus.Int()); -00301 iConsole->Printf(KReceivedMessage); -00302 -00303 // Put the received data in the output file & reset the receive buffer -00304 iTotalBytesRead += iRcvBuffer.Length(); -00305 TInt ret = iOutputFile->Write(iRcvBuffer); -00306 if (ret != KErrNone) iConsole->Printf(KFileErrorMessage); -00307 -00308 // Case 1: error is KErrEof (message complete) or no data received, so stop -00309 if ( ( iStatus==KErrEof ) || ( iRcvBuffer.Length() == 0 ) ) -00310 { -00311 iConsole->Printf(KCompleteMessage, iTotalBytesRead); -00312 // Close the socket neatly -00313 iRunState = EConnectionClosed; -00314 iTimer.After( iStatus, 1000000 ); -00315 SetActive(); -00316 return; -00317 } -00318 -00319 // Case 2: there's more data to get from the server -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 // Clean up -00330 iHostResolver.Close(); -00331 delete iTlsSocket; -00332 iTlsSocket =0; -00333 iSocket.Close(); -00334 -00335 // Wait here for an unload of the ssl.dll to make sure that a session is not -00336 // reconnected next time. -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 // Print issuer and subject -00390 HBufC* issuer = aSource.IssuerL(); -00391 HBufC* subject = aSource.SubjectL(); -00392 iConsole->Printf(KCertInfoMessage1, issuer, subject); -00393 delete issuer; -00394 delete subject; -00395 -00396 // Print validity period -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 } -