--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/kmdserver/src/secpolreader.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,287 @@
+/*
+* Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Security policy module
+*
+*/
+
+
+#include <es_sock.h>
+#include <in_sock.h>
+#include <networking/ipsecerr.h>
+#include <vpnlogmessages.rsg>
+#include "ikedebug.h"
+#include "kmdeventloggerif.h"
+#include "secpolpayload.h"
+
+// CLASS HEADER
+#include "secpolreader.h"
+
+// ======== LOCAL FUNCTIONS ========
+
+#ifdef _DEBUG
+
+// ---------------------------------------------------------------------------
+// Returns error description.
+// ---------------------------------------------------------------------------
+//
+static const TPtrC IpsecError( TInt aReason )
+ {
+ switch ( aReason )
+ {
+ case EIpsec_RMBUF: return _L("RMBUF operation failed unexcpectedly");
+ //
+ // AH and ESP
+ //
+ case EIpsec_CorruptPacketIn: return _L("Truncated or corrupt packet or header");
+ case EIpsec_CorruptPacketOut: return _L("Corrupt packet after IPSEC operations");
+ case EIpsec_EspInboundSA: return _L("The inbound SA for ESP does not exist");
+ case EIpsec_EspAuthentication: return _L("Authentication check failed in ESP");
+ case EIpsec_EspAuthAlg: return _L("Required auth algorithm for ESP not available/installed");
+ case EIpsec_EspEncrAlg: return _L("Required encrypt algorithm for ESP not available/installed");
+ case EIpsec_AhAuthAlg: return _L("Required auth algorithm for AH not available/installed");
+ case EIpsec_AhInboundSA: return _L("The inbound SA for AH does not exist");
+ case EIpsec_AhIcvLength: return _L("ICV length in packet does not match algorithm");
+ case EIpsec_AhAuthentication: return _L("Authentication check failed in AH");
+ case EIpsec_PacketLength: return _L("Invalid/corrupt length of the packet");
+ case EIpsec_DataAlignment: return _L("Data not aligned by block size (ESP)");
+ case EIpsec_EspPadByte: return _L("The ESP pad byte content is invalid");
+ case EIpsec_EspPadLength: return _L("The ESP pad length is corrupt (probably wrong key)");
+ case EIpsec_ReplayDuplicate: return _L("Duplicate packet (replay window test)");
+ //
+ // SECPOL
+ //
+ case EIpsec_OutboundNotFound: return _L("Outbound SA does not exist, ACQUIRE started");
+ case EIpsec_OutboundPending: return _L("Outbooud SA does not exits, ACQUIRE pending");
+ case EIpsec_NoSelectorMatch: return _L("None of the policy selectors matched");
+ case EIpsec_MaxTransforms: return _L("Incoming packet exceed configured max limit of transforms");
+ case EIpsec_TooFewTransforms: return _L("Policy requires IPSEC, none or too little was present");
+ case EIpsec_TunnelMismatch: return _L("Tunnelmode does not match the policy");
+ case EIpsec_MismatchedSA: return _L("Applied SA does not match the policy");
+ case EIpsec_UnrequiredSA: return _L("Applied SA where policy has none");
+ case EIpsec_TooManyTransforms: return _L("Incoming packet had more transforms than policy requires");
+ case EIpsec_NoBundle: return _L("Incoming packet had transforms, but policy doesn't require any");
+ //
+ // IPv6 additions
+ //
+ case EIpsec_AhRMBufSplit: return _L("Inbound AH processing failed (Memory?)");
+ case EIpsec_AhPacketTooLong: return _L("Outbound packet would exeed 2**16-1 with AH");
+ case EIpsec_AhSequenceWrap: return _L("Outbound sequence # wrapped around for this SA");
+ case EIpsec_EspSequenceWrap: return _L("Outbound sequence # wrapped around for this SA");
+ case EIpsec_EspBadCipherBlockSize: return _L("Configuration error, cipher block size must be < 256");
+ case EIpsec_AcquireFailed: return _L("Acquiring SA failed (no SA available or negotiated)");
+ //
+ // Detail reasons for SA not matching the SA spec in the policy
+ // (replace one EIpsec_MismatchedSA with multiple detail errors)
+ //
+ case EIpsec_MismatchedDestination: return _L("SA destination does not match (internal error?)");
+ case EIpsec_MismatchedType: return _L("SA Type (AH/ESP) does not match");
+ case EIpsec_MismatchedPFS: return _L("PFS bit is not same");
+ case EIpsec_MismatchedAuthAlg: return _L("Auth algorithm doesn't match");
+ case EIpsec_MismatchedEncryptAlg: return _L("Encrypt algorithm doesn't match");
+ case EIpsec_MismatchReplayWindow: return _L("ReplayWindow length is shorter than required");
+ case EIpsec_MismatchSource: return _L("source address does not match");
+ case EIpsec_MismatchProxy: return _L("proxy address does not match");
+ case EIpsec_MismatchSourcePort: return _L("source port does not match");
+ case EIpsec_MismatchDestinationPort:return _L("destination port does not match");
+ case EIpsec_MismatchProtocol: return _L("protocol does not match");
+ case EIpsec_MismatchSourceIdentity: return _L("source identity does not match");
+ case EIpsec_MismatchDestinationIdentity: return _L("destination identity does not match");
+
+ case EIpsec_BadCipherKey: return _L("Key in SA is too short (for the algorithm) or is weak");
+ case EIpsec_UnknownCipherNumber: return _L("Attempting to use algorithm number that is not known");
+ case EIpsec_UnknownDigestNumber: return _L("Attempting to use algorithm number that is not known");
+ case EIpsec_UnavailableCipher: return _L("No installed library implements the cipher");
+ case EIpsec_UnavailableDigest: return _L("No installed library implements the digest");
+ //
+ // Temporary place for new errors
+ //
+ case EIpsec_IcmpError: return _L("An ICMP error report containing AH or ESP (for INET6)");
+ case EIpsec_LostSA: return _L("An SA has been lost between Apply and Verify, expired? (for SECPOL)");
+ case EIpsec_NoInnerSource: return _L("Cannot find inner-src for outbound packet when tunneling (for SECPOL)");
+ //
+ // Special code for NAT Traversal
+ //
+ case EIpsec_NotANATTPacket: return _L("UDP packet is NOT a NAT Taversal packet");
+ case EIpsec_FragmentMismatch: return _L("IPSEC on fragment is not same as before, packet dropped");
+
+ default:
+ return _L("Unknown reason");
+ }
+ }
+
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CSecpolReader* CSecpolReader::NewL( MKmdEventLoggerIf& aEventLogger,
+ MIkeDebug& aDebug )
+ {
+ CSecpolReader* self = new (ELeave) CSecpolReader( aEventLogger,
+ aDebug );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CSecpolReader::~CSecpolReader()
+ {
+ DEBUG_LOG(_L("CSecpolReader::~CSecpolReader"));
+ Cancel();
+ iSocket.Close();
+ iSocketServer.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CSecpolReader::CSecpolReader( MKmdEventLoggerIf& aEventLogger,
+ MIkeDebug& aDebug )
+: CActive( EPriorityStandard ),
+ iEventLogger( aEventLogger ),
+ iDebug( aDebug )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------------------------
+// Second phase construction.
+// ---------------------------------------------------------------------------
+//
+void CSecpolReader::ConstructL()
+ {
+ TInetAddr addr;
+ User::LeaveIfError( iSocketServer.Connect() );
+ User::LeaveIfError( iSocket.Open( iSocketServer, _L("secpol6") ) );
+ addr.SetAddress( KInetAddrNone );
+ addr.SetPort( 0 );
+ User::LeaveIfError( iSocket.Bind( addr ) );
+ iSocket.RecvFrom( iMsg, iAddr, 0, iStatus );
+ SetActive();
+ DEBUG_LOG(_L("CSecpolReader::ConstructL - constructed"));
+ }
+
+// ---------------------------------------------------------------------------
+// Returns event logger.
+// ---------------------------------------------------------------------------
+//
+MKmdEventLoggerIf& CSecpolReader::EventLogger()
+ {
+ return iEventLogger;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From class CActive
+// Handles completion of asynchronous reading.
+// ---------------------------------------------------------------------------
+//
+void CSecpolReader::RunL()
+ {
+#ifdef _DEBUG
+ TBuf<40> buf;
+ TBuf<1000> str;
+ TInt protocol = -1;
+#endif // _DEBUG
+ TInt len = 0;
+ TBool processEvent;
+ TSecpolPayload packet( iMsg.Ptr() );
+
+ DEBUG_LOG1(_L("Secpol read, status=%d"), iStatus.Int());
+ __ASSERT_DEBUG( iStatus.Int() == KErrNone,
+ User::Invariant() );
+ if ( iStatus.Int() == KErrNone )
+ {
+ switch ( packet.iIP4->Version() )
+ {
+ case 4:
+ processEvent = ((THdrIP4 *)packet.iRaw)->IsUnicast();
+ if ( processEvent )
+ {
+#ifdef _DEBUG
+ ((THdrIP4 *)packet.iRaw)->Dump( str, iMsg.Length() );
+ protocol = packet.iIP4->Protocol();
+#endif // _DEBUG
+ len = packet.iIP4->HeaderLength();
+ }
+ break;
+ case 6:
+ processEvent = ((THdrIP6 *)packet.iRaw)->IsUnicast();
+ if ( processEvent )
+ {
+#ifdef _DEBUG
+ ((THdrIP6 *)packet.iRaw)->Dump( str, iMsg.Length() );
+ protocol = packet.iIP6->NextHeader();
+#endif // _DEBUG
+ len = packet.iIP6->HeaderLength();
+ }
+ break;
+ default:
+ processEvent = ETrue;
+#ifdef _DEBUG
+ str.Format( _L("Unknown IP protocol version %d"),
+ (TInt)packet.iIP4->Version() );
+#endif // _DEBUG
+ break;
+ }
+
+ if ( processEvent )
+ {
+ if ( len )
+ {
+ packet.iRaw += len;
+#ifdef _DEBUG
+ packet.Dump( str, iMsg.Length()-len, protocol );
+#endif // _DEBUG
+ }
+#ifdef _DEBUG
+ str.Append( _L(" from ") );
+ (TInetAddr::Cast(iAddr)).OutputWithScope( buf );
+ str.Append( buf );
+ str.Append( _L(" because ") );
+ str.Append( IpsecError( iAddr.Port() ) );
+ str.AppendFormat( _L(" (%d)"), iAddr.Port() );
+ DEBUG_LOG(str);
+#endif // _DEBUG
+
+ LOG_KMD_EVENT( MKmdEventLoggerIf::KLogWarning,
+ R_VPN_MSG_DATA_DROPPED_DUE_POLICY,
+ (TInt)iAddr.Port(),
+ 0,
+ &iAddr );
+ }
+ }
+
+ iSocket.RecvFrom( iMsg, iAddr, 0, iStatus ); // start a new read
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// From class CActive
+// Handles cancellation of asynchronous reading.
+// ---------------------------------------------------------------------------
+//
+void CSecpolReader::DoCancel()
+ {
+ iSocket.CancelRecv();
+ }