vpnengine/kmdserver/src/ikepcaptrace.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     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:  Class that logs ike messages in pcap format
       
    15 *
       
    16 */
       
    17 
       
    18 #include <bautils.h>
       
    19 #include <in_sock.h>
       
    20 
       
    21 #include "ikepcaptrace.h"
       
    22 
       
    23 _LIT(KLogDirectoryFormat, "c:\\logs\\%S\\");
       
    24 _LIT(KTraceFileName, "ikemsg.pcap");
       
    25 
       
    26 static const TUint KIpAndUdpHeaderLength = 28;
       
    27 static const TUint KFixedHdrLength       = 28;
       
    28 static const TUint KNonEspMarkerLength   = 4;
       
    29 static const TInt KNatPort = 4500;
       
    30 
       
    31 _LIT(KUnixTimeZeroDes, "19700101:000000.000000");
       
    32 static const TTime KUnixTimeZero(KUnixTimeZeroDes);
       
    33 
       
    34 #define SWAP_BYTE_ORDER32(a) ((a) >> 24) | ((a) >> 8 & 0xff00) |((a) << 8 & 0xff0000) | ((a) << 24);
       
    35 #define SWAP_BYTE_ORDER16(a) ((a) >> 8 | (a) << 8)
       
    36 
       
    37 CIkePcapTrace* CIkePcapTrace::NewL(const TDesC& aLogFolder)
       
    38     {
       
    39     CIkePcapTrace* self = new (ELeave) CIkePcapTrace();
       
    40     CleanupStack::PushL(self);
       
    41     self->ConstructL(aLogFolder);    
       
    42     CleanupStack::Pop(self);
       
    43     
       
    44     return self;
       
    45     }
       
    46 
       
    47 
       
    48 CIkePcapTrace::CIkePcapTrace()
       
    49     {   
       
    50     }
       
    51 
       
    52 
       
    53 void CIkePcapTrace::ConstructL(const TDesC& aLogFolder)
       
    54     {
       
    55     User::LeaveIfError(iFileServer.Connect());   
       
    56     
       
    57     TFileName* traceFileName = new (ELeave) TFileName;
       
    58     CleanupDeletePushL(traceFileName);
       
    59     traceFileName->Format(KLogDirectoryFormat, &aLogFolder);
       
    60     
       
    61     if (BaflUtils::FolderExists(iFileServer, *traceFileName))
       
    62         {
       
    63         traceFileName->Append(KTraceFileName);
       
    64         
       
    65         if (BaflUtils::FileExists(iFileServer, *traceFileName))
       
    66             {
       
    67             TInt position = 0;
       
    68             User::LeaveIfError(iPcapFile.Open(iFileServer, *traceFileName, EFileWrite));
       
    69             User::LeaveIfError(iPcapFile.Seek(ESeekEnd, position));
       
    70             }
       
    71         else
       
    72             {
       
    73             User::LeaveIfError(iPcapFile.Create(iFileServer, *traceFileName, EFileWrite));
       
    74             TInt err = WritePcapHeader();
       
    75             if (err != KErrNone)
       
    76                 {
       
    77                 iPcapFile.Close();
       
    78                 User::LeaveIfError(iFileServer.Delete(*traceFileName));
       
    79                 User::Leave(err);
       
    80                 }                            
       
    81             }
       
    82         iWriteTrace = ETrue;
       
    83         }
       
    84     else
       
    85         {
       
    86         iWriteTrace = EFalse;
       
    87         }         
       
    88     CleanupStack::PopAndDestroy(traceFileName);
       
    89     }
       
    90 
       
    91 
       
    92 CIkePcapTrace::~CIkePcapTrace()
       
    93     {
       
    94     iPcapFile.Close();
       
    95     iFileServer.Close();
       
    96     }
       
    97 
       
    98 void CIkePcapTrace::TraceMessage(const TDesC8& aMessage, 
       
    99                                  const TInetAddr& aSourceAddress, 
       
   100                                  const TInetAddr& aDestinationAddress,
       
   101                                  TEncryptionType aEncryptionType)
       
   102     {
       
   103     if (iWriteTrace)
       
   104         {
       
   105         HBufC8* msgCopy = aMessage.Alloc();        
       
   106         if (msgCopy != NULL)
       
   107             {
       
   108             TPtr8 msgCopyPtr = msgCopy->Des();
       
   109             DoTraceMessage(msgCopyPtr, aSourceAddress, aDestinationAddress,
       
   110                            aEncryptionType);
       
   111             }
       
   112         delete msgCopy;
       
   113         msgCopy = NULL;
       
   114         }
       
   115     }
       
   116 
       
   117 
       
   118 
       
   119 void CIkePcapTrace::DoTraceMessage(TPtr8& aMsgCopy, 
       
   120                                    const TInetAddr& aSourceAddress, 
       
   121                                    const TInetAddr& aDestinationAddress,
       
   122                                    TEncryptionType aEncryptionType)
       
   123     { 
       
   124        
       
   125     if ((aSourceAddress.Family() == KAfInet ||
       
   126          aSourceAddress.IsV4Compat() || 
       
   127          aSourceAddress.IsV4Mapped()) &&
       
   128         (aDestinationAddress.Family() == KAfInet ||  
       
   129          aDestinationAddress.IsV4Compat() || 
       
   130          aDestinationAddress.IsV4Mapped()))
       
   131         {
       
   132             TInt length = aMsgCopy.Length();
       
   133             if (aSourceAddress.Port() == KNatPort)
       
   134                 {
       
   135                 length+=KNonEspMarkerLength;
       
   136                 }
       
   137             WriteRecordHeader(length);
       
   138             WriteIpAndUdpHeader(aMsgCopy, aSourceAddress, aDestinationAddress);
       
   139             if ( aSourceAddress.Port() == KNatPort )
       
   140                 {
       
   141                 WriteNonEspMarker();
       
   142                 }
       
   143             WriteIkeMessage(aMsgCopy, aEncryptionType);
       
   144             iPcapFile.Flush();
       
   145         }
       
   146     }
       
   147 
       
   148 
       
   149 TInt CIkePcapTrace::WriteRecordHeader(TUint32 aIkeMsgLength)
       
   150     {
       
   151     static const TUint KRecordHeaderLength = 4;
       
   152     TUint32 recordHeader[KRecordHeaderLength];
       
   153         
       
   154     TUint32 currentSeconds = 0;
       
   155     TTime currentTime;
       
   156     currentTime.HomeTime();
       
   157     
       
   158     TTimeIntervalSeconds secondsFrom;    
       
   159     if (currentTime.SecondsFrom(KUnixTimeZero, secondsFrom) == KErrNone)
       
   160         {
       
   161         currentSeconds = secondsFrom.Int();
       
   162         }
       
   163     
       
   164     TUint32 microseconds = currentTime.DateTime().MicroSecond();
       
   165     
       
   166     recordHeader[0] = currentSeconds;
       
   167     recordHeader[1] = microseconds;             
       
   168     recordHeader[2] = aIkeMsgLength + KIpAndUdpHeaderLength;
       
   169     recordHeader[3] = aIkeMsgLength + KIpAndUdpHeaderLength;
       
   170     
       
   171     TPtrC8 recordHdrPtr((TUint8*)recordHeader, KRecordHeaderLength * sizeof(TUint32));
       
   172     return iPcapFile.Write(recordHdrPtr);
       
   173     }
       
   174 
       
   175 TInt CIkePcapTrace::WriteIpAndUdpHeader(const TDesC8& aMessage,
       
   176                                         TInetAddr aSourceAddress, 
       
   177                                         TInetAddr aDestinationAddress)
       
   178     {
       
   179     static const TUint KIpHeaderLength = 20;
       
   180     static const TUint KUdpHeaderLength = KIpAndUdpHeaderLength - KIpHeaderLength; 
       
   181         
       
   182     //Generate IP header
       
   183     aSourceAddress.ConvertToV4();
       
   184     aDestinationAddress.ConvertToV4();
       
   185     
       
   186     TUint32 source      = SWAP_BYTE_ORDER32(aSourceAddress.Address());    
       
   187     TUint32 destination = SWAP_BYTE_ORDER32(aDestinationAddress.Address()); 
       
   188     
       
   189     TUint8 ipAndUdpHeader[] = { 0x45, 0x00, 0x13, 0x88, 
       
   190                                 0x00, 0x28, 0x00, 0x00, 
       
   191                                 0xfe, 0x11, 0x00, 0x00,
       
   192                                 0x00, 0x00, 0x00, 0x00, //source IP address
       
   193                                 0x00, 0x00, 0x00, 0x00, //destination IP address
       
   194                                 0x00, 0x00, 0x00, 0x00, //udp header
       
   195                                 0x00, 0x00, 0x00, 0x00}; 
       
   196                           
       
   197     Mem::Copy(ipAndUdpHeader + 12, &source, sizeof(source)); //copies the source address to header
       
   198     Mem::Copy(ipAndUdpHeader + 16, &destination, sizeof(destination)); //copies the source address to header
       
   199    
       
   200     
       
   201     //Generate UDP header
       
   202     TUint16 sourcePort          = aSourceAddress.Port();
       
   203     TUint16 destinationPort     = aDestinationAddress.Port();
       
   204     TUint16 udpDatagramLength   = KUdpHeaderLength + aMessage.Length();
       
   205     if ( sourcePort == KNatPort )
       
   206         {
       
   207         udpDatagramLength += KNonEspMarkerLength; 
       
   208         }
       
   209     sourcePort          = SWAP_BYTE_ORDER16(sourcePort);
       
   210     destinationPort     = SWAP_BYTE_ORDER16(destinationPort);
       
   211     udpDatagramLength   = SWAP_BYTE_ORDER16(udpDatagramLength);
       
   212     
       
   213     TUint8* udpHeader = ipAndUdpHeader + KIpHeaderLength;
       
   214     Mem::Copy(udpHeader, &sourcePort, sizeof(sourcePort));
       
   215     Mem::Copy(udpHeader + 2, &destinationPort, sizeof(destinationPort));
       
   216     Mem::Copy(udpHeader + 4, &udpDatagramLength, sizeof(udpDatagramLength));
       
   217     
       
   218     TPtrC8 headerPtr(ipAndUdpHeader, KIpAndUdpHeaderLength);
       
   219     return iPcapFile.Write(headerPtr);
       
   220     }
       
   221 
       
   222 TInt CIkePcapTrace::WriteNonEspMarker()
       
   223     {
       
   224     TUint8 nonEspMarker[] = { 0x00, 0x00, 0x00, 0x00 };
       
   225 
       
   226     TPtrC8 ptr(nonEspMarker, KNonEspMarkerLength);
       
   227     return iPcapFile.Write(ptr);
       
   228     }
       
   229 
       
   230 TInt CIkePcapTrace::WriteIkeMessage(TPtr8& aMsgCopy, TEncryptionType aEncryptionType)
       
   231     {
       
   232     const TInt KVersionPosition = 17;
       
   233     
       
   234     TInt err = KErrNone;     
       
   235     if (aMsgCopy.Length() < KFixedHdrLength)
       
   236         {
       
   237         //This is a bit too short for an IKE packet.
       
   238         //Just write the packet to log anyway. It might give some info to someone.
       
   239         err = iPcapFile.Write(aMsgCopy);
       
   240         }
       
   241     else
       
   242         {
       
   243         //Version check:
       
   244         if (aMsgCopy[KVersionPosition] == 0x10)
       
   245             {   
       
   246             err = WriteIkeV1Message(aMsgCopy);
       
   247             }
       
   248         else
       
   249             {
       
   250             err = WriteIkeV2Message(aMsgCopy, aEncryptionType);
       
   251             }
       
   252         }
       
   253     
       
   254     return err;
       
   255     }
       
   256 
       
   257 
       
   258 TInt CIkePcapTrace::WriteIkeV1Message(TPtr8& aMsgCopy)
       
   259     {
       
   260     //This should already be checked by the caller.
       
   261     __ASSERT_DEBUG(aMsgCopy.Length() >= KFixedHdrLength, User::Invariant());
       
   262         
       
   263     const TUint KEncryptionBitPosition    = 19;
       
   264     const TUint KFirstNextPayloadPosition = 16;    
       
   265     const TUint KFixedPayloadHdrLength    = 4;
       
   266     
       
   267     const TUint8 KPayloadNone               = 0x00;
       
   268     const TUint8 KPayloadHash               = 0x08;
       
   269     const TUint8 KPayloadSignature          = 0x09;
       
   270     const TUint8 KPayloadReservedRangeStart = 0x0E;
       
   271     
       
   272     aMsgCopy[KEncryptionBitPosition] = aMsgCopy[KEncryptionBitPosition] & 0xFE;
       
   273 
       
   274     TUint8 nextPayloadId = aMsgCopy[KFirstNextPayloadPosition];
       
   275     TPtr8 msgEnd(aMsgCopy.MidTPtr(KFixedHdrLength));
       
   276     
       
   277     while(nextPayloadId != KPayloadNone && 
       
   278           msgEnd.Length() > KFixedPayloadHdrLength)
       
   279         {
       
   280         //Read the lenght of the payload
       
   281         TUint16 payloadLength = ((TUint16)msgEnd[2]) << 8 | msgEnd[3]; 
       
   282       
       
   283         if (nextPayloadId == KPayloadHash ||
       
   284             nextPayloadId == KPayloadSignature ||
       
   285             nextPayloadId >= KPayloadReservedRangeStart)
       
   286             {
       
   287             if(msgEnd.Length() >= payloadLength &&
       
   288                payloadLength >= KFixedPayloadHdrLength )
       
   289                 {
       
   290                 // Zero out payload data.
       
   291                 TUint16 dataLength = payloadLength - KFixedPayloadHdrLength;
       
   292                 TPtr8 payloadData = msgEnd.MidTPtr(KFixedPayloadHdrLength, dataLength);
       
   293                 payloadData.FillZ();
       
   294                 }
       
   295             else
       
   296                 {
       
   297                   //There seems to be something wrong with the packet.
       
   298                   //Zero out the rest of the packet and write it to the log.
       
   299                   msgEnd.FillZ();
       
   300                   msgEnd[0] = KPayloadNone;
       
   301                 }                
       
   302             }
       
   303         
       
   304         nextPayloadId = msgEnd[0];
       
   305         if (nextPayloadId != KPayloadNone && 
       
   306             msgEnd.Length() >= payloadLength)
       
   307             {
       
   308             msgEnd.Set(msgEnd.MidTPtr(payloadLength));
       
   309             }
       
   310         else
       
   311             {
       
   312             msgEnd.Set(msgEnd.MidTPtr(msgEnd.Length()));
       
   313             }        
       
   314         }
       
   315     
       
   316     return iPcapFile.Write(aMsgCopy);
       
   317     }
       
   318 
       
   319 
       
   320 TInt CIkePcapTrace::WriteIkeV2Message(TPtr8& aMsgCopy, TEncryptionType aEncryptionType)
       
   321     {
       
   322     //This should already be checked by the caller.
       
   323     __ASSERT_DEBUG(aMsgCopy.Length() >= KFixedHdrLength, User::Invariant());
       
   324     
       
   325     const TUint KFirstNextPayloadPosition        = 16;
       
   326     const TUint KFixedPayloadHdrLength           = 4;
       
   327     
       
   328     const TUint8 KPayloadNone      = 0x00;
       
   329     const TUint8 KEncryptedPayload = 0x2e;
       
   330     const TUint8 KAuthPayload      = 0x27;
       
   331     const TUint8 KEapPayload       = 0x30;    
       
   332     
       
   333     TUint8 nextPayloadId = aMsgCopy[KFirstNextPayloadPosition];
       
   334     TPtr8 msgEnd(aMsgCopy.MidTPtr(KFixedHdrLength));
       
   335     while(nextPayloadId != KPayloadNone && 
       
   336           msgEnd.Length() > KFixedPayloadHdrLength)
       
   337         {
       
   338         //Read the lenght of the payload
       
   339         TUint16 payloadLength = ((TUint16)msgEnd[2]) << 8 | msgEnd[3]; 
       
   340         
       
   341         switch(nextPayloadId)
       
   342             {
       
   343             case KEncryptedPayload:
       
   344                 //change the encrypted payload length to match
       
   345                 //the initialization vector length.
       
   346                 msgEnd[2] = 0x00;
       
   347                 switch(aEncryptionType)
       
   348                     {   
       
   349                     case EEncrDes: //falls through                    
       
   350                     case EEncrDes3:                        
       
   351                         msgEnd[3] = 0x0c;
       
   352                         break;
       
   353                     case EEncrAesCbc:                       
       
   354                         msgEnd[3] = 0x14;
       
   355                         break;
       
   356                     }
       
   357                 payloadLength = msgEnd[3]; 
       
   358                 break;
       
   359             case KAuthPayload:
       
   360                 {
       
   361                 const TUint8 KAuthPayloadHdrLength = 8;
       
   362                 if (payloadLength > KAuthPayloadHdrLength && 
       
   363                     msgEnd.Length() >= payloadLength)
       
   364                     {
       
   365                     // Zero out payload data.
       
   366                     TPtr8 authData = msgEnd.MidTPtr(KAuthPayloadHdrLength, 
       
   367                                                     payloadLength - KAuthPayloadHdrLength);
       
   368                     authData.FillZ();
       
   369                     }
       
   370                 }
       
   371                 break;
       
   372             case KEapPayload:
       
   373                 {
       
   374                 const TUint8 KTotalFixEapHdrLength = 9;
       
   375                 if (payloadLength > KTotalFixEapHdrLength && 
       
   376                     msgEnd.Length() >= payloadLength)
       
   377                     {
       
   378                     // Zero out payload data.
       
   379                     TPtr8 eapTypeData = msgEnd.MidTPtr(KTotalFixEapHdrLength,
       
   380                                                        payloadLength - KTotalFixEapHdrLength);
       
   381                     eapTypeData.FillZ();
       
   382                     }
       
   383                 }
       
   384                 break;
       
   385             }
       
   386         nextPayloadId = msgEnd[0];
       
   387         if (nextPayloadId != KPayloadNone && 
       
   388             msgEnd.Length() >= payloadLength)
       
   389             {
       
   390             msgEnd.Set(msgEnd.MidTPtr(payloadLength));
       
   391             }
       
   392         else
       
   393             {
       
   394             msgEnd.Set(msgEnd.MidTPtr(msgEnd.Length()));
       
   395             }
       
   396         }
       
   397     
       
   398     return iPcapFile.Write(aMsgCopy);
       
   399     }
       
   400 
       
   401 
       
   402 TInt CIkePcapTrace::WritePcapHeader()
       
   403     {
       
   404     static const TUint KPcapHeaderLength = 24;
       
   405     TUint8 pCapHeader[] = { 0xd4, 0xc3, 0xb2, 0xa1,  // magic number
       
   406                             0x02, 0x00, 0x04, 0x00,  //major, minor version
       
   407                             0x00, 0x00, 0x00, 0x00,  //time offset
       
   408                             0x00, 0x00, 0x00, 0x00,  // accuracy of timestamps
       
   409                             0xff, 0xff, 0x00, 0x00,  // max length of captured packets, in octets 
       
   410                             0x0c, 0x00, 0x00, 0x00,  // data link type 
       
   411                            };
       
   412     
       
   413     TPtrC8 pCapHeaderPtr(pCapHeader, KPcapHeaderLength);    
       
   414     return iPcapFile.Write(pCapHeaderPtr);       
       
   415     }
       
   416 
       
   417