1999-03-29 02:21:34 +00:00
/* packet-ipsec.c
2002-08-28 21:04:11 +00:00
* Routines for IPsec / IPComp packet disassembly
1999-03-29 02:21:34 +00:00
*
2004-07-18 00:24:25 +00:00
* $ Id $
1999-03-29 02:21:34 +00:00
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
1999-03-29 02:21:34 +00:00
* Copyright 1998 Gerald Combs
2006-08-09 02:00:05 +00:00
*
1999-03-29 02:21:34 +00:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2002-08-28 21:04:11 +00:00
*
1999-03-29 02:21:34 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2002-08-28 21:04:11 +00:00
*
1999-03-29 02:21:34 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2006-03-27 16:25:35 +00:00
/*
2006-04-13 22:26:13 +00:00
Addon : ESP Decryption and Authentication Checking
2006-03-27 16:25:35 +00:00
Frederic ROUDAUT ( frederic . roudaut @ free . fr )
Copyright 2006 Frederic ROUDAUT
2006-08-09 02:00:05 +00:00
- Decrypt ESP Payload for the following Algorithms defined in RFC 4305 :
2006-03-27 16:25:35 +00:00
Encryption Algorithm
- - - - - - - - - - - - - - - - - - - -
NULL
TripleDES - CBC [ RFC2451 ] : keylen 192 bits .
AES - CBC with 128 - bit keys [ RFC3602 ] : keylen 128 and 192 / 256 bits .
AES - CTR [ RFC3686 ] : keylen 160 / 224 / 288 bits . The remaining 32 bits will be used as nonce .
DES - CBC [ RFC2405 ] : keylen 64 bits
2006-08-09 02:00:05 +00:00
- Add ESP Payload Decryption support for the following Encryption Algorithms :
BLOWFISH - CBC : keylen 128 bits .
TWOFISH - CBC : keylen 128 / 256 bits .
2006-04-13 22:26:13 +00:00
2006-08-09 02:00:05 +00:00
- Check ESP Authentication for the following Algorithms defined in RFC 4305 :
2006-04-13 22:26:13 +00:00
2006-08-09 02:00:05 +00:00
Authentication Algorithm
2006-03-27 16:25:35 +00:00
- - - - - - - - - - - - - - - - - - - - - - - -
2006-08-09 02:00:05 +00:00
NULL
2006-04-13 22:26:13 +00:00
HMAC - SHA1 - 96 [ RFC2404 ] : any keylen
HMAC - MD5 - 96 [ RFC2403 ] : any keylen
2006-08-09 02:00:05 +00:00
AES - XCBC - MAC - 96 [ RFC3566 ] : Not available because no implementation found .
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
- Add ESP Authentication checking for the following Authentication Algorithm :
2006-04-13 22:26:13 +00:00
HMAC - SHA256 : any keylen
2006-03-27 16:25:35 +00:00
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2006-08-09 02:00:05 +00:00
1999-03-29 02:21:34 +00:00
# include <stdio.h>
2000-11-17 21:00:40 +00:00
# include <string.h>
1999-03-29 02:21:34 +00:00
# include <glib.h>
2002-01-21 07:37:49 +00:00
# include <epan/packet.h>
2006-08-09 02:00:05 +00:00
# include <epan/emem.h>
2000-02-15 21:06:58 +00:00
# include "packet-ipsec.h"
2004-08-06 19:57:49 +00:00
# include <epan/addr_resolv.h>
2004-09-29 00:52:45 +00:00
# include <epan/ipproto.h>
2004-09-27 22:55:15 +00:00
# include <epan/prefs.h>
2000-07-08 10:46:23 +00:00
2006-03-27 16:25:35 +00:00
# include <ctype.h>
1999-03-29 02:21:34 +00:00
2006-09-08 07:32:13 +00:00
/* If you want to be able to decrypt or Check Authentication of ESP packets you MUST define this : */
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
# ifdef _WIN32
# include <winposixtype.h>
# endif /* _WIN32 */
2006-03-27 16:25:35 +00:00
# include <gcrypt.h>
2006-08-09 02:00:05 +00:00
# endif /* HAVE_LIBGCRYPT */
2006-03-27 16:25:35 +00:00
2006-04-13 22:26:13 +00:00
static int proto_ah = - 1 ;
1999-10-11 12:37:50 +00:00
static int hf_ah_spi = - 1 ;
2006-09-12 09:53:10 +00:00
static int hf_ah_iv = - 1 ;
1999-10-11 12:37:50 +00:00
static int hf_ah_sequence = - 1 ;
1999-07-29 05:47:07 +00:00
static int proto_esp = - 1 ;
1999-10-11 12:37:50 +00:00
static int hf_esp_spi = - 1 ;
2006-09-12 09:53:10 +00:00
static int hf_esp_iv = - 1 ;
1999-10-11 12:37:50 +00:00
static int hf_esp_sequence = - 1 ;
2006-04-13 22:26:13 +00:00
static int hf_esp_pad_len = - 1 ;
2004-11-12 10:03:53 +00:00
static int hf_esp_protocol = - 1 ;
1999-10-15 05:30:43 +00:00
static int proto_ipcomp = - 1 ;
1999-10-15 05:46:18 +00:00
static int hf_ipcomp_flags = - 1 ;
1999-10-15 05:30:43 +00:00
static int hf_ipcomp_cpi = - 1 ;
1999-07-29 05:47:07 +00:00
1999-11-16 11:44:20 +00:00
static gint ett_ah = - 1 ;
static gint ett_esp = - 1 ;
static gint ett_ipcomp = - 1 ;
2001-11-26 04:52:51 +00:00
static dissector_handle_t data_handle ;
2003-04-29 17:24:35 +00:00
static dissector_table_t ip_dissector_table ;
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
/* Encryption algorithms defined in RFC 4305 */
# define IPSEC_ENCRYPT_NULL 0
# define IPSEC_ENCRYPT_3DES_CBC 1
# define IPSEC_ENCRYPT_AES_CBC 2
# define IPSEC_ENCRYPT_AES_CTR 3
2006-08-09 02:00:05 +00:00
# define IPSEC_ENCRYPT_DES_CBC 4
2006-03-27 16:25:35 +00:00
# define IPSEC_ENCRYPT_BLOWFISH_CBC 5
# define IPSEC_ENCRYPT_TWOFISH_CBC 6
1999-03-29 02:21:34 +00:00
2006-03-27 16:25:35 +00:00
/* Authentication algorithms defined in RFC 4305 */
# define IPSEC_AUTH_NULL 0
# define IPSEC_AUTH_HMAC_SHA1_96 1
2006-04-13 22:26:13 +00:00
# define IPSEC_AUTH_HMAC_SHA256 2
2006-03-27 16:25:35 +00:00
# define IPSEC_AUTH_HMAC_MD5_96 3
2006-04-13 22:26:13 +00:00
# define IPSEC_AUTH_ANY_12BYTES 5
/* define IPSEC_AUTH_AES_XCBC_MAC_96 6 */
2006-03-27 16:25:35 +00:00
# endif
1999-10-15 05:30:43 +00:00
/* well-known algorithm number (in CPI), from RFC2409 */
# define IPCOMP_OUI 1 /* vendor specific */
# define IPCOMP_DEFLATE 2 /* RFC2394 */
# define IPCOMP_LZS 3 /* RFC2395 */
# define IPCOMP_MAX 4
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
# define IPSEC_IPV6_ADDR_LEN 128
# define IPSEC_IPV4_ADDR_LEN 32
# define IPSEC_STRLEN_IPV6 32
# define IPSEC_STRLEN_IPV4 8
# define IPSEC_SA_IPV4 1
# define IPSEC_SA_IPV6 2
# define IPSEC_SA_UNKNOWN -1
# define IPSEC_SA_WILDCARDS_ANY '*'
# define IPSEC_SA_SEPARATOR '|'
# define IPSEC_SA_ADDR_LEN_SEPARATOR ' / '
2006-08-15 19:28:07 +00:00
# define IPSEC_IPV6_ADDR_MAX 40
# define IPSEC_IPV4_ADDR_MAX 16
# define IPSEC_SPI_LEN_MAX 10
2006-08-18 00:22:48 +00:00
# define IPSEC_TYP_LEN 4
2006-08-15 19:28:07 +00:00
# define IPSEC_ADDR_LEN_MAX 3
2006-03-27 16:25:35 +00:00
/* Number of Security Associations */
2006-08-14 22:34:46 +00:00
# define IPSEC_NB_SA 16
2006-03-27 16:25:35 +00:00
# endif
1999-10-15 05:30:43 +00:00
static const value_string cpi2val [ ] = {
2006-03-27 16:25:35 +00:00
{ IPCOMP_OUI , " OUI " } ,
{ IPCOMP_DEFLATE , " DEFLATE " } ,
{ IPCOMP_LZS , " LZS " } ,
{ 0 , NULL } ,
} ;
struct newah {
guint8 ah_nxt ; /* Next Header */
guint8 ah_len ; /* Length of data + 1, in 32bit */
guint16 ah_reserve ; /* Reserved for future use */
guint32 ah_spi ; /* Security parameter index */
guint32 ah_seq ; /* Sequence number field */
/* variable size, 32bit bound*/ /* Authentication data */
} ;
struct newesp {
guint32 esp_spi ; /* ESP */
guint32 esp_seq ; /* Sequence number */
/*variable size*/ /* (IV and) Payload data */
/*variable size*/ /* padding */
/*8bit*/ /* pad size */
/*8bit*/ /* next header */
/*8bit*/ /* next header */
/*variable size, 32bit bound*/ /* Authentication data */
} ;
struct ipcomp {
guint8 comp_nxt ; /* Next Header */
guint8 comp_flags ; /* Must be zero */
guint16 comp_cpi ; /* Compression parameter index */
1999-10-15 05:30:43 +00:00
} ;
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
/* SA Paramaters and SAD */
static guint g_esp_nb_sa = IPSEC_NB_SA ;
static guint g_max_esp_size_nb_sa = 3 ;
static guint g_max_esp_nb_sa = 100 ;
typedef struct {
2006-08-09 02:00:05 +00:00
const gchar * sa ;
2006-03-27 16:25:35 +00:00
gint typ ;
gchar * src ;
gint src_len ;
gchar * dst ;
gint dst_len ;
gchar * spi ;
2006-08-09 02:00:05 +00:00
gint encryption_algo ;
gint authentication_algo ;
const gchar * encryption_key ;
const gchar * authentication_key ;
2006-03-27 16:25:35 +00:00
gboolean is_valid ;
} g_esp_sa ;
typedef struct {
2006-08-09 02:00:05 +00:00
gint nb ;
2006-03-27 16:25:35 +00:00
g_esp_sa table [ IPSEC_NB_SA ] ;
} g_esp_sa_database ;
static g_esp_sa_database g_esp_sad ;
/* Default ESP payload decode to off */
static gboolean g_esp_enable_encryption_decode = FALSE ;
2006-04-13 22:26:13 +00:00
/* Default ESP payload Authentication Checking to off */
static gboolean g_esp_enable_authentication_check = FALSE ;
2006-03-27 16:25:35 +00:00
# endif
2006-04-13 22:26:13 +00:00
2006-08-09 02:00:05 +00:00
/*
Default ESP payload heuristic decode to off
( only works if payload is NULL encrypted and ESP payload decode is off or payload is NULL encrypted
and the packet does not match a Security Association ) .
*/
2006-03-27 16:25:35 +00:00
static gboolean g_esp_enable_null_encryption_decode_heuristic = FALSE ;
/* Place AH payload in sub tree */
static gboolean g_ah_payload_in_subtree = FALSE ;
1999-03-29 02:21:34 +00:00
# ifndef offsetof
# define offsetof(type, member) ((size_t)(&((type *)0)->member))
# endif
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static int get_ipv6_suffix ( char * ipv6_suffix , char * ipv6_address )
Description : Get the extended IPv6 Suffix of an IPv6 Address
Return : Return the number of char of the IPv6 address suffix parsed
2006-08-09 02:00:05 +00:00
Params :
- char * ipv6_address : the valid ipv6 address to parse in char *
2006-03-27 16:25:35 +00:00
- char * ipv6_suffix : the ipv6 suffix associated in char *
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
ex : if IPv6 address is " 3ffe::1 " the IPv6 suffix will be " 0001 " and the function will return 3
*/
2006-08-09 02:00:05 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static int get_ipv6_suffix ( char * ipv6_suffix , char * ipv6_address )
2001-02-28 06:37:29 +00:00
{
2006-03-27 16:25:35 +00:00
char suffix [ IPSEC_STRLEN_IPV6 + 1 ] ;
int cpt = 0 ;
int cpt_suffix = 0 ;
int cpt_seg = 0 ;
int j = 0 ;
int ipv6_len = 0 ;
gboolean found = FALSE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
ipv6_len = strlen ( ipv6_address ) ;
2006-08-09 02:00:05 +00:00
if ( ipv6_len = = 0 )
2006-03-27 16:25:35 +00:00
{
/* Found a suffix */
2006-08-09 02:00:05 +00:00
found = TRUE ;
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
else
{
2006-03-27 16:25:35 +00:00
while ( ( cpt_suffix < IPSEC_STRLEN_IPV6 ) & & ( ipv6_len - cpt - 1 > = 0 ) & & ( found = = FALSE ) )
{
if ( ipv6_address [ ipv6_len - cpt - 1 ] = = ' : ' )
{
/* Add some 0 to the prefix; */
for ( j = cpt_seg ; j < 4 ; j + + )
{
suffix [ IPSEC_STRLEN_IPV6 - 1 - cpt_suffix ] = ' 0 ' ;
cpt_suffix + + ;
}
cpt_seg = 0 ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( ipv6_len - cpt - 1 = = 0 )
{
/* Found a suffix */
2006-08-09 02:00:05 +00:00
found = TRUE ;
}
else
2006-03-27 16:25:35 +00:00
if ( ipv6_address [ ipv6_len - cpt - 2 ] = = ' : ' )
{
/* found a suffix */
cpt + = 2 ;
2006-08-09 02:00:05 +00:00
found = TRUE ;
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
else
{
cpt + + ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
else
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
suffix [ IPSEC_STRLEN_IPV6 - 1 - cpt_suffix ] = toupper ( ipv6_address [ ipv6_len - cpt - 1 ] ) ;
cpt_seg + + ;
cpt_suffix + + ;
cpt + + ;
2006-08-09 02:00:05 +00:00
}
}
2001-02-28 06:37:29 +00:00
2006-03-27 16:25:35 +00:00
if ( cpt_suffix % 4 ! = 0 )
{
for ( j = cpt_seg ; j < 4 ; j + + )
{
suffix [ IPSEC_STRLEN_IPV6 - 1 - cpt_suffix ] = ' 0 ' ;
cpt_suffix + + ;
}
cpt_seg = 0 ;
}
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
for ( j = 0 ; j < cpt_suffix ; j + + )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
suffix [ j ] = suffix [ j + IPSEC_STRLEN_IPV6 - cpt_suffix ] ;
}
2006-08-09 02:00:05 +00:00
suffix [ j ] = ' \0 ' ;
2006-03-27 16:25:35 +00:00
memcpy ( ipv6_suffix , suffix , j + 1 ) ;
return cpt ;
}
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static int get_full_ipv6_addr ( char * ipv6_addr_expanded , char * ipv6_addr )
Description : Get the extended IPv6 Address of an IPv6 Address
Return : Return the remaining number of char of the IPv6 address parsed
2006-08-09 02:00:05 +00:00
Params :
- char * ipv6_addr : the valid ipv6 address to parse in char *
2006-03-27 16:25:35 +00:00
- char * ipv6_addr_expansed : the expanded ipv6 address associated in char *
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
ex : if IPv6 address is " 3ffe::1 " the IPv6 expanded address will be " 3FFE0000000000000000000000000001 " and the function will return 0
if IPV6 address is " 3ffe::* " the IPv6 expanded address will be " 3FFE000000000000000000000000**** " and the function will return 0
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
static int
2006-03-27 16:25:35 +00:00
get_full_ipv6_addr ( char * ipv6_addr_expanded , char * ipv6_addr )
{
char suffix [ IPSEC_STRLEN_IPV6 + 1 ] ;
char prefix [ IPSEC_STRLEN_IPV6 + 1 ] ;
2006-08-09 02:00:05 +00:00
char * prefix_addr ;
2006-03-27 16:25:35 +00:00
int suffix_cpt = 0 ;
int suffix_len = 0 ;
int prefix_remaining = 0 ;
int prefix_len = 0 ;
int j = 0 ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( ( ipv6_addr = = NULL ) | | ( strcmp ( ipv6_addr , " " ) = = 0 ) ) return - 1 ;
if ( ( strlen ( ipv6_addr ) = = 1 ) & & ( ipv6_addr [ 0 ] = = IPSEC_SA_WILDCARDS_ANY ) )
{
for ( j = 0 ; j < = IPSEC_STRLEN_IPV6 ; j + + )
{
ipv6_addr_expanded [ j ] = IPSEC_SA_WILDCARDS_ANY ;
}
ipv6_addr_expanded [ IPSEC_STRLEN_IPV6 ] = ' \0 ' ;
return 0 ;
1999-03-29 02:21:34 +00:00
}
2006-03-27 16:25:35 +00:00
suffix_cpt = get_ipv6_suffix ( suffix , ipv6_addr ) ;
suffix_len = strlen ( suffix ) ;
if ( suffix_len < IPSEC_STRLEN_IPV6 )
{
2006-08-09 02:00:05 +00:00
prefix_addr = ep_alloc ( strlen ( ipv6_addr ) - suffix_cpt + 1 ) ;
2006-03-27 16:25:35 +00:00
memcpy ( prefix_addr , ipv6_addr , strlen ( ipv6_addr ) - suffix_cpt ) ;
prefix_addr [ strlen ( ipv6_addr ) - suffix_cpt ] = ' \0 ' ;
prefix_remaining = get_ipv6_suffix ( prefix , prefix_addr ) ;
prefix_len = strlen ( prefix ) ;
memcpy ( ipv6_addr_expanded , prefix , prefix_len ) ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
for ( j = 0 ; j < = IPSEC_STRLEN_IPV6 - prefix_len - suffix_len ; j + + )
{
ipv6_addr_expanded [ j + prefix_len ] = ' 0 ' ;
2001-02-28 06:37:29 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
memcpy ( ipv6_addr_expanded + IPSEC_STRLEN_IPV6 - suffix_len , suffix , suffix_len + 1 ) ;
if ( suffix_len < IPSEC_STRLEN_IPV6 )
2006-08-09 02:00:05 +00:00
return ( prefix_len - prefix_remaining ) ;
else
2006-03-27 16:25:35 +00:00
return strlen ( ipv6_addr ) - suffix_cpt ;
1999-03-29 02:21:34 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
1999-03-29 02:21:34 +00:00
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean get_full_ipv4_addr ( char * ipv4_addr_expanded , char * ipv4_addr )
Description : Get the extended IPv4 Address of an IPv4 Address
Return : Return true if it can derive an IPv4 address . It does not mean that the previous one was valid .
2006-08-09 02:00:05 +00:00
Params :
- char * ipv4_addr : the valid ipv4 address to parse in char *
2006-03-27 16:25:35 +00:00
- char * ipv4_addr_expansed : the expanded ipv4 address associated in char *
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
ex : if IPv4 address is " 190.*.*.1 " the IPv4 expanded address will be " BE****01 " and the function will return 0
if IPv4 address is " * " the IPv4 expanded address will be " ******** " and the function will return 0
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
static gboolean
2006-03-27 16:25:35 +00:00
get_full_ipv4_addr ( char * ipv4_addr_expanded , char * ipv4_addr )
2000-06-05 03:21:03 +00:00
{
2006-03-27 16:25:35 +00:00
char addr_byte_string_tmp [ 4 ] ;
char addr_byte_string [ 4 ] ;
guint addr_byte = 0 ;
guint i = 0 ;
guint j = 0 ;
guint k = 0 ;
guint cpt = 0 ;
gboolean done_flag = FALSE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( ( ipv4_addr = = NULL ) | | ( strcmp ( ipv4_addr , " " ) = = 0 ) ) return done_flag ;
if ( ( strlen ( ipv4_addr ) = = 1 ) & & ( ipv4_addr [ 0 ] = = IPSEC_SA_WILDCARDS_ANY ) )
{
for ( i = 0 ; i < = IPSEC_STRLEN_IPV4 ; i + + )
{
ipv4_addr_expanded [ i ] = IPSEC_SA_WILDCARDS_ANY ;
}
ipv4_addr_expanded [ IPSEC_STRLEN_IPV4 ] = ' \0 ' ;
done_flag = TRUE ;
}
else {
j = 0 ;
cpt = 0 ;
k = 0 ;
while ( ( done_flag = = FALSE ) & & ( j < = strlen ( ipv4_addr ) ) & & ( cpt < IPSEC_STRLEN_IPV4 ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
if ( j = = strlen ( ipv4_addr ) )
{
addr_byte_string_tmp [ k ] = ' \0 ' ;
if ( ( strlen ( addr_byte_string_tmp ) = = 1 ) & & ( addr_byte_string_tmp [ 0 ] = = IPSEC_SA_WILDCARDS_ANY ) )
{
for ( i = 0 ; i < 2 ; i + + )
{
ipv4_addr_expanded [ cpt ] = IPSEC_SA_WILDCARDS_ANY ;
cpt + + ;
}
}
else
{
2006-06-14 08:04:43 +00:00
sscanf ( addr_byte_string_tmp , " %u " , & addr_byte ) ;
2006-08-09 02:00:05 +00:00
if ( addr_byte < 16 ) g_snprintf ( addr_byte_string , 4 , " 0%X " , addr_byte ) ;
else g_snprintf ( addr_byte_string , 4 , " %X " , addr_byte ) ;
2006-03-27 16:25:35 +00:00
for ( i = 0 ; i < strlen ( addr_byte_string ) ; i + + )
{
ipv4_addr_expanded [ cpt ] = addr_byte_string [ i ] ;
cpt + + ;
}
}
done_flag = TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
else if ( ipv4_addr [ j ] = = ' . ' )
{
addr_byte_string_tmp [ k ] = ' \0 ' ;
if ( ( strlen ( addr_byte_string_tmp ) = = 1 ) & & ( addr_byte_string_tmp [ 0 ] = = IPSEC_SA_WILDCARDS_ANY ) )
{
for ( i = 0 ; i < 2 ; i + + )
{
ipv4_addr_expanded [ cpt ] = IPSEC_SA_WILDCARDS_ANY ;
cpt + + ;
}
}
else
{
2006-06-14 08:04:43 +00:00
sscanf ( addr_byte_string_tmp , " %u " , & addr_byte ) ;
2006-08-09 02:00:05 +00:00
if ( addr_byte < 16 ) g_snprintf ( addr_byte_string , 4 , " 0%X " , addr_byte ) ;
else g_snprintf ( addr_byte_string , 4 , " %X " , addr_byte ) ;
2006-03-27 16:25:35 +00:00
for ( i = 0 ; i < strlen ( addr_byte_string ) ; i + + )
{
ipv4_addr_expanded [ cpt ] = addr_byte_string [ i ] ;
cpt + + ;
}
}
k = 0 ;
j + + ;
}
else
{
2006-08-09 02:00:05 +00:00
if ( k > = 3 )
2006-03-27 16:25:35 +00:00
{
/* Incorrect IPv4 Address. Erase previous Values in the Byte. (LRU mechanism) */
addr_byte_string_tmp [ 0 ] = ipv4_addr [ j ] ;
k = 1 ;
j + + ;
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
addr_byte_string_tmp [ k ] = ipv4_addr [ j ] ;
k + + ;
j + + ;
}
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
}
ipv4_addr_expanded [ cpt ] = ' \0 ' ;
}
return done_flag ;
}
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean esp_sa_parse_ipv6addr ( const gchar * sa , guint index_start , gchar * * pt_ipv6addr , guint * index_end )
Description : Get the IPv6 address of a Security Association
Return : Return true if it can get an address . It does not mean that the address is valid .
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- guint index_start : the index to start to find the address
- gchar * * pt_ipv6addr : the address found . The Allocation is done here !
2006-08-09 02:00:05 +00:00
- guint * index_end : the last index of the address
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
esp_sa_parse_ipv6addr ( const gchar * sa , guint index_start , gchar * * pt_ipv6addr , guint * index_end )
{
guint cpt = 0 ;
2006-08-09 02:00:05 +00:00
2006-08-15 19:28:07 +00:00
char addr_string [ IPSEC_IPV6_ADDR_MAX + 1 ] ;
2006-08-09 02:00:05 +00:00
gboolean done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
2006-08-15 19:28:07 +00:00
if ( ( sa = = NULL ) | | ( strcmp ( sa , " " ) = = 0 ) )
return FALSE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Get Address */
2006-08-15 19:28:07 +00:00
while ( ( ( cpt + index_start ) < strlen ( sa ) ) & & ( done_flag = = FALSE ) & & ( cpt < = IPSEC_IPV6_ADDR_MAX ) )
2006-08-09 02:00:05 +00:00
{
if ( ( sa [ cpt + index_start ] = = IPSEC_SA_SEPARATOR ) | | ( sa [ cpt + index_start ] = = IPSEC_SA_ADDR_LEN_SEPARATOR ) )
2006-03-27 16:25:35 +00:00
{
if ( cpt = = 0 ) return FALSE ;
* index_end = cpt + index_start ;
addr_string [ cpt ] = ' \0 ' ;
done_flag = TRUE ;
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
2006-08-15 19:28:07 +00:00
if ( ( cpt > = IPSEC_IPV6_ADDR_MAX - 1 ) & & ( ( cpt + index_start ) < strlen ( sa ) ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_ADDR_LEN_SEPARATOR ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_SEPARATOR ) )
return FALSE ;
2006-03-27 16:25:35 +00:00
addr_string [ cpt ] = toupper ( sa [ cpt + index_start ] ) ;
cpt + + ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( done_flag )
{
* pt_ipv6addr = ( gchar * ) g_malloc ( ( strlen ( addr_string ) + 1 ) * sizeof ( gchar ) ) ;
memcpy ( * pt_ipv6addr , addr_string , strlen ( addr_string ) + 1 ) ;
2000-06-05 03:21:03 +00:00
}
2006-03-27 16:25:35 +00:00
return done_flag ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean esp_sa_parse_ipv4addr ( const gchar * sa , guint index_start , gchar * * pt_ipv4addr , guint * index_end )
Description : Get the IPv4 address of a Security Association
Return : Return true if it can get an address . It does not mean that the address is valid .
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- guint index_start : the index to start to find the address
- gchar * * pt_ipv4addr : the address found . The Allocation is done here !
2006-08-09 02:00:05 +00:00
- guint * index_end : the last index of the address
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
esp_sa_parse_ipv4addr ( const gchar * sa , guint index_start , gchar * * pt_ipv4addr , guint * index_end )
{
guint cpt = 0 ;
2006-08-09 02:00:05 +00:00
2006-08-15 19:28:07 +00:00
char addr_string [ IPSEC_IPV4_ADDR_MAX + 1 ] ;
2006-08-09 02:00:05 +00:00
gboolean done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
2006-08-15 19:28:07 +00:00
if ( ( sa = = NULL ) | | ( strcmp ( sa , " " ) = = 0 ) )
return FALSE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Get Address */
2006-08-15 19:28:07 +00:00
while ( ( ( cpt + index_start ) < strlen ( sa ) ) & & ( done_flag = = FALSE ) & & ( cpt < = IPSEC_IPV4_ADDR_MAX ) )
2006-08-09 02:00:05 +00:00
{
if ( ( sa [ cpt + index_start ] = = IPSEC_SA_SEPARATOR ) | | ( sa [ cpt + index_start ] = = IPSEC_SA_ADDR_LEN_SEPARATOR ) )
2006-03-27 16:25:35 +00:00
{
if ( cpt = = 0 ) return FALSE ;
* index_end = cpt + index_start ;
addr_string [ cpt ] = ' \0 ' ;
done_flag = TRUE ;
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
2006-08-15 19:28:07 +00:00
if ( ( cpt = = IPSEC_IPV4_ADDR_MAX - 1 ) & & ( ( cpt + index_start ) < strlen ( sa ) ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_ADDR_LEN_SEPARATOR ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_SEPARATOR ) )
return FALSE ;
2006-03-27 16:25:35 +00:00
addr_string [ cpt ] = toupper ( sa [ cpt + index_start ] ) ;
cpt + + ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( done_flag )
{
* pt_ipv4addr = ( gchar * ) g_malloc ( ( strlen ( addr_string ) + 1 ) * sizeof ( gchar ) ) ;
memcpy ( * pt_ipv4addr , addr_string , strlen ( addr_string ) + 1 ) ;
}
return done_flag ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean esp_sa_parse_spi ( const gchar * sa , guint index_start , gchar * * pt_spi , guint * index_end )
Description : Get the SPI of a Security Association
Return : Return true if it can get a SPI . It does not mean that the SPI is valid .
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- guint index_start : the index to start to find the spi
- gchar * * pt_spi : the spi found . The Allocation is done here !
2006-08-09 02:00:05 +00:00
- guint * index_end : the last index of the address
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
esp_sa_parse_spi ( const gchar * sa , guint index_start , gchar * * pt_spi , guint * index_end )
{
guint cpt = 0 ;
guint32 spi = 0 ;
guint i = 0 ;
2006-08-15 19:28:07 +00:00
gchar spi_string [ IPSEC_SPI_LEN_MAX + 1 ] ;
gchar spi_string_tmp [ IPSEC_SPI_LEN_MAX + 1 ] ;
2006-08-09 02:00:05 +00:00
gboolean done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
if ( ( sa = = NULL ) | | ( strcmp ( sa , " " ) = = 0 ) ) return FALSE ;
2006-08-09 02:00:05 +00:00
2006-08-18 00:22:48 +00:00
while ( ( ( cpt + index_start ) < strlen ( sa ) ) & & ( cpt < IPSEC_SPI_LEN_MAX ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
spi_string [ cpt ] = toupper ( sa [ cpt + index_start ] ) ;
cpt + + ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
2006-08-18 00:22:48 +00:00
if ( cpt = = 0 )
done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
else
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
spi_string [ cpt ] = ' \0 ' ;
if ( ( cpt > = 2 ) & &
( spi_string [ 0 ] = = ' 0 ' ) & &
( spi_string [ 1 ] = = ' X ' ) )
{
for ( i = 0 ; i < = cpt - 2 ; i + + ) spi_string_tmp [ i ] = spi_string [ i + 2 ] ;
sscanf ( spi_string_tmp , " %x " , & spi ) ;
2006-08-15 19:28:07 +00:00
g_snprintf ( spi_string , IPSEC_SPI_LEN_MAX , " %i " , spi ) ;
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
* index_end = cpt + index_start - 1 ;
* pt_spi = ( gchar * ) g_malloc ( ( strlen ( spi_string ) + 1 ) * sizeof ( gchar ) ) ;
memcpy ( * pt_spi , spi_string , strlen ( spi_string ) + 1 ) ;
done_flag = TRUE ;
}
return done_flag ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean esp_sa_parse_protocol_typ ( const gchar * sa , guint index_start , gint * pt_protocol_typ , guint * index_end )
Description : Get the Protocol Type of a Security Association
Return : Return true if it can get a valid protocol type .
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- guint index_start : the index to start to find the protocol type
- gint * pt_protocol_typ : the protocl type found . Either IPv4 , Either IPv6 ( IPSEC_SA_IPV4 , IPSEC_SA_IPV6 )
2006-08-09 02:00:05 +00:00
- guint * index_end : the last index of the protocol type
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
esp_sa_parse_protocol_typ ( const gchar * sa , guint index_start , gint * pt_protocol_typ , guint * index_end )
{
2006-08-09 02:00:05 +00:00
gboolean done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
* pt_protocol_typ = IPSEC_SA_UNKNOWN ;
2006-08-18 00:22:48 +00:00
if ( ( sa = = NULL ) | | ( strlen ( & sa [ index_start ] ) < = IPSEC_TYP_LEN ) | |
( sa [ index_start + IPSEC_TYP_LEN ] ! = IPSEC_SA_SEPARATOR ) )
return FALSE ;
2006-08-09 02:00:05 +00:00
2006-08-18 00:22:48 +00:00
if ( g_strncasecmp ( & sa [ index_start ] , " IPV6 " , IPSEC_TYP_LEN ) = = 0 )
2006-08-09 02:00:05 +00:00
{
2006-08-18 00:22:48 +00:00
* pt_protocol_typ = IPSEC_SA_IPV6 ;
done_flag = TRUE ;
}
else if ( g_strncasecmp ( & sa [ index_start ] , " IPV4 " , IPSEC_TYP_LEN ) = = 0 )
{
* pt_protocol_typ = IPSEC_SA_IPV4 ;
done_flag = TRUE ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
else
2006-08-09 02:00:05 +00:00
{
2006-08-18 00:22:48 +00:00
* pt_protocol_typ = IPSEC_SA_UNKNOWN ;
done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
}
2006-08-18 00:22:48 +00:00
* index_end = IPSEC_TYP_LEN + index_start + 1 ;
2006-03-27 16:25:35 +00:00
2006-08-18 00:22:48 +00:00
g_warning ( " For %s returning %d, %c, %d " , sa , * pt_protocol_typ , sa [ * index_end ] , * index_end ) ;
2006-03-27 16:25:35 +00:00
return done_flag ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static gboolean esp_sa_parse_addr_len ( const gchar * sa , guint index_start , guint * len , guint * index_end )
Description : Get the Address Length of an address ( IPv4 / IPv6 )
Return : Return true if it can get an Address Length . It does not mean that the length is valid
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- guint index_start : the index to start to find the length
- guint * len : the address length found . If none - 1 is given .
- guint * index_end : the last index of the address length in the SA
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
2006-04-13 22:26:13 +00:00
esp_sa_parse_addr_len ( const gchar * sa , guint index_start , gint * len , guint * index_end )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
guint cpt = 0 ;
2006-08-15 19:28:07 +00:00
char len_string [ IPSEC_ADDR_LEN_MAX + 1 ] ;
2006-08-09 02:00:05 +00:00
gboolean done_flag = FALSE ;
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
* len = - 1 ;
2006-03-27 16:25:35 +00:00
if ( ( sa = = NULL ) | | ( strcmp ( sa , " " ) = = 0 ) ) return FALSE ;
2006-08-09 02:00:05 +00:00
if ( sa [ index_start ] = = IPSEC_SA_SEPARATOR )
2006-03-27 16:25:35 +00:00
{
* index_end = index_start + 1 ;
* len = - 1 ;
done_flag = TRUE ;
}
2006-08-09 02:00:05 +00:00
else if ( sa [ index_start ] = = IPSEC_SA_ADDR_LEN_SEPARATOR )
2006-03-27 16:25:35 +00:00
{
cpt + + ;
2006-08-15 19:28:07 +00:00
while ( ( ( cpt + index_start ) < strlen ( sa ) ) & & ( done_flag = = FALSE ) & & ( cpt < IPSEC_ADDR_LEN_MAX ) )
2006-08-09 02:00:05 +00:00
{
if ( sa [ cpt + index_start ] = = IPSEC_SA_SEPARATOR )
2006-03-27 16:25:35 +00:00
{
2006-08-09 02:00:05 +00:00
if ( cpt = = 1 )
{
2006-03-27 16:25:35 +00:00
* index_end = index_start + cpt + 1 ;
* len = - 1 ;
done_flag = TRUE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
}
else
{
* index_end = cpt + index_start + 1 ;
len_string [ cpt - 1 ] = ' \0 ' ;
* len = atoi ( len_string ) ;
done_flag = TRUE ;
}
2001-02-28 06:37:29 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
2006-08-15 19:28:07 +00:00
if ( ( cpt = = IPSEC_ADDR_LEN_MAX ) & & ( ( cpt + index_start ) < strlen ( sa ) ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_ADDR_LEN_SEPARATOR ) & & ( sa [ cpt + index_start + 1 ] ! = IPSEC_SA_SEPARATOR ) )
return FALSE ;
2006-03-27 16:25:35 +00:00
len_string [ cpt - 1 ] = sa [ cpt + index_start ] ;
cpt + + ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
return done_flag ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : esp_sa_remove_white ( const gchar * sa , gchar * * sa_bis )
Description : Remote White Space in a SA
Parse a Security Association and give the SA without space .
There is no need to allocate memory before the call . All is done !
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
Return : Void
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
- char * * sa_bis : the Security Association in char * without white space
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static void
esp_sa_remove_white ( const gchar * sa , gchar * * sa_bis )
2006-08-09 02:00:05 +00:00
{
guint i = 0 ;
guint cpt = 0 ;
gchar * sa_tmp ;
2006-03-27 16:25:35 +00:00
if ( ( sa = = NULL ) | | ( strcmp ( sa , " " ) = = 0 ) )
{
* sa_bis = NULL ;
return ;
}
2006-08-09 02:00:05 +00:00
sa_tmp = ep_alloc ( strlen ( sa ) + 1 ) ;
for ( i = 0 ; i < strlen ( sa ) ; i + + )
{
if ( ( sa [ i ] ! = ' ' ) & & ( sa [ i ] ! = ' \t ' ) )
{
sa_tmp [ cpt ] = sa [ i ] ;
cpt + + ;
}
}
2006-03-27 16:25:35 +00:00
sa_tmp [ cpt ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
/* XXX - Should this be se_allocated instead? */
2006-03-27 16:25:35 +00:00
* sa_bis = ( gchar * ) g_malloc ( ( cpt + 1 ) * sizeof ( gchar ) ) ;
memcpy ( * sa_bis , sa_tmp , cpt ) ;
( * sa_bis ) [ cpt ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static goolean esp_sa_parse_filter ( const gchar * sa , gint * pt_protocol_typ , gchar * * pt_src , gint * pt_src_len , gchar * * pt_dst , gint * pt_dst_len , gchar * * pt_spi )
2006-08-09 02:00:05 +00:00
Description : Parse a Security Association .
2006-03-27 16:25:35 +00:00
Parse a Security Association and give the correspondings parameter : SPI , Source , Destination , Source Length , Destination Length , Protocol Type
There is no need to allocate memory before the call . All is done !
2006-08-09 02:00:05 +00:00
If the SA is not correct FALSE is returned .
2006-03-27 16:25:35 +00:00
This security association Must have the following format :
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
" Type/Source IPv6 or IPv4/Destination IPv6 or IPv4/SPI "
2006-08-09 02:00:05 +00:00
Where Type is either IPv4 either IPv6
- source And destination Must have a correct IPv6 / IPv4 Address Format .
- SPI is an integer on 4 bytes .
2006-03-27 16:25:35 +00:00
Any element may use the following wildcard :
2006-08-09 02:00:05 +00:00
" * " : for an IPv4 Address , it allows all bytes until the next " . " . For IPv6 it is the same until the next " : " .
2006-03-27 16:25:35 +00:00
For SPI it allows any SPI .
2006-08-09 02:00:05 +00:00
ex :
a ) IPV4 / 131.254 .200 . * / 131.254 . * .123 / *
b ) IPv6 / 3ff e : * : 1 / 2001 : : 200 : * / 456
2006-03-27 16:25:35 +00:00
Return : Return true if the parsing is correct .
2006-08-09 02:00:05 +00:00
Params :
- char * sa : the Security Association in char *
2006-03-27 16:25:35 +00:00
- gint * pt_protocol_typ : the protocol type
2006-08-09 02:00:05 +00:00
- gchar * * pt_src : the source address
2006-03-27 16:25:35 +00:00
- gint * pt_src_len : the source address length
2006-08-09 02:00:05 +00:00
- gchar * * pt_dst : the destination address
2006-03-27 16:25:35 +00:00
- gint * pt_dst_len : the destination address length
- gchar * * pt_spi : the spi of the SA
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
static gboolean
2006-03-27 16:25:35 +00:00
esp_sa_parse_filter ( const gchar * sa_src , gint * pt_protocol_typ , gchar * * pt_src , gint * pt_src_len , gchar * * pt_dst , gint * pt_dst_len , gchar * * pt_spi )
{
gchar * src_string ;
gchar * dst_string ;
gchar * spi_string ;
2006-08-09 02:00:05 +00:00
gint src_len = 0 ;
2006-04-13 22:26:13 +00:00
gint dst_len = 0 ;
2006-08-09 02:00:05 +00:00
gchar * src ;
gchar * dst ;
2006-03-27 16:25:35 +00:00
gchar * sa ;
guint index_end1 = 0 ;
guint index_end2 = 0 ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
esp_sa_remove_white ( sa_src , & sa ) ;
if ( ! esp_sa_parse_protocol_typ ( sa , 0 , pt_protocol_typ , & index_end1 ) ) return FALSE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
switch ( * pt_protocol_typ )
{
case IPSEC_SA_IPV4 :
{
if ( esp_sa_parse_ipv4addr ( sa , index_end1 , & src_string , & index_end2 ) )
{
if ( esp_sa_parse_addr_len ( sa , index_end2 , pt_src_len , & index_end1 ) )
{
if ( esp_sa_parse_ipv4addr ( sa , index_end1 , & dst_string , & index_end2 ) )
{
if ( esp_sa_parse_addr_len ( sa , index_end2 , pt_dst_len , & index_end1 ) )
{
if ( ! esp_sa_parse_spi ( sa , index_end1 , & spi_string , & index_end2 ) )
{
g_free ( src_string ) ;
g_free ( dst_string ) ;
g_free ( spi_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
else
{
g_free ( src_string ) ;
g_free ( dst_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
else
{
g_free ( src_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
g_free ( src_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
else
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
g_free ( sa ) ;
return FALSE ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Fill the Source Filter */
2006-08-09 02:00:05 +00:00
src = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV4 + 1 ) * sizeof ( gchar ) ) ;
get_full_ipv4_addr ( src , src_string ) ;
2006-03-27 16:25:35 +00:00
g_free ( src_string ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Fill the Destination Filter */
2006-08-09 02:00:05 +00:00
dst = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV4 + 1 ) * sizeof ( gchar ) ) ;
get_full_ipv4_addr ( dst , dst_string ) ;
2006-03-27 16:25:35 +00:00
g_free ( dst_string ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
g_free ( sa ) ;
break ;
}
case IPSEC_SA_IPV6 :
{
if ( esp_sa_parse_ipv6addr ( sa , index_end1 , & src_string , & index_end2 ) )
{
if ( esp_sa_parse_addr_len ( sa , index_end2 , & src_len , & index_end1 ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
if ( esp_sa_parse_ipv6addr ( sa , index_end1 , & dst_string , & index_end2 ) )
{
if ( esp_sa_parse_addr_len ( sa , index_end2 , & dst_len , & index_end1 ) )
{
if ( ! esp_sa_parse_spi ( sa , index_end1 , & spi_string , & index_end2 ) )
{
g_free ( src_string ) ;
g_free ( dst_string ) ;
g_free ( spi_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
else
{
g_free ( src_string ) ;
g_free ( dst_string ) ;
g_free ( sa ) ;
return FALSE ;
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
else
{
g_free ( src_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
else
{
g_free ( src_string ) ;
g_free ( sa ) ;
return FALSE ;
}
}
2006-08-09 02:00:05 +00:00
else
2006-03-27 16:25:35 +00:00
{
g_free ( sa ) ;
return FALSE ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Fill the Source Filter */
2006-08-09 02:00:05 +00:00
src = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV6 + 1 ) * sizeof ( gchar ) ) ;
get_full_ipv6_addr ( src , src_string ) ;
2006-03-27 16:25:35 +00:00
g_free ( src_string ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/* Fill the Destination Filter */
dst = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV6 + 1 ) * sizeof ( gchar ) ) ;
get_full_ipv6_addr ( dst , dst_string ) ;
g_free ( dst_string ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
g_free ( sa ) ;
break ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
default :
{
g_free ( sa ) ;
return FALSE ;
}
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
* pt_spi = spi_string ;
* pt_src = src ;
* pt_dst = dst ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
return TRUE ;
}
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static goolean filter_address_match ( gchar * address , gchar * filter , gint len , gint typ )
2006-08-09 02:00:05 +00:00
Description : check the matching of an address with a filter
Return : Return TRUE if the filter and the address match
Params :
2006-03-27 16:25:35 +00:00
- gchar * address : the address to check
- gchar * filter : the filter
- gint len : the len of the address that should match the filter
- gint typ : the Address type : either IPv6 or IPv4 ( IPSEC_SA_IPV6 , IPSEC_SA_IPV4 )
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
static gboolean
2006-03-27 16:25:35 +00:00
filter_address_match ( gchar * address , gchar * filter , gint len , gint typ )
{
gint i = 0 ;
guint filter_tmp = 0 ;
guint addr_tmp = 0 ;
char filter_string_tmp [ 3 ] ;
char addr_string_tmp [ 3 ] ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( strlen ( address ) ! = strlen ( filter ) ) return FALSE ;
/* No length specified */
if ( ( len < 0 ) | | ( ( typ = = IPSEC_SA_IPV6 ) & & ( len > IPSEC_IPV6_ADDR_LEN ) ) | | ( ( typ = = IPSEC_SA_IPV4 ) & & ( len > IPSEC_IPV4_ADDR_LEN ) ) )
{
for ( i = 0 ; ( guint ) i < strlen ( address ) ; i + + )
{
if ( ( filter [ i ] ! = IPSEC_SA_WILDCARDS_ANY ) & & ( filter [ i ] ! = address [ i ] ) ) return FALSE ;
}
return TRUE ;
}
2006-08-09 02:00:05 +00:00
else
{
2006-03-27 16:25:35 +00:00
for ( i = 0 ; i < ( len / 4 ) ; i + + )
{
if ( ( filter [ i ] ! = IPSEC_SA_WILDCARDS_ANY ) & & ( filter [ i ] ! = address [ i ] ) ) return FALSE ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( filter [ i ] = = IPSEC_SA_WILDCARDS_ANY ) return TRUE ;
2006-08-09 02:00:05 +00:00
else if ( len % 4 ! = 0 )
2006-03-27 16:25:35 +00:00
{
2006-08-09 02:00:05 +00:00
/* take the end of the Netmask/Prefixlen into account */
2006-03-27 16:25:35 +00:00
filter_string_tmp [ 0 ] = filter [ i ] ;
filter_string_tmp [ 1 ] = ' \0 ' ;
addr_string_tmp [ 0 ] = address [ i ] ;
addr_string_tmp [ 1 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
sscanf ( filter_string_tmp , " %x " , & filter_tmp ) ;
sscanf ( addr_string_tmp , " %x " , & addr_tmp ) ;
for ( i = 0 ; i < ( len % 4 ) ; i + + )
2006-08-09 02:00:05 +00:00
{
if ( ( ( filter_tmp > > ( 4 - i - 1 ) ) & 1 ) ! = ( ( addr_tmp > > ( 4 - i - 1 ) ) & 1 ) )
2006-03-27 16:25:35 +00:00
{
return FALSE ;
}
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
return TRUE ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
}
# endif
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static goolean filter_spi_match ( gchar * spi , gchar * filter )
2006-08-09 02:00:05 +00:00
Description : check the matching of a spi with a filter
Return : Return TRUE if the filter match the spi .
Params :
2006-03-27 16:25:35 +00:00
- gchar * spi : the spi to check
- gchar * filter : the filter
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
static gboolean
2006-03-27 16:25:35 +00:00
filter_spi_match ( gchar * spi , gchar * filter )
{
guint i = 0 ;
if ( ( strlen ( filter ) = = 1 ) & & ( filter [ 0 ] = = IPSEC_SA_WILDCARDS_ANY ) ) {
return TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
else if ( strlen ( spi ) ! = strlen ( filter ) ) {
return FALSE ;
}
for ( i = 0 ; i < strlen ( filter ) ; i + + )
{
if ( ( filter [ i ] ! = IPSEC_SA_WILDCARDS_ANY ) & & ( filter [ i ] ! = spi [ i ] ) ) return FALSE ;
}
2006-08-09 02:00:05 +00:00
return TRUE ;
2006-03-27 16:25:35 +00:00
}
# endif
2006-09-08 07:32:13 +00:00
/*
Name : static gint compute_ascii_key ( gchar * * ascii_key , gchar * key )
Description : Allocate memory for the key and transform the key if it is hexadecimal
Return : Return the key length
Params :
- gchar * * ascii_key : the resulting ascii key allocated here
- gchar * key : the key to compute
*/
# ifdef HAVE_LIBGCRYPT
static gint
compute_ascii_key ( gchar * * ascii_key , gchar * key )
{
guint key_len = 0 ;
gchar key_char [ 5 ] ;
guint i = 0 ;
if ( key ! = NULL )
{
if ( ( strlen ( key ) > 2 ) & & ( key [ 0 ] = = ' 0 ' ) & & ( ( key [ 1 ] = = ' x ' ) | | ( key [ 1 ] = = ' X ' ) ) )
{
if ( strlen ( key ) % 2 = = 0 )
{
key_len = ( strlen ( key ) - 2 ) / 2 ;
* ascii_key = ( gchar * ) g_malloc ( ( key_len + 1 ) * sizeof ( gchar ) ) ;
for ( i = 2 ; i < ( strlen ( key ) - 1 ) ; i + = 2 )
{
key_char [ 0 ] = key [ i ] ;
key_char [ 1 ] = key [ i + 1 ] ;
key_char [ 2 ] = ' \0 ' ;
sprintf ( * ascii_key + ( i - 2 ) / 2 , " %c " , ( int ) strtoul ( key_char , ( char * * ) NULL , 16 ) ) ;
}
}
else
/* give a chance to omit the first 0, in order to have a key in 8-bit unit */
{
key_len = ( strlen ( key ) - 2 ) / 2 + 1 ;
* ascii_key = ( gchar * ) g_malloc ( ( key_len + 1 ) * sizeof ( gchar ) ) ;
key_char [ 0 ] = ' 0 ' ;
key_char [ 1 ] = key [ 2 ] ;
key_char [ 2 ] = ' \0 ' ;
sprintf ( * ascii_key , " %c " , ( int ) strtoul ( key_char , ( char * * ) NULL , 16 ) ) ;
for ( i = 3 ; i < ( strlen ( key ) - 1 ) ; i + = 2 )
{
key_char [ 0 ] = key [ i ] ;
key_char [ 1 ] = key [ i + 1 ] ;
key_char [ 2 ] = ' \0 ' ;
sprintf ( * ascii_key + 1 + ( i - 2 ) / 2 , " %c " , ( int ) strtoul ( key_char , ( char * * ) NULL , 16 ) ) ;
}
}
}
else if ( ( strlen ( key ) = = 2 ) & & ( key [ 0 ] = = ' 0 ' ) & & ( ( key [ 1 ] = = ' x ' ) | | ( key [ 1 ] = = ' X ' ) ) )
{
return 0 ;
}
else
{
key_len = strlen ( key ) ;
* ascii_key = ( gchar * ) g_malloc ( ( key_len + 1 ) * sizeof ( gchar ) ) ;
memcpy ( * ascii_key , key , key_len + 1 ) ;
}
}
return key_len ;
}
# endif
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
/*
2006-03-27 16:25:35 +00:00
Name : static goolean get_esp_sa ( g_esp_sa_database * sad , gint protocol_typ , gchar * src , gchar * dst , gint spi ,
gint * entry_index
2006-08-09 02:00:05 +00:00
gint * encryption_algo ,
gint * authentication_algo ,
2006-09-08 07:32:13 +00:00
gchar * * encryption_key ,
guint * encryption_key_len ,
gchar * * authentication_key ,
guint * authentication_key_len
2006-03-27 16:25:35 +00:00
Description : Give Encryption Algo , Key and Authentification Algo for a Packet if a corresponding SA is available in a Security Association database
Return : If the SA is not present , FALSE is then returned .
2006-08-09 02:00:05 +00:00
Params :
- g_esp_sa_database * sad : the Security Association Database
2006-03-27 16:25:35 +00:00
- gint * pt_protocol_typ : the protocol type
2006-08-09 02:00:05 +00:00
- gchar * src : the source address
- gchar * dst : the destination address
2006-03-27 16:25:35 +00:00
- gchar * spi : the spi of the SA
- gint * entry_index : the index of the SA that matches
- gint * encryption_algo : the Encryption Algorithm to apply the packet
- gint * authentication_algo : the Authentication Algorithm to apply to the packet
2006-09-08 07:32:13 +00:00
- gchar * * encryption_key : the Encryption Key to apply to the packet
- guint * encryption_key_len : the Encryption Key length to apply to the packet
- gchar * * authentication_key : the Authentication Key to apply to the packet
- guint * authentication_key_len : the Authentication Key len to apply to the packet
2006-03-27 16:25:35 +00:00
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
static gboolean
get_esp_sa ( g_esp_sa_database * sad , gint protocol_typ , gchar * src , gchar * dst , gint spi , gint * entry_index ,
2006-08-09 02:00:05 +00:00
gint * encryption_algo ,
gint * authentication_algo ,
2006-04-13 22:26:13 +00:00
gchar * * encryption_key ,
2006-09-08 07:32:13 +00:00
guint * encryption_key_len ,
gchar * * authentication_key ,
guint * authentication_key_len
2006-03-27 16:25:35 +00:00
)
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
gboolean found = FALSE ;
gint i = 0 ;
2006-08-15 19:28:07 +00:00
gchar spi_string [ IPSEC_SPI_LEN_MAX ] ;
2006-03-27 16:25:35 +00:00
* entry_index = - 1 ;
2006-08-15 19:28:07 +00:00
g_snprintf ( spi_string , IPSEC_SPI_LEN_MAX , " %i " , spi ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
while ( ( found = = FALSE ) & & ( i < sad - > nb ) )
2006-08-09 02:00:05 +00:00
{
if ( esp_sa_parse_filter ( sad - > table [ i ] . sa , & sad - > table [ i ] . typ , & sad - > table [ i ] . src , & sad - > table [ i ] . src_len ,
2006-03-27 16:25:35 +00:00
& sad - > table [ i ] . dst , & sad - > table [ i ] . dst_len , & sad - > table [ i ] . spi ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
g_esp_sad . table [ i ] . is_valid = TRUE ;
2006-08-09 02:00:05 +00:00
/* Debugging Purpose */
2006-03-27 16:25:35 +00:00
/*
2006-08-09 02:00:05 +00:00
fprintf ( stderr , " VALID SA => <SA : %s> <Filter Source : %s/%i> <Filter Destination : %s/%i> <SPI : %s> \n " , g_esp_sad . table [ i ] . sa , g_esp_sad . table [ i ] . src , g_esp_sad . table [ i ] . src_len ,
2006-03-27 16:25:35 +00:00
g_esp_sad . table [ i ] . dst , g_esp_sad . table [ i ] . dst_len , g_esp_sad . table [ i ] . spi ) ;
*/
2006-08-09 02:00:05 +00:00
if ( ( protocol_typ = = sad - > table [ i ] . typ )
& & filter_address_match ( src , sad - > table [ i ] . src , sad - > table [ i ] . src_len , protocol_typ )
& & filter_address_match ( dst , sad - > table [ i ] . dst , sad - > table [ i ] . dst_len , protocol_typ )
2006-03-27 16:25:35 +00:00
& & filter_spi_match ( spi_string , sad - > table [ i ] . spi ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
* entry_index = i ;
2006-08-09 02:00:05 +00:00
* encryption_algo = sad - > table [ i ] . encryption_algo ;
* authentication_algo = sad - > table [ i ] . authentication_algo ;
2006-09-08 07:32:13 +00:00
* authentication_key_len = compute_ascii_key ( authentication_key , ( gchar * ) sad - > table [ i ] . authentication_key ) ;
* encryption_key_len = compute_ascii_key ( encryption_key , ( gchar * ) sad - > table [ i ] . encryption_key ) ;
2006-08-09 02:00:05 +00:00
found = TRUE ;
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
/* Debugging Purpose */
2006-03-27 16:25:35 +00:00
/*
fprintf ( stderr , " MATCHING SA => <IP Source : %s> <IP Destination : %s> <SPI : %s> \n \
= > < FILTER Source : % s / % i > < FILTER Destination : % s / % i > < FILTER SPI : % s > \ n \
= > < Encryption Algo : % i > < Encryption Key : % s > < Authentication Algo : % i > \ n " ,
src , dst , spi_string ,
2006-08-09 02:00:05 +00:00
sad - > table [ i ] . src , sad - > table [ i ] . src_len ,
2006-03-27 16:25:35 +00:00
sad - > table [ i ] . dst , sad - > table [ i ] . dst_len ,
sad - > table [ i ] . spi ,
* encryption_algo , * encryption_key , * authentication_algo ) ;
*/
2001-02-28 06:37:29 +00:00
}
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
/* We free the Src, Dst and Spi in the SA, but perhaps to allocate it again with the same value !!! */
2006-03-27 16:25:35 +00:00
g_free ( g_esp_sad . table [ i ] . src ) ;
g_free ( g_esp_sad . table [ i ] . dst ) ;
g_free ( g_esp_sad . table [ i ] . spi ) ;
g_esp_sad . table [ i ] . is_valid = FALSE ;
2006-08-09 02:00:05 +00:00
2000-07-08 10:46:23 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
else
2006-08-09 02:00:05 +00:00
{
/* Debugging Purpose */
/* fprintf(stderr, "INVALID SA => %s \n", g_esp_sad.table[i].sa); */
2006-03-27 16:25:35 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
i + + ;
2000-06-05 03:21:03 +00:00
}
2006-03-27 16:25:35 +00:00
return found ;
}
# endif
static void
dissect_ah ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
proto_tree * next_tree ;
guint8 nxt ;
tvbuff_t * next_tvb ;
int advance ;
advance = dissect_ah_header ( tvb , pinfo , tree , & nxt , & next_tree ) ;
next_tvb = tvb_new_subset ( tvb , advance , - 1 , - 1 ) ;
2000-06-05 03:21:03 +00:00
2006-03-27 16:25:35 +00:00
if ( g_ah_payload_in_subtree ) {
col_set_writable ( pinfo - > cinfo , FALSE ) ;
}
2000-07-08 10:46:23 +00:00
2006-03-27 16:25:35 +00:00
/* do lookup with the subdissector table */
if ( ! dissector_try_port ( ip_dissector_table , nxt , next_tvb , pinfo , next_tree ) ) {
call_dissector ( data_handle , next_tvb , pinfo , next_tree ) ;
}
}
int
dissect_ah_header ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree ,
guint8 * nxt_p , proto_tree * * next_tree_p )
{
proto_tree * ah_tree ;
proto_item * ti ;
struct newah ah ;
int advance ;
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) )
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " AH " ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) )
col_clear ( pinfo - > cinfo , COL_INFO ) ;
tvb_memcpy ( tvb , ( guint8 * ) & ah , 0 , sizeof ( ah ) ) ;
advance = sizeof ( ah ) + ( ( ah . ah_len - 1 ) < < 2 ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) {
col_add_fstr ( pinfo - > cinfo , COL_INFO , " AH (SPI=0x%08x) " ,
( guint32 ) g_ntohl ( ah . ah_spi ) ) ;
}
if ( tree ) {
/* !!! specify length */
ti = proto_tree_add_item ( tree , proto_ah , tvb , 0 , advance , FALSE ) ;
ah_tree = proto_item_add_subtree ( ti , ett_ah ) ;
proto_tree_add_text ( ah_tree , tvb ,
offsetof ( struct newah , ah_nxt ) , 1 ,
" Next Header: %s (0x%02x) " ,
ipprotostr ( ah . ah_nxt ) , ah . ah_nxt ) ;
proto_tree_add_text ( ah_tree , tvb ,
offsetof ( struct newah , ah_len ) , 1 ,
" Length: %u " , ( ah . ah_len + 2 ) < < 2 ) ;
proto_tree_add_uint ( ah_tree , hf_ah_spi , tvb ,
offsetof ( struct newah , ah_spi ) , 4 ,
( guint32 ) g_ntohl ( ah . ah_spi ) ) ;
proto_tree_add_uint ( ah_tree , hf_ah_sequence , tvb ,
offsetof ( struct newah , ah_seq ) , 4 ,
( guint32 ) g_ntohl ( ah . ah_seq ) ) ;
2006-09-12 09:53:10 +00:00
proto_tree_add_item ( ah_tree , hf_ah_iv , tvb ,
2006-03-27 16:25:35 +00:00
sizeof ( ah ) , ( ah . ah_len ) ? ( ah . ah_len - 1 ) < < 2 : 0 ,
2006-09-12 09:53:10 +00:00
FALSE ) ;
2006-03-27 16:25:35 +00:00
if ( next_tree_p ! = NULL ) {
/* Decide where to place next protocol decode */
if ( g_ah_payload_in_subtree ) {
* next_tree_p = ah_tree ;
}
else {
* next_tree_p = tree ;
}
}
} else {
if ( next_tree_p ! = NULL )
* next_tree_p = NULL ;
}
if ( nxt_p ! = NULL )
* nxt_p = ah . ah_nxt ;
/* start of the new header (could be a extension header) */
return advance ;
2000-06-05 03:21:03 +00:00
}
2006-04-13 22:26:13 +00:00
2006-08-09 02:00:05 +00:00
/*
Name : dissect_esp_authentication ( proto_tree * tree , tvbuff_t * tvb , gint len , gint esp_auth_len , guint8 * authenticator_data_computed ,
2006-04-13 22:26:13 +00:00
gboolean authentication_ok , gboolean authentication_checking_ok )
2006-08-09 02:00:05 +00:00
Description : used to print Authenticator field when linked with libgcrypt . Print the expected authenticator value
2006-04-13 22:26:13 +00:00
if requested and if it is wrong .
2006-08-09 02:00:05 +00:00
Return : void
Params :
- proto_tree * tree : the current tree
- tvbuff_t * tvb : the tvbuffer
- gint len : length of the data availabale in tvbuff
2006-04-13 22:26:13 +00:00
- gint esp_auth_len : size of authenticator field
- guint8 * authenticator_data_computed : give the authenticator computed ( only needed when authentication_ok and ! authentication_checking_ok
- gboolean authentication_ok : set to true if the authentication checking has been run successfully
- gboolean authentication_checking_ok : set to true if the authentication was the one expected
*/
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-04-13 22:26:13 +00:00
static void
2006-08-09 02:00:05 +00:00
dissect_esp_authentication ( proto_tree * tree , tvbuff_t * tvb , gint len , gint esp_auth_len , guint8 * authenticator_data_computed ,
2006-04-13 22:26:13 +00:00
gboolean authentication_ok , gboolean authentication_checking_ok )
{
if ( esp_auth_len = = 0 )
{
proto_tree_add_text ( tree , tvb , len , 0 ,
2006-08-09 02:00:05 +00:00
" NULL Authentication " ) ;
2006-04-13 22:26:13 +00:00
}
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
/* Make sure we have the auth trailer data */
else if ( tvb_bytes_exist ( tvb , len - esp_auth_len , esp_auth_len ) )
{
2006-08-09 02:00:05 +00:00
if ( ( authentication_ok ) & & ( authentication_checking_ok ) )
2006-04-13 22:26:13 +00:00
{
proto_tree_add_text ( tree , tvb , len - esp_auth_len , esp_auth_len ,
" Authentication Data [correct] " ) ;
}
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
else if ( ( authentication_ok ) & & ( ! authentication_checking_ok ) )
{
proto_tree_add_text ( tree , tvb , len - esp_auth_len , esp_auth_len ,
" Authentication Data [incorrect, should be 0x%s] " , authenticator_data_computed ) ;
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
g_free ( authenticator_data_computed ) ;
}
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
else proto_tree_add_text ( tree , tvb , len - esp_auth_len , esp_auth_len ,
2006-08-09 02:00:05 +00:00
" Authentication Data " ) ;
2006-04-13 22:26:13 +00:00
}
else
{
/* Truncated so just display what we have */
proto_tree_add_text ( tree , tvb , len - esp_auth_len , esp_auth_len - ( len - tvb_length ( tvb ) ) ,
2006-08-09 02:00:05 +00:00
" Authentication Data (truncated) " ) ;
2006-04-13 22:26:13 +00:00
}
}
# endif
2000-04-20 07:05:58 +00:00
static void
2001-02-28 06:37:29 +00:00
dissect_esp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
1999-03-29 02:21:34 +00:00
{
2006-05-02 19:58:19 +00:00
proto_tree * esp_tree = NULL ;
2006-03-27 16:25:35 +00:00
proto_item * ti ;
struct newesp esp ;
gint len = 0 ;
gint i = 0 ;
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
char res [ 3 ] ;
/* Packet Variables related */
gchar * ip_src = NULL ;
gchar * ip_dst = NULL ;
guint32 spi = 0 ;
# endif
1999-03-29 02:21:34 +00:00
2006-03-27 16:25:35 +00:00
guint encapsulated_protocol = 0 ;
2006-04-13 22:26:13 +00:00
gboolean decrypt_dissect_ok = FALSE ;
2006-03-27 16:25:35 +00:00
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
gboolean get_address_ok = FALSE ;
gboolean null_encryption_decode_heuristic = FALSE ;
guint8 * decrypted_data = NULL ;
guint8 * encrypted_data = NULL ;
2006-08-09 02:00:05 +00:00
guint8 * authenticator_data = NULL ;
2006-04-13 22:26:13 +00:00
guint8 * esp_data = NULL ;
2006-03-27 16:25:35 +00:00
tvbuff_t * tvb_decrypted ;
gint entry_index ;
/* IPSEC encryption Variables related */
gint protocol_typ = IPSEC_SA_UNKNOWN ;
gint esp_crypt_algo = IPSEC_ENCRYPT_NULL ;
gint esp_auth_algo = IPSEC_AUTH_NULL ;
2006-08-15 19:28:07 +00:00
gchar * esp_crypt_key = NULL ;
gchar * esp_auth_key = NULL ;
2006-09-08 07:32:13 +00:00
guint esp_crypt_key_len = 0 ;
guint esp_auth_key_len = 0 ;
2006-03-27 16:25:35 +00:00
gint esp_iv_len = 0 ;
gint esp_auth_len = 0 ;
gint decrypted_len = 0 ;
gboolean decrypt_ok = FALSE ;
gboolean decrypt_using_libgcrypt = FALSE ;
2006-04-13 22:26:13 +00:00
gboolean authentication_check_using_hmac_libgcrypt = FALSE ;
gboolean authentication_ok = FALSE ;
gboolean authentication_checking_ok = FALSE ;
gboolean sad_is_present = FALSE ;
2006-03-27 16:25:35 +00:00
# endif
gint esp_pad_len = 0 ;
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
/* Variables for decryption and authentication checking used for libgrypt */
2006-03-27 16:25:35 +00:00
int decrypted_len_alloc = 0 ;
2006-04-13 22:26:13 +00:00
gcry_cipher_hd_t cypher_hd ;
gcry_md_hd_t md_hd ;
int md_len = 0 ;
2006-03-27 16:25:35 +00:00
gcry_error_t err = 0 ;
int crypt_algo_libgcrypt = 0 ;
int crypt_mode_libgcrypt = 0 ;
2006-04-13 22:26:13 +00:00
int auth_algo_libgcrypt = 0 ;
unsigned char * authenticator_data_computed = NULL ;
unsigned char * authenticator_data_computed_md ;
2006-03-27 16:25:35 +00:00
/*
* load the top pane info . This should be overwritten by
* the next protocol in the stack
*/
2006-08-09 02:00:05 +00:00
# endif
2006-03-27 16:25:35 +00:00
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) )
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " ESP " ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) )
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
tvb_memcpy ( tvb , ( guint8 * ) & esp , 0 , sizeof ( esp ) ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) {
col_add_fstr ( pinfo - > cinfo , COL_INFO , " ESP (SPI=0x%08x) " ,
( guint32 ) g_ntohl ( esp . esp_spi ) ) ;
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
/*
* populate a tree in the second pane with the status of the link layer
* ( ie none )
*/
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
if ( tree ) {
2006-08-09 02:00:05 +00:00
len = 0 , encapsulated_protocol = 0 ;
2006-04-13 22:26:13 +00:00
decrypt_dissect_ok = FALSE ;
2006-03-27 16:25:35 +00:00
i = 0 ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
ti = proto_tree_add_item ( tree , proto_esp , tvb , 0 , - 1 , FALSE ) ;
esp_tree = proto_item_add_subtree ( ti , ett_esp ) ;
proto_tree_add_uint ( esp_tree , hf_esp_spi , tvb ,
offsetof ( struct newesp , esp_spi ) , 4 ,
( guint32 ) g_ntohl ( esp . esp_spi ) ) ;
proto_tree_add_uint ( esp_tree , hf_esp_sequence , tvb ,
offsetof ( struct newesp , esp_seq ) , 4 ,
( guint32 ) g_ntohl ( esp . esp_seq ) ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-05-02 19:58:19 +00:00
/* The SAD is not activated */
if ( g_esp_enable_null_encryption_decode_heuristic & &
! g_esp_enable_encryption_decode )
null_encryption_decode_heuristic = TRUE ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( g_esp_enable_encryption_decode | | g_esp_enable_authentication_check )
{
/* Get Source & Destination Addresses in gchar * with all the bytes available. */
switch ( pinfo - > src . type )
{
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case AT_IPv4 :
{
2006-08-09 02:00:05 +00:00
ip_src = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV4 + 1 ) * sizeof ( gchar ) ) ;
ip_dst = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV4 + 1 ) * sizeof ( gchar ) ) ;
2006-05-02 19:58:19 +00:00
protocol_typ = IPSEC_SA_IPV4 ;
2006-03-27 16:25:35 +00:00
2006-05-02 19:58:19 +00:00
for ( i = 0 ; i < pinfo - > src . len ; i + + )
2006-08-09 02:00:05 +00:00
{
if ( ( ( guint8 * ) ( pinfo - > src . data ) ) [ i ] < 16 )
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " 0%X " , ( pinfo - > src . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " %X " , ( pinfo - > src . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
memcpy ( ip_src + i * 2 , res , 2 ) ;
}
2006-05-02 19:58:19 +00:00
ip_src [ IPSEC_STRLEN_IPV4 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
for ( i = 0 ; i < pinfo - > dst . len ; i + + )
2006-08-09 02:00:05 +00:00
{
if ( ( ( guint8 * ) ( pinfo - > dst . data ) ) [ i ] < 16 )
{
g_snprintf ( res , 3 , " 0%X " , ( pinfo - > dst . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " %X " , ( pinfo - > dst . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
memcpy ( ip_dst + i * 2 , res , 2 ) ;
}
2006-05-02 19:58:19 +00:00
ip_dst [ IPSEC_STRLEN_IPV4 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
get_address_ok = TRUE ;
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case AT_IPv6 :
{
2006-08-09 02:00:05 +00:00
ip_src = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV6 + 1 ) * sizeof ( gchar ) ) ;
ip_dst = ( gchar * ) g_malloc ( ( IPSEC_STRLEN_IPV6 + 1 ) * sizeof ( gchar ) ) ;
2006-05-02 19:58:19 +00:00
protocol_typ = IPSEC_SA_IPV6 ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
for ( i = 0 ; i < pinfo - > src . len ; i + + )
2006-08-09 02:00:05 +00:00
{
if ( ( ( guint8 * ) ( pinfo - > src . data ) ) [ i ] < 16 )
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " 0%X " , ( pinfo - > src . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " %X " , ( pinfo - > src . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
memcpy ( ip_src + i * 2 , res , 2 ) ;
}
2006-05-02 19:58:19 +00:00
ip_src [ IPSEC_STRLEN_IPV6 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
for ( i = 0 ; i < pinfo - > dst . len ; i + + )
2006-08-09 02:00:05 +00:00
{
if ( ( ( guint8 * ) ( pinfo - > dst . data ) ) [ i ] < 16 )
{
g_snprintf ( res , 3 , " 0%X " , ( pinfo - > dst . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
2006-08-09 02:00:05 +00:00
g_snprintf ( res , 3 , " %X " , ( pinfo - > dst . data ) [ i ] ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
memcpy ( ip_dst + i * 2 , res , 2 ) ;
}
2006-05-02 19:58:19 +00:00
ip_dst [ IPSEC_STRLEN_IPV6 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
get_address_ok = TRUE ;
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
default :
{
get_address_ok = FALSE ;
break ;
2006-03-27 16:25:35 +00:00
}
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* The packet cannot be decoded using the SAD */
if ( g_esp_enable_null_encryption_decode_heuristic & & ! get_address_ok )
null_encryption_decode_heuristic = TRUE ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( get_address_ok )
{
/* Get the SPI */
if ( tvb_bytes_exist ( tvb , 0 , 4 ) )
{
spi = tvb_get_ntohl ( tvb , 0 ) ;
}
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/*
PARSE the SAD and fill it . It may take some time since it will
be called every times an ESP Payload is found .
*/
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
if ( ( sad_is_present = get_esp_sa ( & g_esp_sad , protocol_typ , ip_src , ip_dst , spi , & entry_index ,
& esp_crypt_algo , & esp_auth_algo ,
& esp_crypt_key , & esp_crypt_key_len , & esp_auth_key , & esp_auth_key_len ) ) )
2006-08-09 02:00:05 +00:00
{
2006-03-27 16:25:35 +00:00
2006-05-02 19:58:19 +00:00
/* Get length of whole ESP packet. */
len = tvb_reported_length ( tvb ) ;
2006-09-08 07:32:13 +00:00
2006-05-02 19:58:19 +00:00
switch ( esp_auth_algo )
{
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_SHA1_96 :
{
esp_auth_len = 12 ;
break ;
}
2006-04-13 22:26:13 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_SHA256 :
{
esp_auth_len = 12 ;
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_NULL :
{
esp_auth_len = 0 ;
break ;
}
2006-08-09 02:00:05 +00:00
/*
2006-09-08 07:32:13 +00:00
case IPSEC_AUTH_AES_XCBC_MAC_96 :
{
esp_auth_len = 12 ;
break ;
}
2006-05-02 19:58:19 +00:00
*/
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_MD5_96 :
{
esp_auth_len = 12 ;
break ;
2006-03-27 16:25:35 +00:00
}
2006-04-13 22:26:13 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_ANY_12BYTES :
default :
2006-03-27 16:25:35 +00:00
{
2006-05-02 19:58:19 +00:00
esp_auth_len = 12 ;
break ;
}
}
if ( g_esp_enable_authentication_check )
{
switch ( esp_auth_algo )
{
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_SHA1_96 :
/*
RFC 2404 : HMAC - SHA - 1 - 96 is a secret key algorithm .
While no fixed key length is specified in [ RFC - 2104 ] ,
for use with either ESP or AH a fixed key length of
160 - bits MUST be supported . Key lengths other than
2006-08-09 02:00:05 +00:00
160 - bits MUST NOT be supported ( i . e . only 160 - bit keys
2006-05-02 19:58:19 +00:00
are to be used by HMAC - SHA - 1 - 96 ) . A key length of
160 - bits was chosen based on the recommendations in
[ RFC - 2104 ] ( i . e . key lengths less than the
authenticator length decrease security strength and
keys longer than the authenticator length do not
significantly increase security strength ) .
*/
2006-08-09 02:00:05 +00:00
{
2006-05-02 19:58:19 +00:00
auth_algo_libgcrypt = GCRY_MD_SHA1 ;
2006-08-09 02:00:05 +00:00
authentication_check_using_hmac_libgcrypt = TRUE ;
2006-05-02 19:58:19 +00:00
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_NULL :
{
authentication_check_using_hmac_libgcrypt = FALSE ;
authentication_checking_ok = TRUE ;
authentication_ok = TRUE ;
break ;
}
2006-08-09 02:00:05 +00:00
/*
2006-09-08 07:32:13 +00:00
case IPSEC_AUTH_AES_XCBC_MAC_96 :
{
auth_algo_libgcrypt =
authentication_check_using_libgcrypt = TRUE ;
break ;
}
*/
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_SHA256 :
{
auth_algo_libgcrypt = GCRY_MD_SHA256 ;
2006-08-09 02:00:05 +00:00
authentication_check_using_hmac_libgcrypt = TRUE ;
2006-05-02 19:58:19 +00:00
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_HMAC_MD5_96 :
/*
RFC 2403 : HMAC - MD5 - 96 is a secret key algorithm .
While no fixed key length is specified in [ RFC - 2104 ] ,
for use with either ESP or AH a fixed key length of
128 - bits MUST be supported . Key lengths other than
128 - bits MUST NOT be supported ( i . e . only 128 - bit keys
are to be used by HMAC - MD5 - 96 ) . A key length of
128 - bits was chosen based on the recommendations in
[ RFC - 2104 ] ( i . e . key lengths less than the
authenticator length decrease security strength and
keys longer than the authenticator length do not
significantly increase security strength ) .
*/
{
auth_algo_libgcrypt = GCRY_MD_MD5 ;
authentication_check_using_hmac_libgcrypt = TRUE ;
break ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
case IPSEC_AUTH_ANY_12BYTES :
default :
{
authentication_ok = FALSE ;
authentication_check_using_hmac_libgcrypt = FALSE ;
break ;
}
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
if ( ( authentication_check_using_hmac_libgcrypt ) & & ( ! authentication_ok ) )
{
gcry_control ( GCRYCTL_DISABLE_SECMEM , 0 ) ;
gcry_control ( GCRYCTL_INITIALIZATION_FINISHED , 0 ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Allocate Buffers for Authenticator Field */
authenticator_data = ( guint8 * ) g_malloc ( ( esp_auth_len + 1 ) * sizeof ( guint8 ) ) ;
memset ( authenticator_data , 0 , esp_auth_len + 1 ) ;
tvb_memcpy ( tvb , authenticator_data , len - esp_auth_len , esp_auth_len ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
esp_data = ( guint8 * ) g_malloc ( ( len - esp_auth_len + 1 ) * sizeof ( guint8 ) ) ;
memset ( esp_data , 0 , len - esp_auth_len + 1 ) ;
tvb_memcpy ( tvb , esp_data , 0 , len - esp_auth_len ) ;
2006-03-27 16:25:35 +00:00
2006-08-09 02:00:05 +00:00
err = gcry_md_open ( & md_hd , auth_algo_libgcrypt , GCRY_MD_FLAG_HMAC ) ;
2006-05-02 19:58:19 +00:00
if ( err )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s, gcry_md_open failed: %s \n " , gcry_md_algo_name ( auth_algo_libgcrypt ) , gpg_strerror ( err ) ) ;
authentication_ok = FALSE ;
g_free ( authenticator_data ) ;
g_free ( esp_data ) ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
else
{
md_len = gcry_md_get_algo_dlen ( auth_algo_libgcrypt ) ;
if ( md_len < 1 | | md_len < esp_auth_len )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s, grcy_md_get_algo_dlen failed: %d \n " , gcry_md_algo_name ( auth_algo_libgcrypt ) , md_len ) ;
authentication_ok = FALSE ;
}
2006-04-13 22:26:13 +00:00
2006-05-02 19:58:19 +00:00
else
2006-08-09 02:00:05 +00:00
{
2006-09-08 07:32:13 +00:00
gcry_md_setkey ( md_hd , esp_auth_key , esp_auth_key_len ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
gcry_md_write ( md_hd , esp_data , len - esp_auth_len ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
authenticator_data_computed_md = gcry_md_read ( md_hd , auth_algo_libgcrypt ) ;
if ( authenticator_data_computed_md = = 0 )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s, gcry_md_read failed \n " , gcry_md_algo_name ( auth_algo_libgcrypt ) ) ;
authentication_ok = FALSE ;
}
else
2006-08-09 02:00:05 +00:00
{
2006-05-02 19:58:19 +00:00
if ( memcmp ( authenticator_data_computed_md , authenticator_data , esp_auth_len ) )
{
unsigned char authenticator_data_computed_car [ 3 ] ;
2006-06-14 08:04:43 +00:00
authenticator_data_computed = ( guint8 * ) g_malloc ( ( esp_auth_len * 2 + 1 ) * sizeof ( guint8 ) ) ;
2006-05-02 19:58:19 +00:00
for ( i = 0 ; i < esp_auth_len ; i + + )
{
g_snprintf ( ( char * ) authenticator_data_computed_car , 3 , " %02X " , authenticator_data_computed_md [ i ] & 0xFF ) ;
authenticator_data_computed [ i * 2 ] = authenticator_data_computed_car [ 0 ] ;
2006-08-09 02:00:05 +00:00
authenticator_data_computed [ i * 2 + 1 ] = authenticator_data_computed_car [ 1 ] ;
2006-05-02 19:58:19 +00:00
}
authenticator_data_computed [ esp_auth_len * 2 ] = ' \0 ' ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
authentication_ok = TRUE ;
authentication_checking_ok = FALSE ;
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
authentication_ok = TRUE ;
authentication_checking_ok = TRUE ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
gcry_md_close ( md_hd ) ;
g_free ( authenticator_data ) ;
g_free ( esp_data ) ;
2006-08-09 02:00:05 +00:00
}
2006-04-13 22:26:13 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( g_esp_enable_encryption_decode )
{
/* Desactivation of the Heuristic to decrypt using the NULL encryption algorithm since the packet is matching a SA */
2006-08-09 02:00:05 +00:00
null_encryption_decode_heuristic = FALSE ;
2006-05-02 19:58:19 +00:00
switch ( esp_crypt_algo )
{
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_3DES_CBC :
{
/* RFC 2451 says :
3 DES CBC uses a key of 192 bits .
The first 3 DES key is taken from the first 64 bits ,
the second from the next 64 bits , and the third
from the last 64 bits .
Implementations MUST take into consideration the
parity bits when initially accepting a new set of
keys . Each of the three keys is really 56 bits in
length with the extra 8 bits used for parity . */
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Fix parameters for 3DES-CBC */
2006-08-09 02:00:05 +00:00
esp_iv_len = 8 ;
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_3DES ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
if ( esp_crypt_key_len ! = gcry_cipher_get_algo_keylen ( crypt_algo_libgcrypt ) )
2006-05-02 19:58:19 +00:00
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm 3DES-CBC : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-05-02 19:58:19 +00:00
decrypt_ok = FALSE ;
}
else
decrypt_using_libgcrypt = TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_AES_CBC :
{
/* RFC 3602 says :
AES supports three key sizes : 128 bits , 192 bits ,
and 256 bits . The default key size is 128 bits ,
and all implementations MUST support this key size .
Implementations MAY also support key sizes of 192
bits and 256 bits . */
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Fix parameters for AES-CBC */
esp_iv_len = 16 ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
switch ( esp_crypt_key_len * 8 )
2006-05-02 19:58:19 +00:00
{
case 128 :
2006-04-13 22:26:13 +00:00
{
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_AES128 ;
2006-08-09 02:00:05 +00:00
decrypt_using_libgcrypt = TRUE ;
2006-05-02 19:58:19 +00:00
break ;
2006-04-13 22:26:13 +00:00
}
2006-05-02 19:58:19 +00:00
case 192 :
{
crypt_algo_libgcrypt = GCRY_CIPHER_AES192 ;
2006-08-09 02:00:05 +00:00
decrypt_using_libgcrypt = TRUE ;
2006-05-02 19:58:19 +00:00
break ;
}
case 256 :
{
crypt_algo_libgcrypt = GCRY_CIPHER_AES256 ;
2006-08-09 02:00:05 +00:00
decrypt_using_libgcrypt = TRUE ;
2006-05-02 19:58:19 +00:00
break ;
}
default :
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm AES-CBC : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
}
2006-05-02 19:58:19 +00:00
}
}
break ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_DES_CBC :
{
/* RFC 2405 says :
DES - CBC is a symmetric secret key algorithm .
The key size is 64 - bits .
[ It is commonly known as a 56 - bit key as the key
has 56 significant bits ; the least significant
bit in every byte is the parity bit . ] */
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Fix parameters for DES-CBC */
2006-08-09 02:00:05 +00:00
esp_iv_len = 8 ;
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_DES ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC ;
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
if ( esp_crypt_key_len ! = gcry_cipher_get_algo_keylen ( crypt_algo_libgcrypt ) )
2006-05-02 19:58:19 +00:00
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm DES-CBC : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-05-02 19:58:19 +00:00
decrypt_ok = FALSE ;
}
else
decrypt_using_libgcrypt = TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_AES_CTR :
{
/* RFC 3686 says :
AES supports three key sizes : 128 bits , 192 bits ,
and 256 bits . The default key size is 128 bits ,
and all implementations MUST support this key
size . Implementations MAY also support key sizes
of 192 bits and 256 bits . The remaining 32 bits
will be used as nonce . */
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Fix parameters for AES-CTR */
esp_iv_len = 8 ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CTR ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
switch ( esp_crypt_key_len * 8 )
2006-05-02 19:58:19 +00:00
{
case 160 :
2006-04-13 22:26:13 +00:00
{
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_AES128 ;
decrypt_using_libgcrypt = TRUE ;
break ;
2006-04-13 22:26:13 +00:00
}
2006-05-02 19:58:19 +00:00
case 224 :
{
crypt_algo_libgcrypt = GCRY_CIPHER_AES192 ;
decrypt_using_libgcrypt = TRUE ;
break ;
}
case 288 :
{
crypt_algo_libgcrypt = GCRY_CIPHER_AES256 ;
decrypt_using_libgcrypt = TRUE ;
break ;
}
default :
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm AES-CTR : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
}
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_TWOFISH_CBC :
{
/* Twofish is a 128-bit block cipher developed by
Counterpane Labs that accepts a variable - length
key up to 256 bits .
2006-08-09 02:00:05 +00:00
We will only accept key sizes of 128 and 256 bits .
2006-05-02 19:58:19 +00:00
*/
/* Fix parameters for TWOFISH-CBC */
esp_iv_len = 16 ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
switch ( esp_crypt_key_len * 8 )
2006-05-02 19:58:19 +00:00
{
case 128 :
2006-04-13 22:26:13 +00:00
{
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH128 ;
decrypt_using_libgcrypt = TRUE ;
break ;
2006-04-13 22:26:13 +00:00
}
2006-05-02 19:58:19 +00:00
case 256 :
{
crypt_algo_libgcrypt = GCRY_CIPHER_TWOFISH ;
decrypt_using_libgcrypt = TRUE ;
break ;
}
default :
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm TWOFISH-CBC : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
}
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_BLOWFISH_CBC :
{
/* Bruce Schneier of Counterpane Systems developed
2006-08-09 02:00:05 +00:00
the Blowfish block cipher algorithm .
2006-05-02 19:58:19 +00:00
RFC 2451 shows that Blowfish uses key sizes from
2006-08-09 02:00:05 +00:00
40 to 448 bits . The Default size is 128 bits .
2006-05-02 19:58:19 +00:00
We will only accept key sizes of 128 bits , because
2006-08-09 02:00:05 +00:00
libgrypt only accept this key size .
2006-05-02 19:58:19 +00:00
*/
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Fix parameters for BLOWFISH-CBC */
2006-08-09 02:00:05 +00:00
esp_iv_len = 8 ;
2006-05-02 19:58:19 +00:00
crypt_algo_libgcrypt = GCRY_CIPHER_BLOWFISH ;
crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
if ( decrypted_len % esp_iv_len = = 0 )
decrypted_len_alloc = decrypted_len ;
else
decrypted_len_alloc = ( decrypted_len / esp_iv_len ) * esp_iv_len + esp_iv_len ;
2006-08-09 02:00:05 +00:00
2006-09-08 07:32:13 +00:00
if ( esp_crypt_key_len ! = gcry_cipher_get_algo_keylen ( crypt_algo_libgcrypt ) )
2006-05-02 19:58:19 +00:00
{
2006-09-08 07:32:13 +00:00
fprintf ( stderr , " <ESP Preferences> Error in Encryption Algorithm BLOWFISH-CBC : Bad Keylen (%i Bits) \n " , esp_crypt_key_len * 8 ) ;
2006-05-02 19:58:19 +00:00
decrypt_ok = FALSE ;
}
else
decrypt_using_libgcrypt = TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
case IPSEC_ENCRYPT_NULL :
default :
{
/* Fix parameters */
2006-08-09 02:00:05 +00:00
esp_iv_len = 0 ;
2006-05-02 19:58:19 +00:00
decrypted_len = len - sizeof ( struct newesp ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len < = 0 )
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
else
{
/* Allocate Buffers for Encrypted and Decrypted data */
2006-08-09 02:00:05 +00:00
decrypted_data = ( guint8 * ) g_malloc ( ( decrypted_len + 1 ) * sizeof ( guint8 ) ) ;
2006-05-02 19:58:19 +00:00
tvb_memcpy ( tvb , decrypted_data , sizeof ( struct newesp ) , decrypted_len ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
decrypt_ok = TRUE ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
break ;
2006-03-27 16:25:35 +00:00
}
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypt_using_libgcrypt )
{
/* Allocate Buffers for Encrypted and Decrypted data */
encrypted_data = ( guint8 * ) g_malloc ( ( decrypted_len_alloc ) * sizeof ( guint8 ) ) ;
memset ( encrypted_data , 0 , decrypted_len_alloc ) ;
2006-08-09 02:00:05 +00:00
decrypted_data = ( guint8 * ) g_malloc ( ( decrypted_len_alloc + esp_iv_len ) * sizeof ( guint8 ) ) ;
2006-05-02 19:58:19 +00:00
tvb_memcpy ( tvb , encrypted_data , sizeof ( struct newesp ) , decrypted_len ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
err = gcry_cipher_open ( & cypher_hd , crypt_algo_libgcrypt , crypt_mode_libgcrypt , 0 ) ;
if ( err )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s Mode %d, grcy_open_cipher failed: %s \n " ,
gcry_cipher_algo_name ( crypt_algo_libgcrypt ) , crypt_mode_libgcrypt , gpg_strerror ( err ) ) ;
g_free ( encrypted_data ) ;
g_free ( decrypted_data ) ;
decrypt_ok = FALSE ;
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
else
{
2006-09-08 07:32:13 +00:00
err = gcry_cipher_setkey ( cypher_hd , esp_crypt_key , esp_crypt_key_len ) ;
2006-05-02 19:58:19 +00:00
if ( err )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s Mode %d, gcry_cipher_setkey failed: %s \n " ,
gcry_cipher_algo_name ( crypt_algo_libgcrypt ) , crypt_mode_libgcrypt , gpg_strerror ( err ) ) ;
gcry_cipher_close ( cypher_hd ) ;
g_free ( encrypted_data ) ;
g_free ( decrypted_data ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
}
else
2006-08-09 02:00:05 +00:00
{
2006-05-02 19:58:19 +00:00
err = gcry_cipher_decrypt ( cypher_hd , decrypted_data , decrypted_len_alloc + esp_iv_len , encrypted_data , decrypted_len_alloc ) ;
if ( err )
{
fprintf ( stderr , " <IPsec/ESP Dissector> Error in Algorithm %s, Mode %d, gcry_cipher_decrypt failed: %s \n " ,
gcry_cipher_algo_name ( crypt_algo_libgcrypt ) , crypt_mode_libgcrypt , gpg_strerror ( err ) ) ;
gcry_cipher_close ( cypher_hd ) ;
g_free ( encrypted_data ) ;
g_free ( decrypted_data ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = FALSE ;
2006-05-02 19:58:19 +00:00
}
else
{
gcry_cipher_close ( cypher_hd ) ;
/* Add the Authentication which was not encrypted */
if ( decrypted_len > = esp_auth_len )
{
for ( i = 0 ; i < esp_auth_len ; i + + )
{
2006-08-09 02:00:05 +00:00
decrypted_data [ i + decrypted_len - esp_auth_len ] = encrypted_data [ i + decrypted_len - esp_auth_len ] ;
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
fprintf ( stderr , " \n \n " ) ;
g_free ( encrypted_data ) ;
2006-08-09 02:00:05 +00:00
decrypt_ok = TRUE ;
2006-05-02 19:58:19 +00:00
}
}
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypt_ok )
{
tvb_decrypted = tvb_new_real_data ( decrypted_data , decrypted_len , decrypted_len ) ;
tvb_set_child_real_data_tvbuff ( tvb , tvb_decrypted ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
add_new_data_source ( pinfo ,
tvb_decrypted ,
" Decrypted Data " ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Handler to free the Decrypted Data Buffer. */
tvb_set_free_cb ( tvb_decrypted , g_free ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( tvb_bytes_exist ( tvb_decrypted , 0 , esp_iv_len ) )
{
if ( esp_iv_len > 0 )
2006-09-12 09:53:10 +00:00
proto_tree_add_item ( esp_tree , hf_esp_iv ,
tvb_decrypted ,
2006-05-02 19:58:19 +00:00
0 , esp_iv_len ,
2006-09-12 09:53:10 +00:00
FALSE ) ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
else
proto_tree_add_text ( esp_tree , tvb_decrypted ,
0 , - 1 ,
" IV (truncated) " ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Make sure the packet is not truncated before the fields
* we need to read to determine the encapsulated protocol */
if ( tvb_bytes_exist ( tvb_decrypted , decrypted_len - esp_auth_len - 2 , 2 ) )
{
esp_pad_len = tvb_get_guint8 ( tvb_decrypted , decrypted_len - esp_auth_len - 2 ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypted_len - esp_auth_len - esp_pad_len - esp_iv_len - 2 > = esp_iv_len )
{
/* Get the encapsulated protocol */
encapsulated_protocol = tvb_get_guint8 ( tvb_decrypted , decrypted_len - esp_auth_len - 1 ) ;
2006-08-09 02:00:05 +00:00
if ( dissector_try_port ( ip_dissector_table ,
2006-05-02 19:58:19 +00:00
encapsulated_protocol ,
2006-08-09 02:00:05 +00:00
tvb_new_subset ( tvb_decrypted , esp_iv_len ,
decrypted_len - esp_auth_len - esp_pad_len - esp_iv_len - 2 ,
decrypted_len - esp_auth_len - esp_pad_len - esp_iv_len - 2 ) ,
2006-05-02 19:58:19 +00:00
pinfo ,
esp_tree ) ) /*tree))*/
{
decrypt_dissect_ok = TRUE ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypt_dissect_ok )
{
if ( esp_tree )
2006-08-09 02:00:05 +00:00
{
2006-05-02 19:58:19 +00:00
if ( esp_pad_len ! = 0 )
2006-04-13 22:26:13 +00:00
proto_tree_add_text ( esp_tree , tvb_decrypted , decrypted_len - esp_auth_len - 2 - esp_pad_len , esp_pad_len , " Pad " ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
proto_tree_add_uint ( esp_tree , hf_esp_pad_len , tvb_decrypted ,
decrypted_len - esp_auth_len - 2 , 1 ,
esp_pad_len ) ;
2006-09-12 09:53:10 +00:00
proto_tree_add_uint_format ( esp_tree , hf_esp_protocol , tvb_decrypted ,
decrypted_len - esp_auth_len - 1 , 1 ,
encapsulated_protocol ,
" Next header: %s (0x%02x) " ,
ipprotostr ( encapsulated_protocol ) , encapsulated_protocol ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
dissect_esp_authentication ( esp_tree , tvb_decrypted , decrypted_len , esp_auth_len , authenticator_data_computed , authentication_ok , authentication_checking_ok ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
}
}
else
{
call_dissector ( data_handle ,
tvb_new_subset ( tvb_decrypted , 0 , decrypted_len - esp_auth_len , decrypted_len - esp_auth_len ) ,
pinfo , esp_tree ) ;
2006-04-13 22:26:13 +00:00
2006-05-02 19:58:19 +00:00
if ( esp_tree )
2006-04-13 22:26:13 +00:00
dissect_esp_authentication ( esp_tree , tvb_decrypted , decrypted_len , esp_auth_len , authenticator_data_computed , authentication_ok , authentication_checking_ok ) ;
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
else
2006-05-02 19:58:19 +00:00
{
/* The packet does not belong to a security Association */
2006-08-09 02:00:05 +00:00
null_encryption_decode_heuristic = g_esp_enable_null_encryption_decode_heuristic ;
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
g_free ( ip_src ) ;
g_free ( ip_dst ) ;
2006-09-08 07:32:13 +00:00
if ( esp_auth_key_len ! = 0 ) g_free ( esp_auth_key ) ;
if ( esp_crypt_key_len ! = 0 ) g_free ( esp_crypt_key ) ;
2006-05-02 19:58:19 +00:00
}
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/*
If the packet is present in the security association database and the field g_esp_enable_authentication_check set .
2006-08-09 02:00:05 +00:00
*/
2006-05-02 19:58:19 +00:00
if ( ! g_esp_enable_encryption_decode & & g_esp_enable_authentication_check & & sad_is_present )
{
sad_is_present = FALSE ;
call_dissector ( data_handle ,
tvb_new_subset ( tvb , sizeof ( struct newesp ) , len - sizeof ( struct newesp ) - esp_auth_len , - 1 ) ,
pinfo , esp_tree ) ;
2006-03-27 16:25:35 +00:00
2006-05-02 19:58:19 +00:00
if ( esp_tree )
2006-04-13 22:26:13 +00:00
dissect_esp_authentication ( esp_tree , tvb , len , esp_auth_len , authenticator_data_computed , authentication_ok , authentication_checking_ok ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* The packet does not belong to a security association and the field g_esp_enable_null_encryption_decode_heuristic is set */
else if ( null_encryption_decode_heuristic )
{
2006-04-13 22:26:13 +00:00
# endif
2006-05-02 19:58:19 +00:00
if ( g_esp_enable_null_encryption_decode_heuristic )
{
/* Get length of whole ESP packet. */
len = tvb_reported_length ( tvb ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Make sure the packet is not truncated before the fields
* we need to read to determine the encapsulated protocol */
if ( tvb_bytes_exist ( tvb , len - 14 , 2 ) )
{
esp_pad_len = tvb_get_guint8 ( tvb , len - 14 ) ;
encapsulated_protocol = tvb_get_guint8 ( tvb , len - 13 ) ;
2006-08-09 02:00:05 +00:00
if ( dissector_try_port ( ip_dissector_table ,
2006-05-02 19:58:19 +00:00
encapsulated_protocol ,
2006-08-09 02:00:05 +00:00
tvb_new_subset ( tvb ,
sizeof ( struct newesp ) ,
- 1 ,
2006-05-02 19:58:19 +00:00
len - sizeof ( struct newesp ) - 14 - esp_pad_len ) ,
pinfo ,
esp_tree ) )
{
decrypt_dissect_ok = TRUE ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
}
}
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
if ( decrypt_dissect_ok )
{
if ( esp_tree )
{
proto_tree_add_uint ( esp_tree , hf_esp_pad_len , tvb ,
len - 14 , 1 ,
esp_pad_len ) ;
2006-09-12 09:53:10 +00:00
proto_tree_add_uint_format ( esp_tree , hf_esp_protocol , tvb ,
2006-05-02 19:58:19 +00:00
len - 13 , 1 ,
2006-09-12 09:53:10 +00:00
encapsulated_protocol ,
" Next header: %s (0x%02x) " ,
ipprotostr ( encapsulated_protocol ) , encapsulated_protocol ) ;
2006-08-09 02:00:05 +00:00
2006-05-02 19:58:19 +00:00
/* Make sure we have the auth trailer data */
if ( tvb_bytes_exist ( tvb , len - 12 , 12 ) )
{
proto_tree_add_text ( esp_tree , tvb , len - 12 , 12 ,
" Authentication Data " ) ;
2006-08-09 02:00:05 +00:00
}
2006-05-02 19:58:19 +00:00
else
{
/* Truncated so just display what we have */
proto_tree_add_text ( esp_tree , tvb , len - 12 , 12 - ( len - tvb_length ( tvb ) ) ,
" Authentication Data (truncated) " ) ;
}
}
}
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-04-13 22:26:13 +00:00
2006-03-27 16:25:35 +00:00
}
# endif
2006-08-09 02:00:05 +00:00
}
2006-03-27 16:25:35 +00:00
1999-10-15 05:30:43 +00:00
2000-04-20 07:05:58 +00:00
static void
2001-02-28 06:37:29 +00:00
dissect_ipcomp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
1999-10-15 05:30:43 +00:00
{
2006-03-27 16:25:35 +00:00
proto_tree * ipcomp_tree ;
proto_item * ti ;
struct ipcomp ipcomp ;
const char * p ;
1999-10-15 05:30:43 +00:00
2006-03-27 16:25:35 +00:00
/*
* load the top pane info . This should be overwritten by
* the next protocol in the stack
*/
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) )
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " IPComp " ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) )
col_clear ( pinfo - > cinfo , COL_INFO ) ;
tvb_memcpy ( tvb , ( guint8 * ) & ipcomp , 0 , sizeof ( ipcomp ) ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) {
p = match_strval ( g_ntohs ( ipcomp . comp_cpi ) , cpi2val ) ;
if ( p = = NULL ) {
col_add_fstr ( pinfo - > cinfo , COL_INFO , " IPComp (CPI=0x%04x) " ,
g_ntohs ( ipcomp . comp_cpi ) ) ;
} else
col_add_fstr ( pinfo - > cinfo , COL_INFO , " IPComp (CPI=%s) " , p ) ;
}
/*
* populate a tree in the second pane with the status of the link layer
* ( ie none )
*/
if ( tree ) {
ti = proto_tree_add_item ( tree , proto_ipcomp , tvb , 0 , - 1 , FALSE ) ;
ipcomp_tree = proto_item_add_subtree ( ti , ett_ipcomp ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
proto_tree_add_text ( ipcomp_tree , tvb ,
offsetof ( struct ipcomp , comp_nxt ) , 1 ,
" Next Header: %s (0x%02x) " ,
ipprotostr ( ipcomp . comp_nxt ) , ipcomp . comp_nxt ) ;
proto_tree_add_uint ( ipcomp_tree , hf_ipcomp_flags , tvb ,
offsetof ( struct ipcomp , comp_flags ) , 1 ,
ipcomp . comp_flags ) ;
proto_tree_add_uint ( ipcomp_tree , hf_ipcomp_cpi , tvb ,
offsetof ( struct ipcomp , comp_cpi ) , 2 ,
g_ntohs ( ipcomp . comp_cpi ) ) ;
call_dissector ( data_handle ,
tvb_new_subset ( tvb , sizeof ( struct ipcomp ) , - 1 , - 1 ) , pinfo ,
ipcomp_tree ) ;
}
1999-03-29 02:21:34 +00:00
}
1999-07-29 05:47:07 +00:00
void
proto_register_ipsec ( void )
{
1999-10-11 12:37:50 +00:00
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
guint i = 0 ;
# endif
1999-10-11 12:37:50 +00:00
static hf_register_info hf_ah [ ] = {
{ & hf_ah_spi ,
1999-10-12 06:21:15 +00:00
{ " SPI " , " ah.spi " , FT_UINT32 , BASE_HEX , NULL , 0x0 ,
2001-06-18 02:18:27 +00:00
" " , HFILL } } ,
2006-09-12 09:53:10 +00:00
{ & hf_ah_iv ,
{ " IV " , " ah.iv " , FT_BYTES , BASE_HEX , NULL , 0x0 ,
" " , HFILL } } ,
1999-10-11 12:37:50 +00:00
{ & hf_ah_sequence ,
2003-08-16 00:11:07 +00:00
{ " Sequence " , " ah.sequence " , FT_UINT32 , BASE_DEC , NULL , 0x0 ,
2001-06-18 02:18:27 +00:00
" " , HFILL } }
1999-10-11 12:37:50 +00:00
} ;
static hf_register_info hf_esp [ ] = {
{ & hf_esp_spi ,
1999-10-12 06:21:15 +00:00
{ " SPI " , " esp.spi " , FT_UINT32 , BASE_HEX , NULL , 0x0 ,
2001-06-18 02:18:27 +00:00
" " , HFILL } } ,
1999-10-11 12:37:50 +00:00
{ & hf_esp_sequence ,
2003-08-16 00:11:07 +00:00
{ " Sequence " , " esp.sequence " , FT_UINT32 , BASE_DEC , NULL , 0x0 ,
2004-11-12 10:03:53 +00:00
" " , HFILL } } ,
2006-04-13 22:26:13 +00:00
{ & hf_esp_pad_len ,
{ " Pad Length " , " esp.pad_len " , FT_UINT8 , BASE_DEC , NULL , 0x0 ,
2004-11-12 10:03:53 +00:00
" " , HFILL } } ,
{ & hf_esp_protocol ,
{ " Next Header " , " esp.protocol " , FT_UINT8 , BASE_HEX , NULL , 0x0 ,
2006-09-12 09:53:10 +00:00
" " , HFILL } } ,
{ & hf_esp_iv ,
{ " IV " , " esp.iv " , FT_BYTES , BASE_HEX , NULL , 0x0 ,
2001-06-18 02:18:27 +00:00
" " , HFILL } }
1999-10-11 12:37:50 +00:00
} ;
1999-10-15 05:30:43 +00:00
static hf_register_info hf_ipcomp [ ] = {
1999-10-15 05:46:18 +00:00
{ & hf_ipcomp_flags ,
{ " Flags " , " ipcomp.flags " , FT_UINT8 , BASE_HEX , NULL , 0x0 ,
2001-06-18 02:18:27 +00:00
" " , HFILL } } ,
1999-10-15 05:30:43 +00:00
{ & hf_ipcomp_cpi ,
2002-08-28 21:04:11 +00:00
{ " CPI " , " ipcomp.cpi " , FT_UINT16 , BASE_HEX ,
2001-06-18 02:18:27 +00:00
VALS ( cpi2val ) , 0x0 , " " , HFILL } } ,
1999-10-15 05:30:43 +00:00
} ;
1999-11-16 11:44:20 +00:00
static gint * ett [ ] = {
& ett_ah ,
& ett_esp ,
& ett_ipcomp ,
} ;
1999-10-15 05:30:43 +00:00
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
char * str_sa_num ;
2001-08-29 08:12:32 +00:00
2006-03-27 16:25:35 +00:00
static enum_val_t esp_encryption_algo [ ] = {
{ " null " , " NULL " , IPSEC_ENCRYPT_NULL } ,
{ " 3descbc " , " TripleDES-CBC [RFC2451] " , IPSEC_ENCRYPT_3DES_CBC } ,
{ " aescbc " , " AES-CBC [RFC3602] " , IPSEC_ENCRYPT_AES_CBC } ,
{ " aesctr " , " AES-CTR [RFC3686] " , IPSEC_ENCRYPT_AES_CTR } ,
{ " descbc " , " DES-CBC [RFC2405] " , IPSEC_ENCRYPT_DES_CBC } ,
{ " blowfishcbc " , " BLOWFISH-CBC [RFC2451] " , IPSEC_ENCRYPT_BLOWFISH_CBC } ,
{ " twofishcbc " , " TWOFISH-CBC " , IPSEC_ENCRYPT_TWOFISH_CBC } ,
{ NULL , NULL , 0 }
} ;
static enum_val_t esp_authentication_algo [ ] = {
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
{ " null " , " NULL " , IPSEC_AUTH_NULL } ,
{ " hmacsha196 " , " HMAC-SHA1-96 [RFC2404] " , IPSEC_AUTH_HMAC_SHA1_96 } ,
2006-04-13 22:26:13 +00:00
{ " hmacsha256 " , " HMAC-SHA256 " , IPSEC_AUTH_HMAC_SHA256 } ,
2006-03-27 16:25:35 +00:00
{ " hmacmd596 " , " HMAC-MD5-96 [RFC2403] " , IPSEC_AUTH_HMAC_MD5_96 } ,
2006-04-13 22:26:13 +00:00
/* {"aesxcbcmac96", "AES-XCBC-MAC-96 [RFC3566]", IPSEC_AUTH_AES_XCBC_MAC_96}, */
{ " any12bytes " , " ANY 12-bytes of Authentication [No Checking] " , IPSEC_AUTH_ANY_12BYTES } ,
2006-03-27 16:25:35 +00:00
{ NULL , NULL , 0 }
} ;
# endif
2006-08-09 02:00:05 +00:00
2006-06-14 08:04:43 +00:00
module_t * ah_module ;
module_t * esp_module ;
proto_ah = proto_register_protocol ( " Authentication Header " , " AH " , " ah " ) ;
proto_register_field_array ( proto_ah , hf_ah , array_length ( hf_ah ) ) ;
proto_esp = proto_register_protocol ( " Encapsulating Security Payload " ,
" ESP " , " esp " ) ;
proto_register_field_array ( proto_esp , hf_esp , array_length ( hf_esp ) ) ;
proto_ipcomp = proto_register_protocol ( " IP Payload Compression " ,
" IPComp " , " ipcomp " ) ;
proto_register_field_array ( proto_ipcomp , hf_ipcomp , array_length ( hf_ipcomp ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
/* Register a configuration option for placement of AH payload dissection */
ah_module = prefs_register_protocol ( proto_ah , NULL ) ;
prefs_register_bool_preference ( ah_module , " place_ah_payload_in_subtree " ,
" Place AH payload in subtree " ,
" Whether the AH payload decode should be placed in a subtree " ,
& g_ah_payload_in_subtree ) ;
2004-11-12 10:03:53 +00:00
esp_module = prefs_register_protocol ( proto_esp , NULL ) ;
2006-03-27 16:25:35 +00:00
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
/* Register SA configuration options for ESP decryption */
g_esp_sad . nb = g_esp_nb_sa ;
for ( i = 0 ; i < g_esp_nb_sa ; i + + )
{
g_esp_sad . table [ i ] . sa = NULL ;
g_esp_sad . table [ i ] . typ = IPSEC_SA_UNKNOWN ;
g_esp_sad . table [ i ] . src = NULL ;
g_esp_sad . table [ i ] . dst = NULL ;
g_esp_sad . table [ i ] . spi = NULL ;
g_esp_sad . table [ i ] . src_len = - 1 ;
g_esp_sad . table [ i ] . dst_len = - 1 ;
g_esp_sad . table [ i ] . encryption_algo = IPSEC_ENCRYPT_NULL ;
g_esp_sad . table [ i ] . authentication_algo = IPSEC_AUTH_NULL ;
g_esp_sad . table [ i ] . encryption_key = NULL ;
2006-08-09 02:00:05 +00:00
g_esp_sad . table [ i ] . authentication_key = NULL ;
2006-03-27 16:25:35 +00:00
g_esp_sad . table [ i ] . is_valid = FALSE ;
}
# endif
2004-11-12 10:03:53 +00:00
prefs_register_bool_preference ( esp_module , " enable_null_encryption_decode_heuristic " ,
2006-03-27 16:25:35 +00:00
" Attempt to detect/decode NULL encrypted ESP payloads " ,
" This is done only if the Decoding is not SET or the packet does not belong to a SA. Assumes a 12 byte auth (HMAC-SHA1-96/HMAC-MD5-96/AES-XCBC-MAC-96) and attempts decode based on the ethertype 13 bytes from packet end " ,
& g_esp_enable_null_encryption_decode_heuristic ) ;
2006-06-14 08:04:43 +00:00
# ifdef HAVE_LIBGCRYPT
2006-03-27 16:25:35 +00:00
prefs_register_bool_preference ( esp_module , " enable_encryption_decode " ,
" Attempt to detect/decode encrypted ESP payloads " ,
" Attempt to decode based on the SAD described hereafter. " ,
& g_esp_enable_encryption_decode ) ;
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
prefs_register_bool_preference ( esp_module , " enable_authentication_check " ,
" Attempt to Check ESP Authentication " ,
" Attempt to Check ESP Authentication based on the SAD described hereafter. " ,
2006-08-09 02:00:05 +00:00
& g_esp_enable_authentication_check ) ;
2006-04-13 22:26:13 +00:00
2006-03-27 16:25:35 +00:00
/* prefs_register_uint_preference(esp_module, "nb_sa",
" Number of Security Associations " ,
" Number of Security Associations in the SAD " ,
10 , & g_esp_nb_sa ) ; */
2006-06-14 08:04:43 +00:00
str_sa_num = ( char * ) g_malloc ( g_max_esp_size_nb_sa + 1 ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
for ( i = 0 ; i < g_esp_nb_sa ; i + + )
{
2006-06-14 08:04:43 +00:00
char * str_sa , * str_sa_comment ;
char * str_encryption_algorithm , * str_encryption_algorithm_comment ;
char * str_authentication_algorithm , * str_authentication_algorithm_comment ;
char * str_encryption_key , * str_encryption_key_comment ;
char * str_authentication_key , * str_authentication_key_comment ;
2006-03-27 16:25:35 +00:00
if ( i > = g_max_esp_nb_sa )
{
break ;
}
g_snprintf ( str_sa_num , g_max_esp_size_nb_sa + 1 , " %i " , i + 1 ) ;
2006-06-14 08:04:43 +00:00
str_sa = ( char * ) g_malloc ( 3 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_sa , 3 + g_max_esp_size_nb_sa + 2 , " %s%s " , " sa_ " , str_sa_num ) ;
2006-06-14 08:04:43 +00:00
str_sa_comment = ( char * ) g_malloc ( 4 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_sa_comment , 4 + g_max_esp_size_nb_sa + 2 , " %s%s " , " SA # " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
prefs_register_string_preference ( esp_module , str_sa ,
str_sa_comment ,
2006-04-13 22:26:13 +00:00
" This field uses the following syntax : \042 Protocol|Source Address|Destination Adress|SPI \042 . "
2006-03-27 22:37:11 +00:00
" <Protocol>: either IPv4, IPv6 (upper and/or lowercase letters). <SPI> : the Security Parameter Index "
" of the Security Association. You may indicate it in decimal (ex: 123) or in hexadecimal (ex: 0x45). "
2006-09-08 07:32:13 +00:00
" The special keywords '*' may be used to match any SPI. Nevertheless, if you use more than one '*', "
2006-03-27 22:37:11 +00:00
" it will restrict the length of the SPI in decimal to as many '*' as indicated. For example '**' will "
" match 23 but not 234. 234 will be match by '***'. No checking will be done on the SPI value. Thus you "
" have to take into account that the SPI is 4 bytes length. <Addresses> : In this field we may have IPv6 "
" or IPv4 address. Any address is a combination of an address or a prefix and a Prefixlen/Netmask separated "
2006-09-08 07:32:13 +00:00
" by '/'. You may omit the Prefixlen/Netmask, assuming that the Address is 128 bits length for IPv6 and 32 "
2006-03-27 22:37:11 +00:00
" bits length for IPv4. The character '*' used at the Prefixlen/Netmask position will be as if you had omit it. "
" <IPv6 Addresses> : Any valid IPv6 address is accepted. ex: 3FFE::1/128, 3FFE:4:5:6666::/64, ::1/128, 3FFE:4::5 . "
" If your address is incorrect and longer than 16 bytes, only the last 16 bytes will be taken into account. You also "
" may use the special character '*' to indicate any 4 bits block. ie : 3ffe::45*6. If you use only one '*' in the "
" Address field it will accept any IPv6 address. <IPv4 Addresses> : Any valid IPv4 address is accepted. "
" ex : 190.0.0.1/24, 10.0.0.2 .You also may use the special character '*' to indicate any 8 bits block. "
" ie : 190.*.*.3. If you use only one '*' in the Address field it will accept any IPv4 address. No checking "
" of correct IPv4 address will be done. For example 456.345.567.890 will be accepted. Thus you have to take care "
" about what you write. Nevertheless only 3 characters will be taken into account for one byte. "
" Ex : 190.0.0.0184 will not be considered correct. (Instead a kind of LRU Mechanism will be used and the address taken into "
" account will be 190.0.0.418). Moreover only the four first values will be used (Ie 190.0.0.12.13 will be considered as 190.0.0.12). " ,
2006-03-27 16:25:35 +00:00
& g_esp_sad . table [ i ] . sa ) ;
2006-08-09 02:00:05 +00:00
2006-06-14 08:04:43 +00:00
str_encryption_algorithm = ( char * ) g_malloc ( 21 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_encryption_algorithm , 21 + g_max_esp_size_nb_sa + 2 , " %s%s " , " encryption_algorithm_ " , str_sa_num ) ;
2006-06-14 08:04:43 +00:00
str_encryption_algorithm_comment = ( char * ) g_malloc ( 22 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_encryption_algorithm_comment , 22 + g_max_esp_size_nb_sa + 2 , " %s%s " , " Encryption Algorithm # " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
prefs_register_enum_preference ( esp_module , str_encryption_algorithm ,
str_encryption_algorithm_comment ,
2006-03-27 16:25:35 +00:00
" According to RFC 4305 Encryption Algorithms Requirements are the following : NULL (MUST), TripleDES-CBC [RFC2451] (MUST-), AES-CBC [RFC3602] (SHOULD+), AES-CTR [RFC3686] (SHOULD), DES-CBC [RFC2405] (SHOULD NOT). It will also decrypt BLOWFISH-CBC [RFC2451] and TWOFISH-CBC " ,
& g_esp_sad . table [ i ] . encryption_algo , esp_encryption_algo , FALSE ) ;
2006-08-09 02:00:05 +00:00
2006-06-14 08:04:43 +00:00
str_authentication_algorithm = ( char * ) g_malloc ( 25 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_authentication_algorithm , 25 + g_max_esp_size_nb_sa + 2 , " %s%s " , " authentication_algorithm_ " , str_sa_num ) ;
2006-06-14 08:04:43 +00:00
str_authentication_algorithm_comment = ( char * ) g_malloc ( 26 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_authentication_algorithm_comment , 26 + g_max_esp_size_nb_sa + 2 , " %s%s " , " Authentication Algorithm # " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
prefs_register_enum_preference ( esp_module , str_authentication_algorithm ,
str_authentication_algorithm_comment ,
2006-04-13 22:26:13 +00:00
" According to RFC 4305 Authentication Algorithms Requirements are the following : HMAC-SHA1-96 [RFC2404] (MUST), NULL (MUST), AES-XCBC-MAC-96 [RFC3566] (SHOULD+/Not Available), HMAC-MD5-96 [RFC2403] (MAY). It will also Check authentication for HMAC-SHA256 " ,
2006-03-27 16:25:35 +00:00
& g_esp_sad . table [ i ] . authentication_algo , esp_authentication_algo , FALSE ) ;
2006-08-09 02:00:05 +00:00
2006-06-14 08:04:43 +00:00
str_encryption_key = ( char * ) g_malloc ( 15 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_encryption_key , 15 + g_max_esp_size_nb_sa + 2 , " %s%s " , " encryption_key_ " , str_sa_num ) ;
2006-06-14 08:04:43 +00:00
str_encryption_key_comment = ( char * ) g_malloc ( 16 + g_max_esp_size_nb_sa + 2 ) ;
2006-03-27 16:25:35 +00:00
g_snprintf ( str_encryption_key_comment , 16 + g_max_esp_size_nb_sa + 2 , " %s%s " , " Encryption Key # " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
prefs_register_string_preference ( esp_module , str_encryption_key ,
str_encryption_key_comment ,
2006-09-08 07:32:13 +00:00
" The key sizes supported are the following : [TripleDES-CBC] : 192 bits. [AES-CBC] : 128/192/256 bits. [AES-CTR] : 160/224/288 bits. The remaining 32 bits will be used as nonce. [DES-CBC] : 64 bits. [BLOWFISH-CBC] : 128 bits. [TWOFISH-CBC] : 128/256 bits. "
" Keys may be written in Ascii or in Hexadecimal beginning with 0x. " ,
2006-03-27 16:25:35 +00:00
& g_esp_sad . table [ i ] . encryption_key ) ;
2006-06-14 08:04:43 +00:00
str_authentication_key = ( char * ) g_malloc ( 19 + g_max_esp_size_nb_sa + 2 ) ;
2006-04-13 22:26:13 +00:00
g_snprintf ( str_authentication_key , 19 + g_max_esp_size_nb_sa + 2 , " %s%s " , " authentication_key_ " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
2006-06-14 08:04:43 +00:00
str_authentication_key_comment = ( char * ) g_malloc ( 20 + g_max_esp_size_nb_sa + 2 ) ;
2006-04-13 22:26:13 +00:00
g_snprintf ( str_authentication_key_comment , 21 + g_max_esp_size_nb_sa + 2 , " %s%s " , " Authentication Key # " , str_sa_num ) ;
2006-08-09 02:00:05 +00:00
2006-04-13 22:26:13 +00:00
prefs_register_string_preference ( esp_module , str_authentication_key ,
str_authentication_key_comment ,
" The key sizes supported are the following : [HMAC-SHA1-96] : Any. [HMAC-SHA256] : Any. [HMAC-MD5] : Any. "
2006-09-08 07:32:13 +00:00
" Keys may be written in Ascii or in Hexadecimal beginning with 0x. "
2006-04-13 22:26:13 +00:00
,
& g_esp_sad . table [ i ] . authentication_key ) ;
2006-08-09 02:00:05 +00:00
2006-03-27 16:25:35 +00:00
}
g_free ( str_sa_num ) ;
# endif
2004-11-12 10:03:53 +00:00
2001-08-29 08:12:32 +00:00
register_dissector ( " esp " , dissect_esp , proto_esp ) ;
2001-08-30 02:23:17 +00:00
register_dissector ( " ah " , dissect_ah , proto_ah ) ;
2006-03-27 16:25:35 +00:00
1999-07-29 05:47:07 +00:00
}
2000-04-16 22:46:25 +00:00
void
proto_reg_handoff_ipsec ( void )
{
2001-12-03 04:00:26 +00:00
dissector_handle_t esp_handle , ah_handle , ipcomp_handle ;
2006-08-09 02:00:05 +00:00
2001-11-26 04:52:51 +00:00
data_handle = find_dissector ( " data " ) ;
2001-12-03 04:00:26 +00:00
ah_handle = find_dissector ( " ah " ) ;
dissector_add ( " ip.proto " , IP_PROTO_AH , ah_handle ) ;
esp_handle = find_dissector ( " esp " ) ;
dissector_add ( " ip.proto " , IP_PROTO_ESP , esp_handle ) ;
ipcomp_handle = create_dissector_handle ( dissect_ipcomp , proto_ipcomp ) ;
dissector_add ( " ip.proto " , IP_PROTO_IPCOMP , ipcomp_handle ) ;
2006-08-09 02:00:05 +00:00
2003-04-29 17:24:35 +00:00
ip_dissector_table = find_dissector_table ( " ip.proto " ) ;
2000-04-16 22:46:25 +00:00
}
2006-03-27 16:25:35 +00:00