This commit is contained in:
Martin Willi committed 2006-04-28 10:51:19 +00:00
1 parent 51c3484a9f
commit 1029d84d23
514 files changed
+2 -2

No files matched your search

+37
View File
@@ -0,0 +1,37 @@
# Makefile for the KLIPS interface utilities
# Copyright (C) 1998, 1999 Henry Spencer.
# Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: Makefile,v 1.8 2006/04/17 11:04:45 as Exp $
FREESWANSRCDIR=..
include ${FREESWANSRCDIR}/Makefile.inc
SUBDIRS=pluto _copyright _updown _updown_espmark ipsec starter openac scepclient
ifeq ($(USE_IKEV2),true)
SUBDIRS+=charon
endif
def:
@echo "Please read doc/intro.html or INSTALL before running make"
@false
# programs
cleanall distclean mostlyclean realclean install programs checkprograms check clean spotless install_file_list:
@for d in $(SUBDIRS) ; \
do \
(cd $$d && $(MAKE) FREESWANSRCDIR=$(FREESWANSRCDIR)/.. $@ ) || exit 1;\
done; \
+150
View File
@@ -0,0 +1,150 @@
include ${FREESWANSRCDIR}/Makefile.ver
CFLAGS+=$(USERCOMPILE) -I${KLIPSINC}
CFLAGS+= -Wall
#CFLAGS+= -Wconversion
#CFLAGS+= -Wmissing-prototypes
CFLAGS+= -Wpointer-arith
CFLAGS+= -Wcast-qual
#CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wstrict-prototypes
#CFLAGS+= -pedantic
#CFLAGS+= -W
#CFLAGS+= -Wwrite-strings
CFLAGS+= -Wbad-function-cast
# die if there are any warnings
ifndef WERROR
WERROR:= -Werror
endif
#CFLAGS+= ${WERROR}
ifneq ($(LD_LIBRARY_PATH),)
LDFLAGS=-L$(LD_LIBRARY_PATH)
endif
MANDIR8=$(MANTREE)/man8
MANDIR5=$(MANTREE)/man5
ifndef PROGRAMDIR
PROGRAMDIR=${LIBEXECDIR}
endif
ifndef MANPROGPREFIX
MANPROGPREFIX=ipsec_
endif
ifndef CONFDSUBDIR
CONFDSUBDIR=.
endif
all: $(PROGRAM)
programs: all
ifneq ($(PROGRAM),check)
check: $(PROGRAM)
endif
ifneq ($(NOINSTALL),true)
install:: $(PROGRAM) $(CONFFILES) $(EXTRA8MAN) $(EXTRA5MAN) $(EXTRA5PROC) $(LIBFILES) $(CONFDFILES)
@mkdir -p $(PROGRAMDIR) $(MANDIR8) $(MANDIR5) $(LIBDIR) $(CONFDIR) $(CONFDDIR) $(CONFDDIR)/$(CONFDSUBDIR) $(EXAMPLECONFDIR)
@if [ -n "$(PROGRAM)" ]; then $(INSTALL) $(INSTBINFLAGS) $(PROGRAM) $(PROGRAMDIR); fi
@$(foreach f, $(addsuffix .8, $(PROGRAM)), \
$(INSTALL) $(INSTMANFLAGS) $f $(MANDIR8)/$(MANPROGPREFIX)$f || exit 1; \
)
@$(foreach f, $(EXTRA8MAN), \
$(INSTALL) $(INSTMANFLAGS) $f $(MANDIR8)/ipsec_$f || exit 1; \
)
@$(foreach f, $(EXTRA5MAN), \
$(INSTALL) $(INSTMANFLAGS) $f $(MANDIR5)/$f || exit 1 ;\
)
@$(foreach f, $(EXTRA5PROC), \
$(INSTALL) $(INSTMANFLAGS) $f $(MANDIR5)/ipsec_$f || exit 1 ;\
)
@$(foreach f, $(LIBFILES), \
$(INSTALL) $(INSTCONFFLAGS) $f $(LIBDIR)/$f || exit 1 ;\
)
@$(foreach f, $(CONFFILES), \
if [ ! -f $(CONFDIR)/$f ]; then $(INSTALL) $(INSTCONFFLAGS) $f $(CONFDIR)/$f || exit 1; fi;\
$(INSTALL) $(INSTCONFFLAGS) $f $(EXAMPLECONFDIR)/$f-sample || exit 1; \
)
@$(foreach f, $(CONFDFILES), \
if [ ! -f $(CONFDDIR)/$(CONFDSUBDIR)/$f ]; then $(INSTALL) $(INSTCONFFLAGS) $f $(CONFDDIR)/$(CONFDSUBDIR)/$f || exit 1; fi;\
)
install_file_list::
@if [ -n "$(PROGRAM)" ]; then echo $(PROGRAMDIR)/$(PROGRAM); fi
@$(foreach f, $(addsuffix .8, $(PROGRAM)), \
echo $(MANDIR8)/${MANPROGPREFIX}$f; \
)
@$(foreach f, $(EXTRA8MAN), \
echo $(MANDIR8)/ipsec_$f; \
)
@$(foreach f, $(EXTRA5MAN), \
echo $(MANDIR5)/$f;\
)
@$(foreach f, $(EXTRA5PROC), \
echo $(MANDIR5)/ipsec_$f; \
)
@$(foreach f, $(LIBFILES), \
echo $(LIBDIR)/$f;\
)
@$(foreach f, $(CONFFILES), \
echo $(CONFDIR)/$f;\
echo $(EXAMPLECONFDIR)/$f-sample;\
)
@$(foreach f, $(CONFDFILES), \
echo $(CONFDDIR)/${CONFDSUBDIR}/$f;\
)
endif
# cancel the rule that compiles directly
%: %.c
%: %.o $(OBJS)
$(CC) $(CFLAGS) -o $@ $@.o ${OBJS} $(LDFLAGS) $(LIBS)
%: %.in ${FREESWANSRCDIR}/Makefile.inc ${FREESWANSRCDIR}/Makefile.ver
cat $< | sed -e "s/xxx/$(IPSECVERSION)/" \
-e "s:@IPSEC_DIR@:$(FINALBINDIR):" \
-e "s:@IPSEC_EXECDIR@:$(FINALLIBEXECDIR):" \
-e "s:@IPSEC_SBINDIR@:$(FINALSBINDIR):" \
-e "s:@IPSEC_LIBDIR@:$(FINALLIBDIR):" \
-e "s:@FINALCONFDIR@:$(FINALCONFDIR):" \
-e "s:@EXAMPLECONFDIR@:$(EXAMPLECONFDIR):" \
-e "s:@FINALDOCDIR@:$(FINALDOCDIR):" \
-e "s:@FINALEXAMPLECONFDIR@:$(FINALEXAMPLECONFDIR):" \
-e "s:@MODULE_GOO_LIST@:$(MODULE_GOO_LIST):" \
-e "s:@IPSEC_CONFS@:$(FINALCONFDIR):" \
-e "s:@IPSEC_CONFDDIR@:$(FINALCONFDDIR):" \
-e "s:@USE_IPROUTE2@:$(USE_IPROUTE2):" \
-e "s:@IPSEC_FIREWALLTYPE@:$(IPSEC_FIREWALLTYPE):" \
| cat >$@
if [ -x $< ]; then chmod +x $@; fi
if [ "${PROGRAM}.in" = $< ]; then chmod +x $@; fi
cleanall: clean
distclean: clean
mostlyclean: clean
realclean: clean
clean::
ifneq ($(strip $(PROGRAM)),)
@if [ -r $(PROGRAM).in ]; then rm -f $(PROGRAM); fi
@if [ -r $(PROGRAM).c ]; then rm -f $(PROGRAM); fi
@if [ -n "$(OBJS)" ]; then rm -f $(PROGRAM); fi
endif
@rm -f *.o
checkprograms:
+1
View File
@@ -0,0 +1 @@
_copyright
+44
View File
@@ -0,0 +1,44 @@
# Makefile for miscelaneous programs
# Copyright (C) 2002 Michael Richardson <mcr@freeswan.org>
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: Makefile,v 1.1 2004/03/15 20:35:27 as Exp $
FREESWANSRCDIR=../..
include ${FREESWANSRCDIR}/Makefile.inc
PROGRAM=_copyright
PROGRAMDIR=${LIBDIR}
LIBS=${FREESWANLIB}
include ../Makefile.program
#
# $Log: Makefile,v $
# Revision 1.1 2004/03/15 20:35:27 as
# added files from freeswan-2.04-x509-1.5.3
#
# Revision 1.3 2002/08/02 16:01:07 mcr
# moved user visible programs to $PREFIX/libexec, while moving
# private files to $PREFIX/lib.
#
# Revision 1.2 2002/06/02 22:02:14 mcr
# changed TOPDIR->FREESWANSRCDIR in all Makefiles.
# (note that linux/net/ipsec/Makefile uses TOPDIR because this is the
# kernel sense.)
#
# Revision 1.1 2002/04/24 07:55:32 mcr
# #include patches and Makefiles for post-reorg compilation.
#
#
#
+32
View File
@@ -0,0 +1,32 @@
.TH _COPYRIGHT 8 "25 Apr 2002"
.\"
.\" RCSID $Id: _copyright.8,v 1.1 2004/03/15 20:35:27 as Exp $
.\"
.SH NAME
ipsec _copyright \- prints FreeSWAN copyright
.SH DESCRIPTION
.I _copyright
outputs the FreeSWAN copyright, and version numbers for "ipsec --copyright"
.SH "SEE ALSO"
ipsec(8)
.SH HISTORY
Man page written for the Linux FreeS/WAN project
<http://www.freeswan.org/>
by Michael Richardson. Program written by Henry Spencer.
.\"
.\" $Log: _copyright.8,v $
.\" Revision 1.1 2004/03/15 20:35:27 as
.\" added files from freeswan-2.04-x509-1.5.3
.\"
.\" Revision 1.2 2002/04/29 22:39:31 mcr
.\" added basic man page for all internal commands.
.\"
.\" Revision 1.1 2002/04/26 01:21:43 mcr
.\" while tracking down a missing (not installed) /etc/ipsec.conf,
.\" MCR has decided that it is not okay for each program subdir to have
.\" some subset (determined with -f) of possible files.
.\" Each subdir that defines $PROGRAM, MUST have a PROGRAM.8 file as well as a PROGRAM file.
.\" Optional PROGRAM.5 files have been added to the makefiles.
.\"
.\"
.\"
+69
View File
@@ -0,0 +1,69 @@
/*
* copyright reporter
* (just avoids having the info in more than one place in the source)
* Copyright (C) 2001 Henry Spencer.
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*
* RCSID $Id: _copyright.c,v 1.1 2004/03/15 20:35:27 as Exp $
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <freeswan.h>
char usage[] = "Usage: ipsec _copyright";
struct option opts[] = {
{"help", 0, NULL, 'h',},
{"version", 0, NULL, 'v',},
{0, 0, NULL, 0, },
};
char me[] = "ipsec _copyright"; /* for messages */
int
main(int argc, char *argv[])
{
int opt;
extern int optind;
int errflg = 0;
const char *version = ipsec_version_code();
const char **notice = ipsec_copyright_notice();
const char **co;
while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
switch (opt) {
case 'h': /* help */
printf("%s\n", usage);
exit(0);
break;
case 'v': /* version */
printf("%s %s\n", me, version);
exit(0);
break;
case '?':
default:
errflg = 1;
break;
}
if (errflg || optind != argc) {
fprintf(stderr, "%s\n", usage);
exit(2);
}
for (co = notice; *co != NULL; co++)
printf("%s\n", *co);
exit(0);
}
+2
View File
@@ -0,0 +1,2 @@
_updown
_updown.in
+22
View File
@@ -0,0 +1,22 @@
# Makefile for miscelaneous programs
# Copyright (C) 2002 Michael Richardson <mcr@freeswan.org>
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: Makefile,v 1.3 2006/04/17 06:48:49 as Exp $
FREESWANSRCDIR=../..
include ${FREESWANSRCDIR}/Makefile.inc
PROGRAM=_updown
PROGRAMDIR=${LIBDIR}
include ../Makefile.program
+19
View File
@@ -0,0 +1,19 @@
.TH _UPDOWN 8 "27 Apr 2006"
.\"
.\" RCSID $Id: _updown.8,v 1.2 2006/04/17 06:48:49 as Exp $
.\"
.SH NAME
ipsec _updown \- route and firewall manipulation script
.SH SYNOPSIS
.I _updown
is invoked by pluto when it has brought up a new connection. This script
is used to insert the appropriate routing entries for IPsec operation.
It can also be used to insert and delete dynamic iptables firewall rules.
The interface to the script is documented in the pluto man page.
.SH "SEE ALSO"
ipsec(8), ipsec_pluto(8).
.SH HISTORY
Man page written for the Linux FreeS/WAN project <http://www.freeswan.org/>
by Michael Richardson. Original program written by Henry Spencer. Extended
for the Linux strongSwan project <http://www.strongswan.org/> by Andreas
Steffen.
+503
View File
@@ -0,0 +1,503 @@
#! /bin/sh
# iproute2 version, default updown script
#
# Copyright (C) 2003-2004 Nigel Meteringham
# Copyright (C) 2003-2004 Tuomo Soini
# Copyright (C) 2002-2004 Michael Richardson
# Copyright (C) 2005-2006 Andreas Steffen <andreas.steffen@strongswan.org>
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: _updown.in,v 1.2 2006/04/17 15:06:29 as Exp $
# CAUTION: Installing a new version of strongSwan will install a new
# copy of this script, wiping out any custom changes you make. If
# you need changes, make a copy of this under another name, and customize
# that, and use the (left/right)updown parameters in ipsec.conf to make
# strongSwan use yours instead of this default one.
# things that this script gets (from ipsec_pluto(8) man page)
#
# PLUTO_VERSION
# indicates what version of this interface is being
# used. This document describes version 1.1. This
# is upwardly compatible with version 1.0.
#
# PLUTO_VERB
# specifies the name of the operation to be performed
# (prepare-host, prepare-client, up-host, up-client,
# down-host, or down-client). If the address family
# for security gateway to security gateway communica­
# tions is IPv6, then a suffix of -v6 is added to the
# verb.
#
# PLUTO_CONNECTION
# is the name of the connection for which we are
# routing.
#
# PLUTO_NEXT_HOP
# is the next hop to which packets bound for the peer
# must be sent.
#
# PLUTO_INTERFACE
# is the name of the ipsec interface to be used.
#
# PLUTO_REQID
# is the requid of the ESP policy
#
# PLUTO_ME
# is the IP address of our host.
#
# PLUTO_MY_ID
# is the ID of our host.
#
# PLUTO_MY_CLIENT
# is the IP address / count of our client subnet. If
# the client is just the host, this will be the
# host's own IP address / max (where max is 32 for
# IPv4 and 128 for IPv6).
#
# PLUTO_MY_CLIENT_NET
# is the IP address of our client net. If the client
# is just the host, this will be the host's own IP
# address.
#
# PLUTO_MY_CLIENT_MASK
# is the mask for our client net. If the client is
# just the host, this will be 255.255.255.255.
#
# PLUTO_MY_SOURCEIP
# if non-empty, then the source address for the route will be
# set to this IP address.
#
# PLUTO_MY_PROTOCOL
# is the IP protocol that will be transported.
#
# PLUTO_MY_PORT
# is the UDP/TCP port to which the IPsec SA is
# restricted on our side.
#
# PLUTO_PEER
# is the IP address of our peer.
#
# PLUTO_PEER_ID
# is the ID of our peer.
#
# PLUTO_PEER_CA
# is the CA which issued the cert of our peer.
#
# PLUTO_PEER_CLIENT
# is the IP address / count of the peer's client sub­
# net. If the client is just the peer, this will be
# the peer's own IP address / max (where max is 32
# for IPv4 and 128 for IPv6).
#
# PLUTO_PEER_CLIENT_NET
# is the IP address of the peer's client net. If the
# client is just the peer, this will be the peer's
# own IP address.
#
# PLUTO_PEER_CLIENT_MASK
# is the mask for the peer's client net. If the
# client is just the peer, this will be
# 255.255.255.255.
#
# PLUTO_PEER_PROTOCOL
# is the IP protocol that will be transported.
#
# PLUTO_PEER_PORT
# is the UDP/TCP port to which the IPsec SA is
# restricted on the peer side.
#
# uncomment to log VPN connections
VPN_LOGGING=1
#
# tag put in front of each log entry:
TAG=vpn
#
# syslog facility and priority used:
FAC_PRIO=local0.notice
#
# to create a special vpn logging file, put the following line into
# the syslog configuration file /etc/syslog.conf:
#
# local0.notice -/var/log/vpn
#
# check interface version
case "$PLUTO_VERSION" in
1.[0|1]) # Older Pluto?!? Play it safe, script may be using new features.
echo "$0: obsolete interface version \`$PLUTO_VERSION'," >&2
echo "$0: called by obsolete Pluto?" >&2
exit 2
;;
1.*) ;;
*) echo "$0: unknown interface version \`$PLUTO_VERSION'" >&2
exit 2
;;
esac
# check parameter(s)
case "$1:$*" in
':') # no parameters
;;
iptables:iptables) # due to (left/right)firewall; for default script only
;;
custom:*) # custom parameters (see above CAUTION comment)
;;
*) echo "$0: unknown parameters \`$*'" >&2
exit 2
;;
esac
# utility functions for route manipulation
# Meddling with this stuff should not be necessary and requires great care.
uproute() {
doroute add
ip route flush cache
}
downroute() {
doroute delete
ip route flush cache
}
addsource() {
st=0
if ! ip -o route get ${PLUTO_MY_SOURCEIP%/*} | grep -q ^local
then
it="ip addr add ${PLUTO_MY_SOURCEIP%/*}/32 dev $PLUTO_INTERFACE"
oops="`eval $it 2>&1`"
st=$?
if test " $oops" = " " -a " $st" != " 0"
then
oops="silent error, exit status $st"
fi
if test " $oops" != " " -o " $st" != " 0"
then
echo "$0: addsource \`$it' failed ($oops)" >&2
fi
fi
return $st
}
doroute() {
st=0
parms="$PLUTO_PEER_CLIENT"
parms2=
if [ -n "$PLUTO_NEXT_HOP" ]
then
parms2="via $PLUTO_NEXT_HOP"
fi
parms2="$parms2 dev $PLUTO_INTERFACE"
if [ -z "$PLUTO_MY_SOURCEIP" ]
then
if [ -f /etc/sysconfig/defaultsource ]
then
. /etc/sysconfig/defaultsource
fi
if [ -f /etc/conf.d/defaultsource ]
then
. /etc/conf.d/defaultsource
fi
if [ -n "$DEFAULTSOURCE" ]
then
PLUTO_MY_SOURCEIP=$DEFAULTSOURCE
fi
fi
parms3=
if test "$1" = "add" -a -n "$PLUTO_MY_SOURCEIP"
then
addsource
parms3="$parms3 src ${PLUTO_MY_SOURCEIP%/*}"
fi
case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
"0.0.0.0/0.0.0.0")
# opportunistic encryption work around
# need to provide route that eclipses default, without
# replacing it.
it="ip route $1 0.0.0.0/1 $parms2 $parms3 &&
ip route $1 128.0.0.0/1 $parms2 $parms3"
;;
*) it="ip route $1 $parms $parms2 $parms3"
;;
esac
oops="`eval $it 2>&1`"
st=$?
if test " $oops" = " " -a " $st" != " 0"
then
oops="silent error, exit status $st"
fi
if test " $oops" != " " -o " $st" != " 0"
then
echo "$0: doroute \`$it' failed ($oops)" >&2
fi
return $st
}
# in the presence of KLIPS and ipsecN interfaces do not use IPSEC_POLICY
if [ `echo "$PLUTO_INTERFACE" | grep "ipsec"` ]
then
IPSEC_POLICY_IN=""
IPSEC_POLICY_OUT=""
else
IPSEC_POLICY="-m policy --pol ipsec --proto esp --reqid $PLUTO_REQID"
IPSEC_POLICY_IN="$IPSEC_POLICY --dir in"
IPSEC_POLICY_OUT="$IPSEC_POLICY --dir out"
fi
# are there port numbers?
if [ "$PLUTO_MY_PORT" != 0 ]
then
S_MY_PORT="--sport $PLUTO_MY_PORT"
D_MY_PORT="--dport $PLUTO_MY_PORT"
fi
if [ "$PLUTO_PEER_PORT" != 0 ]
then
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
fi
# the big choice
case "$PLUTO_VERB:$1" in
prepare-host:*|prepare-client:*)
# delete possibly-existing route (preliminary to adding a route)
case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
"0.0.0.0/0.0.0.0")
# need to provide route that eclipses default, without
# replacing it.
parms1="0.0.0.0/1"
parms2="128.0.0.0/1"
it="ip route delete $parms1 2>&1 ; ip route delete $parms2 2>&1"
oops="`ip route delete $parms1 2>&1 ; ip route delete $parms2 2>&1`"
;;
*)
parms="$PLUTO_PEER_CLIENT"
it="ip route delete $parms 2>&1"
oops="`ip route delete $parms 2>&1`"
;;
esac
status="$?"
if test " $oops" = " " -a " $status" != " 0"
then
oops="silent error, exit status $status"
fi
case "$oops" in
*'RTNETLINK answers: No such process'*)
# This is what route (currently -- not documented!) gives
# for "could not find such a route".
oops=
status=0
;;
esac
if test " $oops" != " " -o " $status" != " 0"
then
echo "$0: \`$it' failed ($oops)" >&2
fi
exit $status
;;
route-host:*|route-client:*)
# connection to me or my client subnet being routed
uproute
;;
unroute-host:*|unroute-client:*)
# connection to me or my client subnet being unrouted
downroute
;;
up-host:)
# connection to me coming up
# If you are doing a custom version, firewall commands go here.
;;
down-host:)
# connection to me going down
# If you are doing a custom version, firewall commands go here.
;;
up-client:)
# connection to my client subnet coming up
# If you are doing a custom version, firewall commands go here.
;;
down-client:)
# connection to my client subnet going down
# If you are doing a custom version, firewall commands go here.
;;
up-host:iptables)
# connection to me, with (left/right)firewall=yes, coming up
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
iptables -I INPUT 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_ME $D_MY_PORT $IPSEC_POLICY_IN -j ACCEPT
iptables -I OUTPUT 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_ME $S_MY_PORT $IPSEC_POLICY_OUT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
#
# log IPsec host connection setup
if [ $VPN_LOGGING ]
then
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
else
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
fi
fi
;;
down-host:iptables)
# connection to me, with (left/right)firewall=yes, going down
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
iptables -D INPUT -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_ME $D_MY_PORT $IPSEC_POLICY_IN -j ACCEPT
iptables -D OUTPUT -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_ME $S_MY_PORT $IPSEC_POLICY_OUT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
#
# log IPsec host connection teardown
if [ $VPN_LOGGING ]
then
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
else
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
fi
fi
;;
up-client:iptables)
# connection to client subnet, with (left/right)firewall=yes, coming up
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
if [ "$PLUTO_PEER_CLIENT" != "$PLUTO_MY_SOURCEIP/32" ]
then
iptables -I FORWARD 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT \
$IPSEC_POLICY_OUT -j ACCEPT
iptables -I FORWARD 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$IPSEC_POLICY_IN -j ACCEPT
fi
#
# a virtual IP requires an INPUT and OUTPUT rule on the host
# or sometimes host access via the internal IP is needed
if [ -n "$PLUTO_MY_SOURCEIP" -o -n "$PLUTO_HOST_ACCESS" ]
then
iptables -I INPUT 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$IPSEC_POLICY_IN -j ACCEPT
iptables -I OUTPUT 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT \
$IPSEC_POLICY_OUT -j ACCEPT
fi
#
# log IPsec client connection setup
if [ $VPN_LOGGING ]
then
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
else
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
fi
fi
;;
down-client:iptables)
# connection to client subnet, with (left/right)firewall=yes, going down
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
if [ "$PLUTO_PEER_CLIENT" != "$PLUTO_MY_SOURCEIP/32" ]
then
iptables -D FORWARD -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT \
$IPSEC_POLICY_OUT -j ACCEPT
iptables -D FORWARD -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$IPSEC_POLICY_IN -j ACCEPT
fi
#
# a virtual IP requires an INPUT and OUTPUT rule on the host
# or sometimes host access via the internal IP is needed
if [ -n "$PLUTO_MY_SOURCEIP" -o -n "$PLUTO_HOST_ACCESS" ]
then
iptables -D INPUT -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$IPSEC_POLICY_IN -j ACCEPT
iptables -D OUTPUT -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT \
$IPSEC_POLICY_OUT -j ACCEPT
fi
#
# log IPsec client connection teardown
if [ $VPN_LOGGING ]
then
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
else
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
fi
fi
;;
#
# IPv6
#
prepare-host-v6:*|prepare-client-v6:*)
;;
route-host-v6:*|route-client-v6:*)
# connection to me or my client subnet being routed
#uproute_v6
;;
unroute-host-v6:*|unroute-client-v6:*)
# connection to me or my client subnet being unrouted
#downroute_v6
;;
up-host-v6:*)
# connection to me coming up
# If you are doing a custom version, firewall commands go here.
;;
down-host-v6:*)
# connection to me going down
# If you are doing a custom version, firewall commands go here.
;;
up-client-v6:)
# connection to my client subnet coming up
# If you are doing a custom version, firewall commands go here.
;;
down-client-v6:)
# connection to my client subnet going down
# If you are doing a custom version, firewall commands go here.
;;
*) echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2
exit 1
;;
esac
+22
View File
@@ -0,0 +1,22 @@
# Makefile for miscelaneous programs
# Copyright (C) 2002 Michael Richardson <mcr@freeswan.org>
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: Makefile,v 1.1 2005/04/07 21:34:19 as Exp $
FREESWANSRCDIR=../..
include ${FREESWANSRCDIR}/Makefile.inc
PROGRAM=_updown_espmark
PROGRAMDIR=${LIBDIR}
include ../Makefile.program
+18
View File
@@ -0,0 +1,18 @@
.TH _UPDOWN_ESPMARK 8 "7 Apr 2005"
.\"
.\" RCSID $Id: _updown_espmark.8,v 1.1 2005/04/07 21:34:19 as Exp $
.\"
.SH NAME
ipsec _updown_espmark \- manages routes and firewall rules
.SH SYNOPSIS
.I _updown_espmark
is invoked by pluto when it has brought up a new connection. This script
is used to insert the appropriate routing and iptables firewall entries for
IPsec operation. The incoming ESP traffic must be marked by a static rule
in the mangle table. The default value for the mark is 50.
The interface to the script is documented in the pluto man page.
.SH "SEE ALSO"
ipsec(8), ipsec_pluto(8).
.SH HISTORY
Man page written for the Linux strongSwan project <http://www.strongswan.org/>
by Andreas Steffen. Original program written by Henry Spencer.
+452
View File
@@ -0,0 +1,452 @@
#! /bin/sh
# iproute2 version, default updown script
#
# Copyright (C) 2003-2004 Nigel Meteringham
# Copyright (C) 2003-2004 Tuomo Soini
# Copyright (C) 2002-2004 Michael Richardson
# Copyright (C) 2005 Andreas Steffen <andreas.steffen@strongsec.com>
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
# RCSID $Id: _updown_espmark.in,v 1.4 2005/09/14 14:33:05 as Exp $
# CAUTION: Installing a new version of strongSwan will install a new
# copy of this script, wiping out any custom changes you make. If
# you need changes, make a copy of this under another name, and customize
# that, and use the (left/right)updown parameters in ipsec.conf to make
# FreeS/WAN use yours instead of this default one.
# things that this script gets (from ipsec_pluto(8) man page)
#
#
# PLUTO_VERSION
# indicates what version of this interface is being
# used. This document describes version 1.1. This
# is upwardly compatible with version 1.0.
#
# PLUTO_VERB
# specifies the name of the operation to be performed
# (prepare-host, prepare-client, up-host, up-client,
# down-host, or down-client). If the address family
# for security gateway to security gateway communica­
# tions is IPv6, then a suffix of -v6 is added to the
# verb.
#
# PLUTO_CONNECTION
# is the name of the connection for which we are
# routing.
#
# PLUTO_NEXT_HOP
# is the next hop to which packets bound for the peer
# must be sent.
#
# PLUTO_INTERFACE
# is the name of the ipsec interface to be used.
#
# PLUTO_ME
# is the IP address of our host.
#
# PLUTO_MY_ID
# is the ID of our host.
#
# PLUTO_MY_CLIENT
# is the IP address / count of our client subnet. If
# the client is just the host, this will be the
# host's own IP address / max (where max is 32 for
# IPv4 and 128 for IPv6).
#
# PLUTO_MY_CLIENT_NET
# is the IP address of our client net. If the client
# is just the host, this will be the host's own IP
# address.
#
# PLUTO_MY_CLIENT_MASK
# is the mask for our client net. If the client is
# just the host, this will be 255.255.255.255.
#
# PLUTO_MY_SOURCEIP
# if non-empty, then the source address for the route will be
# set to this IP address.
#
# PLUTO_MY_PROTOCOL
# is the IP protocol that will be transported.
#
# PLUTO_MY_PORT
# is the UDP/TCP port to which the IPsec SA is
# restricted on our side.
#
# PLUTO_PEER
# is the IP address of our peer.
#
# PLUTO_PEER_ID
# is the ID of our peer.
#
# PLUTO_PEER_CA
# is the CA which issued the cert of our peer.
#
# PLUTO_PEER_CLIENT
# is the IP address / count of the peer's client sub­
# net. If the client is just the peer, this will be
# the peer's own IP address / max (where max is 32
# for IPv4 and 128 for IPv6).
#
# PLUTO_PEER_CLIENT_NET
# is the IP address of the peer's client net. If the
# client is just the peer, this will be the peer's
# own IP address.
#
# PLUTO_PEER_CLIENT_MASK
# is the mask for the peer's client net. If the
# client is just the peer, this will be
# 255.255.255.255.
#
# PLUTO_PEER_PROTOCOL
# is the IP protocol that will be transported.
#
# PLUTO_PEER_PORT
# is the UDP/TCP port to which the IPsec SA is
# restricted on the peer side.
#
# logging of VPN connections
#
# tag put in front of each log entry:
TAG=vpn
#
# syslog facility and priority used:
FAC_PRIO=local0.notice
#
# to create a special vpn logging file, put the following line into
# the syslog configuration file /etc/syslog.conf:
#
# local0.notice -/var/log/vpn
#
# check interface version
case "$PLUTO_VERSION" in
1.[0]) # Older Pluto?!? Play it safe, script may be using new features.
echo "$0: obsolete interface version \`$PLUTO_VERSION'," >&2
echo "$0: called by obsolete Pluto?" >&2
exit 2
;;
1.*) ;;
*) echo "$0: unknown interface version \`$PLUTO_VERSION'" >&2
exit 2
;;
esac
# check parameter(s)
case "$1:$*" in
':') # no parameters
;;
ipfwadm:ipfwadm) # due to (left/right)firewall; for default script only
;;
custom:*) # custom parameters (see above CAUTION comment)
;;
*) echo "$0: unknown parameters \`$*'" >&2
exit 2
;;
esac
# utility functions for route manipulation
# Meddling with this stuff should not be necessary and requires great care.
uproute() {
doroute add
ip route flush cache
}
downroute() {
doroute delete
ip route flush cache
}
addsource() {
st=0
if ! ip -o route get ${PLUTO_MY_SOURCEIP%/*} | grep -q ^local
then
it="ip addr add ${PLUTO_MY_SOURCEIP%/*}/32 dev $PLUTO_INTERFACE"
oops="`eval $it 2>&1`"
st=$?
if test " $oops" = " " -a " $st" != " 0"
then
oops="silent error, exit status $st"
fi
if test " $oops" != " " -o " $st" != " 0"
then
echo "$0: addsource \`$it' failed ($oops)" >&2
fi
fi
return $st
}
doroute() {
st=0
parms="$PLUTO_PEER_CLIENT"
parms2=
if [ -n "$PLUTO_NEXT_HOP" ]
then
parms2="via $PLUTO_NEXT_HOP"
fi
parms2="$parms2 dev $PLUTO_INTERFACE"
if [ -z "$PLUTO_MY_SOURCEIP" ]
then
if [ -f /etc/sysconfig/defaultsource ]
then
. /etc/sysconfig/defaultsource
fi
if [ -f /etc/conf.d/defaultsource ]
then
. /etc/conf.d/defaultsource
fi
if [ -n "$DEFAULTSOURCE" ]
then
PLUTO_MY_SOURCEIP=$DEFAULTSOURCE
fi
fi
parms3=
if test "$1" = "add" -a -n "$PLUTO_MY_SOURCEIP"
then
addsource
parms3="$parms3 src ${PLUTO_MY_SOURCEIP%/*}"
fi
case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
"0.0.0.0/0.0.0.0")
# opportunistic encryption work around
# need to provide route that eclipses default, without
# replacing it.
it="ip route $1 0.0.0.0/1 $parms2 $parms3 &&
ip route $1 128.0.0.0/1 $parms2 $parms3"
;;
*) it="ip route $1 $parms $parms2 $parms3"
;;
esac
oops="`eval $it 2>&1`"
st=$?
if test " $oops" = " " -a " $st" != " 0"
then
oops="silent error, exit status $st"
fi
if test " $oops" != " " -o " $st" != " 0"
then
echo "$0: doroute \`$it' failed ($oops)" >&2
fi
return $st
}
# define ESP mark
ESP_MARK=50
# add the following static rule to the INPUT chain in the mangle table
# iptables -t mangle -A INPUT -p 50 -j MARK --set-mark 50
# NAT traversal via UDP encapsulation is supported with the rule
# iptables -t mangle -A INPUT -p udp --dport 4500 -j MARK --set-mark 50
# in the presence of KLIPS and ipsecN interfaces do not use ESP mark rules
if [ `echo "$PLUTO_INTERFACE" | grep "ipsec"` ]
then
CHECK_MARK=""
else
CHECK_MARK="-m mark --mark $ESP_MARK"
fi
# are there port numbers?
if [ "$PLUTO_MY_PORT" != 0 ]
then
S_MY_PORT="--sport $PLUTO_MY_PORT"
D_MY_PORT="--dport $PLUTO_MY_PORT"
fi
if [ "$PLUTO_PEER_PORT" != 0 ]
then
S_PEER_PORT="--sport $PLUTO_PEER_PORT"
D_PEER_PORT="--dport $PLUTO_PEER_PORT"
fi
# the big choice
case "$PLUTO_VERB:$1" in
prepare-host:*|prepare-client:*)
# delete possibly-existing route (preliminary to adding a route)
case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
"0.0.0.0/0.0.0.0")
# need to provide route that eclipses default, without
# replacing it.
parms1="0.0.0.0/1"
parms2="128.0.0.0/1"
it="ip route delete $parms1 2>&1 ; ip route delete $parms2 2>&1"
oops="`ip route delete $parms1 2>&1 ; ip route delete $parms2 2>&1`"
;;
*)
parms="$PLUTO_PEER_CLIENT"
it="ip route delete $parms 2>&1"
oops="`ip route delete $parms 2>&1`"
;;
esac
status="$?"
if test " $oops" = " " -a " $status" != " 0"
then
oops="silent error, exit status $status"
fi
case "$oops" in
*'RTNETLINK answers: No such process'*)
# This is what route (currently -- not documented!) gives
# for "could not find such a route".
oops=
status=0
;;
esac
if test " $oops" != " " -o " $status" != " 0"
then
echo "$0: \`$it' failed ($oops)" >&2
fi
exit $status
;;
route-host:*|route-client:*)
# connection to me or my client subnet being routed
uproute
;;
unroute-host:*|unroute-client:*)
# connection to me or my client subnet being unrouted
downroute
;;
up-host:*)
# connection to me coming up
# If you are doing a custom version, firewall commands go here.
iptables -I INPUT 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_ME $D_MY_PORT $CHECK_MARK -j ACCEPT
iptables -I OUTPUT 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_ME $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
#
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
else
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
fi
;;
down-host:*)
# connection to me going down
# If you are doing a custom version, firewall commands go here.
# connection to me going down
# If you are doing a custom version, firewall commands go here.
iptables -D INPUT -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_ME $D_MY_PORT $CHECK_MARK -j ACCEPT
iptables -D OUTPUT -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_ME $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
#
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME"
else
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME"
fi
;;
up-client:)
# connection to my client subnet coming up
# If you are doing a custom version, firewall commands go here.
iptables -I FORWARD 1 -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
iptables -I FORWARD 1 -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$CHECK_MARK -j ACCEPT
#
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
else
logger -t $TAG -p $FAC_PRIO \
"+ `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
fi
;;
down-client:)
# connection to my client subnet going down
# If you are doing a custom version, firewall commands go here.
iptables -D FORWARD -o $PLUTO_INTERFACE -p $PLUTO_PEER_PROTOCOL \
-s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $S_MY_PORT \
-d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $D_PEER_PORT -j ACCEPT
iptables -D FORWARD -i $PLUTO_INTERFACE -p $PLUTO_MY_PROTOCOL \
-s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK $S_PEER_PORT \
-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK $D_MY_PORT \
$CHECK_MARK -j ACCEPT
#
if [ "$PLUTO_PEER_CLIENT" == "$PLUTO_PEER/32" ]
then
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
else
logger -t $TAG -p $FAC_PRIO -- \
"- `echo -e $PLUTO_PEER_ID` $PLUTO_PEER_CLIENT == $PLUTO_PEER -- $PLUTO_ME == $PLUTO_MY_CLIENT"
fi
;;
up-client:ipfwadm)
# connection to client subnet, with (left/right)firewall=yes, coming up
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
ipfwadm -F -i accept -b -S $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
-D $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
;;
down-client:ipfwadm)
# connection to client subnet, with (left/right)firewall=yes, going down
# This is used only by the default updown script, not by your custom
# ones, so do not mess with it; see CAUTION comment up at top.
ipfwadm -F -d accept -b -S $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
-D $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
;;
#
# IPv6
#
prepare-host-v6:*|prepare-client-v6:*)
;;
route-host-v6:*|route-client-v6:*)
# connection to me or my client subnet being routed
#uproute_v6
;;
unroute-host-v6:*|unroute-client-v6:*)
# connection to me or my client subnet being unrouted
#downroute_v6
;;
up-host-v6:*)
# connection to me coming up
# If you are doing a custom version, firewall commands go here.
;;
down-host-v6:*)
# connection to me going down
# If you are doing a custom version, firewall commands go here.
;;
up-client-v6:)
# connection to my client subnet coming up
# If you are doing a custom version, firewall commands go here.
;;
down-client-v6:)
# connection to my client subnet going down
# If you are doing a custom version, firewall commands go here.
;;
*) echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2
exit 1
;;
esac
+220
View File
@@ -0,0 +1,220 @@
# Doxyfile 1.4.1-KDevelop
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = "charon"
PROJECT_NUMBER = 1.0
OUTPUT_DIRECTORY = doc/api
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 1
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST = YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ./
FILE_PATTERNS = *.h *.txt
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = .
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = YES
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = YES
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = LEAK_DETECTIVE
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
+99
View File
@@ -0,0 +1,99 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
FREESWANSRCDIR=../..
# include strongswan Makefile, if charon sits in its tree
ifeq ($(shell ls $(FREESWANSRCDIR)/Makefile.inc 2>&1), ../../Makefile.inc)
include ${FREESWANSRCDIR}/Makefile.inc
else
# Defaults if not using strongswan defines
USE_LEAK_DETECTIVE?=false
INSTALL=install
INSTBINFLAGS=-b --suffix=.old
LIBEXECDIR=/usr/local/libexec/ipsec
SHAREDLIBDIR=/usr/local/lib
endif
BUILD_DIR= ./bin/
BINNAMECHARON= $(BUILD_DIR)charon
BINNAMESTROKE= $(BUILD_DIR)stroke
BINNAMETEST= $(BUILD_DIR)run_tests
BINNAMELIB= $(BUILD_DIR)libstrongswan.so
MAIN_DIR= ./
CFLAGS= -Icharon -Ilib -Istroke -fPIC -Wall -g
ifeq ($(USE_LEAK_DETECTIVE),true)
CFLAGS+= -DLEAK_DETECTIVE
endif
# objects is extended by each included Makefile
CHARON_OBJS=
LIB_OBJS=
TEST_OBJS=
all : programs
include $(MAIN_DIR)charon/Makefile.charon
include $(MAIN_DIR)lib/Makefile.lib
include $(MAIN_DIR)stroke/Makefile.stroke
include $(MAIN_DIR)testing/Makefile.testcases
programs : $(BINNAMECHARON) $(BINNAMESTROKE)
test : $(BINNAMETEST)
LD_LIBRARY_PATH=$(BUILD_DIR) $(BINNAMETEST)
run : $(BINNAMECHARON)
LD_LIBRARY_PATH=$(BUILD_DIR) $(BINNAMECHARON)
apidoc :
doxygen Doxyfile
build_dir:
mkdir -p $(BUILD_DIR)
$(BINNAMELIB) : build_dir $(LIB_OBJS)
$(CC) -lpthread -ldl -lgmp -shared $(LIB_OBJS) -o $@
$(BINNAMECHARON) : build_dir $(CHARON_OBJS) $(BINNAMELIB) $(BUILD_DIR)daemon.o
$(CC) -L./bin -lstrongswan $(CHARON_OBJS) $(BUILD_DIR)daemon.o -o $@
$(BINNAMETEST) : build_dir $(CHARON_OBJS) $(TEST_OBJS) $(BINNAMELIB) $(BUILD_DIR)testcases.o
$(CC) -L./bin -lstrongswan $(LDFLAGS) $(CHARON_OBJS) $(TEST_OBJS) $(BUILD_DIR)testcases.o -o $@
$(BINNAMESTROKE) : build_dir $(BINNAMELIB) $(BUILD_DIR)stroke.o
$(CC) $(LDFLAGS) $(CFLAGS) $(BUILD_DIR)stroke.o -o $@
install : $(BINNAMECHARON) $(BINNAMESTROKE)
$(INSTALL) $(INSTBINFLAGS) $(BINNAMECHARON) $(BINNAMESTROKE) $(LIBEXECDIR)
$(INSTALL) $(INSTBINFLAGS) $(BINNAMELIB) $(SHAREDLIBDIR)
install_file_list:
@echo $(LIBEXECDIR)/charon
@echo $(LIBEXECDIR)/stroke
@echo $(SHAREDLIBDIR)/libstrongswan.so
clean :
rm -fR $(BUILD_DIR)
cleanall: clean
distclean: clean
mostlyclean: clean
realclean: clean
+105
View File
@@ -0,0 +1,105 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Martin Willi</author>
<email>martin@strongswan.org</email>
<version>$VERSION$</version>
<projectmanagement>KDevCustomProject</projectmanagement>
<primarylanguage>C</primarylanguage>
<ignoreparts/>
</general>
<kdevcustomproject>
<run>
<mainprogram>Source</mainprogram>
<directoryradio>executable</directoryradio>
</run>
<general>
<activedir/>
</general>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell/>
</general>
</kdevdebugger>
<kdevdoctreeview>
<ignoretocs>
<toc>ada</toc>
<toc>ada_bugs_gcc</toc>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>libstdc++</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>stl</toc>
<toc>sw</toc>
<toc>w3c-dom-level2-html</toc>
<toc>w3c-svg</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="c" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevcppsupport>
<references/>
<codecompletion>
<includeGlobalFunctions>true</includeGlobalFunctions>
<includeTypes>true</includeTypes>
<includeEnums>true</includeEnums>
<includeTypedefs>false</includeTypedefs>
<automaticCodeCompletion>true</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
</codecompletion>
</kdevcppsupport>
<kdevfileview>
<groups>
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
</kdevelop>
+25
View File
@@ -0,0 +1,25 @@
# Copyright (C) 2006 Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
CHARON_DIR= $(MAIN_DIR)charon/
$(BUILD_DIR)daemon.o : $(CHARON_DIR)daemon.c $(CHARON_DIR)daemon.h
$(CC) $(CFLAGS) -c -o $@ $<
include $(CHARON_DIR)network/Makefile.network
include $(CHARON_DIR)config/Makefile.config
include $(CHARON_DIR)encoding/Makefile.encoding
include $(CHARON_DIR)queues/Makefile.queues
include $(CHARON_DIR)sa/Makefile.sa
include $(CHARON_DIR)threads/Makefile.threads
+32
View File
@@ -0,0 +1,32 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
CONFIG_DIR= $(CHARON_DIR)config/
CHARON_OBJS+= $(BUILD_DIR)traffic_selector.o
$(BUILD_DIR)traffic_selector.o : $(CONFIG_DIR)traffic_selector.c $(CONFIG_DIR)traffic_selector.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)proposal.o
$(BUILD_DIR)proposal.o : $(CONFIG_DIR)proposal.c $(CONFIG_DIR)proposal.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)configuration.o
$(BUILD_DIR)configuration.o : $(CONFIG_DIR)configuration.c $(CONFIG_DIR)configuration.h
$(CC) $(CFLAGS) -c -o $@ $<
include $(CONFIG_DIR)connections/Makefile.connections
include $(CONFIG_DIR)credentials/Makefile.credentials
include $(CONFIG_DIR)policies/Makefile.policies
+112
View File
@@ -0,0 +1,112 @@
/**
* @file configuration.c
*
* @brief Implementation of configuration_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include "configuration.h"
#include <types.h>
/**
* First retransmit timeout in milliseconds.
* Timeout value is increasing in each retransmit round.
*/
#define RETRANSMIT_TIMEOUT 3000
/**
* Timeout in milliseconds after that a half open IKE_SA gets deleted.
*/
#define HALF_OPEN_IKE_SA_TIMEOUT 30000
/**
* Max retransmit count.
* 0 for infinite. The max time a half open IKE_SA is alive is set by
* RETRANSMIT_TIMEOUT.
*/
#define MAX_RETRANSMIT_COUNT 0
typedef struct private_configuration_t private_configuration_t;
/**
* Private data of an configuration_t object.
*/
struct private_configuration_t {
/**
* Public part of configuration_t object.
*/
configuration_t public;
};
/**
* Implementation of configuration_t.get_retransmit_timeout.
*/
static status_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
{
int new_timeout = RETRANSMIT_TIMEOUT, i;
if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0)
{
return FAILED;
}
for (i = 0; i < retransmit_count; i++)
{
new_timeout *= 2;
}
*timeout = new_timeout;
return SUCCESS;
}
/**
* Implementation of configuration_t.get_half_open_ike_sa_timeout.
*/
static u_int32_t get_half_open_ike_sa_timeout (private_configuration_t *this)
{
return HALF_OPEN_IKE_SA_TIMEOUT;
}
/**
* Implementation of configuration_t.destroy.
*/
static void destroy(private_configuration_t *this)
{
free(this);
}
/*
* Described in header-file
*/
configuration_t *configuration_create()
{
private_configuration_t *this = malloc_thing(private_configuration_t);
/* public functions */
this->public.destroy = (void(*)(configuration_t*))destroy;
this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout;
return (&this->public);
}
+89
View File
@@ -0,0 +1,89 @@
/**
* @file configuration.h
*
* @brief Interface configuration_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CONFIGURATION_H_
#define CONFIGURATION_H_
#include <types.h>
typedef struct configuration_t configuration_t;
/**
* @brief The interface for various daemon related configs.
*
* @b Constructors:
* - configuration_create()
*
* @ingroup config
*/
struct configuration_t {
/**
* @brief Returns the retransmit timeout.
*
* The timeout values are managed by the configuration, so
* another backoff algorithm may be implemented here.
*
* @param this calling object
* @param retransmit_count number of times a message was retransmitted so far
* @param[out] timeout the new retransmit timeout in milliseconds
*
* @return
* - FAILED, if the message should not be retransmitted
* - SUCCESS
*/
status_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout);
/**
* @brief Returns the timeout for an half open IKE_SA in ms.
*
* Half open means that the IKE_SA is still in one of the following states:
* - INITIATOR_INIT
* - RESPONDER_INIT
* - IKE_SA_INIT_REQUESTED
* - IKE_SA_INIT_RESPONDED
* - IKE_AUTH_REQUESTED
*
* @param this calling object
* @return timeout in milliseconds (ms)
*/
u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this);
/**
* @brief Destroys a configuration_t object.
*
* @param this calling object
*/
void (*destroy) (configuration_t *this);
};
/**
* @brief Creates a configuration backend.
*
* @return static_configuration_t object
*
* @ingroup config
*/
configuration_t *configuration_create();
#endif /*CONFIGURATION_H_*/
@@ -0,0 +1,24 @@
# Copyright (C) 2006 Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
CONNECTIONS_DIR= $(CONFIG_DIR)connections/
CHARON_OBJS+= $(BUILD_DIR)connection.o
$(BUILD_DIR)connection.o : $(CONNECTIONS_DIR)connection.c $(CONNECTIONS_DIR)connection.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)local_connection_store.o
$(BUILD_DIR)local_connection_store.o : $(CONNECTIONS_DIR)local_connection_store.c $(CONNECTIONS_DIR)local_connection_store.h
$(CC) $(CFLAGS) -c -o $@ $<
@@ -0,0 +1,367 @@
/**
* @file connection.c
*
* @brief Implementation of connection_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <string.h>
#include "connection.h"
#include <utils/linked_list.h>
#include <utils/logger.h>
/**
* String mappings for auth_method_t.
*/
mapping_t auth_method_m[] = {
{RSA_DIGITAL_SIGNATURE, "RSA"},
{SHARED_KEY_MESSAGE_INTEGRITY_CODE, "SHARED_KEY"},
{DSS_DIGITAL_SIGNATURE, "DSS"},
{MAPPING_END, NULL}
};
typedef struct private_connection_t private_connection_t;
/**
* Private data of an connection_t object
*/
struct private_connection_t {
/**
* Public part
*/
connection_t public;
/**
* Name of the connection
*/
char *name;
/**
* ID of us
*/
identification_t *my_id;
/**
* ID of remote peer
*/
identification_t *other_id;
/**
* Host information of my host.
*/
host_t *my_host;
/**
* Host information of other host.
*/
host_t *other_host;
/**
* Method to use for own authentication data
*/
auth_method_t auth_method;
/**
* Supported proposals
*/
linked_list_t *proposals;
};
/**
* Implementation of connection_t.get_name.
*/
static char *get_name (private_connection_t *this)
{
return this->name;
}
/**
* Implementation of connection_t.get_my_id.
*/
static identification_t *get_my_id (private_connection_t *this)
{
return this->my_id;
}
/**
* Implementation of connection_t.get_other_id.
*/
static identification_t *get_other_id(private_connection_t *this)
{
return this->other_id;
}
/**
* Implementation of connection_t.update_my_id
*/
static void update_my_id(private_connection_t *this, identification_t *my_id)
{
this->my_id->destroy(this->my_id);
this->my_id = my_id;
}
/**
* Implementation of connection_t.update_other_id
*/
static void update_other_id(private_connection_t *this, identification_t *other_id)
{
this->other_id->destroy(this->other_id);
this->other_id = other_id;
}
/**
* Implementation of connection_t.get_my_host.
*/
static host_t * get_my_host (private_connection_t *this)
{
return this->my_host;
}
/**
* Implementation of connection_t.update_my_host.
*/
static void update_my_host(private_connection_t *this, host_t *my_host)
{
this->my_host->destroy(this->my_host);
this->my_host = my_host;
}
/**
* Implementation of connection_t.update_other_host.
*/
static void update_other_host(private_connection_t *this, host_t *other_host)
{
this->other_host->destroy(this->other_host);
this->other_host = other_host;
}
/**
* Implementation of connection_t.get_other_host.
*/
static host_t * get_other_host (private_connection_t *this)
{
return this->other_host;
}
/**
* Implementation of connection_t.get_proposals.
*/
static linked_list_t* get_proposals (private_connection_t *this)
{
return this->proposals;
}
/**
* Implementation of connection_t.select_proposal.
*/
static proposal_t *select_proposal(private_connection_t *this, linked_list_t *proposals)
{
iterator_t *stored_iter, *supplied_iter;
proposal_t *stored, *supplied, *selected;
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
supplied_iter = proposals->create_iterator(proposals, TRUE);
/* compare all stored proposals with all supplied. Stored ones are preferred. */
while (stored_iter->has_next(stored_iter))
{
supplied_iter->reset(supplied_iter);
stored_iter->current(stored_iter, (void**)&stored);
while (supplied_iter->has_next(supplied_iter))
{
supplied_iter->current(supplied_iter, (void**)&supplied);
selected = stored->select(stored, supplied);
if (selected)
{
/* they match, return */
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return selected;
}
}
}
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return NULL;
}
/**
* Implementation of connection_t.add_proposal.
*/
static void add_proposal (private_connection_t *this, proposal_t *proposal)
{
this->proposals->insert_last(this->proposals, proposal);
}
/**
* Implementation of connection_t.auth_method_t.
*/
static auth_method_t get_auth_method(private_connection_t *this)
{
return this->auth_method;
}
/**
* Implementation of connection_t.get_dh_group.
*/
static diffie_hellman_group_t get_dh_group(private_connection_t *this)
{
iterator_t *iterator;
proposal_t *proposal;
algorithm_t *algo;
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&proposal);
proposal->get_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, &algo);
if (algo)
{
iterator->destroy(iterator);
return algo->algorithm;
}
}
iterator->destroy(iterator);
return MODP_UNDEFINED;
}
/**
* Implementation of connection_t.check_dh_group.
*/
static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh_group)
{
iterator_t *prop_iter, *alg_iter;
proposal_t *proposal;
algorithm_t *algo;
prop_iter = this->proposals->create_iterator(this->proposals, TRUE);
while (prop_iter->has_next(prop_iter))
{
prop_iter->current(prop_iter, (void**)&proposal);
alg_iter = proposal->create_algorithm_iterator(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP);
while (alg_iter->has_next(alg_iter))
{
alg_iter->current(alg_iter, (void**)&algo);
if (algo->algorithm == dh_group)
{
prop_iter->destroy(prop_iter);
alg_iter->destroy(alg_iter);
return TRUE;
}
}
}
prop_iter->destroy(prop_iter);
alg_iter->destroy(alg_iter);
return FALSE;
}
/**
* Implementation of connection_t.clone.
*/
static connection_t *clone(private_connection_t *this)
{
iterator_t *iterator;
proposal_t *proposal;
private_connection_t *clone = (private_connection_t*)connection_create(
this->name,
this->my_host->clone(this->my_host),
this->other_host->clone(this->other_host),
this->my_id->clone(this->my_id),
this->other_id->clone(this->other_id),
this->auth_method);
/* clone all proposals */
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&proposal);
proposal = proposal->clone(proposal);
clone->proposals->insert_last(clone->proposals, (void*)proposal);
}
iterator->destroy(iterator);
return &clone->public;
}
/**
* Implementation of connection_t.destroy.
*/
static void destroy (private_connection_t *this)
{
proposal_t *proposal;
while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
{
proposal->destroy(proposal);
}
this->proposals->destroy(this->proposals);
this->my_host->destroy(this->my_host);
this->other_host->destroy(this->other_host);
this->my_id->destroy(this->my_id);
this->other_id->destroy(this->other_id);
free(this->name);
free(this);
}
/**
* Described in header.
*/
connection_t * connection_create(char *name, host_t *my_host, host_t *other_host, identification_t *my_id, identification_t *other_id, auth_method_t auth_method)
{
private_connection_t *this = malloc_thing(private_connection_t);
/* public functions */
this->public.get_name = (char*(*)(connection_t*))get_name;
this->public.get_my_id = (identification_t*(*)(connection_t*))get_my_id;
this->public.get_other_id = (identification_t*(*)(connection_t*))get_other_id;
this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
this->public.update_my_id = (void(*)(connection_t*,identification_t*))update_my_id;
this->public.update_other_id = (void(*)(connection_t*,identification_t*))update_other_id;
this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
this->public.clone = (connection_t*(*)(connection_t*))clone;
this->public.destroy = (void(*)(connection_t*))destroy;
/* private variables */
this->name = strdup(name);
this->my_host = my_host;
this->other_host = other_host;
this->my_id = my_id;
this->other_id = other_id;
this->auth_method = auth_method;
this->proposals = linked_list_create();
return (&this->public);
}
@@ -0,0 +1,283 @@
/**
* @file connection.h
*
* @brief Interface of connection_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CONNECTION_H_
#define CONNECTION_H_
#include <types.h>
#include <utils/host.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <config/proposal.h>
#include <crypto/diffie_hellman.h>
typedef enum auth_method_t auth_method_t;
/**
* AUTH Method to use.
*
* @ingroup config
*/
enum auth_method_t {
/**
* Computed as specified in section 2.15 of RFC using
* an RSA private key over a PKCS#1 padded hash.
*/
RSA_DIGITAL_SIGNATURE = 1,
/**
* Computed as specified in section 2.15 of RFC using the
* shared key associated with the identity in the ID payload
* and the negotiated prf function
*/
SHARED_KEY_MESSAGE_INTEGRITY_CODE = 2,
/**
* Computed as specified in section 2.15 of RFC using a
* DSS private key over a SHA-1 hash.
*/
DSS_DIGITAL_SIGNATURE = 3,
};
/**
* string mappings for auth method.
*
* @ingroup config
*/
extern mapping_t auth_method_m[];
typedef struct connection_t connection_t;
/**
* @brief A connection_t defines the rules to set up an IKE_SA.
*
*
* @b Constructors:
* - connection_create()
*
* @ingroup config
*/
struct connection_t {
/**
* @brief Get my ID for this connection.
*
* Object is NOT getting cloned.
*
* @param this calling object
* @return host information as identification_t object
*/
identification_t *(*get_my_id) (connection_t *this);
/**
* @brief Get others ID for this connection.
*
* Object is NOT getting cloned.
*
* @param this calling object
* @return host information as identification_t object
*/
identification_t *(*get_other_id) (connection_t *this);
/**
* @brief Get my address as host_t object.
*
* Object is NOT getting cloned.
*
* @param this calling object
* @return host information as host_t object
*/
host_t *(*get_my_host) (connection_t *this);
/**
* @brief Get others address as host_t object.
*
* Object is NOT getting cloned.
*
* @param this calling object
* @return host information as host_t object
*/
host_t *(*get_other_host) (connection_t *this);
/**
* @brief Update address of my host.
*
* It may be necessary to uptdate own address, as it
* is set to the default route (0.0.0.0) in some cases.
* Old host is destroyed, new one NOT cloned.
*
* @param this calling object
* @param my_host new host to set as my_host
*/
void (*update_my_host) (connection_t *this, host_t *my_host);
/**
* @brief Update address of remote host.
*
* It may be necessary to uptdate remote address, as a
* connection may define %any (0.0.0.0) or a subnet.
* Old host is destroyed, new one NOT cloned.
*
* @param this calling object
* @param my_host new host to set as other_host
*/
void (*update_other_host) (connection_t *this, host_t *other_host);
/**
* @brief Update own ID.
*
* It may be necessary to uptdate own ID, as it
* is set to %any or to e.g. *@strongswan.org in
* some cases.
* Old ID is destroyed, new one NOT cloned.
*
* @param this calling object
* @param my_id new ID to set as my_id
*/
void (*update_my_id) (connection_t *this, identification_t *my_id);
/**
* @brief Update others ID.
*
* It may be necessary to uptdate others ID, as it
* is set to %any or to e.g. *@strongswan.org in
* some cases.
* Old ID is destroyed, new one NOT cloned.
*
* @param this calling object
* @param other_id new ID to set as other_id
*/
void (*update_other_id) (connection_t *this, identification_t *other_id);
/**
* @brief Returns a list of all supported proposals.
*
* Returned list is still owned by connection and MUST NOT
* modified or destroyed.
*
* @param this calling object
* @return list containing all the proposals
*/
linked_list_t *(*get_proposals) (connection_t *this);
/**
* @brief Adds a proposal to the list.
*
* The first added proposal has the highest priority, the last
* added the lowest.
*
* @param this calling object
* @param proposal proposal to add
*/
void (*add_proposal) (connection_t *this, proposal_t *proposal);
/**
* @brief Select a proposed from suggested proposals.
*
* Returned proposal must be destroyed after usage.
*
* @param this calling object
* @param proposals list of proposals to select from
* @return selected proposal, or NULL if none matches.
*/
proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals);
/**
* @brief Get the authentication method to use
*
* @param this calling object
* @return authentication method
*/
auth_method_t (*get_auth_method) (connection_t *this);
/**
* @brief Get the connection name.
*
* Name must not be freed, since it points to
* internal data.
*
* @param this calling object
* @return name of the connection
*/
char* (*get_name) (connection_t *this);
/**
* @brief Get the DH group to use for connection initialization.
*
* @param this calling object
* @return dh group to use for initialization
*/
diffie_hellman_group_t (*get_dh_group) (connection_t *this);
/**
* @brief Check if a suggested dh group is acceptable.
*
* If we guess a wrong DH group for IKE_SA_INIT, the other
* peer will send us a offer. But is this acceptable for us?
*
* @param this calling object
* @return TRUE if group acceptable
*/
bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group);
/**
* @brief Clone a connection_t object.
*
* @param this connection to clone
* @return clone of it
*/
connection_t *(*clone) (connection_t *this);
/**
* @brief Destroys a connection_t object.
*
* @param this calling object
*/
void (*destroy) (connection_t *this);
};
/**
* @brief Creates a connection_t object.
*
* Supplied hosts/IDs become owned by connection, so
* do not modify or destroy them after a call to
* connection_create(). Name gets cloned internally.
*
* @param name connection identifier
* @param my_host host_t representing local address
* @param other_host host_t representing remote address
* @param my_id identification_t for me
* @param other_id identification_t for other
* @param auth_method Authentication method to use for our(!) auth data
* @return connection_t object.
*
* @ingroup config
*/
connection_t * connection_create(char *name,
host_t *my_host, host_t *other_host,
identification_t *my_id,
identification_t *other_id,
auth_method_t auth_method);
#endif /* CONNECTION_H_ */
+112
View File
@@ -0,0 +1,112 @@
/**
* @file connection_store.h
*
* @brief Interface connection_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CONNECTION_STORE_H_
#define CONNECTION_STORE_H_
#include <types.h>
#include <config/connections/connection.h>
typedef struct connection_store_t connection_store_t;
/**
* @brief The interface for a store of connection_t's.
*
* @b Constructors:
* - stroke_create()
*
* @ingroup config
*/
struct connection_store_t {
/**
* @brief Returns a connection definition identified by two IDs.
*
* This call is useful to get a connection which is identified by IDs
* rather than addresses, e.g. for connection setup on user request.
* The returned connection gets created/cloned and therefore must
* be destroyed after usage.
*
* @param this calling object
* @param my_id own ID of connection
* @param other_id others ID of connection
* @return
* - connection_t, if found
* - NULL otherwise
*/
connection_t *(*get_connection_by_ids) (connection_store_t *this, identification_t *my_id, identification_t *other_id);
/**
* @brief Returns a connection definition identified by two hosts.
*
* This call is usefull to get a connection identified by addresses.
* It may be used after kernel request for traffic protection.
* The returned connection gets created/cloned and therefore must
* be destroyed after usage.
*
* @param this calling object
* @param my_id own address of connection
* @param other_id others address of connection
* @return
* - connection_t, if found
* - NULL otherwise
*/
connection_t *(*get_connection_by_hosts) (connection_store_t *this, host_t *my_host, host_t *other_host);
/**
* @brief Returns a connection identified by its name.
*
* This call is usefull to get a connection identified its
* name, as on an connection setup.
*
* @param this calling object
* @param name name of the connection to get
* @return
* - connection_t, if found
* - NULL otherwise
*/
connection_t *(*get_connection_by_name) (connection_store_t *this, char *name);
/**
* @brief Add a connection to the store.
*
* After a successful call, the connection is owned by the store and may
* not be manipulated nor destroyed.
*
* @param this calling object
* @param connection connection to add
* @return
* - SUCCESS, or
* - FAILED
*/
status_t (*add_connection) (connection_store_t *this, connection_t *connection);
/**
* @brief Destroys a connection_store_t object.
*
* @param this calling object
*/
void (*destroy) (connection_store_t *this);
};
#endif /* CONNECTION_STORE_H_ */
@@ -0,0 +1,228 @@
/**
* @file local_connection_store.c
*
* @brief Implementation of local_connection_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <string.h>
#include "local_connection_store.h"
#include <utils/linked_list.h>
#include <utils/logger_manager.h>
typedef struct private_local_connection_store_t private_local_connection_store_t;
/**
* Private data of an local_connection_store_t object
*/
struct private_local_connection_store_t {
/**
* Public part
*/
local_connection_store_t public;
/**
* stored connection
*/
linked_list_t *connections;
/**
* Assigned logger
*/
logger_t *logger;
};
/**
* Implementation of connection_store_t.get_connection_by_hosts.
*/
static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host)
{
iterator_t *iterator;
connection_t *current, *found = NULL;
this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s",
my_host->get_address(my_host), other_host->get_address(other_host));
iterator = this->connections->create_iterator(this->connections, TRUE);
while (iterator->has_next(iterator))
{
host_t *config_my_host, *config_other_host;
iterator->current(iterator, (void**)&current);
config_my_host = current->get_my_host(current);
config_other_host = current->get_other_host(current);
/* first check if ip is equal */
if(config_other_host->ip_equals(config_other_host, other_host))
{
this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s",
config_other_host->get_address(config_other_host));
/* could be right one, check my_host for default route*/
if (config_my_host->is_default_route(config_my_host))
{
found = current->clone(current);
break;
}
/* check now if host informations are the same */
else if (config_my_host->ip_equals(config_my_host,my_host))
{
found = current->clone(current);
break;
}
}
/* Then check for wildcard hosts!
* TODO
* actually its only checked if other host with default route can be found! */
else if (config_other_host->is_default_route(config_other_host))
{
/* could be right one, check my_host for default route*/
if (config_my_host->is_default_route(config_my_host))
{
found = current->clone(current);
break;
}
/* check now if host informations are the same */
else if (config_my_host->ip_equals(config_my_host,my_host))
{
found = current->clone(current);
break;
}
}
}
iterator->destroy(iterator);
/* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */
if (found)
{
found->update_my_host(found, my_host->clone(my_host));
found->update_other_host(found, other_host->clone(other_host));
}
return found;
}
/**
* Implementation of connection_store_t.get_connection_by_ids.
*/
static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id)
{
iterator_t *iterator;
connection_t *current, *found = NULL;
this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s",
my_id->get_string(my_id), other_id->get_string(other_id));
iterator = this->connections->create_iterator(this->connections, TRUE);
while (iterator->has_next(iterator))
{
identification_t *config_my_id, *config_other_id;
iterator->current(iterator, (void**)&current);
config_my_id = current->get_my_id(current);
config_other_id = current->get_other_id(current);
/* first check if ids are equal
* TODO: Add wildcard checks */
if (config_other_id->equals(config_other_id, other_id) &&
config_my_id->equals(config_my_id, my_id))
{
this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s",
config_other_id->get_string(config_other_id));
found = current->clone(current);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of connection_store_t.get_connection_by_name.
*/
static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name)
{
iterator_t *iterator;
connection_t *current, *found = NULL;
iterator = this->connections->create_iterator(this->connections, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
if (strcmp(name, current->get_name(current)) == 0)
{
found = current->clone(current);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of connection_store_t.add_connection.
*/
static status_t add_connection(private_local_connection_store_t *this, connection_t *connection)
{
this->connections->insert_last(this->connections, connection);
return SUCCESS;
}
/**
* Implementation of connection_store_t.destroy.
*/
static void destroy (private_local_connection_store_t *this)
{
connection_t *connection;
while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS)
{
connection->destroy(connection);
}
this->connections->destroy(this->connections);
free(this);
}
/**
* Described in header.
*/
local_connection_store_t * local_connection_store_create()
{
private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t);
this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts;
this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids;
this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name;
this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection;
this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy;
/* private variables */
this->connections = linked_list_create();
this->logger = logger_manager->get_logger(logger_manager, CONFIG);
return (&this->public);
}
@@ -0,0 +1,63 @@
/**
* @file local_connection_store.h
*
* @brief Interface of local_connection_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef LOCAL_CONNECTION_H_
#define LOCAL_CONNECTION_H_
#include <types.h>
#include <config/connections/connection_store.h>
typedef struct local_connection_store_t local_connection_store_t;
/**
* @brief A connection_store_t implementation using a simple connection list.
*
* The local_connection_store_t class implements the connection_store_t interface
* as simple as possible. connection_t's are stored in an in-memory list.
*
* @b Constructors:
* - local_connection_store_create()
*
* @todo Make thread-save first
* @todo Add remove_connection method
*
* @ingroup config
*/
struct local_connection_store_t {
/**
* Implements connection_store_t interface
*/
connection_store_t connection_store;
};
/**
* @brief Creates a local_connection_store_t instance.
*
* @return connection store instance.
*
* @ingroup config
*/
local_connection_store_t * local_connection_store_create();
#endif /* LOCAL_CONNECTION_H_ */
@@ -0,0 +1,20 @@
# Copyright (C) 2006 Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
CREDENTIALS_DIR= $(CONFIG_DIR)credentials/
CHARON_OBJS+= $(BUILD_DIR)local_credential_store.o
$(BUILD_DIR)local_credential_store.o : $(CREDENTIALS_DIR)local_credential_store.c $(CREDENTIALS_DIR)local_credential_store.h
$(CC) $(CFLAGS) -c -o $@ $<
+91
View File
@@ -0,0 +1,91 @@
/**
* @file credential_store.h
*
* @brief Interface credential_store_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CREDENTIAL_STORE_H_
#define CREDENTIAL_STORE_H_
#include <types.h>
#include <crypto/rsa/rsa_private_key.h>
#include <crypto/rsa/rsa_public_key.h>
#include <utils/identification.h>
typedef struct credential_store_t credential_store_t;
/**
* @brief The interface for a credential_store backend.
*
* @b Constructors:
* - stroke_create()
*
* @ingroup config
*/
struct credential_store_t {
/**
* @brief Returns the preshared secret of a specific ID.
*
* The returned chunk must be destroyed by the caller after usage.
*
* @param this calling object
* @param identification identification_t object identifiying the secret.
* @param[out] preshared_secret the preshared secret will be written there.
* @return
* - NOT_FOUND if no preshared secrets for specific ID could be found
* - SUCCESS
*
* @todo We should use two IDs to query shared secrets, since we want to use different
* keys for different peers...
*/
status_t (*get_shared_secret) (credential_store_t *this, identification_t *identification, chunk_t *preshared_secret);
/**
* @brief Returns the RSA public key of a specific ID.
*
* The returned rsa_public_key_t must be destroyed by the caller after usage.
*
* @param this calling object
* @param identification identification_t object identifiying the key.
* @return public key, or NULL if not found
*/
rsa_public_key_t * (*get_rsa_public_key) (credential_store_t *this, identification_t *identification);
/**
* @brief Returns the RSA private key of a specific ID.
*
* The returned rsa_private_key_t must be destroyed by the caller after usage.
*
* @param this calling object
* @param identification identification_t object identifiying the key
* @return private key, or NULL if not found
*/
rsa_private_key_t *(*get_rsa_private_key) (credential_store_t *this, identification_t *identification);
/**
* @brief Destroys a credential_store_t object.
*
* @param this calling object
*/
void (*destroy) (credential_store_t *this);
};
#endif /*CREDENTIAL_STORE_H_*/
@@ -0,0 +1,315 @@
/**
* @file local_credential_store.c
*
* @brief Implementation of local_credential_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <sys/stat.h>
#include <dirent.h>
#include "local_credential_store.h"
#include <utils/linked_list.h>
#include <utils/logger_manager.h>
#include <crypto/x509.h>
typedef struct key_entry_t key_entry_t;
/**
* Private key with an associated ID to find it
*/
struct key_entry_t {
/**
* ID, as added
*/
identification_t *id;
/**
* Associated rsa private key
*/
rsa_private_key_t *key;
};
typedef struct private_local_credential_store_t private_local_credential_store_t;
/**
* Private data of an local_credential_store_t object
*/
struct private_local_credential_store_t {
/**
* Public part
*/
local_credential_store_t public;
/**
* list of key_entry_t's with private keys
*/
linked_list_t *private_keys;
/**
* list of x509 certificates with public keys
*/
linked_list_t *certificates;
/**
* Assigned logger
*/
logger_t *logger;
};
/**
* Implementation of credential_store_t.get_shared_secret.
*/
static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *identification, chunk_t *preshared_secret)
{
return FAILED;
}
/**
* Implementation of credential_store_t.get_rsa_public_key.
*/
static rsa_public_key_t * get_rsa_public_key(private_local_credential_store_t *this, identification_t *identification)
{
x509_t *current;
rsa_public_key_t *found = NULL;
iterator_t *iterator;
this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s",
identification->get_string(identification));
iterator = this->certificates->create_iterator(this->certificates, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
identification_t *stored = current->get_subject(current);
this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s",
stored->get_string(stored));
if (identification->equals(identification, stored))
{
found = current->get_public_key(current);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implementation of credential_store_t.get_rsa_private_key.
*/
static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, identification_t *identification)
{
rsa_private_key_t *found = NULL;
key_entry_t *current;
iterator_t *iterator;
iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current);
if (identification->equals(identification, current->id))
{
found = current->key->clone(current->key);
break;
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implements local_credential_store_t.load_private_keys
*/
static void load_certificates(private_local_credential_store_t *this, char *path)
{
struct dirent* entry;
struct stat stb;
DIR* dir;
x509_t *cert;
dir = opendir(path);
if (dir == NULL) {
this->logger->log(this->logger, ERROR, "error opening certificate directory \"%s\"", path);
return;
}
while ((entry = readdir(dir)) != NULL)
{
char file[256];
snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
if (stat(file, &stb) == -1)
{
continue;
}
/* try to parse all regular files */
if (stb.st_mode & S_IFREG)
{
cert = x509_create_from_file(file);
if (cert)
{
this->certificates->insert_last(this->certificates, (void*)cert);
this->logger->log(this->logger, CONTROL|LEVEL1, "loaded certificate \"%s\"", file);
}
else
{
this->logger->log(this->logger, ERROR, "certificate \"%s\" invalid, skipped", file);
}
}
}
closedir(dir);
}
/**
* Query the ID for a private key, by doing a lookup in the certificates
*/
static identification_t *get_id_for_private_key(private_local_credential_store_t *this, rsa_private_key_t *private_key)
{
iterator_t *iterator;
x509_t *cert;
identification_t *found = NULL;
rsa_public_key_t *public_key;
this->logger->log(this->logger, CONTROL|LEVEL2, "Getting ID for a private key...");
iterator = this->certificates->create_iterator(this->certificates, TRUE);
while (!found && iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&cert);
public_key = cert->get_public_key(cert);
if (public_key)
{
if (private_key->belongs_to(private_key, public_key))
{
this->logger->log(this->logger, CONTROL|LEVEL2, "found a match");
found = cert->get_subject(cert);
found = found->clone(found);
}
else
{
this->logger->log(this->logger, CONTROL|LEVEL3, "this one did not match");
}
public_key->destroy(public_key);
}
}
iterator->destroy(iterator);
return found;
}
/**
* Implements local_credential_store_t.load_private_keys
*/
static void load_private_keys(private_local_credential_store_t *this, char *path)
{
struct dirent* entry;
struct stat stb;
DIR* dir;
rsa_private_key_t *key;
dir = opendir(path);
if (dir == NULL) {
this->logger->log(this->logger, ERROR, "error opening private key directory \"%s\"", path);
return;
}
while ((entry = readdir(dir)) != NULL)
{
char file[256];
snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
if (stat(file, &stb) == -1)
{
continue;
}
/* try to parse all regular files */
if (stb.st_mode & S_IFREG)
{
key = rsa_private_key_create_from_file(file, NULL);
if (key)
{
key_entry_t *entry;
identification_t *id = get_id_for_private_key(this, key);
if (!id)
{
this->logger->log(this->logger, ERROR,
"no certificate found for private key \"%s\", skipped", file);
key->destroy(key);
continue;
}
entry = malloc_thing(key_entry_t);
entry->key = key;
entry->id = id;
this->private_keys->insert_last(this->private_keys, (void*)entry);
this->logger->log(this->logger, CONTROL|LEVEL1, "loaded private key \"%s\"", file);
}
else
{
this->logger->log(this->logger, ERROR, "private key \"%s\" invalid, skipped", file);
}
}
}
closedir(dir);
}
/**
* Implementation of credential_store_t.destroy.
*/
static void destroy(private_local_credential_store_t *this)
{
x509_t *certificate;
key_entry_t *key_entry;
while (this->certificates->remove_last(this->certificates, (void**)&certificate) == SUCCESS)
{
certificate->destroy(certificate);
}
this->certificates->destroy(this->certificates);
while (this->private_keys->remove_last(this->private_keys, (void**)&key_entry) == SUCCESS)
{
key_entry->id->destroy(key_entry->id);
key_entry->key->destroy(key_entry->key);
free(key_entry);
}
this->private_keys->destroy(this->private_keys);
free(this);
}
/**
* Described in header.
*/
local_credential_store_t * local_credential_store_create()
{
private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret;
this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,identification_t*))get_rsa_private_key;
this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
this->public.load_certificates = (void(*)(local_credential_store_t*,char*))load_certificates;
this->public.load_private_keys = (void(*)(local_credential_store_t*,char*))load_private_keys;
this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy;
/* private variables */
this->private_keys = linked_list_create();
this->certificates = linked_list_create();
this->logger = logger_manager->get_logger(logger_manager, CONFIG);
return (&this->public);
}
@@ -0,0 +1,84 @@
/**
* @file local_credential_store.h
*
* @brief Interface of local_credential_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef LOCAL_CREDENTIAL_H_
#define LOCAL_CREDENTIAL_H_
#include <types.h>
#include <config/credentials/credential_store.h>
typedef struct local_credential_store_t local_credential_store_t;
/**
* @brief A credential_store_t implementation using simple credentail lists.
*
* The local_credential_store_t class implements the credential_store_t interface
* as simple as possible. The credentials are stored in lists, and can be loaded
* from folders.
* Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND.
*
* @b Constructors:
* - local_credential_store_create()
*
* @ingroup config
*/
struct local_credential_store_t {
/**
* Implements credential_store_t interface
*/
credential_store_t credential_store;
/**
* @brief Loads trusted certificates from a folder.
*
* Currently, all keys must be in binary DER format.
*
* @param this calling object
* @param path directory to load certificates from
*/
void (*load_certificates) (local_credential_store_t *this, char *path);
/**
* @brief Loads RSA private keys from a folder.
*
* Currently, all keys must be unencrypted in binary DER format. Anything
* other gets ignored. Further, a certificate for the specific private
* key must already be loaded to get the ID from.
*
* @param this calling object
* @param path directory to load keys from
*/
void (*load_private_keys) (local_credential_store_t *this, char *path);
};
/**
* @brief Creates a local_credential_store_t instance.
*
* @return credential store instance.
*
* @ingroup config
*/
local_credential_store_t *local_credential_store_create();
#endif /* LOCAL_CREDENTIAL_H_ */
@@ -0,0 +1,24 @@
# Copyright (C) 2006 Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
POLICIES_DIR= $(CONFIG_DIR)policies/
CHARON_OBJS+= $(BUILD_DIR)policy.o
$(BUILD_DIR)policy.o : $(POLICIES_DIR)policy.c $(POLICIES_DIR)policy.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)local_policy_store.o
$(BUILD_DIR)local_policy_store.o : $(POLICIES_DIR)local_policy_store.c $(POLICIES_DIR)local_policy_store.h
$(CC) $(CFLAGS) -c -o $@ $<
@@ -0,0 +1,136 @@
/**
* @file local_policy_store.c
*
* @brief Implementation of local_policy_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "local_policy_store.h"
#include <utils/linked_list.h>
#include <utils/logger_manager.h>
typedef struct private_local_policy_store_t private_local_policy_store_t;
/**
* Private data of an local_policy_store_t object
*/
struct private_local_policy_store_t {
/**
* Public part
*/
local_policy_store_t public;
/**
* list of policy_t's
*/
linked_list_t *policies;
/**
* Assigned logger
*/
logger_t *logger;
};
/**
* Implementation of policy_store_t.add_policy.
*/
static void add_policy(private_local_policy_store_t *this, policy_t *policy)
{
this->policies->insert_last(this->policies, (void*)policy);
}
/**
* Implementation of policy_store_t.get_policy.
*/
static policy_t *get_policy(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id)
{
iterator_t *iterator;
policy_t *current, *found = NULL;
this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy for IDs %s - %s",
my_id ? my_id->get_string(my_id) : "%any",
other_id->get_string(other_id));
iterator = this->policies->create_iterator(this->policies, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void **)&current);
identification_t *config_my_id = current->get_my_id(current);
identification_t *config_other_id = current->get_other_id(current);
this->logger->log(this->logger, CONTROL|LEVEL2, "Found one for %s - %s",
config_my_id->get_string(config_my_id),
config_other_id->get_string(config_other_id));
/* check other host first */
if (other_id->belongs_to(other_id, config_other_id))
{
/* get it if my_id not specified */
if (my_id->belongs_to(my_id, config_my_id))
{
found = current->clone(current);
break;
}
}
}
iterator->destroy(iterator);
/* apply IDs as they are requsted, since they may be configured as %any or such */
if (found)
{
found->update_my_id(found, my_id->clone(my_id));
found->update_other_id(found, other_id->clone(other_id));
}
return found;
}
/**
* Implementation of policy_store_t.destroy.
*/
static void destroy(private_local_policy_store_t *this)
{
policy_t *policy;
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
{
policy->destroy(policy);
}
this->policies->destroy(this->policies);
free(this);
}
/**
* Described in header.
*/
local_policy_store_t *local_policy_store_create()
{
private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t);
this->public.policy_store.add_policy = (void(*)(policy_store_t*,policy_t*))add_policy;
this->public.policy_store.get_policy = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy;
this->public.policy_store.destroy = (void(*)(policy_store_t*))destroy;
/* private variables */
this->policies = linked_list_create();
this->logger = logger_manager->get_logger(logger_manager, CONFIG);
return (&this->public);
}
@@ -0,0 +1,60 @@
/**
* @file local_policy_store.h
*
* @brief Interface of local_policy_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef LOCAL_POLICY_STORE_H_
#define LOCAL_POLICY_STORE_H_
#include <types.h>
#include <config/policies/policy_store.h>
typedef struct local_policy_store_t local_policy_store_t;
/**
* @brief A policy_store_t implementation using a simple policy lists.
*
* The local_policy_store_t class implements the policy_store_t interface
* as simple as possible. The policies are stored in a in-memory list.
*
* @b Constructors:
* - local_policy_store_create()
*
* @ingroup config
*/
struct local_policy_store_t {
/**
* Implements policy_store_t interface
*/
policy_store_t policy_store;
};
/**
* @brief Creates a local_policy_store_t instance.
*
* @return policy store instance.
*
* @ingroup config
*/
local_policy_store_t *local_policy_store_create();
#endif /* LOCAL_POLICY_STORE_H_ */
+397
View File
@@ -0,0 +1,397 @@
/**
* @file policy.c
*
* @brief Implementation of policy_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "policy.h"
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <utils/logger.h>
typedef struct private_policy_t private_policy_t;
/**
* Private data of an policy_t object
*/
struct private_policy_t {
/**
* Public part
*/
policy_t public;
/**
* id to use to identify us
*/
identification_t *my_id;
/**
* allowed id for other
*/
identification_t *other_id;
/**
* list for all proposals
*/
linked_list_t *proposals;
/**
* list for traffic selectors for my site
*/
linked_list_t *my_ts;
/**
* list for traffic selectors for others site
*/
linked_list_t *other_ts;
/**
* select_traffic_selectors for both
*/
linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*);
};
/**
* Implementation of policy_t.get_my_id
*/
static identification_t *get_my_id(private_policy_t *this)
{
return this->my_id;
}
/**
* Implementation of policy_t.get_other_id
*/
static identification_t *get_other_id(private_policy_t *this)
{
return this->other_id;
}
/**
* Implementation of policy_t.update_my_id
*/
static void update_my_id(private_policy_t *this, identification_t *my_id)
{
this->my_id->destroy(this->my_id);
this->my_id = my_id;
}
/**
* Implementation of policy_t.update_other_id
*/
static void update_other_id(private_policy_t *this, identification_t *other_id)
{
this->other_id->destroy(this->other_id);
this->other_id = other_id;
}
/**
* Helper function which does the work for policy_t.update_my_ts and update_other_ts
*/
static void update_ts(linked_list_t* list, host_t *new_host)
{
traffic_selector_t *ts;
iterator_t *iterator;
iterator = list->create_iterator(list, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&ts);
ts->update_address_range(ts, new_host);
}
iterator->destroy(iterator);
}
/**
* Implementation of policy_t.update_my_id
*/
static void update_my_ts(private_policy_t *this, host_t *my_host)
{
update_ts(this->my_ts, my_host);
}
/**
* Implementation of policy_t.update_other_ts
*/
static void update_other_ts(private_policy_t *this, host_t *my_host)
{
update_ts(this->other_ts, my_host);
}
/**
* Implementation of policy_t.get_my_traffic_selectors
*/
static linked_list_t *get_my_traffic_selectors(private_policy_t *this)
{
return this->my_ts;
}
/**
* Implementation of policy_t.get_other_traffic_selectors
*/
static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[])
{
return this->other_ts;
}
/**
* Implementation of private_policy_t.select_my_traffic_selectors
*/
static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
{
return this->select_traffic_selectors(this, this->my_ts, supplied);
}
/**
* Implementation of private_policy_t.select_other_traffic_selectors
*/
static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
{
return this->select_traffic_selectors(this, this->other_ts, supplied);
}
/**
* Implementation of private_policy_t.select_traffic_selectors
*/
static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
{
iterator_t *supplied_iter, *stored_iter;
traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
linked_list_t *selected = linked_list_create();
stored_iter = stored->create_iterator(stored, TRUE);
supplied_iter = supplied->create_iterator(supplied, TRUE);
/* iterate over all stored selectors */
while (stored_iter->has_next(stored_iter))
{
stored_iter->current(stored_iter, (void**)&stored_ts);
supplied_iter->reset(supplied_iter);
/* iterate over all supplied traffic selectors */
while (supplied_iter->has_next(supplied_iter))
{
supplied_iter->current(supplied_iter, (void**)&supplied_ts);
selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
if (selected_ts)
{
/* got a match, add to list */
selected->insert_last(selected, (void*)selected_ts);
}
}
}
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return selected;
}
/**
* Implementation of policy_t.get_proposal_iterator
*/
static linked_list_t *get_proposals(private_policy_t *this)
{
return this->proposals;
}
/**
* Implementation of policy_t.select_proposal
*/
static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals)
{
iterator_t *stored_iter, *supplied_iter;
proposal_t *stored, *supplied, *selected;
stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
supplied_iter = proposals->create_iterator(proposals, TRUE);
/* compare all stored proposals with all supplied. Stored ones are preferred. */
while (stored_iter->has_next(stored_iter))
{
supplied_iter->reset(supplied_iter);
stored_iter->current(stored_iter, (void**)&stored);
while (supplied_iter->has_next(supplied_iter))
{
supplied_iter->current(supplied_iter, (void**)&supplied);
selected = stored->select(stored, supplied);
if (selected)
{
/* they match, return */
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return selected;
}
}
}
/* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
return NULL;
}
/**
* Implementation of policy_t.add_my_traffic_selector
*/
static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
{
this->my_ts->insert_last(this->my_ts, (void*)traffic_selector);
}
/**
* Implementation of policy_t.add_other_traffic_selector
*/
static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
{
this->other_ts->insert_last(this->other_ts, (void*)traffic_selector);
}
/**
* Implementation of policy_t.add_proposal
*/
static void add_proposal(private_policy_t *this, proposal_t *proposal)
{
this->proposals->insert_last(this->proposals, (void*)proposal);
}
/**
* Implements policy_t.destroy.
*/
static status_t destroy(private_policy_t *this)
{
proposal_t *proposal;
traffic_selector_t *traffic_selector;
/* delete proposals */
while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
{
proposal->destroy(proposal);
}
this->proposals->destroy(this->proposals);
/* delete traffic selectors */
while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
{
traffic_selector->destroy(traffic_selector);
}
this->my_ts->destroy(this->my_ts);
/* delete traffic selectors */
while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
{
traffic_selector->destroy(traffic_selector);
}
this->other_ts->destroy(this->other_ts);
/* delete ids */
this->my_id->destroy(this->my_id);
this->other_id->destroy(this->other_id);
free(this);
return SUCCESS;
}
/**
* Implements policy_t.clone.
*/
static policy_t *clone(private_policy_t *this)
{
private_policy_t *clone = (private_policy_t*)policy_create(this->my_id->clone(this->my_id),
this->other_id->clone(this->other_id));
iterator_t *iterator;
proposal_t *proposal;
traffic_selector_t *ts;
/* clone all proposals */
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&proposal);
proposal = proposal->clone(proposal);
clone->proposals->insert_last(clone->proposals, (void*)proposal);
}
iterator->destroy(iterator);
/* clone all local traffic selectors */
iterator = this->my_ts->create_iterator(this->my_ts, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&ts);
ts = ts->clone(ts);
clone->my_ts->insert_last(clone->my_ts, (void*)ts);
}
iterator->destroy(iterator);
/* clone all remote traffic selectors */
iterator = this->other_ts->create_iterator(this->other_ts, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&ts);
ts = ts->clone(ts);
clone->other_ts->insert_last(clone->other_ts, (void*)ts);
}
iterator->destroy(iterator);
return &clone->public;
}
/*
* Described in header-file
*/
policy_t *policy_create(identification_t *my_id, identification_t *other_id)
{
private_policy_t *this = malloc_thing(private_policy_t);
/* public functions */
this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id;
this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id;
this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id;
this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id;
this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts;
this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts;
this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors;
this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors;
this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors;
this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors;
this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal;
this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
this->public.clone = (policy_t*(*)(policy_t*))clone;
this->public.destroy = (void(*)(policy_t*))destroy;
/* apply init values */
this->my_id = my_id;
this->other_id = other_id;
/* init private members*/
this->select_traffic_selectors = select_traffic_selectors;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
return (&this->public);
}
+249
View File
@@ -0,0 +1,249 @@
/**
* @file policy.h
*
* @brief Interface of policy_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef POLICY_H_
#define POLICY_H_
#include <types.h>
#include <utils/identification.h>
#include <config/traffic_selector.h>
#include <config/proposal.h>
#include <encoding/payloads/auth_payload.h>
typedef struct policy_t policy_t;
/**
* @brief A policy_t defines the policies to apply to CHILD_SAs.
*
* The given two IDs identify a policy. These rules define how
* child SAs may be set up and which traffic may be IPsec'ed.
*
* @b Constructors:
* - policy_create()
*
* @ingroup config
*/
struct policy_t {
/**
* @brief Get own id to use for identification.
*
* Returned object is not getting cloned.
*
* @param this calling object
* @return own id
*/
identification_t *(*get_my_id) (policy_t *this);
/**
* @brief Get id of communication partner.
*
* Returned object is not getting cloned.
*
* @param this calling object
* @return other id
*/
identification_t *(*get_other_id) (policy_t *this);
/**
* @brief Update own ID.
*
* It may be necessary to uptdate own ID, as it
* is set to %any or to e.g. *@strongswan.org in
* some cases.
* Old ID is destroyed, new one NOT cloned.
*
* @param this calling object
* @param my_id new ID to set as my_id
*/
void (*update_my_id) (policy_t *this, identification_t *my_id);
/**
* @brief Update others ID.
*
* It may be necessary to uptdate others ID, as it
* is set to %any or to e.g. *@strongswan.org in
* some cases.
* Old ID is destroyed, new one NOT cloned.
*
* @param this calling object
* @param other_id new ID to set as other_id
*/
void (*update_other_id) (policy_t *this, identification_t *other_id);
/**
* @brief Update own address in traffic selectors.
*
* Update own 0.0.0.0 address in traffic selectors
* with supplied one. The size of the subnet will be
* set to /32.
*
* @param this calling object
* @param my_host new address to set in traffic selectors
*/
void (*update_my_ts) (policy_t *this, host_t *my_host);
/**
* @brief Update others address in traffic selectors.
*
* Update remote 0.0.0.0 address in traffic selectors
* with supplied one. The size of the subnet will be
* set to /32.
*
* @param this calling object
* @param other_host new address to set in traffic selectors
*/
void (*update_other_ts) (policy_t *this, host_t *other_host);
/**
* @brief Get configured traffic selectors for our site.
*
* Returns a list with all traffic selectors for the local
* site. List and items MUST NOT be freed nor modified.
*
* @param this calling object
* @return list with traffic selectors
*/
linked_list_t *(*get_my_traffic_selectors) (policy_t *this);
/**
* @brief Get configured traffic selectors for others site.
*
* Returns a list with all traffic selectors for the remote
* site. List and items MUST NOT be freed nor modified.
*
* @param this calling object
* @return list with traffic selectors
*/
linked_list_t *(*get_other_traffic_selectors) (policy_t *this);
/**
* @brief Select traffic selectors from a supplied list for local site.
*
* Resulted list and traffic selectors must be destroyed after usage.
*
* @param this calling object
* @param supplied linked list with traffic selectors
* @return list containing the selected traffic selectors
*/
linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied);
/**
* @brief Select traffic selectors from a supplied list for remote site.
*
* Resulted list and traffic selectors must be destroyed after usage.
*
* @param this calling object
* @param supplied linked list with traffic selectors
* @return list containing the selected traffic selectors
*/
linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied);
/**
* @brief Get the list of internally stored proposals.
*
* Rembember: policy_t does store proposals for AH/ESP,
* IKE proposals are in the connection_t
*
* @warning List and Items are still owned by policy and MUST NOT
* be manipulated or freed!
*
* @param this calling object
* @return lists with proposals
*/
linked_list_t *(*get_proposals) (policy_t *this);
/**
* @brief Select a proposal from a supplied list.
*
* @param this calling object
* @param proposals list from from wich proposals are selected
* @return selected proposal, or NULL if nothing matches
*/
proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals);
/**
* @brief Add a traffic selector to the list for local site.
*
* After add, proposal is owned by policy.
*
* @warning Do not add while other threads are reading.
*
* @param this calling object
* @param traffic_selector traffic_selector to add
*/
void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
/**
* @brief Add a traffic selector to the list for remote site.
*
* After add, proposal is owned by policy.
*
* @warning Do not add while other threads are reading.
*
* @param this calling object
* @param traffic_selector traffic_selector to add
*/
void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
/**
* @brief Add a proposal to the list.
*
* The proposals are stored by priority, first added
* is the most prefered.
*
* @warning Do not add while other threads are reading.
*
* @param this calling object
* @param proposal proposal to add
*/
void (*add_proposal) (policy_t *this, proposal_t *proposal);
/**
* @brief Clone a policy.
*
* @param this policy to clone
* @return clone of it
*/
policy_t *(*clone) (policy_t *this);
/**
* @brief Destroys the policy object
*
* @param this calling object
*/
void (*destroy) (policy_t *this);
};
/**
* @brief Create a configuration object for IKE_AUTH and later.
*
* @param my_id identification_t for ourselves
* @param other_id identification_t for the remote guy
* @return policy_t object
*
* @ingroup config
*/
policy_t *policy_create(identification_t *my_id, identification_t *other_id);
#endif /* POLICY_H_ */
+76
View File
@@ -0,0 +1,76 @@
/**
* @file policy_store.h
*
* @brief Interface policy_store_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef POLICY_STORE_H_
#define POLICY_STORE_H_
#include <types.h>
#include <config/policies/policy.h>
typedef struct policy_store_t policy_store_t;
/**
* @brief The interface for a store of policy_t's.
*
* @b Constructors:
* - stroke_create()
*
* @ingroup config
*/
struct policy_store_t {
/**
* @brief Returns a policy identified by two IDs.
*
* The returned policy gets created/cloned and therefore must be
* destroyed by the caller.
*
* @param this calling object
* @param my_id own ID of the policy
* @param other_id others ID of the policy
* @return
* - matching policy_t, if found
* - NULL otherwise
*/
policy_t *(*get_policy) (policy_store_t *this, identification_t *my_id, identification_t *other_id);
/**
* @brief Add a policy to the list.
*
* The policy is owned by the store after the call. Do
* not modify nor free.
*
* @param this calling object
* @param policy policy to add
*/
void (*add_policy) (policy_store_t *this, policy_t *policy);
/**
* @brief Destroys a policy_store_t object.
*
* @param this calling object
*/
void (*destroy) (policy_store_t *this);
};
#endif /*POLICY_STORE_H_*/
+642
View File
@@ -0,0 +1,642 @@
/**
* @file proposal.c
*
* @brief Implementation of proposal_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <string.h>
#include "proposal.h"
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <utils/logger.h>
/**
* String mappings for protocol_id_t.
*/
mapping_t protocol_id_m[] = {
{PROTO_NONE, "PROTO_NONE"},
{PROTO_IKE, "PROTO_IKE"},
{PROTO_AH, "PROTO_AH"},
{PROTO_ESP, "PROTO_ESP"},
{MAPPING_END, NULL}
};
/**
* String mappings for transform_type_t.
*/
mapping_t transform_type_m[] = {
{UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"},
{ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"},
{PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"},
{INTEGRITY_ALGORITHM, "INTEGRITY_ALGORITHM"},
{DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"},
{EXTENDED_SEQUENCE_NUMBERS, "EXTENDED_SEQUENCE_NUMBERS"},
{MAPPING_END, NULL}
};
/**
* String mappings for extended_sequence_numbers_t.
*/
mapping_t extended_sequence_numbers_m[] = {
{NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"},
{EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"},
{MAPPING_END, NULL}
};
typedef struct protocol_proposal_t protocol_proposal_t;
/**
* substructure which holds all data algos for a specific protocol
*/
struct protocol_proposal_t {
/**
* protocol (ESP or AH)
*/
protocol_id_t protocol;
/**
* priority ordered list of encryption algorithms
*/
linked_list_t *encryption_algos;
/**
* priority ordered list of integrity algorithms
*/
linked_list_t *integrity_algos;
/**
* priority ordered list of pseudo random functions
*/
linked_list_t *prf_algos;
/**
* priority ordered list of dh groups
*/
linked_list_t *dh_groups;
/**
* priority ordered list of extended sequence number flags
*/
linked_list_t *esns;
/**
* senders SPI
*/
chunk_t spi;
};
typedef struct private_proposal_t private_proposal_t;
/**
* Private data of an proposal_t object
*/
struct private_proposal_t {
/**
* Public part
*/
proposal_t public;
/**
* number of this proposal, as used in the payload
*/
u_int8_t number;
/**
* list of protocol_proposal_t's
*/
linked_list_t *protocol_proposals;
};
/**
* Look up a protocol_proposal, or create one if necessary...
*/
static protocol_proposal_t *get_protocol_proposal(private_proposal_t *this, protocol_id_t proto, bool create)
{
protocol_proposal_t *proto_proposal = NULL, *current_proto_proposal;;
iterator_t *iterator;
/* find our protocol in the proposals */
iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current_proto_proposal);
if (current_proto_proposal->protocol == proto)
{
proto_proposal = current_proto_proposal;
break;
}
}
iterator->destroy(iterator);
if (!proto_proposal && create)
{
/* nope, create a new one */
proto_proposal = malloc_thing(protocol_proposal_t);
proto_proposal->protocol = proto;
proto_proposal->encryption_algos = linked_list_create();
proto_proposal->integrity_algos = linked_list_create();
proto_proposal->prf_algos = linked_list_create();
proto_proposal->dh_groups = linked_list_create();
proto_proposal->esns = linked_list_create();
if (proto == PROTO_IKE)
{
proto_proposal->spi.len = 8;
}
else
{
proto_proposal->spi.len = 4;
}
proto_proposal->spi.ptr = malloc(proto_proposal->spi.len);
/* add to the list */
this->protocol_proposals->insert_last(this->protocol_proposals, (void*)proto_proposal);
}
return proto_proposal;
}
/**
* Add algorithm/keysize to a algorithm list
*/
static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size)
{
algorithm_t *algo_key = malloc_thing(algorithm_t);
algo_key->algorithm = algo;
algo_key->key_size = key_size;
list->insert_last(list, (void*)algo_key);
}
/**
* Implements proposal_t.add_algorithm
*/
static void add_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t algo, size_t key_size)
{
protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, TRUE);
switch (type)
{
case ENCRYPTION_ALGORITHM:
add_algo(proto_proposal->encryption_algos, algo, key_size);
break;
case INTEGRITY_ALGORITHM:
add_algo(proto_proposal->integrity_algos, algo, key_size);
break;
case PSEUDO_RANDOM_FUNCTION:
add_algo(proto_proposal->prf_algos, algo, key_size);
break;
case DIFFIE_HELLMAN_GROUP:
add_algo(proto_proposal->dh_groups, algo, 0);
break;
case EXTENDED_SEQUENCE_NUMBERS:
add_algo(proto_proposal->esns, algo, 0);
break;
default:
break;
}
}
/**
* Implements proposal_t.get_algorithm.
*/
static bool get_algorithm(private_proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo)
{
linked_list_t * list;
protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
if (proto_proposal == NULL)
{
return FALSE;
}
switch (type)
{
case ENCRYPTION_ALGORITHM:
list = proto_proposal->encryption_algos;
break;
case INTEGRITY_ALGORITHM:
list = proto_proposal->integrity_algos;
break;
case PSEUDO_RANDOM_FUNCTION:
list = proto_proposal->prf_algos;
break;
case DIFFIE_HELLMAN_GROUP:
list = proto_proposal->dh_groups;
break;
case EXTENDED_SEQUENCE_NUMBERS:
list = proto_proposal->esns;
break;
default:
return FALSE;
}
if (list->get_first(list, (void**)algo) != SUCCESS)
{
return FALSE;
}
return TRUE;
}
/**
* Implements proposal_t.create_algorithm_iterator.
*/
static iterator_t *create_algorithm_iterator(private_proposal_t *this, protocol_id_t proto, transform_type_t type)
{
protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
if (proto_proposal == NULL)
{
return NULL;
}
switch (type)
{
case ENCRYPTION_ALGORITHM:
return proto_proposal->encryption_algos->create_iterator(proto_proposal->encryption_algos, TRUE);
case INTEGRITY_ALGORITHM:
return proto_proposal->integrity_algos->create_iterator(proto_proposal->integrity_algos, TRUE);
case PSEUDO_RANDOM_FUNCTION:
return proto_proposal->prf_algos->create_iterator(proto_proposal->prf_algos, TRUE);
case DIFFIE_HELLMAN_GROUP:
return proto_proposal->dh_groups->create_iterator(proto_proposal->dh_groups, TRUE);
case EXTENDED_SEQUENCE_NUMBERS:
return proto_proposal->esns->create_iterator(proto_proposal->esns, TRUE);
default:
break;
}
return NULL;
}
/**
* Find a matching alg/keysize in two linked lists
*/
static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size)
{
iterator_t *first_iter, *second_iter;
algorithm_t *first_alg, *second_alg;
/* if in both are zero algorithms specified, we HAVE a match */
if (first->get_count(first) == 0 && second->get_count(second) == 0)
{
*add = FALSE;
return TRUE;
}
first_iter = first->create_iterator(first, TRUE);
second_iter = second->create_iterator(second, TRUE);
/* compare algs, order of algs in "first" is preferred */
while (first_iter->has_next(first_iter))
{
first_iter->current(first_iter, (void**)&first_alg);
second_iter->reset(second_iter);
while (second_iter->has_next(second_iter))
{
second_iter->current(second_iter, (void**)&second_alg);
if (first_alg->algorithm == second_alg->algorithm &&
first_alg->key_size == second_alg->key_size)
{
/* ok, we have an algorithm */
*alg = first_alg->algorithm;
*key_size = first_alg->key_size;
*add = TRUE;
first_iter->destroy(first_iter);
second_iter->destroy(second_iter);
return TRUE;
}
}
}
/* no match in all comparisons */
first_iter->destroy(first_iter);
second_iter->destroy(second_iter);
return FALSE;
}
/**
* Implements proposal_t.select.
*/
static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other)
{
proposal_t *selected;
u_int16_t algo;
size_t key_size;
iterator_t *iterator;
protocol_proposal_t *this_prop, *other_prop;
protocol_id_t proto;
bool add;
u_int64_t spi;
/* empty proposal? no match */
if (this->protocol_proposals->get_count(this->protocol_proposals) == 0 ||
other->protocol_proposals->get_count(other->protocol_proposals) == 0)
{
return NULL;
}
/* they MUST have the same amount of protocols */
if (this->protocol_proposals->get_count(this->protocol_proposals) !=
other->protocol_proposals->get_count(other->protocol_proposals))
{
return NULL;
}
selected = proposal_create(this->number);
/* iterate over supplied proposals */
iterator = other->protocol_proposals->create_iterator(other->protocol_proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&other_prop);
/* get the proposal with the same protocol */
proto = other_prop->protocol;
this_prop = get_protocol_proposal(this, proto, FALSE);
if (this_prop == NULL)
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
/* select encryption algorithm */
if (select_algo(this_prop->encryption_algos, other_prop->encryption_algos, &add, &algo, &key_size))
{
if (add)
{
selected->add_algorithm(selected, proto, ENCRYPTION_ALGORITHM, algo, key_size);
}
}
else
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
/* select integrity algorithm */
if (select_algo(this_prop->integrity_algos, other_prop->integrity_algos, &add, &algo, &key_size))
{
if (add)
{
selected->add_algorithm(selected, proto, INTEGRITY_ALGORITHM, algo, key_size);
}
}
else
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
/* select prf algorithm */
if (select_algo(this_prop->prf_algos, other_prop->prf_algos, &add, &algo, &key_size))
{
if (add)
{
selected->add_algorithm(selected, proto, PSEUDO_RANDOM_FUNCTION, algo, key_size);
}
}
else
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
/* select a DH-group */
if (select_algo(this_prop->dh_groups, other_prop->dh_groups, &add, &algo, &key_size))
{
if (add)
{
selected->add_algorithm(selected, proto, DIFFIE_HELLMAN_GROUP, algo, 0);
}
}
else
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
/* select if we use ESNs */
if (select_algo(this_prop->esns, other_prop->esns, &add, &algo, &key_size))
{
if (add)
{
selected->add_algorithm(selected, proto, EXTENDED_SEQUENCE_NUMBERS, algo, 0);
}
}
else
{
iterator->destroy(iterator);
selected->destroy(selected);
return NULL;
}
}
iterator->destroy(iterator);
/* apply spis from "other" */
spi = other->public.get_spi(&(other->public), PROTO_AH);
if (spi)
{
selected->set_spi(selected, PROTO_AH, spi);
}
spi = other->public.get_spi(&(other->public), PROTO_ESP);
if (spi)
{
selected->set_spi(selected, PROTO_ESP, spi);
}
/* everything matched, return new proposal */
return selected;
}
/**
* Implements proposal_t.get_number.
*/
static u_int8_t get_number(private_proposal_t *this)
{
return this->number;
}
/**
* Implements proposal_t.get_protocols.
*/
static void get_protocols(private_proposal_t *this, protocol_id_t ids[2])
{
iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE);
u_int i = 0;
ids[0] = PROTO_NONE;
ids[1] = PROTO_NONE;
while (iterator->has_next(iterator))
{
protocol_proposal_t *proto_prop;
iterator->current(iterator, (void**)&proto_prop);
ids[i++] = proto_prop->protocol;
if (i>1)
{
/* should not happen, but who knows */
break;
}
}
iterator->destroy(iterator);
}
/**
* Implements proposal_t.set_spi.
*/
static void set_spi(private_proposal_t *this, protocol_id_t proto, u_int64_t spi)
{
protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
if (proto_proposal)
{
if (proto == PROTO_AH || proto == PROTO_ESP)
{
*((u_int32_t*)proto_proposal->spi.ptr) = (u_int32_t)spi;
}
else
{
*((u_int64_t*)proto_proposal->spi.ptr) = spi;
}
}
}
/**
* Implements proposal_t.get_spi.
*/
static u_int64_t get_spi(private_proposal_t *this, protocol_id_t proto)
{
protocol_proposal_t *proto_proposal = get_protocol_proposal(this, proto, FALSE);
if (proto_proposal)
{
if (proto == PROTO_AH || proto == PROTO_ESP)
{
return (u_int64_t)*((u_int32_t*)proto_proposal->spi.ptr);
}
else
{
return *((u_int64_t*)proto_proposal->spi.ptr);
}
}
return 0;
}
/**
* Clone a algorithm list
*/
static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
{
algorithm_t *algo, *clone_algo;
iterator_t *iterator = list->create_iterator(list, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&algo);
clone_algo = malloc_thing(algorithm_t);
memcpy(clone_algo, algo, sizeof(algorithm_t));
clone_list->insert_last(clone_list, (void*)clone_algo);
}
iterator->destroy(iterator);
}
/**
* Implements proposal_t.clone
*/
static proposal_t *clone(private_proposal_t *this)
{
private_proposal_t *clone = (private_proposal_t*)proposal_create(this->number);
iterator_t *iterator = this->protocol_proposals->create_iterator(this->protocol_proposals, TRUE);
while (iterator->has_next(iterator))
{
protocol_proposal_t *proto_prop, *clone_proto_prop;
iterator->current(iterator, (void**)&proto_prop);
clone_proto_prop = get_protocol_proposal(clone, proto_prop->protocol, TRUE);
memcpy(clone_proto_prop->spi.ptr, proto_prop->spi.ptr, clone_proto_prop->spi.len);
clone_algo_list(proto_prop->encryption_algos, clone_proto_prop->encryption_algos);
clone_algo_list(proto_prop->integrity_algos, clone_proto_prop->integrity_algos);
clone_algo_list(proto_prop->prf_algos, clone_proto_prop->prf_algos);
clone_algo_list(proto_prop->dh_groups, clone_proto_prop->dh_groups);
clone_algo_list(proto_prop->esns, clone_proto_prop->esns);
}
iterator->destroy(iterator);
return &clone->public;
}
/**
* Frees all list items and destroys the list
*/
static void free_algo_list(linked_list_t *list)
{
algorithm_t *algo;
while(list->get_count(list) > 0)
{
list->remove_last(list, (void**)&algo);
free(algo);
}
list->destroy(list);
}
/**
* Implements proposal_t.destroy.
*/
static void destroy(private_proposal_t *this)
{
while(this->protocol_proposals->get_count(this->protocol_proposals) > 0)
{
protocol_proposal_t *proto_prop;
this->protocol_proposals->remove_last(this->protocol_proposals, (void**)&proto_prop);
free_algo_list(proto_prop->encryption_algos);
free_algo_list(proto_prop->integrity_algos);
free_algo_list(proto_prop->prf_algos);
free_algo_list(proto_prop->dh_groups);
free_algo_list(proto_prop->esns);
free(proto_prop->spi.ptr);
free(proto_prop);
}
this->protocol_proposals->destroy(this->protocol_proposals);
free(this);
}
/*
* Describtion in header-file
*/
proposal_t *proposal_create(u_int8_t number)
{
private_proposal_t *this = malloc_thing(private_proposal_t);
this->public.add_algorithm = (void (*)(proposal_t*,protocol_id_t,transform_type_t,u_int16_t,size_t))add_algorithm;
this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,protocol_id_t,transform_type_t))create_algorithm_iterator;
this->public.get_algorithm = (bool (*)(proposal_t*,protocol_id_t,transform_type_t,algorithm_t**))get_algorithm;
this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal;
this->public.get_number = (u_int8_t (*)(proposal_t*))get_number;
this->public.get_protocols = (void(*)(proposal_t *this, protocol_id_t ids[2]))get_protocols;
this->public.set_spi = (void(*)(proposal_t*,protocol_id_t,u_int64_t spi))set_spi;
this->public.get_spi = (u_int64_t(*)(proposal_t*,protocol_id_t))get_spi;
this->public.clone = (proposal_t*(*)(proposal_t*))clone;
this->public.destroy = (void(*)(proposal_t*))destroy;
/* init private members*/
this->number = number;
this->protocol_proposals = linked_list_create();
return (&this->public);
}
+269
View File
@@ -0,0 +1,269 @@
/**
* @file proposal.h
*
* @brief Interface of proposal_t.
*
*/
/*
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef PROPOSAL_H_
#define PROPOSAL_H_
#include <types.h>
#include <utils/identification.h>
#include <utils/linked_list.h>
#include <utils/host.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <crypto/diffie_hellman.h>
#include <config/traffic_selector.h>
typedef enum protocol_id_t protocol_id_t;
/**
* Protocol ID of a proposal.
*
* @ingroup config
*/
enum protocol_id_t {
PROTO_NONE = 0,
PROTO_IKE = 1,
PROTO_AH = 2,
PROTO_ESP = 3,
};
/**
* String mappings for protocol_id_t.
*
* @ingroup config
*/
extern mapping_t protocol_id_m[];
typedef enum transform_type_t transform_type_t;
/**
* Type of a transform, as in IKEv2 RFC 3.3.2.
*
* @ingroup payloads
*/
enum transform_type_t {
UNDEFINED_TRANSFORM_TYPE = 241,
ENCRYPTION_ALGORITHM = 1,
PSEUDO_RANDOM_FUNCTION = 2,
INTEGRITY_ALGORITHM = 3,
DIFFIE_HELLMAN_GROUP = 4,
EXTENDED_SEQUENCE_NUMBERS = 5
};
/**
* String mappings for transform_type_t.
*
* @ingroup payloads
*/
extern mapping_t transform_type_m[];
typedef enum extended_sequence_numbers_t extended_sequence_numbers_t;
/**
* Extended sequence numbers, as in IKEv2 RFC 3.3.2.
*
* @ingroup payloads
*/
enum extended_sequence_numbers_t {
NO_EXT_SEQ_NUMBERS = 0,
EXT_SEQ_NUMBERS = 1
};
/**
* String mappings for extended_sequence_numbers_t.
*
* @ingroup payloads
*/
extern mapping_t extended_sequence_numbers_m[];
typedef struct algorithm_t algorithm_t;
/**
* Struct used to store different kinds of algorithms. The internal
* lists of algorithms contain such structures.
*/
struct algorithm_t {
/**
* Value from an encryption_algorithm_t/integrity_algorithm_t/...
*/
u_int16_t algorithm;
/**
* the associated key size, or zero if not needed
*/
u_int16_t key_size;
};
typedef struct proposal_t proposal_t;
/**
* @brief Stores a set of algorithms used for an SA.
*
* A proposal stores algorithms for a specific
* protocol. It can store algorithms for more than
* one protocol (e.g. AH and ESP). Then the proposal
* means both protocols must be used.
* A proposal may contain more than one algorithm
* of the same kind. ONE of them can be selected.
*
* @warning This class is NOT thread-save!
*
* @b Constructors:
* - proposal_create()
*
* @ingroup config
*/
struct proposal_t {
/**
* @brief Add an algorithm to the proposal.
*
* The algorithms are stored by priority, first added
* is the most preferred.
* Key size is only needed for encryption algorithms
* with variable key size (such as AES). Must be set
* to zero if key size is not specified.
* The alg parameter accepts encryption_algorithm_t,
* integrity_algorithm_t, dh_group_number_t and
* extended_sequence_numbers_t.
*
* @warning Do not add while other threads are reading.
*
* @param this calling object
* @param proto desired protocol
* @param type kind of algorithm
* @param alg identifier for algorithm
* @param key_size key size to use
*/
void (*add_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, u_int16_t alg, size_t key_size);
/**
* @brief Get an iterator over algorithms for a specifc protocol/algo type.
*
* @param this calling object
* @param proto desired protocol
* @param type kind of algorithm
* @return iterator over algorithms
*/
iterator_t *(*create_algorithm_iterator) (proposal_t *this, protocol_id_t proto, transform_type_t type);
/**
* @brief Get the algorithm for a type to use.
*
* If there are multiple algorithms, only the first is returned.
* Result is still owned by proposal, do not modify!
*
* @param this calling object
* @param proto desired protocol
* @param type kind of algorithm
* @param[out] algo pointer which receives algorithm and key size
* @return TRUE if algorithm of this kind available
*/
bool (*get_algorithm) (proposal_t *this, protocol_id_t proto, transform_type_t type, algorithm_t** algo);
/**
* @brief Compare two proposal, and select a matching subset.
*
* If the proposals are for the same protocols (AH/ESP), they are
* compared. If they have at least one algorithm of each type
* in common, a resulting proposal of this kind is created.
*
* @param this calling object
* @param other proposal to compair agains
* @return
* - selected proposal, if possible
* - NULL, if proposals don't match
*/
proposal_t *(*select) (proposal_t *this, proposal_t *other);
/**
* @brief Get the number set on construction.
*
* @param this calling object
* @return number
*/
u_int8_t (*get_number) (proposal_t *this);
/**
* @brief Get the protocol ids in the proposals.
*
* With AH and ESP, there could be two protocols in one
* proposal.
*
* @param this calling object
* @param ids array of protocol ids,
*/
void (*get_protocols) (proposal_t *this, protocol_id_t ids[2]);
/**
* @brief Get the spi for a specific protocol.
*
* @param this calling object
* @param proto AH/ESP
* @return spi for proto
*/
u_int64_t (*get_spi) (proposal_t *this, protocol_id_t proto);
/**
* @brief Set the spi for a specific protocol.
*
* @param this calling object
* @param proto AH/ESP
* @param spi spi to set for proto
*/
void (*set_spi) (proposal_t *this, protocol_id_t proto, u_int64_t spi);
/**
* @brief Clone a proposal.
*
* @param this proposal to clone
* @return clone of it
*/
proposal_t *(*clone) (proposal_t *this);
/**
* @brief Destroys the proposal object.
*
* @param this calling object
*/
void (*destroy) (proposal_t *this);
};
/**
* @brief Create a child proposal for AH and/or ESP.
*
* Since the order of multiple proposals is important for
* key derivation, we must assign them numbers as they
* appear in the raw payload. Numbering starts at 1.
*
* @param number number of the proposal, as in the payload
* @return proposal_t object
*
* @ingroup config
*/
proposal_t *proposal_create(u_int8_t number);
#endif /* PROPOSAL_H_ */
+425
View File
@@ -0,0 +1,425 @@
/**
* @file traffic_selector.c
*
* @brief Implementation of traffic_selector_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "traffic_selector.h"
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <arpa/inet.h>
#include <string.h>
typedef struct private_traffic_selector_t private_traffic_selector_t;
/**
* Private data of an traffic_selector_t object
*/
struct private_traffic_selector_t {
/**
* Public part
*/
traffic_selector_t public;
/**
* Type of address
*/
ts_type_t type;
/**
* IP protocol (UDP, TCP, ICMP, ...)
*/
u_int8_t protocol;
/**
* begin of address range, host order
*/
union {
u_int32_t from_addr_ipv4;
};
/**
* end of address range, host order
*/
union {
u_int32_t to_addr_ipv4;
};
/**
* begin of port range
*/
u_int16_t from_port;
/**
* end of port range
*/
u_int16_t to_port;
};
/**
* internal generic constructor
*/
static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port);
/**
* implements traffic_selector_t.get_subset
*/
static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
{
if ((this->type == TS_IPV4_ADDR_RANGE) &&
(other->type == TS_IPV4_ADDR_RANGE) &&
(this->protocol == other->protocol))
{
u_int32_t from_addr, to_addr;
u_int16_t from_port, to_port;
private_traffic_selector_t *new_ts;
/* calculate the maximum address range allowed for both */
from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4);
to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4);
if (from_addr > to_addr)
{
/* no match */
return NULL;
}
/* calculate the maximum port range allowed for both */
from_port = max(this->from_port, other->from_port);
to_port = min(this->to_port, other->to_port);
if (from_port > to_port)
{
/* no match */
return NULL;
}
/* got a match, return it */
new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port);
new_ts->from_addr_ipv4 = from_addr;
new_ts->to_addr_ipv4 = to_addr;
new_ts->type = TS_IPV4_ADDR_RANGE;
return &(new_ts->public);
}
return NULL;
}
/**
* Implements traffic_selector_t.get_from_address.
*/
static chunk_t get_from_address(private_traffic_selector_t *this)
{
chunk_t from_addr = CHUNK_INITIALIZER;
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
{
u_int32_t network;
from_addr.len = sizeof(network);
from_addr.ptr = malloc(from_addr.len);
/* chunk must contain network order, convert! */
network = htonl(this->from_addr_ipv4);
memcpy(from_addr.ptr, &network, from_addr.len);
break;
}
case TS_IPV6_ADDR_RANGE:
{
break;
}
}
return from_addr;
}
/**
* Implements traffic_selector_t.get_to_address.
*/
static chunk_t get_to_address(private_traffic_selector_t *this)
{
chunk_t to_addr = CHUNK_INITIALIZER;
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
{
u_int32_t network;
to_addr.len = sizeof(network);
to_addr.ptr = malloc(to_addr.len);
/* chunk must contain network order, convert! */
network = htonl(this->to_addr_ipv4);
memcpy(to_addr.ptr, &network, to_addr.len);
break;
}
case TS_IPV6_ADDR_RANGE:
{
break;
}
}
return to_addr;
}
/**
* Implements traffic_selector_t.get_from_port.
*/
static u_int16_t get_from_port(private_traffic_selector_t *this)
{
return this->from_port;
}
/**
* Implements traffic_selector_t.get_to_port.
*/
static u_int16_t get_to_port(private_traffic_selector_t *this)
{
return this->to_port;
}
/**
* Implements traffic_selector_t.get_type.
*/
static ts_type_t get_type(private_traffic_selector_t *this)
{
return this->type;
}
/**
* Implements traffic_selector_t.get_protocol.
*/
static u_int8_t get_protocol(private_traffic_selector_t *this)
{
return this->protocol;
}
/**
* Implements traffic_selector_t.get_netmask.
*/
static u_int8_t get_netmask(private_traffic_selector_t *this)
{
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
{
u_int32_t from, to, bit;
from = htonl(this->from_addr_ipv4);
to = htonl(this->to_addr_ipv4);
for (bit = 0; bit < 32; bit++)
{
if ((1<<bit & from) != (1<<bit & to))
{
return bit;
}
}
return 32;
}
case TS_IPV6_ADDR_RANGE:
default:
{
return 0;
}
}
}
/**
* Implements traffic_selector_t.update_address_range.
*/
static void update_address_range(private_traffic_selector_t *this, host_t *host)
{
if (host->get_family(host) == AF_INET &&
this->type == TS_IPV4_ADDR_RANGE)
{
if (this->from_addr_ipv4 == 0)
{
chunk_t from = host->get_address_as_chunk(host);
this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
this->to_addr_ipv4 = this->from_addr_ipv4;
chunk_free(&from);
}
}
}
/**
* Implements traffic_selector_t.clone.
*/
static traffic_selector_t *clone(private_traffic_selector_t *this)
{
private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port);
clone->type = this->type;
switch (clone->type)
{
case TS_IPV4_ADDR_RANGE:
{
clone->from_addr_ipv4 = this->from_addr_ipv4;
clone->to_addr_ipv4 = this->to_addr_ipv4;
return &(clone->public);
}
case TS_IPV6_ADDR_RANGE:
default:
{
free(this);
return NULL;
}
}
}
/**
* Implements traffic_selector_t.destroy.
*/
static void destroy(private_traffic_selector_t *this)
{
free(this);
}
/*
* see header
*/
traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port)
{
private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
this->type = type;
switch (type)
{
case TS_IPV4_ADDR_RANGE:
{
if (from_addr.len != 4 || to_addr.len != 4)
{
free(this);
return NULL;
}
/* chunk contains network order, convert! */
this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr));
this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr));
break;
}
case TS_IPV6_ADDR_RANGE:
default:
{
free(this);
return NULL;
}
}
return (&this->public);
}
/*
* see header
*/
traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits)
{
private_traffic_selector_t *this = traffic_selector_create(0, 0, 0, 65535);
switch (net->get_family(net))
{
case AF_INET:
{
chunk_t from;
this->type = TS_IPV4_ADDR_RANGE;
from = net->get_address_as_chunk(net);
this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
if (this->from_addr_ipv4 == 0)
{
/* use /32 for 0.0.0.0 */
this->to_addr_ipv4 = 0xFFFFFF;
}
else
{
this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1);
}
chunk_free(&from);
break;
}
case AF_INET6:
default:
{
free(this);
return NULL;
}
}
return (&this->public);
}
/*
* see header
*/
traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port)
{
private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
/* public functions */
this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
this->public.destroy = (void(*)(traffic_selector_t*))destroy;
this->type = type;
switch (type)
{
case TS_IPV4_ADDR_RANGE:
{
if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0)
{
free(this);
return NULL;
}
if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0)
{
free(this);
return NULL;
}
/* convert to host order, inet_aton has network order */
this->from_addr_ipv4 = ntohl(this->from_addr_ipv4);
this->to_addr_ipv4 = ntohl(this->to_addr_ipv4);
break;
}
case TS_IPV6_ADDR_RANGE:
{
free(this);
return NULL;
}
}
return (&this->public);
}
/*
* see declaration
*/
static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port)
{
private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
/* public functions */
this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
this->public.get_netmask = (u_int8_t(*)(traffic_selector_t*))get_netmask;
this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range;
this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone;
this->public.destroy = (void(*)(traffic_selector_t*))destroy;
this->from_port = from_port;
this->to_port = to_port;
this->protocol = protocol;
this->type = type;
return this;
}
+258
View File
@@ -0,0 +1,258 @@
/**
* @file traffic_selector.h
*
* @brief Interface of traffic_selector_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef TRAFFIC_SELECTOR_H_
#define TRAFFIC_SELECTOR_H_
#include <types.h>
#include <utils/host.h>
typedef enum ts_type_t ts_type_t;
/**
* Traffic selector types.
*
* @ingroup config
*/
enum ts_type_t {
/**
* A range of IPv4 addresses, represented by two four (4) octet
* values. The first value is the beginning IPv4 address
* (inclusive) and the second value is the ending IPv4 address
* (inclusive). All addresses falling between the two specified
* addresses are considered to be within the list.
*/
TS_IPV4_ADDR_RANGE = 7,
/**
* A range of IPv6 addresses, represented by two sixteen (16)
* octet values. The first value is the beginning IPv6 address
* (inclusive) and the second value is the ending IPv6 address
* (inclusive). All addresses falling between the two specified
* addresses are considered to be within the list.
*/
TS_IPV6_ADDR_RANGE = 8
};
/**
* string mappings for ts_type_t
*/
extern mapping_t ts_type_m[];
typedef struct traffic_selector_t traffic_selector_t;
/**
* @brief Object representing a traffic selector entry.
*
* A traffic selector defines an range of addresses
* and a range of ports. IPv6 is not fully supported yet.
*
* @b Constructors:
* - traffic_selector_create_from_bytes()
* - traffic_selector_create_from_string()
*
* @todo Add IPv6 support
*
* @ingroup config
*/
struct traffic_selector_t {
/**
* @brief Compare two traffic selectors, and create a new one
* which is the largest subset of both (subnet & port).
*
* Resulting traffic_selector is newly created and must be destroyed.
*
* @param this first to compare
* @param other second to compare
* @return
* - created subset of them
* - or NULL if no match between this and other
*/
traffic_selector_t *(*get_subset) (traffic_selector_t *this, traffic_selector_t *other);
/**
* @brief Clone a traffic selector.
*
* @param this traffic selector to clone
* @return clone of it
*/
traffic_selector_t *(*clone) (traffic_selector_t *this);
/**
* @brief Get starting address of this ts as a chunk.
*
* Data is in network order and represents the address.
* Size depends on protocol.
*
* Resulting chunk data is allocated and must be freed!
*
* @param this calling object
* @return chunk containing the address
*/
chunk_t (*get_from_address) (traffic_selector_t *this);
/**
* @brief Get ending address of this ts as a chunk.
*
* Data is in network order and represents the address.
* Size depends on protocol.
*
* Resulting chunk data is allocated and must be freed!
*
* @param this calling object
* @return chunk containing the address
*/
chunk_t (*get_to_address) (traffic_selector_t *this);
/**
* @brief Get starting port of this ts.
*
* Port is in host order, since the parser converts it.
* Size depends on protocol.
*
* @param this calling object
* @return port
*/
u_int16_t (*get_from_port) (traffic_selector_t *this);
/**
* @brief Get ending port of this ts.
*
* Port is in host order, since the parser converts it.
* Size depends on protocol.
*
* @param this calling object
* @return port
*/
u_int16_t (*get_to_port) (traffic_selector_t *this);
/**
* @brief Get the type of the traffic selector.
*
* @param this calling obect
* @return ts_type_t specifying the type
*/
ts_type_t (*get_type) (traffic_selector_t *this);
/**
* @brief Get the protocol id of this ts.
*
* @param this calling obect
* @return protocol id
*/
u_int8_t (*get_protocol) (traffic_selector_t *this);
/**
* @brief Get the netmask of the address range.
*
* Returns the number of bits associated to the subnet.
* (As the "24" in "192.168.0.0/24"). This is approximated
* if the address range is not a complete subnet! Since Linux
* does not support full IP address ranges (yet), we can't do this
* (much) better.
*
* @param this calling obect
* @return netmask as "bits for subnet"
*/
u_int8_t (*get_netmask) (traffic_selector_t *this);
/**
* @brief Update the address of a traffic selector.
*
* Update the address range of a traffic selector,
* if the current address is 0.0.0.0. The new address range
* starts from the supplied address and also ends there
* (which means it is a one-host-address-range ;-).
*
* @param this calling obect
* @param host host_t specifying the address range
*/
void (*update_address_range) (traffic_selector_t *this, host_t* host);
/**
* @brief Destroys the ts object
*
* @param this calling object
*/
void (*destroy) (traffic_selector_t *this);
};
/**
* @brief Create a new traffic selector using human readable params.
*
* @param protocol protocol for this ts, such as TCP or UDP
* @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
* @param from_addr start of address range as string
* @param from_port port number in host order
* @param to_addr end of address range as string
* @param to_port port number in host order
* @return
* - traffic_selector_t object
* - NULL if invalid address strings/protocol
*
* @ingroup config
*/
traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port);
/**
* @brief Create a new traffic selector using data read from the net.
*
* There exists a mix of network and host order in the params.
* But the parser gives us this data in this format, so we
* don't have to convert twice.
*
* @param protocol protocol for this ts, such as TCP or UDP
* @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
* @param from_address start of address range, network order
* @param from_port port number, host order
* @param to_address end of address range as string, network
* @param to_port port number, host order
* @return
* - traffic_selector_t object
* - NULL if invalid address input/protocol
*
* @ingroup config
*/
traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_address, int16_t from_port, chunk_t to_address, u_int16_t to_port);
/**
* @brief Create a new traffic selector defining a whole subnet.
*
* In most cases, definition of a traffic selector for full subnets
* is sufficient. This constructor creates a traffic selector for
* all protocols, all ports and the address range specified by the
* subnet.
*
* @param net subnet to use
* @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation
* @return
* - traffic_selector_t object
* - NULL if address family of net not supported
*
* @ingroup config
*/
traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits);
#endif /* TRAFFIC_SELECTOR_H_ */
+390
View File
@@ -0,0 +1,390 @@
/**
* @file daemon.c
*
* @brief Implementation of daemon_t and main of IKEv2-Daemon.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <execinfo.h>
#include <string.h>
#include "daemon.h"
#include <types.h>
#include <config/connections/local_connection_store.h>
#include <config/credentials/local_credential_store.h>
#include <config/policies/local_policy_store.h>
typedef struct private_daemon_t private_daemon_t;
/**
* Private additions to daemon_t, contains threads and internal functions.
*/
struct private_daemon_t {
/**
* Public members of daemon_t.
*/
daemon_t public;
/**
* A logger_t object assigned for daemon things.
*/
logger_t *logger;
/**
* Signal set used for signal handling.
*/
sigset_t signal_set;
/**
* The thread_id of main-thread.
*/
pthread_t main_thread_id;
/**
* Main loop function.
*
* @param this calling object
*/
void (*run) (private_daemon_t *this);
/**
* Initialize the daemon.
*
* @param this calling object
*/
void (*initialize) (private_daemon_t *this);
/**
* Destroy the daemon.
*
* @param this calling object
*/
void (*destroy) (private_daemon_t *this);
};
/**
* One and only instance of the daemon.
*/
daemon_t *charon;
/**
* Implementation of private_daemon_t.run.
*/
static void run(private_daemon_t *this)
{
/* reselect signals for this thread */
sigemptyset(&(this->signal_set));
sigaddset(&(this->signal_set), SIGINT);
sigaddset(&(this->signal_set), SIGHUP);
sigaddset(&(this->signal_set), SIGTERM);
pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0);
while(TRUE)
{
int signal_number;
int error;
error = sigwait(&(this->signal_set), &signal_number);
if(error)
{
this->logger->log(this->logger, ERROR, "Error %d when waiting for signal", error);
return;
}
switch (signal_number)
{
case SIGHUP:
{
this->logger->log(this->logger, CONTROL, "Signal of type SIGHUP received. Do nothing");
break;
}
case SIGINT:
{
this->logger->log(this->logger, CONTROL, "Signal of type SIGINT received. Exit main loop");
return;
}
case SIGTERM:
this->logger->log(this->logger, CONTROL, "Signal of type SIGTERM received. Exit main loop");
return;
default:
{
this->logger->log(this->logger, CONTROL, "Unknown signal %d received. Do nothing", signal_number);
break;
}
}
}
}
/**
* Implementation of daemon_t.kill.
*/
static void kill_daemon(private_daemon_t *this, char *reason)
{
/* we send SIGTERM, so the daemon can cleanly shut down */
this->logger->log(this->logger, CONTROL, "Killing daemon: %s", reason);
if (this->main_thread_id == pthread_self())
{
/* initialization failed, terminate daemon */
this->destroy(this);
unlink(PID_FILE);
exit(-1);
}
else
{
this->logger->log(this->logger, CONTROL, "sending SIGTERM to ourself", reason);
kill(0, SIGTERM);
/* thread must die, since he produced a ciritcal failure and can't continue */
pthread_exit(NULL);
}
}
/**
* Implementation of private_daemon_t.initialize.
*/
static void initialize(private_daemon_t *this)
{
local_credential_store_t* cred_store;
this->public.configuration = configuration_create();
this->public.socket = socket_create(IKEV2_UDP_PORT);
this->public.ike_sa_manager = ike_sa_manager_create();
this->public.job_queue = job_queue_create();
this->public.event_queue = event_queue_create();
this->public.send_queue = send_queue_create();
this->public.connections = (connection_store_t*)local_connection_store_create();
this->public.policies = (policy_store_t*)local_policy_store_create();
this->public.credentials = (credential_store_t*)(cred_store = local_credential_store_create());
/* load keys & certs */
cred_store->load_certificates(cred_store, CERTIFICATE_DIR);
cred_store->load_private_keys(cred_store, PRIVATE_KEY_DIR);
/* start building threads, we are multi-threaded NOW */
this->public.stroke = stroke_create();
this->public.sender = sender_create();
this->public.receiver = receiver_create();
this->public.scheduler = scheduler_create();
this->public.kernel_interface = kernel_interface_create();
this->public.thread_pool = thread_pool_create(NUMBER_OF_WORKING_THREADS);
}
/**
* Destory all initiated objects
*/
static void destroy(private_daemon_t *this)
{
if (this->public.ike_sa_manager != NULL)
{
this->public.ike_sa_manager->destroy(this->public.ike_sa_manager);
}
if (this->public.kernel_interface != NULL)
{
this->public.kernel_interface->destroy(this->public.kernel_interface);
}
if (this->public.receiver != NULL)
{
this->public.receiver->destroy(this->public.receiver);
}
if (this->public.scheduler != NULL)
{
this->public.scheduler->destroy(this->public.scheduler);
}
if (this->public.sender != NULL)
{
this->public.sender->destroy(this->public.sender);
}
if (this->public.thread_pool != NULL)
{
this->public.thread_pool->destroy(this->public.thread_pool);
}
if (this->public.job_queue != NULL)
{
this->public.job_queue->destroy(this->public.job_queue);
}
if (this->public.event_queue != NULL)
{
this->public.event_queue->destroy(this->public.event_queue);
}
if (this->public.send_queue != NULL)
{
this->public.send_queue->destroy(this->public.send_queue);
}
if (this->public.socket != NULL)
{
this->public.socket->destroy(this->public.socket);
}
if (this->public.configuration != NULL)
{
this->public.configuration->destroy(this->public.configuration);
}
if (this->public.credentials != NULL)
{
this->public.credentials->destroy(this->public.credentials);
}
if (this->public.connections != NULL)
{
this->public.connections->destroy(this->public.connections);
}
if (this->public.policies != NULL)
{
this->public.policies->destroy(this->public.policies);
}
if (this->public.stroke != NULL)
{
this->public.stroke->destroy(this->public.stroke);
}
free(this);
}
void signal_handler(int signal)
{
void *array[20];
size_t size;
char **strings;
size_t i;
logger_t *logger;
size = backtrace(array, 20);
strings = backtrace_symbols(array, size);
logger = logger_manager->get_logger(logger_manager, DAEMON);
logger->log(logger, ERROR, "Thread %u received SIGSEGV. Dumping %d frames from stack:", pthread_self(), size);
for (i = 0; i < size; i++)
{
logger->log(logger, ERROR, " %s", strings[i]);
}
free (strings);
logger->log(logger, ERROR, "Killing ourself hard after SIGSEGV");
kill(getpid(), SIGKILL);
}
/**
* @brief Create the daemon.
*
* @return created daemon_t
*/
private_daemon_t *daemon_create()
{
private_daemon_t *this = malloc_thing(private_daemon_t);
struct sigaction action;
/* assign methods */
this->run = run;
this->destroy = destroy;
this->initialize = initialize;
this->public.kill = (void (*) (daemon_t*,char*))kill_daemon;
/* NULL members for clean destruction */
this->public.socket = NULL;
this->public.ike_sa_manager = NULL;
this->public.job_queue = NULL;
this->public.event_queue = NULL;
this->public.send_queue = NULL;
this->public.configuration = NULL;
this->public.credentials = NULL;
this->public.connections = NULL;
this->public.policies = NULL;
this->public.sender= NULL;
this->public.receiver = NULL;
this->public.scheduler = NULL;
this->public.kernel_interface = NULL;
this->public.thread_pool = NULL;
this->public.stroke = NULL;
this->main_thread_id = pthread_self();
/* setup signal handling for all threads */
sigemptyset(&(this->signal_set));
sigaddset(&(this->signal_set), SIGSEGV);
sigaddset(&(this->signal_set), SIGINT);
sigaddset(&(this->signal_set), SIGHUP);
sigaddset(&(this->signal_set), SIGTERM);
pthread_sigmask(SIG_BLOCK, &(this->signal_set), 0);
/* setup SIGSEGV handler for all threads */
action.sa_handler = signal_handler;
action.sa_mask = this->signal_set;
action.sa_flags = 0;
if (sigaction(SIGSEGV, &action, NULL) == -1)
{
this->logger->log(this->logger, ERROR, "signal handler setup for SIGSEGV failed");
}
return this;
}
/**
* Main function, manages the daemon.
*/
int main(int argc, char *argv[])
{
private_daemon_t *private_charon;
FILE *pid_file;
struct stat stb;
int i;
/* trivial argument parsing */
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], "--use-syslog") == 0)
{
logger_manager->set_output(logger_manager, ALL_LOGGERS, NULL);
}
}
private_charon = daemon_create();
charon = (daemon_t*)private_charon;
private_charon->logger = logger_manager->get_logger(logger_manager, DAEMON);
/* initialize daemon */
private_charon->initialize(private_charon);
/* check/setup PID file */
if (stat(PID_FILE, &stb) == 0)
{
private_charon->logger->log(private_charon->logger, ERROR,
"charon already running (\""PID_FILE"\" exists)");
private_charon->destroy(private_charon);
exit(-1);
}
pid_file = fopen(PID_FILE, "w");
if (pid_file)
{
fprintf(pid_file, "%d\n", getpid());
fclose(pid_file);
}
/* run daemon */
private_charon->run(private_charon);
/* normal termination, cleanup and exit */
private_charon->destroy(private_charon);
unlink(PID_FILE);
return 0;
}
+324
View File
@@ -0,0 +1,324 @@
/**
* @file daemon.h
*
* @brief Interface of daemon_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef DAEMON_H_
#define DAEMON_H_
#include <threads/sender.h>
#include <threads/receiver.h>
#include <threads/scheduler.h>
#include <threads/kernel_interface.h>
#include <threads/thread_pool.h>
#include <threads/stroke_interface.h>
#include <network/socket.h>
#include <sa/ike_sa_manager.h>
#include <queues/send_queue.h>
#include <queues/job_queue.h>
#include <queues/event_queue.h>
#include <utils/logger_manager.h>
#include <config/configuration.h>
#include <config/connections/connection_store.h>
#include <config/policies/policy_store.h>
#include <config/credentials/credential_store.h>
/**
* @defgroup charon charon
*
* @brief IKEv2 keying daemon.
*
* @section Architecture
*
* All IKEv2 stuff is handled in charon. It uses a newer and more flexible
* architecture than pluto. Charon uses a thread-pool, which allows parallel
* execution SA-management. Beside the thread-pool, there are some special purpose
* threads which do their job for the common health of the daemon.
@verbatim
+------+
| E Q |
| v u |---+ +------+ +------+
| e e | | | | | IKE- |
| n u | +-----------+ | |--| SA |
| t e | | | | I M | +------+
+------------+ | - | | Scheduler | | K a |
| receiver | +------+ | | | E n | +------+
+----+-------+ +-----------+ | - a | | IKE- |
| | +------+ | | S g |--| SA |
+-------+--+ +-----| J Q |---+ +------------+ | A e | +------+
-| socket | | o u | | | | - r |
+-------+--+ | b e | | Thread- | | |
| | - u | | Pool | | |
+----+-------+ | e |------| |---| |
| sender | +------+ +------------+ +------+
+----+-------+
| +------+
| | S Q |
| | e u |
| | n e |
+------------| d u |
| - e |
+--+---+
@endverbatim
* The thread-pool is the heart of the architecture. It processes jobs from a
* (fully synchronized) job-queue. Mostly, a job is associated with a specific
* IKE SA. These IKE SAs are synchronized, only one thread can work one an IKE SA.
* This makes it unnecesary to use further synchronisation methods once a IKE SA
* is checked out. The (rather complex) synchronization of IKE SAs is completely
* done in the IKE SA manager.
* The sceduler is responsible for event firing. It waits until a event in the
* (fully synchronized) event-queue is ready for processing and pushes the event
* down to the job-queue. A thread form the pool will pick it up as quick as
* possible. Every thread can queue events or jobs. Furter, an event can place a
* packet in the send-queue. The sender thread waits for those packets and sends
* them over the wire, via the socket. The receiver does exactly the opposite of
* the sender. It waits on the socket, reads in packets an places them on the
* job-queue for further processing by a thread from the pool.
* There are even more threads, not drawn in the upper scheme. The stroke thread
* is responsible for reading and processessing commands from another process. The
* kernel interface thread handles communication from and to the kernel via a
* netlink socket. It waits for kernel events and processes them appropriately.
*/
/**
* @defgroup config config
*
* Classes implementing configuration related things.
*
* @ingroup charon
*/
/**
* @defgroup encoding encoding
*
* Classes used to encode and decode IKEv2 messages.
*
* @ingroup charon
*/
/**
* @defgroup payloads payloads
*
* Classes representing specific IKEv2 payloads.
*
* @ingroup encoding
*/
/**
* @defgroup network network
*
* Classes for network relevant stuff.
*
* @ingroup charon
*/
/**
* @defgroup queues queues
*
* Different kind of queues
* (thread save lists).
*
* @ingroup charon
*/
/**
* @defgroup jobs jobs
*
* Jobs used in job queue and event queue.
*
* @ingroup queues
*/
/**
* @defgroup sa sa
*
* Security associations for IKE and IPSec,
* and some helper classes.
*
* @ingroup charon
*/
/**
* @defgroup states states
*
* Varius states in which an IKE SA can be.
*
* @ingroup sa
*/
/**
* @defgroup threads threads
*
* Threaded classes, which will do their job alone.
*
* @ingroup charon
*/
/**
* Name of the daemon.
*
* @ingroup charon
*/
#define DAEMON_NAME "charon"
/**
* @brief Number of threads in the thread pool.
*
* There are several other threads, this defines
* only the number of threads in thread_pool_t.
*
* @ingroup charon
*/
#define NUMBER_OF_WORKING_THREADS 4
/**
* UDP Port on which the daemon will listen for incoming traffic.
*
* @ingroup charon
*/
#define IKEV2_UDP_PORT 500
/**
* PID file, in which charon stores its process id
*
* @ingroup charon
*/
#define PID_FILE "/var/run/charon.pid"
/**
* Directory of IPsec relevant files
*
* @ingroup charon
*/
#define IPSEC_DIR "/etc/ipsec.d"
/**
* Directory for private keys
*
* @ingroup charon
*/
#define PRIVATE_KEY_DIR IPSEC_DIR "/private"
/**
* Directory for trusted certificates
*
* @ingroup charon
*/
#define CERTIFICATE_DIR IPSEC_DIR "/certs"
typedef struct daemon_t daemon_t;
/**
* @brief Main class of daemon, contains some globals.
*
* @ingroup charon
*/
struct daemon_t {
/**
* A socket_t instance.
*/
socket_t *socket;
/**
* A send_queue_t instance.
*/
send_queue_t *send_queue;
/**
* A job_queue_t instance.
*/
job_queue_t *job_queue;
/**
* A event_queue_t instance.
*/
event_queue_t *event_queue;
/**
* A ike_sa_manager_t instance.
*/
ike_sa_manager_t *ike_sa_manager;
/**
* A configuration_t instance.
*/
configuration_t *configuration;
/**
* A connection_store_t instance.
*/
connection_store_t *connections;
/**
* A policy_store_t instance.
*/
policy_store_t *policies;
/**
* A credential_store_t instance.
*/
credential_store_t *credentials;
/**
* The Sender-Thread.
*/
sender_t *sender;
/**
* The Receiver-Thread.
*/
receiver_t *receiver;
/**
* The Scheduler-Thread.
*/
scheduler_t *scheduler;
/**
* The Thread pool managing the worker threads.
*/
thread_pool_t *thread_pool;
/**
* Kernel Interface to communicate with kernel
*/
kernel_interface_t *kernel_interface;
/**
* IPC interface, as whack in pluto
*/
stroke_t *stroke;
/**
* @brief Shut down the daemon.
*
* @param this the daemon to kill
* @param reason describtion why it will be killed
*/
void (*kill) (daemon_t *this, char *reason);
};
/**
* The one and only instance of the daemon.
*/
extern daemon_t *charon;
#endif /*DAEMON_H_*/
@@ -0,0 +1,30 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
ENCODING_DIR= $(CHARON_DIR)encoding/
CHARON_OBJS+= $(BUILD_DIR)generator.o
$(BUILD_DIR)generator.o : $(ENCODING_DIR)generator.c $(ENCODING_DIR)generator.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)parser.o
$(BUILD_DIR)parser.o : $(ENCODING_DIR)parser.c $(ENCODING_DIR)parser.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)message.o
$(BUILD_DIR)message.o : $(ENCODING_DIR)message.c $(ENCODING_DIR)message.h
$(CC) $(CFLAGS) -c -o $@ $<
include $(ENCODING_DIR)payloads/Makefile.payloads
File diff suppressed because it is too large. Load diff
+101
View File
@@ -0,0 +1,101 @@
/**
* @file generator.h
*
* @brief Interface of generator_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef GENERATOR_H_
#define GENERATOR_H_
#include <types.h>
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
/**
* Generating is done in a data buffer.
* This is thehe start size of this buffer in bytes.
*
* @ingroup enconding
*/
#define GENERATOR_DATA_BUFFER_SIZE 500
/**
* Number of bytes to increase the buffer, if it is to small.
*
* @ingroup enconding
*/
#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
typedef struct generator_t generator_t;
/**
* @brief A generator_t class used to generate IKEv2 payloads.
*
* After creation, multiple payloads can be generated with the generate_payload
* method. The generated bytes are appended. After all payloads are added,
* the write_to_chunk method writes out all generated data since
* the creation of the generator. After that, the generator must be destroyed.
* The generater uses a set of encoding rules, which it can get from
* the supplied payload. With this rules, the generater can generate
* the payload and all substructures automatically.
*
* @b Constructor:
* - generator_create()
*
* @ingroup encoding
*/
struct generator_t {
/**
* @brief Generates a specific payload from given payload object.
*
* Remember: Header and substructures are also handled as payloads.
*
* @param this generator_t object
* @param[in] payload interface payload_t implementing object
*/
void (*generate_payload) (generator_t *this,payload_t *payload);
/**
* @brief Writes all generated data of the generator to a chunk.
*
* @param this generator_t object
* @param[out] data chunk to write the data to
*/
void (*write_to_chunk) (generator_t *this,chunk_t *data);
/**
* @brief Destroys a generator_t object.
*
* @param this generator_t object
*/
void (*destroy) (generator_t *this);
};
/**
* @brief Constructor to create a generator.
*
* @return generator_t object.
*
* @ingroup encoding
*/
generator_t *generator_create();
#endif /*GENERATOR_H_*/
File diff suppressed because it is too large. Load diff
+367
View File
@@ -0,0 +1,367 @@
/**
* @file message.h
*
* @brief Interface of message_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef MESSAGE_H_
#define MESSAGE_H_
#include <types.h>
#include <sa/ike_sa_id.h>
#include <network/packet.h>
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/notify_payload.h>
#include <utils/linked_list.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
typedef struct message_t message_t;
/**
* @brief This class is used to represent an IKEv2-Message.
*
* The message handles parsing and generation of payloads
* via parser_t/generator_t. Encryption is done transparently
* via the encryption_payload_t. A set of rules for messages
* and payloads does check parsed messages.
*
* @b Constructors:
* - message_create()
* - message_create_from_packet()
* - message_create_notify_reply()
*
* @ingroup encoding
*/
struct message_t {
/**
* @brief Sets the IKE major version of the message.
*
* @param this message_t object
* @param major_version major version to set
*/
void (*set_major_version) (message_t *this,u_int8_t major_version);
/**
* @brief Gets the IKE major version of the message.
*
* @param this message_t object
* @return major version of the message
*/
u_int8_t (*get_major_version) (message_t *this);
/**
* @brief Sets the IKE minor version of the message.
*
* @param this message_t object
* @param minor_version minor version to set
*/
void (*set_minor_version) (message_t *this,u_int8_t minor_version);
/**
* @brief Gets the IKE minor version of the message.
*
* @param this message_t object
* @return minor version of the message
*/
u_int8_t (*get_minor_version) (message_t *this);
/**
* @brief Sets the Message ID of the message.
*
* @param this message_t object
* @param message_id message_id to set
*/
void (*set_message_id) (message_t *this,u_int32_t message_id);
/**
* @brief Gets the Message ID of the message.
*
* @param this message_t object
* @return message_id type of the message
*/
u_int32_t (*get_message_id) (message_t *this);
/**
* @brief Gets the responder SPI of the message.
*
* @param this message_t object
* @return responder spi of the message
*/
u_int64_t (*get_responder_spi) (message_t *this);
/**
* @brief Sets the IKE_SA ID of the message.
*
* @warning ike_sa_id gets cloned internaly and
* so can be destroyed afterwards.
*
* @param this message_t object
* @param ike_sa_id ike_sa_id to set
*/
void (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id);
/**
* @brief Gets the IKE_SA ID of the message.
*
* @warning The returned ike_sa_id is a clone of the internal one.
* So it has to be destroyed by the caller.
*
* @param this message_t object
* @param ike_sa_id pointer to ike_sa_id pointer which will be set
* @return
* - SUCCESS
* - FAILED if no ike_sa_id is set
*/
status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id);
/**
* @brief Sets the exchange type of the message.
*
* @param this message_t object
* @param exchange_type exchange_type to set
*/
void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type);
/**
* @brief Gets the exchange type of the message.
*
* @param this message_t object
* @return exchange type of the message
*/
exchange_type_t (*get_exchange_type) (message_t *this);
/**
* @brief Sets the request flag.
*
* @param this message_t object
* @param original_initiator TRUE if message is a request, FALSE if it is a reply
*/
void (*set_request) (message_t *this,bool request);
/**
* @brief Gets request flag.
*
* @param this message_t object
* @return TRUE if message is a request, FALSE if it is a reply
*/
bool (*get_request) (message_t *this);
/**
* @brief Append a payload to the message.
*
* If the payload must be encrypted is not specified here. Encryption
* of payloads is evaluated via internal rules for the messages and
* is done before generation. The order of payloads may change, since
* all payloads to encrypt are added to the encryption payload, which is
* always the last one.
*
* @param this message_t object
* @param payload payload to append
*/
void (*add_payload) (message_t *this, payload_t *payload);
/**
* @brief Parses header of message.
*
* Begins parisng of a message created via message_create_from_packet().
* The parsing context is stored, so a subsequent call to parse_body()
* will continue the parsing process.
*
* @param this message_t object
* @return
* - SUCCESS if header could be parsed
* - PARSE_ERROR if corrupted/invalid data found
* - FAILED if consistence check of header failed
*/
status_t (*parse_header) (message_t *this);
/**
* @brief Parses body of message.
*
* The body gets not only parsed, but rather it gets verified.
* All payloads are verified if they are allowed to exist in the message
* of this type and if their own structure is ok.
* If there are encrypted payloads, they get decrypted via the supplied
* crypter. Also the message integrity gets verified with the supplied
* signer.
* Crypter/signer can be omitted (by passing NULL) when no encryption
* payload is expected.
*
* @param this message_t object
* @param crypter crypter to decrypt encryption payloads
* @param signer signer to verifiy a message with an encryption payload
* @return
* - SUCCESS if header could be parsed
* - NOT_SUPPORTED if ciritcal unknown payloads found
* - FAILED if message type is not suppported!
* - PARSE_ERROR if corrupted/invalid data found
* - VERIFY_ERROR if verification of some payload failed
* - INVALID_STATE if crypter/signer not supplied, but needed
*/
status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer);
/**
* @brief Generates the UDP packet of specific message.
*
* Payloads which must be encrypted are generated first and added to
* an encryption payload. This encryption payload will get encrypted via
* the supplied crypter. Then all other payloads and the header get generated.
* After that, the checksum is added to the encryption payload over the full
* message.
* Crypter/signer can be omitted (by passing NULL) when no encryption
* payload is expected.
*
* @param this message_t object
* @param crypter crypter to use when a payload must be encrypted
* @param signer signer to build a mac
* @return
* - SUCCESS if packet could be generated
* - INVALID_STATE if exchange type is currently not set
* - NOT_FOUND if no rules found for message generation
* - INVALID_STATE if crypter/signer not supplied but needed.
*/
status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet);
/**
* @brief Gets the source host informations.
*
* @warning Returned host_t object is not getting cloned,
* do not destroy nor modify.
*
* @param this message_t object
* @return host_t object representing source host
*/
host_t * (*get_source) (message_t *this);
/**
* @brief Sets the source host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
* message_t.destroy or next call of message_t.set_source.
*
* @param this message_t object
* @param host host_t object representing source host
*/
void (*set_source) (message_t *this, host_t *host);
/**
* @brief Gets the destination host informations.
*
* @warning Returned host_t object is not getting cloned,
* do not destroy nor modify.
*
* @param this message_t object
* @return host_t object representing destination host
*/
host_t * (*get_destination) (message_t *this);
/**
* @brief Sets the destination host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
* message_t.destroy or next call of message_t.set_destination.
*
* @param this message_t object
* @param host host_t object representing destination host
*/
void (*set_destination) (message_t *this, host_t *host);
/**
* @brief Returns an iterator on all stored payloads.
*
* @warning Don't insert payloads over this iterator.
* Use add_payload() instead.
*
* @param this message_t object
* @return iterator_t object which has to get destroyd by the caller
*/
iterator_t * (*get_payload_iterator) (message_t *this);
/**
* Returns a clone of the internal stored packet_t object.
*
* @param this message_t object
* @return packet_t object as clone of internal one
*/
packet_t * (*get_packet) (message_t *this);
/**
* Returns a clone of the internal stored packet_t data.
*
* @param this message_t object
* @return clone of the internal stored packet_t data.
*/
chunk_t (*get_packet_data) (message_t *this);
/**
* @brief Destroys a message and all including objects.
*
* @param this message_t object
*/
void (*destroy) (message_t *this);
};
/**
* @brief Creates an message_t object from a incoming UDP Packet.
*
* @warning the given packet_t object is not copied and gets
* destroyed in message_t's destroy call.
*
* @warning Packet is not parsed in here!
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
* Call message_t.parse_header afterwards.
*
* @param packet packet_t object which is assigned to message
* @return message_t object
*
* @ingroup encoding
*/
message_t * message_create_from_packet(packet_t *packet);
/**
* @brief Creates an empty message_t object.
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
*
* @return message_t object
*
* @ingroup encoding
*/
message_t * message_create();
/**
* @brief Creates an message_t object of type reply containing a notify payload.
*
* @return message_t object
*
* @ingroup encoding
*/
message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type);
#endif /*MESSAGE_H_*/
File diff suppressed because it is too large. Load diff
+95
View File
@@ -0,0 +1,95 @@
/**
* @file parser.h
*
* @brief Interface of parser_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef PARSER_H_
#define PARSER_H_
#include <types.h>
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
typedef struct parser_t parser_t;
/**
* @brief A parser_t class to parse IKEv2 payloads.
*
* A parser is used for parsing one chunk of data. Multiple
* payloads can be parsed out of the chunk using parse_payload.
* The parser remains the state until destroyed.
*
* @b Constructors:
* - parser_create()
*
* @ingroup encoding
*/
struct parser_t {
/**
* @brief Parses the next payload.
*
* @warning Caller is responsible for freeing allocated payload.
*
* Rules for parsing are described in the payload definition.
*
* @param this parser_t bject
* @param payload_type payload type to parse
* @param[out] payload pointer where parsed payload was allocated
* @return
* - SUCCESSFUL if succeeded,
* - PARSE_ERROR if corrupted/invalid data found
*/
status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
/**
* Gets the remaining byte count which is not currently parsed.
*
* @param parser parser_t object
*/
int (*get_remaining_byte_count) (parser_t *this);
/**
* @brief Resets the current parser context.
*
* @param parser parser_t object
*/
void (*reset_context) (parser_t *this);
/**
* @brief Destroys a parser_t object.
*
* @param parser parser_t object
*/
void (*destroy) (parser_t *this);
};
/**
* @brief Constructor to create a parser_t object.
*
* @param data chunk of data to parse with this parser_t object
* @return parser_t object
*
* @ingroup encoding
*/
parser_t *parser_create(chunk_t data);
#endif /*PARSER_H_*/
@@ -0,0 +1,108 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
PAYLOADS_DIR= $(ENCODING_DIR)payloads/
CHARON_OBJS+= $(BUILD_DIR)encodings.o
$(BUILD_DIR)encodings.o : $(PAYLOADS_DIR)encodings.c $(PAYLOADS_DIR)encodings.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ike_header.o
$(BUILD_DIR)ike_header.o : $(PAYLOADS_DIR)ike_header.c $(PAYLOADS_DIR)ike_header.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ke_payload.o
$(BUILD_DIR)ke_payload.o : $(PAYLOADS_DIR)ke_payload.c $(PAYLOADS_DIR)ke_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)nonce_payload.o
$(BUILD_DIR)nonce_payload.o : $(PAYLOADS_DIR)nonce_payload.c $(PAYLOADS_DIR)nonce_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)notify_payload.o
$(BUILD_DIR)notify_payload.o : $(PAYLOADS_DIR)notify_payload.c $(PAYLOADS_DIR)notify_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)id_payload.o
$(BUILD_DIR)id_payload.o : $(PAYLOADS_DIR)id_payload.c $(PAYLOADS_DIR)id_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)auth_payload.o
$(BUILD_DIR)auth_payload.o : $(PAYLOADS_DIR)auth_payload.c $(PAYLOADS_DIR)auth_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)cert_payload.o
$(BUILD_DIR)cert_payload.o : $(PAYLOADS_DIR)cert_payload.c $(PAYLOADS_DIR)cert_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)certreq_payload.o
$(BUILD_DIR)certreq_payload.o : $(PAYLOADS_DIR)certreq_payload.c $(PAYLOADS_DIR)certreq_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)delete_payload.o
$(BUILD_DIR)delete_payload.o : $(PAYLOADS_DIR)delete_payload.c $(PAYLOADS_DIR)delete_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)vendor_id_payload.o
$(BUILD_DIR)vendor_id_payload.o : $(PAYLOADS_DIR)vendor_id_payload.c $(PAYLOADS_DIR)vendor_id_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)cp_payload.o
$(BUILD_DIR)cp_payload.o : $(PAYLOADS_DIR)cp_payload.c $(PAYLOADS_DIR)cp_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)configuration_attribute.o
$(BUILD_DIR)configuration_attribute.o : $(PAYLOADS_DIR)configuration_attribute.c $(PAYLOADS_DIR)configuration_attribute.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)eap_payload.o
$(BUILD_DIR)eap_payload.o : $(PAYLOADS_DIR)eap_payload.c $(PAYLOADS_DIR)eap_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)unknown_payload.o
$(BUILD_DIR)unknown_payload.o : $(PAYLOADS_DIR)unknown_payload.c $(PAYLOADS_DIR)unknown_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ts_payload.o
$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)traffic_selector_substructure.o
$(BUILD_DIR)traffic_selector_substructure.o : $(PAYLOADS_DIR)traffic_selector_substructure.c $(PAYLOADS_DIR)traffic_selector_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)payload.o
$(BUILD_DIR)payload.o : $(PAYLOADS_DIR)payload.c $(PAYLOADS_DIR)payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)proposal_substructure.o
$(BUILD_DIR)proposal_substructure.o : $(PAYLOADS_DIR)proposal_substructure.c $(PAYLOADS_DIR)proposal_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)sa_payload.o
$(BUILD_DIR)sa_payload.o : $(PAYLOADS_DIR)sa_payload.c $(PAYLOADS_DIR)sa_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)transform_attribute.o
$(BUILD_DIR)transform_attribute.o : $(PAYLOADS_DIR)transform_attribute.c $(PAYLOADS_DIR)transform_attribute.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)transform_substructure.o
$(BUILD_DIR)transform_substructure.o : $(PAYLOADS_DIR)transform_substructure.c $(PAYLOADS_DIR)transform_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)encryption_payload.o
$(BUILD_DIR)encryption_payload.o : $(PAYLOADS_DIR)encryption_payload.c $(PAYLOADS_DIR)encryption_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
@@ -0,0 +1,265 @@
/**
* @file auth_payload.h
*
* @brief Implementation of auth_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "auth_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_auth_payload_t private_auth_payload_t;
/**
* Private data of an auth_payload_t object.
*
*/
struct private_auth_payload_t {
/**
* Public auth_payload_t interface.
*/
auth_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Method of the AUTH Data.
*/
u_int8_t auth_method;
/**
* The contained auth data value.
*/
chunk_t auth_data;
};
/**
* Encoding rules to parse or generate a AUTH payload
*
* The defined offsets are the positions in a object of type
* private_auth_payload_t.
*
*/
encoding_rule_t auth_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_auth_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_auth_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)},
/* 1 Byte AUTH type*/
{ U_INT_8, offsetof(private_auth_payload_t, auth_method) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some auth data bytes, length is defined in PAYLOAD_LENGTH */
{ AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Auth Method ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Authentication Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_auth_payload_t *this)
{
if ((this->auth_method == 0) ||
((this->auth_method >= 4) && (this->auth_method <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of auth_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = auth_payload_encodings;
*rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_auth_payload_t *this)
{
return AUTHENTICATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_auth_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_auth_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_auth_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of auth_payload_t.set_auth_method.
*/
static void set_auth_method (private_auth_payload_t *this, auth_method_t method)
{
this->auth_method = method;
}
/**
* Implementation of auth_payload_t.get_auth_method.
*/
static auth_method_t get_auth_method (private_auth_payload_t *this)
{
return (this->auth_method);
}
/**
* Implementation of auth_payload_t.set_data.
*/
static void set_data (private_auth_payload_t *this, chunk_t data)
{
if (this->auth_data.ptr != NULL)
{
chunk_free(&(this->auth_data));
}
this->auth_data.ptr = clalloc(data.ptr,data.len);
this->auth_data.len = data.len;
this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
}
/**
* Implementation of auth_payload_t.get_data.
*/
static chunk_t get_data (private_auth_payload_t *this)
{
return (this->auth_data);
}
/**
* Implementation of auth_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_auth_payload_t *this)
{
chunk_t cloned_data;
if (this->auth_data.ptr == NULL)
{
return (this->auth_data);
}
cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len);
cloned_data.len = this->auth_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and auth_payload_t.destroy.
*/
static void destroy(private_auth_payload_t *this)
{
if (this->auth_data.ptr != NULL)
{
chunk_free(&(this->auth_data));
}
free(this);
}
/*
* Described in header
*/
auth_payload_t *auth_payload_create()
{
private_auth_payload_t *this = malloc_thing(private_auth_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (auth_payload_t *)) destroy;
this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method;
this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method;
this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH;
this->auth_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,122 @@
/**
* @file auth_payload.h
*
* @brief Interface of auth_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef AUTH_PAYLOAD_H_
#define AUTH_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <config/connections/connection.h>
/**
* Length of a auth payload without the auth data in bytes.
*
* @ingroup payloads
*/
#define AUTH_PAYLOAD_HEADER_LENGTH 8
typedef struct auth_payload_t auth_payload_t;
/**
* @brief Class representing an IKEv2 AUTH payload.
*
* The AUTH payload format is described in RFC section 3.8.
*
* @b Constructors:
* - auth_payload_create()
*
* @ingroup payloads
*/
struct auth_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the AUTH method.
*
* @param this calling auth_payload_t object
* @param method auth_method_t to use
*/
void (*set_auth_method) (auth_payload_t *this, auth_method_t method);
/**
* @brief Get the AUTH method.
*
* @param this calling auth_payload_t object
* @return auth_method_t used
*/
auth_method_t (*get_auth_method) (auth_payload_t *this);
/**
* @brief Set the AUTH data.
*
* Data are getting cloned.
*
* @param this calling auth_payload_t object
* @param data AUTH data as chunk_t
*/
void (*set_data) (auth_payload_t *this, chunk_t data);
/**
* @brief Get the AUTH data.
*
* Returned data are a copy of the internal one.
*
* @param this calling auth_payload_t object
* @return AUTH data as chunk_t
*/
chunk_t (*get_data_clone) (auth_payload_t *this);
/**
* @brief Get the AUTH data.
*
* Returned data are NOT copied
*
* @param this calling auth_payload_t object
* @return AUTH data as chunk_t
*/
chunk_t (*get_data) (auth_payload_t *this);
/**
* @brief Destroys an auth_payload_t object.
*
* @param this auth_payload_t object to destroy
*/
void (*destroy) (auth_payload_t *this);
};
/**
* @brief Creates an empty auth_payload_t object.
*
* @return auth_payload_t object
*
* @ingroup payloads
*/
auth_payload_t *auth_payload_create();
#endif /* AUTH_PAYLOAD_H_ */
@@ -0,0 +1,279 @@
/**
* @file cert_payload.c
*
* @brief Implementation of cert_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "cert_payload.h"
/**
* String mappings for cert_encoding_t.
*/
mapping_t cert_encoding_m[] = {
{PKCS7_WRAPPED_X509_CERTIFICATE, "PKCS7_WRAPPED_X509_CERTIFICATE"},
{PGP_CERTIFICATE, "PGP_CERTIFICATE"},
{DNS_SIGNED_KEY, "DNS_SIGNED_KEY"},
{X509_CERTIFICATE_SIGNATURE, "X509_CERTIFICATE_SIGNATURE"},
{KERBEROS_TOKEN, "KERBEROS_TOKEN"},
{CERTIFICATE_REVOCATION_LIST, "CERTIFICATE_REVOCATION_LIST"},
{AUTHORITY_REVOCATION_LIST, "AUTHORITY_REVOCATION_LIST"},
{SPKI_CERTIFICATE, "SPKI_CERTIFICATE"},
{X509_CERTIFICATE_ATTRIBUTE, "X509_CERTIFICATE_ATTRIBUTE"},
{RAW_SA_KEY, "RAW_SA_KEY"},
{HASH_AND_URL_X509_CERTIFICATE, "HASH_AND_URL_X509_CERTIFICATE"},
{HASH_AND_URL_X509_BUNDLE, "HASH_AND_URL_X509_BUNDLE"},
{MAPPING_END, NULL}
};
typedef struct private_cert_payload_t private_cert_payload_t;
/**
* Private data of an cert_payload_t object.
*
*/
struct private_cert_payload_t {
/**
* Public cert_payload_t interface.
*/
cert_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Encoding of the CERT Data.
*/
u_int8_t cert_encoding;
/**
* The contained cert data value.
*/
chunk_t cert_data;
};
/**
* Encoding rules to parse or generate a CERT payload
*
* The defined offsets are the positions in a object of type
* private_cert_payload_t.
*
*/
encoding_rule_t cert_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cert_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_cert_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
/* 1 Byte CERT type*/
{ U_INT_8, offsetof(private_cert_payload_t, cert_encoding) },
/* some cert data bytes, length is defined in PAYLOAD_LENGTH */
{ CERT_DATA, offsetof(private_cert_payload_t, cert_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certificate Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_cert_payload_t *this)
{
if ((this->cert_encoding == 0) ||
((this->cert_encoding >= 14) && (this->cert_encoding <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of cert_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cert_payload_encodings;
*rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_cert_payload_t *this)
{
return CERTIFICATE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_cert_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_cert_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_cert_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of cert_payload_t.set_cert_encoding.
*/
static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding)
{
this->cert_encoding = encoding;
}
/**
* Implementation of cert_payload_t.get_cert_encoding.
*/
static cert_encoding_t get_cert_encoding (private_cert_payload_t *this)
{
return (this->cert_encoding);
}
/**
* Implementation of cert_payload_t.set_data.
*/
static void set_data (private_cert_payload_t *this, chunk_t data)
{
if (this->cert_data.ptr != NULL)
{
chunk_free(&(this->cert_data));
}
this->cert_data.ptr = clalloc(data.ptr,data.len);
this->cert_data.len = data.len;
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len;
}
/**
* Implementation of cert_payload_t.get_data.
*/
static chunk_t get_data (private_cert_payload_t *this)
{
return (this->cert_data);
}
/**
* Implementation of cert_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_cert_payload_t *this)
{
chunk_t cloned_data;
if (this->cert_data.ptr == NULL)
{
return (this->cert_data);
}
cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len);
cloned_data.len = this->cert_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and cert_payload_t.destroy.
*/
static void destroy(private_cert_payload_t *this)
{
if (this->cert_data.ptr != NULL)
{
chunk_free(&(this->cert_data));
}
free(this);
}
/*
* Described in header
*/
cert_payload_t *cert_payload_create()
{
private_cert_payload_t *this = malloc_thing(private_cert_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (cert_payload_t *)) destroy;
this->public.set_cert_encoding = (void (*) (cert_payload_t *,cert_encoding_t)) set_cert_encoding;
this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t *)) get_cert_encoding;
this->public.set_data = (void (*) (cert_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (cert_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (cert_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =CERT_PAYLOAD_HEADER_LENGTH;
this->cert_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,155 @@
/**
* @file cert_payload.h
*
* @brief Interface of cert_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CERT_PAYLOAD_H_
#define CERT_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a cert payload without the cert data in bytes.
*
* @ingroup payloads
*/
#define CERT_PAYLOAD_HEADER_LENGTH 5
typedef enum cert_encoding_t cert_encoding_t;
/**
* @brief Certificate encoding, as described in IKEv2 RFC section 3.6
*
* @ingroup payloads
*/
enum cert_encoding_t {
PKCS7_WRAPPED_X509_CERTIFICATE = 1,
PGP_CERTIFICATE = 2,
DNS_SIGNED_KEY = 3,
X509_CERTIFICATE_SIGNATURE = 4,
KERBEROS_TOKEN = 6,
CERTIFICATE_REVOCATION_LIST = 7,
AUTHORITY_REVOCATION_LIST = 8,
SPKI_CERTIFICATE = 9,
X509_CERTIFICATE_ATTRIBUTE = 10,
RAW_SA_KEY = 11,
HASH_AND_URL_X509_CERTIFICATE = 12,
HASH_AND_URL_X509_BUNDLE = 13
};
/**
* string mappings for cert_encoding_t.
*
* @ingroup payloads
*/
extern mapping_t cert_encoding_m[];
typedef struct cert_payload_t cert_payload_t;
/**
* @brief Class representing an IKEv2 CERT payload.
*
* The CERT payload format is described in RFC section 3.6.
* This is just a dummy implementation to fullfill the standards
* requirements. A full implementation would offer setters/getters
* for the different encoding types.
*
* @b Constructors:
* - cert_payload_create()
*
* @todo Implement setters/getters for the different certificate encodings.
*
* @ingroup payloads
*/
struct cert_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the CERT encoding.
*
* @param this calling cert_payload_t object
* @param encoding CERT encoding
*/
void (*set_cert_encoding) (cert_payload_t *this, cert_encoding_t encoding);
/**
* @brief Get the CERT encoding.
*
* @param this calling cert_payload_t object
* @return Encoding of the CERT
*/
cert_encoding_t (*get_cert_encoding) (cert_payload_t *this);
/**
* @brief Set the CERT data.
*
* Data are getting cloned.
*
* @param this calling cert_payload_t object
* @param data CERT data as chunk_t
*/
void (*set_data) (cert_payload_t *this, chunk_t data);
/**
* @brief Get the CERT data.
*
* Returned data are a copy of the internal one.
*
* @param this calling cert_payload_t object
* @return CERT data as chunk_t
*/
chunk_t (*get_data_clone) (cert_payload_t *this);
/**
* @brief Get the CERT data.
*
* Returned data are NOT copied.
*
* @param this calling cert_payload_t object
* @return CERT data as chunk_t
*/
chunk_t (*get_data) (cert_payload_t *this);
/**
* @brief Destroys an cert_payload_t object.
*
* @param this cert_payload_t object to destroy
*/
void (*destroy) (cert_payload_t *this);
};
/**
* @brief Creates an empty cert_payload_t object.
*
* @return cert_payload_t object
*
* @ingroup payloads
*/
cert_payload_t *cert_payload_create();
#endif /* CERT_PAYLOAD_H_ */
@@ -0,0 +1,259 @@
/**
* @file certreq_payload.c
*
* @brief Implementation of certreq_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "certreq_payload.h"
typedef struct private_certreq_payload_t private_certreq_payload_t;
/**
* Private data of an certreq_payload_t object.
*
*/
struct private_certreq_payload_t {
/**
* Public certreq_payload_t interface.
*/
certreq_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Encoding of the CERT Data.
*/
u_int8_t cert_encoding;
/**
* The contained certreq data value.
*/
chunk_t certreq_data;
};
/**
* Encoding rules to parse or generate a CERTREQ payload
*
* The defined offsets are the positions in a object of type
* private_certreq_payload_t.
*
*/
encoding_rule_t certreq_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_certreq_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)},
/* 1 Byte CERTREQ type*/
{ U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)},
/* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
{ CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certification Authority ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_certreq_payload_t *this)
{
if ((this->cert_encoding == 0) ||
((this->cert_encoding >= 14) && (this->cert_encoding <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of certreq_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = certreq_payload_encodings;
*rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_certreq_payload_t *this)
{
return CERTIFICATE_REQUEST;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_certreq_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_certreq_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_certreq_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of certreq_payload_t.set_cert_encoding.
*/
static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding)
{
this->cert_encoding = encoding;
}
/**
* Implementation of certreq_payload_t.get_cert_encoding.
*/
static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this)
{
return (this->cert_encoding);
}
/**
* Implementation of certreq_payload_t.set_data.
*/
static void set_data (private_certreq_payload_t *this, chunk_t data)
{
if (this->certreq_data.ptr != NULL)
{
chunk_free(&(this->certreq_data));
}
this->certreq_data.ptr = clalloc(data.ptr,data.len);
this->certreq_data.len = data.len;
this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len;
}
/**
* Implementation of certreq_payload_t.get_data.
*/
static chunk_t get_data (private_certreq_payload_t *this)
{
return (this->certreq_data);
}
/**
* Implementation of certreq_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_certreq_payload_t *this)
{
chunk_t cloned_data;
if (this->certreq_data.ptr == NULL)
{
return (this->certreq_data);
}
cloned_data.ptr = clalloc(this->certreq_data.ptr,this->certreq_data.len);
cloned_data.len = this->certreq_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and certreq_payload_t.destroy.
*/
static void destroy(private_certreq_payload_t *this)
{
if (this->certreq_data.ptr != NULL)
{
chunk_free(&(this->certreq_data));
}
free(this);
}
/*
* Described in header
*/
certreq_payload_t *certreq_payload_create()
{
private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (certreq_payload_t *)) destroy;
this->public.set_cert_encoding = (void (*) (certreq_payload_t *,cert_encoding_t)) set_cert_encoding;
this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t *)) get_cert_encoding;
this->public.set_data = (void (*) (certreq_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (certreq_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (certreq_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH;
this->certreq_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,125 @@
/**
* @file certreq_payload.h
*
* @brief Interface of certreq_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CERTREQ_PAYLOAD_H_
#define CERTREQ_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/cert_payload.h>
/**
* Length of a CERTREQ payload without the CERTREQ data in bytes.
*
* @ingroup payloads
*/
#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
typedef struct certreq_payload_t certreq_payload_t;
/**
* @brief Class representing an IKEv2 CERTREQ payload.
*
* The CERTREQ payload format is described in RFC section 3.7.
* This is just a dummy implementation to fullfill the standards
* requirements. A full implementation would offer setters/getters
* for the different encoding types.
*
* @b Constructors:
* - certreq_payload_create()
*
* @todo Implement payload functionality.
*
* @ingroup payloads
*/
struct certreq_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the CERT encoding.
*
* @param this calling certreq_payload_t object
* @param encoding CERT encoding
*/
void (*set_cert_encoding) (certreq_payload_t *this, cert_encoding_t encoding);
/**
* @brief Get the CERT encoding.
*
* @param this calling certreq_payload_t object
* @return Encoding of the CERT
*/
cert_encoding_t (*get_cert_encoding) (certreq_payload_t *this);
/**
* @brief Set the CERTREQ data.
*
* Data are getting cloned.
*
* @param this calling certreq_payload_t object
* @param data CERTREQ data as chunk_t
*/
void (*set_data) (certreq_payload_t *this, chunk_t data);
/**
* @brief Get the CERTREQ data.
*
* Returned data are a copy of the internal one.
*
* @param this calling certreq_payload_t object
* @return CERTREQ data as chunk_t
*/
chunk_t (*get_data_clone) (certreq_payload_t *this);
/**
* @brief Get the CERTREQ data.
*
* Returned data are NOT copied.
*
* @param this calling certreq_payload_t object
* @return CERTREQ data as chunk_t
*/
chunk_t (*get_data) (certreq_payload_t *this);
/**
* @brief Destroys an certreq_payload_t object.
*
* @param this certreq_payload_t object to destroy
*/
void (*destroy) (certreq_payload_t *this);
};
/**
* @brief Creates an empty certreq_payload_t object.
*
* @return certreq_payload_t object
*
* @ingroup payloads
*/
certreq_payload_t *certreq_payload_create();
#endif /* CERTREQ_PAYLOAD_H_ */
@@ -0,0 +1,282 @@
/**
* @file configuration_attribute.c
*
* @brief Implementation of configuration_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "configuration_attribute.h"
#include <encoding/payloads/encodings.h>
#include <types.h>
typedef struct private_configuration_attribute_t private_configuration_attribute_t;
/**
* Private data of an configuration_attribute_t object.
*
*/
struct private_configuration_attribute_t {
/**
* Public configuration_attribute_t interface.
*/
configuration_attribute_t public;
/**
* Type of the attribute.
*/
u_int16_t attribute_type;
/**
* Length of the attribute.
*/
u_int16_t attribute_length;
/**
* Attribute value as chunk.
*/
chunk_t attribute_value;
};
/**
* String mappings for configuration_attribute_type_t.
*/
mapping_t configuration_attribute_type_m[] = {
{INTERNAL_IP4_ADDRESS, "INTERNAL_IP4_ADDRESS"},
{INTERNAL_IP4_NETMASK, "INTERNAL_IP4_NETMASK"},
{INTERNAL_IP4_DNS, "INTERNAL_IP4_DNS"},
{INTERNAL_IP4_NBNS, "INTERNAL_IP4_NBNS"},
{INTERNAL_ADDRESS_EXPIRY, "INTERNAL_ADDRESS_EXPIRY"},
{INTERNAL_IP4_DHCP, "INTERNAL_IP4_DHCP"},
{APPLICATION_VERSION, "APPLICATION_VERSION"},
{INTERNAL_IP6_ADDRESS, "INTERNAL_IP6_ADDRESS"},
{INTERNAL_IP6_DNS, "INTERNAL_IP6_DNS"},
{INTERNAL_IP6_NBNS, "INTERNAL_IP6_NBNS"},
{INTERNAL_IP6_DHCP, "INTERNAL_IP6_DHCP"},
{INTERNAL_IP4_SUBNET, "INTERNAL_IP4_SUBNET"},
{SUPPORTED_ATTRIBUTES, "SUPPORTED_ATTRIBUTES"},
{INTERNAL_IP6_SUBNET, "INTERNAL_IP6_SUBNET"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a configuration attribute.
*
* The defined offsets are the positions in a object of type
* private_configuration_attribute_t.
*
*/
encoding_rule_t configuration_attribute_encodings[] = {
{ RESERVED_BIT, 0 },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attribute_type) },
/* Length of attribute value */
{ CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, attribute_length)},
/* Value of attribute if attribute format flag is zero */
{ CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, attribute_value)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!R| Attribute Type ! Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Value ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_configuration_attribute_t *this)
{
switch (this->attribute_type)
{
case INTERNAL_IP4_ADDRESS:
case INTERNAL_IP4_NETMASK:
case INTERNAL_IP4_DNS:
case INTERNAL_IP4_NBNS:
case INTERNAL_ADDRESS_EXPIRY:
case INTERNAL_IP4_DHCP:
case APPLICATION_VERSION:
case INTERNAL_IP6_ADDRESS:
case INTERNAL_IP6_DNS:
case INTERNAL_IP6_NBNS:
case INTERNAL_IP6_DHCP:
case INTERNAL_IP4_SUBNET:
case SUPPORTED_ATTRIBUTES:
case INTERNAL_IP6_SUBNET:
{
/* Attribute types are not checked in here */
break;
}
default:
return FAILED;
}
if (this->attribute_length != this->attribute_value.len)
{
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_configuration_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = configuration_attribute_encodings;
*rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_configuration_attribute_t *this)
{
return CONFIGURATION_ATTRIBUTE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_configuration_attribute_t *this)
{
return (NO_PAYLOAD);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_configuration_attribute_t *this,payload_type_t type)
{
}
/**
* Implementation of configuration_attribute_t.get_length.
*/
static size_t get_length(private_configuration_attribute_t *this)
{
return (this->attribute_value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH);
}
/**
* Implementation of configuration_attribute_t.set_value.
*/
static void set_value(private_configuration_attribute_t *this, chunk_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
chunk_free(&(this->attribute_value));
}
this->attribute_value.ptr = clalloc(value.ptr,value.len);
this->attribute_value.len = value.len;
this->attribute_length = this->attribute_value.len;
}
/**
* Implementation of configuration_attribute_t.get_value.
*/
static chunk_t get_value (private_configuration_attribute_t *this)
{
return this->attribute_value;
}
/**
* Implementation of configuration_attribute_t.set_attribute_type.
*/
static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
/**
* Implementation of configuration_attribute_t.get_attribute_type.
*/
static u_int16_t get_attribute_type (private_configuration_attribute_t *this)
{
return this->attribute_type;
}
/**
* Implementation of configuration_attribute_t.get_attribute_length.
*/
static u_int16_t get_attribute_length (private_configuration_attribute_t *this)
{
return this->attribute_length;
}
/**
* Implementation of configuration_attribute_t.destroy and payload_t.destroy.
*/
static void destroy(private_configuration_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
free(this->attribute_value.ptr);
}
free(this);
}
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create()
{
private_configuration_attribute_t *this = malloc_thing(private_configuration_attribute_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.set_value = (void (*) (configuration_attribute_t *,chunk_t)) set_value;
this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value;
this->public.set_attribute_type = (void (*) (configuration_attribute_t *,u_int16_t type)) set_attribute_type;
this->public.get_attribute_type = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_type;
this->public.get_attribute_length = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_length;
this->public.destroy = (void (*) (configuration_attribute_t *)) destroy;
/* set default values of the fields */
this->attribute_type = 0;
this->attribute_value = CHUNK_INITIALIZER;
this->attribute_length = 0;
return (&(this->public));
}
@@ -0,0 +1,149 @@
/**
* @file configuration_attribute.h
*
* @brief Interface of configuration_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CONFIGURATION_ATTRIBUTE_H_
#define CONFIGURATION_ATTRIBUTE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Configuration attribute header length in bytes.
*
* @ingroup payloads
*/
#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
typedef enum configuration_attribute_type_t configuration_attribute_type_t;
/**
* Type of the attribute, as in IKEv2 RFC 3.15.1.
*
* @ingroup payloads
*/
enum configuration_attribute_type_t {
INTERNAL_IP4_ADDRESS = 1,
INTERNAL_IP4_NETMASK = 2,
INTERNAL_IP4_DNS = 3,
INTERNAL_IP4_NBNS = 4,
INTERNAL_ADDRESS_EXPIRY = 5,
INTERNAL_IP4_DHCP = 6,
APPLICATION_VERSION = 7,
INTERNAL_IP6_ADDRESS = 8,
INTERNAL_IP6_DNS = 10,
INTERNAL_IP6_NBNS = 11,
INTERNAL_IP6_DHCP = 12,
INTERNAL_IP4_SUBNET = 13,
SUPPORTED_ATTRIBUTES = 14,
INTERNAL_IP6_SUBNET = 15
};
/**
* String mappings for configuration_attribute_type_t.
*
* @ingroup payloads
*/
extern mapping_t configuration_attribute_type_m[];
typedef struct configuration_attribute_t configuration_attribute_t;
/**
* @brief Class representing an IKEv2-CONFIGURATION Attribute.
*
* The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
*
* @b Constructors:
* - configuration_attribute_create()
*
* @ingroup payloads
*/
struct configuration_attribute_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling configuration_attribute_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_value) (configuration_attribute_t *this);
/**
* @brief Sets the value of the attribute.
*
* @warning Value is getting copied.
*
* @param this calling configuration_attribute_t object
* @param value chunk_t pointing to the value to set
*/
void (*set_value) (configuration_attribute_t *this, chunk_t value);
/**
* @brief Sets the type of the attribute.
*
* @param this calling configuration_attribute_t object
* @param type type to set (most significant bit is set to zero)
*/
void (*set_attribute_type) (configuration_attribute_t *this, u_int16_t type);
/**
* @brief get the type of the attribute.
*
* @param this calling configuration_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_type) (configuration_attribute_t *this);
/**
* @brief get the length of an attribute.
*
* @param this calling configuration_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_length) (configuration_attribute_t *this);
/**
* @brief Destroys an configuration_attribute_t object.
*
* @param this configuration_attribute_t object to destroy
*/
void (*destroy) (configuration_attribute_t *this);
};
/**
* @brief Creates an empty configuration_attribute_t object.
*
* @return created configuration_attribute_t object
*
* @ingroup payloads
*/
configuration_attribute_t *configuration_attribute_create();
#endif /* CONFIGURATION_ATTRIBUTE_H_*/
@@ -0,0 +1,305 @@
/**
* @file cp_payload.c
*
* @brief Implementation of cp_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "cp_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
/**
* String mappings for config_type_t.
*/
mapping_t config_type_m[] = {
{CFG_REQUEST, "CFG_REQUEST"},
{CFG_REPLY, "CFG_REPLY"},
{CFG_SET, "CFG_SET"},
{CFG_ACK, "CFG_ACK"},
{MAPPING_END, NULL}
};
typedef struct private_cp_payload_t private_cp_payload_t;
/**
* Private data of an cp_payload_t object.
*
*/
struct private_cp_payload_t {
/**
* Public cp_payload_t interface.
*/
cp_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Configuration Attributes in this payload are stored in a linked_list_t.
*/
linked_list_t * attributes;
/**
* Config Type.
*/
u_int8_t config_type;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_cp_payload_t object
*/
void (*compute_length) (private_cp_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-CP Payload
*
* The defined offsets are the positions in a object of type
* private_cp_payload_t.
*
*/
encoding_rule_t cp_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_cp_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole CP payload*/
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ U_INT_8, offsetof(private_cp_payload_t, config_type) },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
{ CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! CFG Type ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Configuration Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_cp_payload_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while(iterator->has_next(iterator))
{
configuration_attribute_t *attribute;
iterator->current(iterator,(void **)&attribute);
status = attribute->payload_interface.verify(&(attribute->payload_interface));
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cp_payload_encodings;
*rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_cp_payload_t *this)
{
return CONFIGURATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_cp_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_cp_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_cp_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of cp_payload_t.create_configuration_attribute_iterator.
*/
static iterator_t *create_configuration_attribute_iterator (private_cp_payload_t *this,bool forward)
{
return this->attributes->create_iterator(this->attributes,forward);
}
/**
* Implementation of cp_payload_t.add_proposal_substructure.
*/
static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes,(void *) attribute);
this->compute_length(this);
}
/**
* Implementation of cp_payload_t.set_config_type.
*/
static void set_config_type (private_cp_payload_t *this,config_type_t config_type)
{
this->config_type = config_type;
}
/**
* Implementation of cp_payload_t.get_config_type.
*/
static config_type_t get_config_type (private_cp_payload_t *this)
{
return this->config_type;
}
/**
* Implementation of private_cp_payload_t.compute_length.
*/
static void compute_length (private_cp_payload_t *this)
{
iterator_t *iterator;
size_t length = CP_PAYLOAD_HEADER_LENGTH;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while (iterator->has_next(iterator))
{
payload_t *current_attribute;
iterator->current(iterator,(void **) &current_attribute);
length += current_attribute->get_length(current_attribute);
}
iterator->destroy(iterator);
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy and cp_payload_t.destroy.
*/
static status_t destroy(private_cp_payload_t *this)
{
/* all attributes are getting destroyed */
while (this->attributes->get_count(this->attributes) > 0)
{
configuration_attribute_t *current_attribute;
this->attributes->remove_last(this->attributes,(void **)&current_attribute);
current_attribute->destroy(current_attribute);
}
this->attributes->destroy(this->attributes);
free(this);
return SUCCESS;
}
/*
* Described in header.
*/
cp_payload_t *cp_payload_create()
{
private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
/* public interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_configuration_attribute_iterator = (iterator_t* (*) (cp_payload_t *,bool)) create_configuration_attribute_iterator;
this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute;
this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type;
this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type;
this->public.destroy = (void (*) (cp_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
this->attributes = linked_list_create();
return (&(this->public));
}
@@ -0,0 +1,138 @@
/**
* @file cp_payload.h
*
* @brief Interface of cp_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef CP_PAYLOAD_H_
#define CP_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <utils/linked_list.h>
/**
* CP_PAYLOAD length in bytes without any proposal substructure.
*
* @ingroup payloads
*/
#define CP_PAYLOAD_HEADER_LENGTH 8
typedef enum config_type_t config_type_t;
/**
* Config Type of an Configuration Payload.
*
* @ingroup payloads
*/
enum config_type_t {
CFG_REQUEST = 1,
CFG_REPLY = 2,
CFG_SET = 3,
CFG_ACK = 4,
};
/**
* string mappings for config_type_t.
*
* @ingroup payloads
*/
extern mapping_t config_type_m[];
typedef struct cp_payload_t cp_payload_t;
/**
* @brief Class representing an IKEv2-CP Payload.
*
* The CP Payload format is described in RFC section 3.15.
*
* @b Constructors:
* - cp_payload_create()
*
* @ingroup payloads
*/
struct cp_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored configuration_attribute_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an attribute using this iterator,
* the length of this configuration_attribute_t has to be refreshed
* by calling get_length()!
*
* @param this calling cp_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_configuration_attribute_iterator) (cp_payload_t *this, bool forward);
/**
* @brief Adds a configuration_attribute_t object to this object.
*
* @warning The added configuration_attribute_t object is
* getting destroyed in destroy function of cp_payload_t.
*
* @param this calling cp_payload_t object
* @param attribute configuration_attribute_t object to add
*/
void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute);
/**
* @brief Set the config type.
*
* @param this calling cp_payload_t object
* @param config_type config_type_t to set
*/
void (*set_config_type) (cp_payload_t *this,config_type_t config_type);
/**
* @brief Get the config type.
*
* @param this calling cp_payload_t object
* @return config_type_t
*/
config_type_t (*get_config_type) (cp_payload_t *this);
/**
* @brief Destroys an cp_payload_t object.
*
* @param this cp_payload_t object to destroy
*/
void (*destroy) (cp_payload_t *this);
};
/**
* @brief Creates an empty cp_payload_t object
*
* @return cp_payload_t object
*
* @ingroup payloads
*/
cp_payload_t *cp_payload_create();
#endif /*CP_PAYLOAD_H_*/
@@ -0,0 +1,322 @@
/**
* @file delete_payload.c
*
* @brief Implementation of delete_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "delete_payload.h"
typedef struct private_delete_payload_t private_delete_payload_t;
/**
* Private data of an delete_payload_t object.
*
*/
struct private_delete_payload_t {
/**
* Public delete_payload_t interface.
*/
delete_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Protocol ID.
*/
u_int8_t protocol_id;
/**
* SPI Size.
*/
u_int8_t spi_size;
/**
* Number of SPI's.
*/
u_int16_t spi_count;
/**
* The contained SPI's.
*/
chunk_t spis;
};
/**
* Encoding rules to parse or generate a DELETE payload
*
* The defined offsets are the positions in a object of type
* private_delete_payload_t.
*
*/
encoding_rule_t delete_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_delete_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length)},
{ U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
{ U_INT_8, offsetof(private_delete_payload_t, spi_size) },
{ U_INT_16, offsetof(private_delete_payload_t, spi_count) },
/* some delete data bytes, length is defined in PAYLOAD_LENGTH */
{ SPIS, offsetof(private_delete_payload_t, spis) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! # of SPIs !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index(es) (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_delete_payload_t *this)
{
if ((this->protocol_id == 0) ||
(this->protocol_id > 3))
{
/* reserved IDs */
return FAILED;
}
if (this->spis.len != (this->spi_count * this->spi_size))
{
return FAILED;
}
if ((this->protocol_id == PROTO_IKE) && (this->spis.len != 0))
{
/* IKE deletion has no spi assigned! */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of delete_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = delete_payload_encodings;
*rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_delete_payload_t *this)
{
return DELETE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_delete_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_delete_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_delete_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of delete_payload_t.set_protocol_id.
*/
static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of delete_payload_t.get_protocol_id.
*/
static protocol_id_t get_protocol_id (private_delete_payload_t *this)
{
return (this->protocol_id);
}
/**
* Implementation of delete_payload_t.set_spi_size.
*/
static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size)
{
this->spi_size = spi_size;
}
/**
* Implementation of delete_payload_t.get_spi_size.
*/
static u_int8_t get_spi_size (private_delete_payload_t *this)
{
return (this->spi_size);
}
/**
* Implementation of delete_payload_t.set_spi_count.
*/
static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count)
{
this->spi_count = spi_count;
}
/**
* Implementation of delete_payload_t.get_spi_count.
*/
static u_int16_t get_spi_count (private_delete_payload_t *this)
{
return (this->spi_count);
}
/**
* Implementation of delete_payload_t.set_spis.
*/
static void set_spis (private_delete_payload_t *this, chunk_t spis)
{
if (this->spis.ptr != NULL)
{
chunk_free(&(this->spis));
}
this->spis.ptr = clalloc(spis.ptr,spis.len);
this->spis.len = spis.len;
this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len;
}
/**
* Implementation of delete_payload_t.get_spis.
*/
static chunk_t get_spis (private_delete_payload_t *this)
{
return (this->spis);
}
/**
* Implementation of delete_payload_t.get_spis_clone.
*/
static chunk_t get_spis_clone (private_delete_payload_t *this)
{
chunk_t cloned_spis;
if (this->spis.ptr == NULL)
{
return (this->spis);
}
cloned_spis.ptr = clalloc(this->spis.ptr,this->spis.len);
cloned_spis.len = this->spis.len;
return cloned_spis;
}
/**
* Implementation of payload_t.destroy and delete_payload_t.destroy.
*/
static void destroy(private_delete_payload_t *this)
{
if (this->spis.ptr != NULL)
{
chunk_free(&(this->spis));
}
free(this);
}
/*
* Described in header
*/
delete_payload_t *delete_payload_create()
{
private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (delete_payload_t *)) destroy;
this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id;
this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size;
this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size;
this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count;
this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count;
this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis;
this->public.get_spis_clone = (chunk_t (*) (delete_payload_t *)) get_spis_clone;
this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =DELETE_PAYLOAD_HEADER_LENGTH;
this->protocol_id = PROTO_NONE;
this->spi_size = 0;
this->spi_count = 0;
this->spis = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,156 @@
/**
* @file delete_payload.h
*
* @brief Interface of delete_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef DELETE_PAYLOAD_H_
#define DELETE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
/**
* Length of a delete payload without the SPI in bytes.
*
* @ingroup payloads
*/
#define DELETE_PAYLOAD_HEADER_LENGTH 8
typedef struct delete_payload_t delete_payload_t;
/**
* @brief Class representing an IKEv2 DELETE payload.
*
* The DELETE payload format is described in RFC section 3.11.
*
* @b Constructors:
* - delete_payload_create()
*
* @todo Implement better setter/getters
*
* @ingroup payloads
*/
struct delete_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the protocol ID.
*
* @param this calling delete_payload_t object
* @param protocol_id protocol ID
*/
void (*set_protocol_id) (delete_payload_t *this, protocol_id_t protocol_id);
/**
* @brief Get the protocol ID.
*
* @param this calling delete_payload_t object
* @return protocol ID
*/
protocol_id_t (*get_protocol_id) (delete_payload_t *this);
/**
* @brief Set the SPI size.
*
*
* @param this calling delete_payload_t object
* @param spi_size SPI size
*/
void (*set_spi_size) (delete_payload_t *this, u_int8_t spi_size);
/**
* @brief Get the SPI size.
*
* @param this calling delete_payload_t object
* @return SPI size
*/
u_int8_t (*get_spi_size) (delete_payload_t *this);
/**
* @brief Set the SPI count.
*
* @param this calling delete_payload_t object
* @param spi_count SPI count
*/
void (*set_spi_count) (delete_payload_t *this, u_int16_t spi_count);
/**
* @brief Get the SPI count.
*
* @param this calling delete_payload_t object
* @return Number of SPI's
*/
u_int16_t (*get_spi_count) (delete_payload_t *this);
/**
* @brief Set the SPI's.
*
* Data are getting cloned.
*
* @param this calling delete_payload_t object
* @param data SPI's as chunk_t
*/
void (*set_spis) (delete_payload_t *this, chunk_t spis);
/**
* @brief Get the SPI's.
*
* Returned data are a copy of the internal one.
*
* @param this calling delete_payload_t object
* @return SPI's chunk_t
*/
chunk_t (*get_spis_clone) (delete_payload_t *this);
/**
* @brief Get the SPI's.
*
* Returned data are NOT copied.
*
* @param this calling delete_payload_t object
* @return SPI's as chunk_t
*/
chunk_t (*get_spis) (delete_payload_t *this);
/**
* @brief Destroys an delete_payload_t object.
*
* @param this delete_payload_t object to destroy
*/
void (*destroy) (delete_payload_t *this);
};
/**
* @brief Creates an empty delete_payload_t object.
*
* @return delete_payload_t object
*
* @ingroup payloads
*/
delete_payload_t *delete_payload_create();
#endif /* DELETE_PAYLOAD_H_ */
@@ -0,0 +1,227 @@
/**
* @file eap_payload.c
*
* @brief Implementation of eap_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "eap_payload.h"
typedef struct private_eap_payload_t private_eap_payload_t;
/**
* Private data of an eap_payload_t object.
*
*/
struct private_eap_payload_t {
/**
* Public eap_payload_t interface.
*/
eap_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained message.
*/
chunk_t message;
};
/**
* Encoding rules to parse or generate a EAP payload.
*
* The defined offsets are the positions in a object of type
* private_eap_payload_t.
*
*/
encoding_rule_t eap_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_eap_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_eap_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length)},
/* some eap data bytes, length is defined in PAYLOAD_LENGTH */
{ EAP_MESSAGE, offsetof(private_eap_payload_t, message) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ EAP Message ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_eap_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of eap_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = eap_payload_encodings;
*rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_eap_payload_t *this)
{
return EXTENSIBLE_AUTHENTICATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_eap_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_eap_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_eap_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of eap_payload_t.set_message.
*/
static void set_message (private_eap_payload_t *this, chunk_t message)
{
if (this->message.ptr != NULL)
{
chunk_free(&(this->message));
}
this->message.ptr = clalloc(message.ptr,message.len);
this->message.len = message.len;
this->payload_length = EAP_PAYLOAD_HEADER_LENGTH + this->message.len;
}
/**
* Implementation of eap_payload_t.get_message.
*/
static chunk_t get_message (private_eap_payload_t *this)
{
return (this->message);
}
/**
* Implementation of eap_payload_t.get_data_clone.
*/
static chunk_t get_message_clone (private_eap_payload_t *this)
{
chunk_t cloned_message;
if (this->message.ptr == NULL)
{
return (this->message);
}
cloned_message.ptr = clalloc(this->message.ptr,this->message.len);
cloned_message.len = this->message.len;
return cloned_message;
}
/**
* Implementation of payload_t.destroy and eap_payload_t.destroy.
*/
static void destroy(private_eap_payload_t *this)
{
if (this->message.ptr != NULL)
{
chunk_free(&(this->message));
}
free(this);
}
/*
* Described in header
*/
eap_payload_t *eap_payload_create()
{
private_eap_payload_t *this = malloc_thing(private_eap_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (eap_payload_t *)) destroy;
this->public.set_message = (void (*) (eap_payload_t *,chunk_t)) set_message;
this->public.get_message_clone = (chunk_t (*) (eap_payload_t *)) get_message_clone;
this->public.get_message = (chunk_t (*) (eap_payload_t *)) get_message;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = EAP_PAYLOAD_HEADER_LENGTH;
this->message = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,105 @@
/**
* @file eap_payload.h
*
* @brief Interface of eap_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef EAP_PAYLOAD_H_
#define EAP_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a EAP payload without the EAP Message in bytes.
*
* @ingroup payloads
*/
#define EAP_PAYLOAD_HEADER_LENGTH 4
typedef struct eap_payload_t eap_payload_t;
/**
* @brief Class representing an IKEv2 EAP payload.
*
* The EAP payload format is described in RFC section 3.16.
*
* @b Constructors:
* - eap_payload_create()
*
* @todo Implement functionality for this payload
*
* @ingroup payloads
*/
struct eap_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the EAP Message.
*
* Data are getting cloned.
*
* @param this calling eap_payload_t object
* @param message EAP message as chunk_t
*/
void (*set_message) (eap_payload_t *this, chunk_t message);
/**
* @brief Get the EAP message.
*
* Returned data are a copy of the internal one.
*
* @param this calling eap_payload_t object
* @return EAP message as chunk_t
*/
chunk_t (*get_message_clone) (eap_payload_t *this);
/**
* @brief Get the EAP message.
*
* Returned data are NOT copied.
*
* @param this calling eap_payload_t object
* @return EAP message as chunk_t
*/
chunk_t (*get_message) (eap_payload_t *this);
/**
* @brief Destroys an eap_payload_t object.
*
* @param this eap_payload_t object to destroy
*/
void (*destroy) (eap_payload_t *this);
};
/**
* @brief Creates an empty eap_payload_t object.
*
* @return eap_payload_t object
*
* @ingroup payloads
*/
eap_payload_t *eap_payload_create();
#endif /* EAP_PAYLOAD_H_ */
@@ -0,0 +1,68 @@
/**
* @file encodings.c
*
* @brief String mappings of encoding_type_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "encodings.h"
mapping_t encoding_type_m[] = {
{U_INT_4, "U_INT_4"},
{U_INT_8, "U_INT_8"},
{U_INT_16, "U_INT_16"},
{U_INT_32, "U_INT_32"},
{U_INT_64, "U_INT_64"},
{IKE_SPI, "IKE_SPI"},
{RESERVED_BIT, "RESERVED_BIT"},
{RESERVED_BYTE, "RESERVED_BYTE"},
{FLAG, "FLAG"},
{PAYLOAD_LENGTH, "PAYLOAD_LENGTH"},
{HEADER_LENGTH, "HEADER_LENGTH"},
{SPI_SIZE, "SPI_SIZE"},
{SPI, "SPI"},
{KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"},
{NOTIFICATION_DATA, "NOTIFICATION_DATA"},
{PROPOSALS, "PROPOSALS"},
{TRANSFORMS, "TRANSFORMS"},
{TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"},
{ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"},
{ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"},
{ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"},
{ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"},
{NONCE_DATA, "NONCE_DATA"},
{ID_DATA, "ID_DATA"},
{AUTH_DATA, "AUTH_DATA"},
{ENCRYPTED_DATA, "ENCRYPTED_DATA"},
{TS_TYPE, "TS_TYPE"},
{ADDRESS, "ADDRESS"},
{TRAFFIC_SELECTORS, "TRAFFIC_SELECTORS"},
{CERT_DATA, "CERT_DATA"},
{CERTREQ_DATA, "CERTREQ_DATA"},
{SPIS, "SPIS"},
{VID_DATA, "VID_DATA"},
{VID_DATA, "VID_DATA"},
{CONFIGURATION_ATTRIBUTES, "CONFIGURATION_ATTRIBUTES"},
{CONFIGURATION_ATTRIBUTE_LENGTH, "CONFIGURATION_ATTRIBUTE_LENGTH"},
{CONFIGURATION_ATTRIBUTE_VALUE, "CONFIGURATION_ATTRIBUTE_VALUE"},
{EAP_MESSAGE, "EAP_MESSAGE"},
{UNKNOWN_DATA,"UNKNOWN_DATA"},
{MAPPING_END, NULL}
};
@@ -0,0 +1,540 @@
/**
* @file encodings.h
*
* @brief Definition of encoding_type_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef ENCODINGS_H_
#define ENCODINGS_H_
#include <types.h>
#include <definitions.h>
typedef enum encoding_type_t encoding_type_t;
/**
* @brief All different kinds of encoding types.
*
* Each field of an IKEv2-Message (in header or payload)
* which has to be parsed or generated differently has its own
* type defined here.
*
* Header is parsed like a payload and gets its one payload_id
* from PRIVATE USE space. Also the substructures
* of specific payload types get their own payload_id
* from PRIVATE_USE space. See IKEv2-Draft for more informations.
*
* @ingroup payloads
*/
enum encoding_type_t {
/**
* Representing a 4 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 4 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 4 bit forward afterwards.
*/
U_INT_4,
/**
* Representing a 8 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
U_INT_8,
/**
* Representing a 16 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
U_INT_16,
/**
* Representing a 32 Bit unsigned int value.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
U_INT_32,
/**
* Representing a 64 Bit unsigned int value.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 64 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 64 bit forward afterwards.
*/
U_INT_64,
/**
* @brief represents a RESERVED_BIT used in FLAG-Bytes.
*
* When generating, the next bit is set to zero and the current write
* position is moved one bit forward.
* No value is read from the associated data struct.
* The current write position is moved 1 bit forward afterwards.
*
* When parsing, the current read pointer is moved one bit forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 bit forward afterwards.
*/
RESERVED_BIT,
/**
* @brief represents a RESERVED_BYTE.
*
* When generating, the next byte is set to zero and the current write
* position is moved one byte forward.
* No value is read from the associated data struct.
* The current write position is moved 1 byte forward afterwards.
*
* When parsing, the current read pointer is moved one byte forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 byte forward afterwards.
*/
RESERVED_BYTE,
/**
* Representing a 1 Bit flag.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards
*/
FLAG,
/**
* Representating a length field of a payload.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
PAYLOAD_LENGTH,
/**
* Representating a length field of a header.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
HEADER_LENGTH,
/**
* Representating a spi size field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
SPI_SIZE,
/**
* Representating a spi field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
SPI,
/**
* Representating a Key Exchange Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
KEY_EXCHANGE_DATA,
/**
* Representating a Notification field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
*/
NOTIFICATION_DATA,
/**
* Representating one or more proposal substructures.
*
* The offset points to a linked_list_t pointer.
*
* When generating the proposal_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed proposal_substructure_t objects have
* to be stored in the pointed linked_list.
*/
PROPOSALS,
/**
* Representating one or more transform substructures.
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_substructure_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORMS,
/**
* Representating one or more Attributes of a transform substructure.
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_attribute_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_attribute_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORM_ATTRIBUTES,
/**
* Representating one or more Attributes of a configuration payload.
*
* The offset points to a linked_list_t pointer.
*
* When generating the configuration_attribute_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed configuration_attribute_t objects have
* to be stored in the pointed linked_list.
*/
CONFIGURATION_ATTRIBUTES,
/**
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
CONFIGURATION_ATTRIBUTE_VALUE,
/**
* Representing a 1 Bit flag specifying the format of a transform attribute.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards.
*/
ATTRIBUTE_FORMAT,
/**
* Representing a 15 Bit unsigned int value used as attribute type
* in an attribute transform.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 15 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 15 bit forward afterwards.
*/
ATTRIBUTE_TYPE,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
* this field contains the length or the value of an transform attribute.
* Its stored in a 16 unsigned integer field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
ATTRIBUTE_LENGTH_OR_VALUE,
/**
* This field contains the length or the value of an configuration attribute.
* Its stored in a 16 unsigned integer field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
CONFIGURATION_ATTRIBUTE_LENGTH,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
* this field is available or missing and so parsed/generated
* or not parsed/not generated.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
ATTRIBUTE_VALUE,
/**
* Representating one or more Traffic selectors of a TS payload.
*
* The offset points to a linked_list_t pointer.
*
* When generating the traffic_selector_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed traffic_selector_substructure_t objects have
* to be stored in the pointed linked_list.
*/
TRAFFIC_SELECTORS,
/**
* Representating a Traffic selector type field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
TS_TYPE,
/**
* Representating an address field in a traffic selector.
*
* Depending on the last field of type TS_TYPE
* this field is either 4 or 16 byte long.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing 4 or 16 bytes are read and written into the chunk pointing to.
*/
ADDRESS,
/**
* Representating a Nonce Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
NONCE_DATA,
/**
* Representating a ID Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
ID_DATA,
/**
* Representating a AUTH Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
AUTH_DATA,
/**
* Representating a CERT Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
*/
CERT_DATA,
/**
* Representating a CERTREQ Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
*/
CERTREQ_DATA,
/**
* Representating an EAP message field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
EAP_MESSAGE,
/**
* Representating the SPIS field in a DELETE payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
SPIS,
/**
* Representating the VID DATA field in a VENDOR ID payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
VID_DATA,
/**
* Representating the DATA of an unknown payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
UNKNOWN_DATA,
/**
* Representating an IKE_SPI field in an IKEv2 Header.
*
* When generating the value of the u_int64_t pointing to
* is written (host and networ order is not changed).
*
* When parsing 8 bytes are read and written into the u_int64_t pointing to.
*/
IKE_SPI,
/**
* Representing the encrypted data body of a encryption payload.
*/
ENCRYPTED_DATA,
};
/**
* mappings to map encoding_type_t's to strings
*
* @ingroup payloads
*/
extern mapping_t encoding_type_m[];
typedef struct encoding_rule_t encoding_rule_t;
/**
* An encoding rule is a mapping of a specific encoding type to
* a location in the data struct where the current field is stored to
* or read from.
*
* For examples see files in this directory.
*
* This rules are used by parser and generator.
*
* @ingroup payloads
*/
struct encoding_rule_t {
/**
* Encoding type.
*/
encoding_type_t type;
/**
* Offset in the data struct.
*
* When parsing, data are written to this offset of the
* data struct.
*
* When generating, data are read from this offset in the
* data struct.
*/
u_int32_t offset;
};
#endif /*ENCODINGS_H_*/
@@ -0,0 +1,702 @@
/**
* @file encryption_payload.c
*
* @brief Implementation of encryption_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include <string.h>
#include "encryption_payload.h"
#include <daemon.h>
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
#include <utils/logger.h>
#include <encoding/generator.h>
#include <encoding/parser.h>
#include <utils/iterator.h>
#include <utils/randomizer.h>
#include <crypto/signers/signer.h>
typedef struct private_encryption_payload_t private_encryption_payload_t;
/**
* Private data of an encryption_payload_t' Object.
*
*/
struct private_encryption_payload_t {
/**
* Public encryption_payload_t interface.
*/
encryption_payload_t public;
/**
* There is no next payload for an encryption payload,
* since encryption payload MUST be the last one.
* next_payload means here the first payload of the
* contained, encrypted payload.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* Chunk containing the iv, data, padding,
* and (an eventually not calculated) signature.
*/
chunk_t encrypted;
/**
* Chunk containing the data in decrypted (unpadded) form.
*/
chunk_t decrypted;
/**
* Signer set by set_signer.
*/
signer_t *signer;
/**
* Crypter, supplied by encrypt/decrypt
*/
crypter_t *crypter;
/**
* Contained payloads of this encrpytion_payload.
*/
linked_list_t *payloads;
/**
* logger for this payload, uses MESSAGE context
*/
logger_t *logger;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_encryption_payload_t object
*/
void (*compute_length) (private_encryption_payload_t *this);
/**
* @brief Generate payloads (unencrypted) in chunk decrypted.
*
* @param this calling private_encryption_payload_t object
*/
void (*generate) (private_encryption_payload_t *this);
/**
* @brief Parse payloads from a (unencrypted) chunk.
*
* @param this calling private_encryption_payload_t object
*/
status_t (*parse) (private_encryption_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-Encryption Payload.
*
* The defined offsets are the positions in a object of type
* private_encryption_payload_t.
*
*/
encoding_rule_t encryption_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_encryption_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole encryption payload*/
{ PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
/* encrypted data, stored in a chunk. contains iv, data, padding */
{ ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initialization Vector !
! (length is block size for encryption algorithm) !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Encrypted IKE Payloads !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ! Padding (0-255 octets) !
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
! ! Pad Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Integrity Checksum Data ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_encryption_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = encryption_payload_encodings;
*rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_encryption_payload_t *this)
{
return ENCRYPTED;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_encryption_payload_t *this)
{
/* returns first contained payload here */
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_encryption_payload_t *this, payload_type_t type)
{
/* set next type is not allowed, since this payload MUST be the last one
* and so nothing is done in here*/
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_encryption_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of payload_t.create_payload_iterator.
*/
static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward)
{
return (this->payloads->create_iterator(this->payloads, forward));
}
/**
* Implementation of payload_t.add_payload.
*/
static void add_payload(private_encryption_payload_t *this, payload_t *payload)
{
payload_t *last_payload;
if (this->payloads->get_count(this->payloads) > 0)
{
this->payloads->get_last(this->payloads,(void **) &last_payload);
last_payload->set_next_type(last_payload, payload->get_type(payload));
}
else
{
this->next_payload = payload->get_type(payload);
}
payload->set_next_type(payload, NO_PAYLOAD);
this->payloads->insert_last(this->payloads, (void*)payload);
this->compute_length(this);
}
/**
* Implementation of encryption_payload_t.remove_first_payload.
*/
static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload)
{
return this->payloads->remove_first(this->payloads, (void**)payload);
}
/**
* Implementation of encryption_payload_t.get_payload_count.
*/
static size_t get_payload_count(private_encryption_payload_t *this)
{
return this->payloads->get_count(this->payloads);
}
/**
* Implementation of encryption_payload_t.encrypt.
*/
static status_t encrypt(private_encryption_payload_t *this)
{
chunk_t iv, padding, to_crypt, result;
randomizer_t *randomizer;
status_t status;
size_t block_size;
if (this->signer == NULL || this->crypter == NULL)
{
this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set");
return INVALID_STATE;
}
/* for random data in iv and padding */
randomizer = randomizer_create();
/* build payload chunk */
this->generate(this);
this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads");
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted);
/* build padding */
block_size = this->crypter->get_block_size(this->crypter);
padding.len = block_size - ((this->decrypted.len + 1) % block_size);
status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding);
if (status != SUCCESS)
{
randomizer->destroy(randomizer);
return status;
}
/* concatenate payload data, padding, padding len */
to_crypt.len = this->decrypted.len + padding.len + 1;
to_crypt.ptr = malloc(to_crypt.len);
memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len);
memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len);
*(to_crypt.ptr + to_crypt.len - 1) = padding.len;
/* build iv */
iv.len = block_size;
status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv);
randomizer->destroy(randomizer);
if (status != SUCCESS)
{
chunk_free(&to_crypt);
chunk_free(&padding);
return status;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt);
/* encrypt to_crypt chunk */
free(this->encrypted.ptr);
status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result);
free(padding.ptr);
free(to_crypt.ptr);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed");
free(iv.ptr);
return status;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result);
/* build encrypted result with iv and signature */
this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
free(this->encrypted.ptr);
this->encrypted.ptr = malloc(this->encrypted.len);
/* fill in result, signature is left out */
memcpy(this->encrypted.ptr, iv.ptr, iv.len);
memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len);
free(result.ptr);
free(iv.ptr);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted);
return SUCCESS;
}
/**
* Implementation of encryption_payload_t.encrypt.
*/
static status_t decrypt(private_encryption_payload_t *this)
{
chunk_t iv, concatenated;
u_int8_t padding_length;
status_t status;
this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload");
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted);
if (this->signer == NULL || this->crypter == NULL)
{
this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set");
return INVALID_STATE;
}
/* get IV */
iv.len = this->crypter->get_block_size(this->crypter);
iv.ptr = this->encrypted.ptr;
/* point concatenated to data + padding + padding_length*/
concatenated.ptr = this->encrypted.ptr + iv.len;
concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer);
/* check the size of input:
* concatenated must be at least on block_size of crypter
*/
if (concatenated.len < iv.len)
{
this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input");
return FAILED;
}
/* free previus data, if any */
free(this->decrypted.ptr);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated);
status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted));
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed");
return FAILED;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted);
/* get padding length, sits just bevore signature */
padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
/* add one byte to the padding length, since the padding_length field is not included */
padding_length++;
this->decrypted.len -= padding_length;
/* check size again */
if (padding_length > concatenated.len || this->decrypted.len < 0)
{
this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?");
/* decryption failed :-/ */
return FAILED;
}
/* free padding */
this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted);
this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content");
return (this->parse(this));
}
/**
* Implementation of encryption_payload_t.set_transforms.
*/
static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer)
{
this->signer = signer;
this->crypter = crypter;
}
/**
* Implementation of encryption_payload_t.build_signature.
*/
static status_t build_signature(private_encryption_payload_t *this, chunk_t data)
{
chunk_t data_without_sig = data;
chunk_t sig;
if (this->signer == NULL)
{
this->logger->log(this->logger, ERROR, "unable to build signature, no signer set");
return INVALID_STATE;
}
sig.len = this->signer->get_block_size(this->signer);
data_without_sig.len -= sig.len;
sig.ptr = data.ptr + data_without_sig.len;
this->logger->log(this->logger, CONTROL|LEVEL2, "building signature");
this->signer->get_signature(this->signer, data_without_sig, sig.ptr);
return SUCCESS;
}
/**
* Implementation of encryption_payload_t.verify_signature.
*/
static status_t verify_signature(private_encryption_payload_t *this, chunk_t data)
{
chunk_t sig, data_without_sig;
bool valid;
if (this->signer == NULL)
{
this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set");
return INVALID_STATE;
}
/* find signature in data chunk */
sig.len = this->signer->get_block_size(this->signer);
if (data.len <= sig.len)
{
this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input");
return FAILED;
}
sig.ptr = data.ptr + data.len - sig.len;
/* verify it */
data_without_sig.len = data.len - sig.len;
data_without_sig.ptr = data.ptr;
valid = this->signer->verify_signature(this->signer, data_without_sig, sig);
if (!valid)
{
this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed");
return FAILED;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful");
return SUCCESS;
}
/**
* Implementation of private_encryption_payload_t.generate.
*/
static void generate(private_encryption_payload_t *this)
{
payload_t *current_payload, *next_payload;
generator_t *generator;
iterator_t *iterator;
/* recalculate length before generating */
this->compute_length(this);
/* create iterator */
iterator = this->payloads->create_iterator(this->payloads, TRUE);
/* get first payload */
if (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current_payload);
this->next_payload = current_payload->get_type(current_payload);
}
else
{
/* no paylads? */
this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available");
free(this->decrypted.ptr);
this->decrypted = CHUNK_INITIALIZER;
iterator->destroy(iterator);
return;
}
generator = generator_create();
/* build all payload, except last */
while(iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&next_payload);
current_payload->set_next_type(current_payload, next_payload->get_type(next_payload));
generator->generate_payload(generator, current_payload);
current_payload = next_payload;
}
iterator->destroy(iterator);
/* build last payload */
current_payload->set_next_type(current_payload, NO_PAYLOAD);
generator->generate_payload(generator, current_payload);
/* free already generated data */
free(this->decrypted.ptr);
generator->write_to_chunk(generator, &(this->decrypted));
generator->destroy(generator);
this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload");
}
/**
* Implementation of private_encryption_payload_t.parse.
*/
static status_t parse(private_encryption_payload_t *this)
{
parser_t *parser;
status_t status;
payload_type_t current_payload_type;
/* check if there is decrypted data */
if (this->decrypted.ptr == NULL)
{
this->logger->log(this->logger, ERROR, "unable to parse, no input!");
return INVALID_STATE;
}
/* build a parser on the decrypted data */
parser = parser_create(this->decrypted);
current_payload_type = this->next_payload;
/* parse all payloads */
while (current_payload_type != NO_PAYLOAD)
{
payload_t *current_payload;
status = parser->parse_payload(parser, current_payload_type, (payload_t**)&current_payload);
if (status != SUCCESS)
{
parser->destroy(parser);
return PARSE_ERROR;
}
status = current_payload->verify(current_payload);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s",
mapping_find(payload_type_m,current_payload->get_type(current_payload)),
mapping_find(status_m, status));
current_payload->destroy(current_payload);
parser->destroy(parser);
return VERIFY_ERROR;
}
/* get next payload type */
current_payload_type = current_payload->get_next_type(current_payload);
this->payloads->insert_last(this->payloads,current_payload);
}
parser->destroy(parser);
this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload");
return SUCCESS;
}
/**
* Implementation of private_encryption_payload_t.compute_length.
*/
static void compute_length(private_encryption_payload_t *this)
{
iterator_t *iterator;
size_t block_size, length = 0;
iterator = this->payloads->create_iterator(this->payloads, TRUE);
/* count payload length */
while (iterator->has_next(iterator))
{
payload_t *current_payload;
iterator->current(iterator, (void **) &current_payload);
length += current_payload->get_length(current_payload);
}
iterator->destroy(iterator);
if (this->crypter && this->signer)
{
/* append one byte for padding length */
length++;
/* append padding */
block_size = this->crypter->get_block_size(this->crypter);
length += block_size - length % block_size;
/* add iv */
length += block_size;
/* add signature */
length += this->signer->get_block_size(this->signer);
}
length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy.
*/
static void destroy(private_encryption_payload_t *this)
{
/* all proposals are getting destroyed */
while (this->payloads->get_count(this->payloads) > 0)
{
payload_t *current_payload;
this->payloads->remove_last(this->payloads,(void **)&current_payload);
current_payload->destroy(current_payload);
}
this->payloads->destroy(this->payloads);
free(this->encrypted.ptr);
free(this->decrypted.ptr);
free(this);
}
/*
* Described in header
*/
encryption_payload_t *encryption_payload_create()
{
private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t);
/* payload_t interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator;
this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload;
this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload;
this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count;
this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt;
this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt;
this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms;
this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature;
this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature;
this->public.destroy = (void (*) (encryption_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
this->generate = generate;
this->parse = parse;
this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD);
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH;
this->encrypted = CHUNK_INITIALIZER;
this->decrypted = CHUNK_INITIALIZER;
this->signer = NULL;
this->crypter = NULL;
this->payloads = linked_list_create();
return (&(this->public));
}
@@ -0,0 +1,196 @@
/**
* @file encryption_payload.h
*
* @brief Interface of encryption_payload_t.
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef ENCRYPTION_PAYLOAD_H_
#define ENCRYPTION_PAYLOAD_H_
#include <types.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <encoding/payloads/payload.h>
#include <utils/linked_list.h>
/**
* Encrpytion payload length in bytes without IV and following data.
*
* @ingroup payloads
*/
#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
typedef struct encryption_payload_t encryption_payload_t;
/**
* @brief The encryption payload as described in RFC section 3.14.
*
* Before any crypt/decrypt/sign/verify operation can occur,
* the transforms must be set. After that, a parsed encryption payload
* can be decrypted, which also will parse the contained payloads.
* Encryption is done the same way, added payloads will get generated
* and then encrypted.
* For signature building, there is the FULL packet needed. Meaning it
* must be builded after generation of all payloads and the encryption
* of the encryption payload.
* Signature verificatin is done before decryption.
*
* @b Constructors:
* - encryption_payload_create()
*
* @ingroup payloads
*/
struct encryption_payload_t {
/**
* Implements payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator for all contained payloads.
*
* @warning iterator_t object has to get destroyed by the caller.
*
* @param this calling encryption_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* return created iterator_t object
*/
iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward);
/**
* @brief Adds a payload to this encryption payload.
*
* @param this calling encryption_payload_t object
* @param payload payload_t object to add
*/
void (*add_payload) (encryption_payload_t *this, payload_t *payload);
/**
* @brief Reove the last payload in the contained payload list.
*
* @param this calling encryption_payload_t object
* @param[out] payload removed payload
* @return
* - SUCCESS, or
* - NOT_FOUND if list empty
*/
status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload);
/**
* @brief Get the number of payloads.
*
* @param this calling encryption_payload_t object
* @return number of contained payloads
*/
size_t (*get_payload_count) (encryption_payload_t *this);
/**
* @brief Set transforms to use.
*
* To decryption, encryption, signature building and verifying,
* the payload needs a crypter and a signer object.
*
* @warning Do NOT call this function again after encryption, since
* the signer must be the same while encrypting and signature building!
*
* @param this calling encryption_payload_t
* @param crypter crypter_t to use for data de-/encryption
* @param signer signer_t to use for data signing/verifying
*/
void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer);
/**
* @brief Generate and encrypt contained payloads.
*
* This function generates the content for added payloads
* and encrypts them. Signature is not built, since we need
* additional data (the full message).
*
* @param this calling encryption_payload_t
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set
*/
status_t (*encrypt) (encryption_payload_t *this);
/**
* @brief Decrypt and parse contained payloads.
*
* This function decrypts the contained data. After,
* the payloads are parsed internally and are accessible
* via the iterator.
*
* @param this calling encryption_payload_t
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set, or
* - FAILED if data is invalid
*/
status_t (*decrypt) (encryption_payload_t *this);
/**
* @brief Build the signature.
*
* The signature is built over the FULL message, so the header
* and every payload (inclusive this one) must already be generated.
* The generated message is supplied via the data paramater.
*
* @param this calling encryption_payload_t
* @param data chunk contains the already generated message
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set
*/
status_t (*build_signature) (encryption_payload_t *this, chunk_t data);
/**
* @brief Verify the signature.
*
* Since the signature is built over the full message, we need
* this data to do the verification. The message data
* is supplied via the data argument.
*
* @param this calling encryption_payload_t
* @param data chunk contains the message
* @return
* - SUCCESS, or
* - FAILED if signature invalid, or
* - INVALID_STATE if transforms not set
*/
status_t (*verify_signature) (encryption_payload_t *this, chunk_t data);
/**
* @brief Destroys an encryption_payload_t object.
*
* @param this encryption_payload_t object to destroy
*/
void (*destroy) (encryption_payload_t *this);
};
/**
* @brief Creates an empty encryption_payload_t object.
*
* @return encryption_payload_t object
*
* @ingroup payloads
*/
encryption_payload_t *encryption_payload_create();
#endif /*ENCRYPTION_PAYLOAD_H_*/
@@ -0,0 +1,320 @@
/**
* @file id_payload.h
*
* @brief Interface of id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "id_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_id_payload_t private_id_payload_t;
/**
* Private data of an id_payload_t object.
*
*/
struct private_id_payload_t {
/**
* Public id_payload_t interface.
*/
id_payload_t public;
/**
* TRUE if this ID payload is of type IDi, FALSE for IDr.
*/
bool is_initiator;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Type of the ID Data.
*/
u_int8_t id_type;
/**
* The contained id data value.
*/
chunk_t id_data;
};
/**
* Encoding rules to parse or generate a ID payload
*
* The defined offsets are the positions in a object of type
* private_id_payload_t.
*
*/
encoding_rule_t id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_id_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
/* 1 Byte ID type*/
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
{ ID_DATA, offsetof(private_id_payload_t, id_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ID Type ! RESERVED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Identification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_id_payload_t *this)
{
if ((this->id_type == 0) ||
(this->id_type == 4) ||
((this->id_type >= 6) && (this->id_type <= 8)) ||
((this->id_type >= 12) && (this->id_type <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of id_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = id_payload_encodings;
*rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_id_payload_t *this)
{
if (this->is_initiator)
{
return ID_INITIATOR;
}
else
{
return ID_RESPONDER;
}
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_id_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_id_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_id_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of id_payload_t.set_type.
*/
static void set_id_type (private_id_payload_t *this, id_type_t type)
{
this->id_type = type;
}
/**
* Implementation of id_payload_t.get_id_type.
*/
static id_type_t get_id_type (private_id_payload_t *this)
{
return (this->id_type);
}
/**
* Implementation of id_payload_t.set_data.
*/
static void set_data (private_id_payload_t *this, chunk_t data)
{
if (this->id_data.ptr != NULL)
{
chunk_free(&(this->id_data));
}
this->id_data.ptr = clalloc(data.ptr,data.len);
this->id_data.len = data.len;
this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len;
}
/**
* Implementation of id_payload_t.get_data_clone.
*/
static chunk_t get_data (private_id_payload_t *this)
{
return (this->id_data);
}
/**
* Implementation of id_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_id_payload_t *this)
{
chunk_t cloned_data;
if (this->id_data.ptr == NULL)
{
return (this->id_data);
}
cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len);
cloned_data.len = this->id_data.len;
return cloned_data;
}
/**
* Implementation of id_payload_t.get_initiator.
*/
static bool get_initiator (private_id_payload_t *this)
{
return (this->is_initiator);
}
/**
* Implementation of id_payload_t.set_initiator.
*/
static void set_initiator (private_id_payload_t *this,bool is_initiator)
{
this->is_initiator = is_initiator;
}
/**
* Implementation of id_payload_t.get_identification.
*/
static identification_t *get_identification (private_id_payload_t *this)
{
return identification_create_from_encoding(this->id_type,this->id_data);
}
/**
* Implementation of payload_t.destroy and id_payload_t.destroy.
*/
static void destroy(private_id_payload_t *this)
{
if (this->id_data.ptr != NULL)
{
chunk_free(&(this->id_data));
}
free(this);
}
/*
* Described in header.
*/
id_payload_t *id_payload_create(bool is_initiator)
{
private_id_payload_t *this = malloc_thing(private_id_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (id_payload_t *)) destroy;
this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type;
this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type;
this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data;
this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data;
this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone;
this->public.get_initiator = (bool (*) (id_payload_t *)) get_initiator;
this->public.set_initiator = (void (*) (id_payload_t *,bool)) set_initiator;
this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =ID_PAYLOAD_HEADER_LENGTH;
this->id_data = CHUNK_INITIALIZER;
this->is_initiator = is_initiator;
return (&(this->public));
}
/*
* Described in header.
*/
id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification)
{
id_payload_t *this= id_payload_create(is_initiator);
this->set_data(this,identification->get_encoding(identification));
this->set_id_type(this,identification->get_type(identification));
return this;
}
@@ -0,0 +1,172 @@
/**
* @file id_payload.h
*
* @brief Interface of id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef ID_PAYLOAD_H_
#define ID_PAYLOAD_H_
#include <types.h>
#include <utils/identification.h>
#include <encoding/payloads/payload.h>
/**
* Length of a id payload without the data in bytes.
*
* @ingroup payloads
*/
#define ID_PAYLOAD_HEADER_LENGTH 8
typedef struct id_payload_t id_payload_t;
/**
* Object representing an IKEv2 ID payload.
*
* The ID payload format is described in RFC section 3.5.
*
* @b Constructors:
* - id_payload_create_from_identification()
* - id_payload_create()
*
* @ingroup payloads
*/
struct id_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the ID type.
*
* @param this calling id_payload_t object
* @param type Type of ID
*/
void (*set_id_type) (id_payload_t *this, id_type_t type);
/**
* @brief Get the ID type.
*
* @param this calling id_payload_t object
* @return type of the ID
*/
id_type_t (*get_id_type) (id_payload_t *this);
/**
* @brief Set the ID data.
*
* Data are getting cloned.
*
* @param this calling id_payload_t object
* @param data ID data as chunk_t
*/
void (*set_data) (id_payload_t *this, chunk_t data);
/**
* @brief Get the ID data.
*
* Returned data are a copy of the internal one
*
* @param this calling id_payload_t object
* @return ID data as chunk_t
*/
chunk_t (*get_data_clone) (id_payload_t *this);
/**
* @brief Get the ID data.
*
* Returned data are NOT copied.
*
* @param this calling id_payload_t object
* @return ID data as chunk_t
*/
chunk_t (*get_data) (id_payload_t *this);
/**
* @brief Creates an identification object of this id payload.
*
* Returned object has to get destroyed by the caller.
*
* @param this calling id_payload_t object
* @return identification_t object
*/
identification_t *(*get_identification) (id_payload_t *this);
/**
* @brief Get the type of ID payload (IDi or IDr).
*
* @param this calling id_payload_t object
* @return
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
*/
bool (*get_initiator) (id_payload_t *this);
/**
* @brief Set the type of ID payload (IDi or IDr).
*
* @param this calling id_payload_t object
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
*/
void (*set_initiator) (id_payload_t *this,bool is_initiator);
/**
* @brief Destroys an id_payload_t object.
*
* @param this id_payload_t object to destroy
*/
void (*destroy) (id_payload_t *this);
};
/**
* @brief Creates an empty id_payload_t object.
*
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
* @return id_payload_t object
*
* @ingroup payloads
*/
id_payload_t *id_payload_create(bool is_initiator);
/**
* @brief Creates an id_payload_t from an existing identification_t object.
*
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
* @param identification identification_t object
* @return id_payload_t object
*
* @ingroup payloads
*/
id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification);
#endif /* ID_PAYLOAD_H_ */
@@ -0,0 +1,408 @@
/**
* @file ike_header.c
*
* @brief Implementation of ike_header_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/* offsetof macro */
#include <stddef.h>
#include "ike_header.h"
#include <encoding/payloads/encodings.h>
typedef struct private_ike_header_t private_ike_header_t;
/**
* Private data of an ike_header_t object.
*
*/
struct private_ike_header_t {
/**
* Public interface.
*/
ike_header_t public;
/**
* SPI of the initiator.
*/
u_int64_t initiator_spi;
/**
* SPI of the responder.
*/
u_int64_t responder_spi;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* IKE major version.
*/
u_int8_t maj_version;
/**
* IKE minor version.
*/
u_int8_t min_version;
/**
* Exchange type .
*/
u_int8_t exchange_type;
/**
* Flags of the Message.
*
*/
struct {
/**
* Sender is initiator of the associated IKE_SA_INIT-Exchange.
*/
bool initiator;
/**
* Is protocol supporting higher version?
*/
bool version;
/**
* TRUE, if this is a response, FALSE if its a Request.
*/
bool response;
} flags;
/**
* Associated Message-ID.
*/
u_int32_t message_id;
/**
* Length of the whole IKEv2-Message (header and all payloads).
*/
u_int32_t length;
};
/**
* Mappings used to get strings for exchange_type_t.
*/
mapping_t exchange_type_m[] = {
{EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"},
{IKE_SA_INIT, "IKE_SA_INIT"},
{IKE_AUTH, "IKE_AUTH"},
{CREATE_CHILD_SA, "CREATE_CHILD_SA"},
{INFORMATIONAL, "INFORMATIONAL"}
};
/**
* Encoding rules to parse or generate a IKEv2-Header.
*
* The defined offsets are the positions in a object of type
* ike_header_t.
*
*/
encoding_rule_t ike_header_encodings[] = {
/* 8 Byte SPI, stored in the field initiator_spi */
{ IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
/* 8 Byte SPI, stored in the field responder_spi */
{ IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ike_header_t, next_payload) },
/* 4 Bit major version, stored in the field maj_version */
{ U_INT_4, offsetof(private_ike_header_t, maj_version) },
/* 4 Bit minor version, stored in the field min_version */
{ U_INT_4, offsetof(private_ike_header_t, min_version) },
/* 8 Bit for the exchange type */
{ U_INT_8, offsetof(private_ike_header_t, exchange_type) },
/* 2 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 3 Bit flags, stored in the fields response, version and initiator */
{ FLAG, offsetof(private_ike_header_t, flags.response) },
{ FLAG, offsetof(private_ike_header_t, flags.version) },
{ FLAG, offsetof(private_ike_header_t, flags.initiator) },
/* 3 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 4 Byte message id, stored in the field message_id */
{ U_INT_32, offsetof(private_ike_header_t, message_id) },
/* 4 Byte length fied, stored in the field length */
{ HEADER_LENGTH, offsetof(private_ike_header_t, length) }
};
/* 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Initiator's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Responder's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Message ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL))
{
/* unsupported exchange type */
return FAILED;
}
if (this->initiator_spi == 0)
{
/* initiator spi not set */
return FAILED;
}
/* verification of version is not done in here */
return SUCCESS;
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(payload_t *this,payload_type_t type)
{
((private_ike_header_t *)this)->next_payload = type;
}
/**
* Implementation of ike_header_t.get_initiator_spi.
*/
static u_int64_t get_initiator_spi(private_ike_header_t *this)
{
return this->initiator_spi;
}
/**
* Implementation of ike_header_t.set_initiator_spi.
*/
static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
/**
* Implementation of ike_header_t.get_responder_spi.
*/
static u_int64_t get_responder_spi(private_ike_header_t *this)
{
return this->responder_spi;
}
/**
* Implementation of ike_header_t.set_responder_spi.
*/
static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
{
this->responder_spi = responder_spi;
}
/**
* Implementation of ike_header_t.get_maj_version.
*/
static u_int8_t get_maj_version(private_ike_header_t *this)
{
return this->maj_version;
}
/**
* Implementation of ike_header_t.get_min_version.
*/
static u_int8_t get_min_version(private_ike_header_t *this)
{
return this->min_version;
}
/**
* Implementation of ike_header_t.get_response_flag.
*/
static bool get_response_flag(private_ike_header_t *this)
{
return this->flags.response;
}
/**
* Implementation of ike_header_t.set_response_flag.
*/
static void set_response_flag(private_ike_header_t *this, bool response)
{
this->flags.response = response;
}
/**
* Implementation of ike_header_t.get_version_flag.
*/
static bool get_version_flag(private_ike_header_t *this)
{
return this->flags.version;
}
/**
* Implementation of ike_header_t.get_initiator_flag.
*/
static bool get_initiator_flag(private_ike_header_t *this)
{
return this->flags.initiator;
}
/**
* Implementation of ike_header_t.set_initiator_flag.
*/
static void set_initiator_flag(private_ike_header_t *this, bool initiator)
{
this->flags.initiator = initiator;
}
/**
* Implementation of ike_header_t.get_exchange_type.
*/
static u_int8_t get_exchange_type(private_ike_header_t *this)
{
return this->exchange_type;
}
/**
* Implementation of ike_header_t.set_exchange_type.
*/
static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
{
this->exchange_type = exchange_type;
}
/**
* Implements ike_header_t's get_message_id function.
* See #ike_header_t.get_message_id for description.
*/
static u_int32_t get_message_id(private_ike_header_t *this)
{
return this->message_id;
}
/**
* Implementation of ike_header_t.set_message_id.
*/
static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
{
this->message_id = message_id;
}
/**
* Implementation of ike_header_t.destroy and payload_t.destroy.
*/
static void destroy(ike_header_t *this)
{
free(this);
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ike_header_encodings;
*rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(payload_t *this)
{
return HEADER;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(payload_t *this)
{
return (((private_ike_header_t*)this)->next_payload);
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(payload_t *this)
{
return (((private_ike_header_t*)this)->length);
}
/*
* Described in header.
*/
ike_header_t *ike_header_create()
{
private_ike_header_t *this = malloc_thing(private_ike_header_t);
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = get_encoding_rules;
this->public.payload_interface.get_length = get_length;
this->public.payload_interface.get_next_type = get_next_type;
this->public.payload_interface.set_next_type = set_next_type;
this->public.payload_interface.get_type = get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
this->public.destroy = destroy;
this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
/* set default values of the fields */
this->initiator_spi = 0;
this->responder_spi = 0;
this->next_payload = 0;
this->maj_version = IKE_MAJOR_VERSION;
this->min_version = IKE_MINOR_VERSION;
this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
this->flags.initiator = TRUE;
this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
this->flags.response = FALSE;
this->message_id = 0;
this->length = IKE_HEADER_LENGTH;
return (ike_header_t*)this;
}
@@ -0,0 +1,261 @@
/**
* @file ike_header.h
*
* @brief Interface of ike_header_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef IKE_HEADER_H_
#define IKE_HEADER_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Major Version of IKEv2.
*
* @ingroup payloads
*/
#define IKE_MAJOR_VERSION 2
/**
* Minor Version of IKEv2.
*
* @ingroup payloads
*/
#define IKE_MINOR_VERSION 0
/**
* Flag in IKEv2-Header. Always 0.
*
* @ingroup payloads
*/
#define HIGHER_VERSION_SUPPORTED_FLAG 0
/**
* Length of IKE Header in Bytes.
*
* @ingroup payloads
*/
#define IKE_HEADER_LENGTH 28
typedef enum exchange_type_t exchange_type_t;
/**
* @brief Different types of IKE-Exchanges.
*
* See Draft for different types.
*
* @ingroup payloads
*/
enum exchange_type_t{
/**
* EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
*/
EXCHANGE_TYPE_UNDEFINED = 240,
/**
* IKE_SA_INIT.
*/
IKE_SA_INIT = 34,
/**
* IKE_AUTH.
*/
IKE_AUTH = 35,
/**
* CREATE_CHILD_SA.
*/
CREATE_CHILD_SA = 36,
/**
* INFORMATIONAL.
*/
INFORMATIONAL = 37
};
/**
* string mappings for exchange_type_t
*
* @ingroup payloads
*/
extern mapping_t exchange_type_m[];
typedef struct ike_header_t ike_header_t;
/**
* @brief An object of this type represents an IKEv2 header and is used to
* generate and parse IKEv2 headers.
*
* The header format of an IKEv2-Message is compatible to the
* ISAKMP-Header format to allow implementations supporting
* both versions of the IKE-protocol.
*
* @b Constructors:
* - ike_header_create()
*
* @ingroup payloads
*/
struct ike_header_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the initiator spi.
*
* @param this ike_header_t object
* @return initiator_spi
*/
u_int64_t (*get_initiator_spi) (ike_header_t *this);
/**
* @brief Set the initiator spi.
*
* @param this ike_header_t object
* @param initiator_spi initiator_spi
*/
void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
/**
* @brief Get the responder spi.
*
* @param this ike_header_t object
* @return responder_spi
*/
u_int64_t (*get_responder_spi) (ike_header_t *this);
/**
* @brief Set the responder spi.
*
* @param this ike_header_t object
* @param responder_spi responder_spi
*/
void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
/**
* @brief Get the major version.
*
* @param this ike_header_t object
* @return major version
*/
u_int8_t (*get_maj_version) (ike_header_t *this);
/**
* @brief Get the minor version.
*
* @param this ike_header_t object
* @return minor version
*/
u_int8_t (*get_min_version) (ike_header_t *this);
/**
* @brief Get the response flag.
*
* @param this ike_header_t object
* @return response flag
*/
bool (*get_response_flag) (ike_header_t *this);
/**
* @brief Set the response flag-
*
* @param this ike_header_t object
* @param response response flag
*
*/
void (*set_response_flag) (ike_header_t *this, bool response);
/**
* @brief Get "higher version supported"-flag.
*
* @param this ike_header_t object
* @return version flag
*/
bool (*get_version_flag) (ike_header_t *this);
/**
* @brief Get the initiator flag.
*
* @param this ike_header_t object
* @return initiator flag
*/
bool (*get_initiator_flag) (ike_header_t *this);
/**
* @brief Set the initiator flag.
*
* @param this ike_header_t object
* @param initiator initiator flag
*
*/
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
/**
* @brief Get the exchange type.
*
* @param this ike_header_t object
* @return exchange type
*/
u_int8_t (*get_exchange_type) (ike_header_t *this);
/**
* @brief Set the exchange type.
*
* @param this ike_header_t object
* @param exchange_type exchange type
*/
void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
/**
* @brief Get the message id.
*
* @param this ike_header_t object
* @return message id
*/
u_int32_t (*get_message_id) (ike_header_t *this);
/**
* @brief Set the message id.
*
* @param this ike_header_t object
* @param initiator_spi message id
*/
void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
/**
* @brief Destroys a ike_header_t object.
*
* @param this ike_header_t object to destroy
*/
void (*destroy) (ike_header_t *this);
};
/**
* @brief Create an ike_header_t object
*
* @return ike_header_t object
*
* @ingroup payloads
*/
ike_header_t *ike_header_create();
#endif /*IKE_HEADER_H_*/
@@ -0,0 +1,276 @@
/**
* @file ke_payload.c
*
* @brief Implementation of ke_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "ke_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_ke_payload_t private_ke_payload_t;
/**
* Private data of an ke_payload_t object.
*
*/
struct private_ke_payload_t {
/**
* Public ke_payload_t interface.
*/
ke_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* DH Group Number.
*/
diffie_hellman_group_t dh_group_number;
/**
* Key Exchange Data of this KE payload.
*/
chunk_t key_exchange_data;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
*/
void (*compute_length) (private_ke_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-KE Payload.
*
* The defined offsets are the positions in a object of type
* private_ke_payload_t.
*
*/
encoding_rule_t ke_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_ke_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
/* DH Group number as 16 bit field*/
{ U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* Key Exchange Data is from variable size */
{ KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DH Group # ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Key Exchange Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ke_payload_t *this)
{
/* dh group is not verified in here */
return SUCCESS;
}
/**
* Implementation of payload_t.destroy.
*/
static void destroy(private_ke_payload_t *this)
{
if (this->key_exchange_data.ptr != NULL)
{
free(this->key_exchange_data.ptr);
}
free(this);
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ke_payload_encodings;
*rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_ke_payload_t *this)
{
return KEY_EXCHANGE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_ke_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_ke_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_ke_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_ke_payload_t.compute_length.
*/
static void compute_length (private_ke_payload_t *this)
{
size_t length = KE_PAYLOAD_HEADER_LENGTH;
if (this->key_exchange_data.ptr != NULL)
{
length += this->key_exchange_data.len;
}
this->payload_length = length;
}
/**
* Implementation of ke_payload_t.get_key_exchange_data.
*/
static chunk_t get_key_exchange_data(private_ke_payload_t *this)
{
return (this->key_exchange_data);
}
/**
* Implementation of ke_payload_t.set_key_exchange_data.
*/
static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
{
/* destroy existing data first */
if (this->key_exchange_data.ptr != NULL)
{
/* free existing value */
free(this->key_exchange_data.ptr);
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
}
this->key_exchange_data.ptr = clalloc(key_exchange_data.ptr,key_exchange_data.len);
this->key_exchange_data.len = key_exchange_data.len;
this->compute_length(this);
}
/**
* Implementation of ke_payload_t.get_dh_group_number.
*/
static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
{
return this->dh_group_number;
}
/**
* Implementation of ke_payload_t.set_dh_group_number.
*/
static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
{
this->dh_group_number = dh_group_number;
}
/*
* Described in header
*/
ke_payload_t *ke_payload_create()
{
private_ke_payload_t *this = malloc_thing(private_ke_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
this->public.set_key_exchange_data = (void (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
this->public.set_dh_group_number =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
this->public.destroy = (void (*) (ke_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
this->dh_group_number = 0;
return (&(this->public));
}
@@ -0,0 +1,110 @@
/**
* @file ke_payload.h
*
* @brief Interface of ke_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef KE_PAYLOAD_H_
#define KE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <utils/linked_list.h>
/**
* KE payload length in bytes without any key exchange data.
*
* @ingroup payloads
*/
#define KE_PAYLOAD_HEADER_LENGTH 8
typedef struct ke_payload_t ke_payload_t;
/**
* @brief Class representing an IKEv2-KE Payload.
*
* The KE Payload format is described in RFC section 3.4.
*
* @b Constructors:
* - ke_payload_create()
*
* @ingroup payloads
*/
struct ke_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set key exchange data of this KE payload.
*
* @warning Returned data are not copied.
*
* @param this calling ke_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
* @brief Sets the key exchange data of this KE payload.
*
* @warning Value is getting copied.
*
* @param this calling ke_payload_t object
* @param key_exchange_data chunk_t pointing to the value to set
*/
void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
/**
* @brief Gets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @return DH Group Number of this payload
*/
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
* @brief Sets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @param dh_group_number DH Group to set
*/
void (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number);
/**
* @brief Destroys an ke_payload_t object.
*
* @param this ke_payload_t object to destroy
*/
void (*destroy) (ke_payload_t *this);
};
/**
* @brief Creates an empty ke_payload_t object
*
* @return ke_payload_t object
*
* @ingroup payloads
*/
ke_payload_t *ke_payload_create();
#endif /*KE_PAYLOAD_H_*/
@@ -0,0 +1,241 @@
/**
* @file nonce_payload.h
*
* @brief Implementation of nonce_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/* offsetof macro */
#include <stddef.h>
#include "nonce_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_nonce_payload_t private_nonce_payload_t;
/**
* Private data of an nonce_payload_t object.
*
*/
struct private_nonce_payload_t {
/**
* Public nonce_payload_t interface.
*/
nonce_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained nonce value.
*/
chunk_t nonce;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_nonce_payload_t object
*/
void (*compute_length) (private_nonce_payload_t *this);
};
/**
* Encoding rules to parse or generate a nonce payload
*
* The defined offsets are the positions in a object of type
* private_nonce_payload_t.
*
*/
encoding_rule_t nonce_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_nonce_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole nonce payload*/
{ PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
/* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
{ NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }
};
/* 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Nonce Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_nonce_payload_t *this)
{
if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
{
/* nonce length is wrong */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of nonce_payload_t.set_nonce.
*/
static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
{
this->nonce.ptr = clalloc(nonce.ptr, nonce.len);
this->nonce.len = nonce.len;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
return SUCCESS;
}
/**
* Implementation of nonce_payload_t.get_nonce.
*/
static chunk_t get_nonce(private_nonce_payload_t *this)
{
chunk_t nonce;
nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len);
nonce.len = this->nonce.len;
return nonce;
}
/**
* Implementation of nonce_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = nonce_payload_encodings;
*rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_nonce_payload_t *this)
{
return NONCE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_nonce_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_nonce_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_nonce_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_id_payload_t.compute_length.
*/
static void compute_length(private_nonce_payload_t *this)
{
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len;
}
/**
* Implementation of payload_t.destroy and nonce_payload_t.destroy.
*/
static void destroy(private_nonce_payload_t *this)
{
if (this->nonce.ptr != NULL)
{
free(this->nonce.ptr);
}
free(this);
}
/*
* Described in header
*/
nonce_payload_t *nonce_payload_create()
{
private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (nonce_payload_t *)) destroy;
this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce;
this->public.get_nonce = (chunk_t (*) (nonce_payload_t *)) get_nonce;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
this->nonce.ptr = NULL;
this->nonce.len = 0;
return (&(this->public));
}
@@ -0,0 +1,89 @@
/**
* @file nonce_payload.h
*
* @brief Interface of nonce_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef NONCE_PAYLOAD_H_
#define NONCE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a nonce payload without a nonce in bytes.
*
* @ingroup payloads
*/
#define NONCE_PAYLOAD_HEADER_LENGTH 4
typedef struct nonce_payload_t nonce_payload_t;
/**
* Object representing an IKEv2 Nonce payload.
*
* The Nonce payload format is described in RFC section 3.3.
*
* @b Constructors:
* - nonce_payload_create()
*
* @ingroup payloads
*/
struct nonce_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the nonce value.
*
* @param this calling nonce_payload_t object
* @param nonce chunk containing the nonce, will be cloned
*/
void (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
/**
* @brief Get the nonce value.
*
* @param this calling nonce_payload_t object
* @return a chunk containing the cloned nonce
*/
chunk_t (*get_nonce) (nonce_payload_t *this);
/**
* @brief Destroys an nonce_payload_t object.
*
* @param this nonce_payload_t object to destroy
*/
void (*destroy) (nonce_payload_t *this);
};
/**
* @brief Creates an empty nonce_payload_t object
*
* @return nonce_payload_t object
*
* @ingroup payloads
*/
nonce_payload_t *nonce_payload_create();
#endif /*NONCE_PAYLOAD_H_*/
@@ -0,0 +1,441 @@
/**
* @file notify_payload.c
*
* @brief Implementation of notify_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "notify_payload.h"
#include <daemon.h>
#include <encoding/payloads/encodings.h>
/**
* String mappings for notify_message_type_t.
*/
mapping_t notify_message_type_m[] = {
{UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
{INVALID_IKE_SPI, "INVALID_IKE_SPI"},
{INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
{INVALID_SYNTAX, "INVALID_SYNTAX"},
{INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"},
{INVALID_SPI, "INVALID_SPI"},
{NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"},
{INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"},
{AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"},
{SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"},
{NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
{INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
{FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
{TS_UACCEPTABLE, "TS_UACCEPTABLE"},
{INVALID_SELECTORS, "INVALID_SELECTORS"},
{INITIAL_CONTACT, "INITIAL_CONTACT"},
{SET_WINDOW_SIZE, "SET_WINDOW_SIZE"},
{MAPPING_END, NULL}
};
typedef struct private_notify_payload_t private_notify_payload_t;
/**
* Private data of an notify_payload_t object.
*
*/
struct private_notify_payload_t {
/**
* Public notify_payload_t interface.
*/
notify_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Protocol id.
*/
u_int8_t protocol_id;
/**
* Spi size.
*/
u_int8_t spi_size;
/**
* Notify message type.
*/
u_int16_t notify_message_type;
/**
* Security parameter index (spi).
*/
chunk_t spi;
/**
* Notification data.
*/
chunk_t notification_data;
/**
* Assigned logger
*/
logger_t *logger;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
*/
void (*compute_length) (private_notify_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-Notify Payload.
*
* The defined offsets are the positions in a object of type
* private_notify_payload_t.
*
*/
encoding_rule_t notify_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
/* Protocol ID as 8 bit field*/
{ U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
/* SPI Size as 8 bit field*/
{ SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
/* Notify message type as 16 bit field*/
{ U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
/* SPI as variable length field*/
{ SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
{ NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! Notify Message Type !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Notification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_notify_payload_t *this)
{
if (this->protocol_id > 3)
{
/* reserved for future use */
return FAILED;
}
/* TODO: Check all kinds of notify */
if (this->notify_message_type == INVALID_KE_PAYLOAD)
{
/* check notification data */
diffie_hellman_group_t dh_group;
if (this->notification_data.len != 2)
{
return FAILED;
}
dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
switch (dh_group)
{
case MODP_768_BIT:
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_6144_BIT:
case MODP_8192_BIT:
break;
default:
this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group);
return FAILED;
}
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = notify_payload_encodings;
*rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_notify_payload_t *this)
{
return NOTIFY;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_notify_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_notify_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_notify_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_notify_payload_t.compute_length.
*/
static void compute_length (private_notify_payload_t *this)
{
size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
if (this->notification_data.ptr != NULL)
{
length += this->notification_data.len;
}
if (this->spi.ptr != NULL)
{
length += this->spi.len;
}
this->payload_length = length;
}
/**
* Implementation of notify_payload_t.get_protocol_id.
*/
static u_int8_t get_protocol_id(private_notify_payload_t *this)
{
return this->protocol_id;
}
/**
* Implementation of notify_payload_t.set_protocol_id.
*/
static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of notify_payload_t.get_notify_message_type.
*/
static u_int16_t get_notify_message_type(private_notify_payload_t *this)
{
return this->notify_message_type;
}
/**
* Implementation of notify_payload_t.set_notify_message_type.
*/
static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
{
this->notify_message_type = notify_message_type;
}
/**
* Implementation of notify_payload_t.get_spi.
*/
static chunk_t get_spi(private_notify_payload_t *this)
{
return (this->spi);
}
/**
* Implementation of notify_payload_t.set_spi.
*/
static void set_spi(private_notify_payload_t *this, chunk_t spi)
{
/* destroy existing data first */
if (this->spi.ptr != NULL)
{
/* free existing value */
free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
}
this->spi.ptr = clalloc(spi.ptr,spi.len);
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
}
/**
* Implementation of notify_payload_t.get_notification_data.
*/
static chunk_t get_notification_data(private_notify_payload_t *this)
{
return (this->notification_data);
}
/**
* Implementation of notify_payload_t.set_notification_data.
*/
static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
{
/* destroy existing data first */
if (this->notification_data.ptr != NULL)
{
/* free existing value */
free(this->notification_data.ptr);
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
}
this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len);
this->notification_data.len = notification_data.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
*/
static status_t destroy(private_notify_payload_t *this)
{
if (this->notification_data.ptr != NULL)
{
free(this->notification_data.ptr);
}
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
}
free(this);
return SUCCESS;
}
/*
* Described in header
*/
notify_payload_t *notify_payload_create()
{
private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi;
this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
this->public.destroy = (void (*) (notify_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
this->protocol_id = 0;
this->notify_message_type = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->spi_size = 0;
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
this->logger = logger_manager->get_logger(logger_manager, PAYLOAD);
return (&(this->public));
}
/*
* Described in header.
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
{
notify_payload_t *notify = notify_payload_create();
notify->set_notify_message_type(notify,notify_message_type);
notify->set_protocol_id(notify,protocol_id);
return notify;
}
@@ -0,0 +1,200 @@
/**
* @file notify_payload.h
*
* @brief Interface of notify_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef NOTIFY_PAYLOAD_H_
#define NOTIFY_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
/**
* Notify payload length in bytes without any spi and notification data.
*
* @ingroup payloads
*/
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
typedef enum notify_message_type_t notify_message_type_t;
/**
* @brief Notify message types.
*
* See IKEv2 RFC 3.10.1.
*
* @ingroup payloads
*/
enum notify_message_type_t {
UNSUPPORTED_CRITICAL_PAYLOAD = 1,
INVALID_IKE_SPI = 4,
INVALID_MAJOR_VERSION = 5,
INVALID_SYNTAX = 7,
INVALID_MESSAGE_ID = 9,
INVALID_SPI = 11,
NO_PROPOSAL_CHOSEN = 14,
INVALID_KE_PAYLOAD = 17,
AUTHENTICATION_FAILED = 24,
SINGLE_PAIR_REQUIRED = 34,
NO_ADDITIONAL_SAS = 35,
INTERNAL_ADDRESS_FAILURE = 36,
FAILED_CP_REQUIRED = 37,
TS_UACCEPTABLE = 38,
INVALID_SELECTORS = 39,
INITIAL_CONTACT = 16384,
SET_WINDOW_SIZE = 16385
};
/**
* String mappings for notify_message_type_t.
*
* @ingroup payloads
*/
extern mapping_t notify_message_type_m[];
typedef struct notify_payload_t notify_payload_t;
/**
* @brief Class representing an IKEv2-Notify Payload.
*
* The Notify Payload format is described in Draft section 3.10.
*
* @b Constructors:
* - notify_payload_create()
* - notify_payload_create_from_protocol_and_type()
*
* @todo Build specified constructor/getter for notify's
*
* @ingroup payloads
*/
struct notify_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Gets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @return protocol id of this payload
*/
u_int8_t (*get_protocol_id) (notify_payload_t *this);
/**
* @brief Sets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @param protocol_id protocol id to set
*/
void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
/**
* @brief Gets the notify message type of this payload.
*
* @param this calling notify_payload_t object
* @return notify message type of this payload
*/
u_int16_t (*get_notify_message_type) (notify_payload_t *this);
/**
* @brief Sets notify message type of this payload.
*
* @param this calling notify_payload_t object
* @param notify_message_type notify message type to set
*/
void (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type);
/**
* @brief Returns the currently set spi of this payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (notify_payload_t *this);
/**
* @brief Sets the spi of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param spi chunk_t pointing to the value to set
*/
void (*set_spi) (notify_payload_t *this, chunk_t spi);
/**
* @brief Returns the currently set notification data of payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_notification_data) (notify_payload_t *this);
/**
* @brief Sets the notification data of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param notification_data chunk_t pointing to the value to set
*/
void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data);
/**
* @brief Destroys an notify_payload_t object.
*
* @param this notify_payload_t object to destroy
*/
void (*destroy) (notify_payload_t *this);
};
/**
* @brief Creates an empty notify_payload_t object
*
* @return created notify_payload_t object
*
* @ingroup payloads
*/
notify_payload_t *notify_payload_create();
/**
* @brief Creates an notify_payload_t object of specific type for specific protocol id.
*
* @param protocol_id protocol id (IKE, AH or ESP)
* @param notify_message_type notify type (see notify_message_type_t)
* @return notify_payload_t object
*
* @ingroup payloads
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type);
#endif /*NOTIFY_PAYLOAD_H_*/
@@ -0,0 +1,131 @@
/**
* @file payload.c
*
* @brief Generic constructor to the payload_t interface.
*
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "payload.h"
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/ke_payload.h>
#include <encoding/payloads/notify_payload.h>
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/certreq_payload.h>
#include <encoding/payloads/encryption_payload.h>
#include <encoding/payloads/ts_payload.h>
#include <encoding/payloads/delete_payload.h>
#include <encoding/payloads/vendor_id_payload.h>
#include <encoding/payloads/cp_payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/unknown_payload.h>
/*
* build the mappings for payload_type_t
*/
mapping_t payload_type_m[] = {
{NO_PAYLOAD, "NO_PAYLOAD"},
{SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"},
{KEY_EXCHANGE, "KEY_EXCHANGE"},
{ID_INITIATOR, "ID_INITIATOR"},
{ID_RESPONDER, "ID_RESPONDER"},
{CERTIFICATE, "CERTIFICATE"},
{CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"},
{AUTHENTICATION, "AUTHENTICATION"},
{NONCE, "NONCE"},
{NOTIFY, "NOTIFY"},
{DELETE, "DELETE"},
{VENDOR_ID, "VENDOR_ID"},
{TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"},
{TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"},
{ENCRYPTED, "ENCRYPTED"},
{CONFIGURATION, "CONFIGURATION"},
{EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"},
{HEADER, "HEADER"},
{PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"},
{TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"},
{TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"},
{TRAFFIC_SELECTOR_SUBSTRUCTURE, "TRAFFIC_SELECTOR_SUBSTRUCTURE"},
{CONFIGURATION_ATTRIBUTE,"CONFIGURATION_ATTRIBUTE"},
{UNKNOWN_PAYLOAD,"UNKNOWN_PAYLOAD"},
{MAPPING_END, NULL}
};
/*
* see header
*/
payload_t *payload_create(payload_type_t type)
{
switch (type)
{
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create();
case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create();
case TRANSFORM_SUBSTRUCTURE:
return (payload_t*)transform_substructure_create();
case TRANSFORM_ATTRIBUTE:
return (payload_t*)transform_attribute_create();
case NONCE:
return (payload_t*)nonce_payload_create();
case ID_INITIATOR:
return (payload_t*)id_payload_create(TRUE);
case ID_RESPONDER:
return (payload_t*)id_payload_create(FALSE);
case AUTHENTICATION:
return (payload_t*)auth_payload_create();
case CERTIFICATE:
return (payload_t*)cert_payload_create();
case CERTIFICATE_REQUEST:
return (payload_t*)certreq_payload_create();
case TRAFFIC_SELECTOR_SUBSTRUCTURE:
return (payload_t*)traffic_selector_substructure_create();
case TRAFFIC_SELECTOR_INITIATOR:
return (payload_t*)ts_payload_create(TRUE);
case TRAFFIC_SELECTOR_RESPONDER:
return (payload_t*)ts_payload_create(FALSE);
case KEY_EXCHANGE:
return (payload_t*)ke_payload_create();
case NOTIFY:
return (payload_t*)notify_payload_create();
case DELETE:
return (payload_t*)delete_payload_create();
case VENDOR_ID:
return (payload_t*)vendor_id_payload_create();
case CONFIGURATION:
return (payload_t*)cp_payload_create();
case CONFIGURATION_ATTRIBUTE:
return (payload_t*)configuration_attribute_create();
case EXTENSIBLE_AUTHENTICATION:
return (payload_t*)eap_payload_create();
case ENCRYPTED:
return (payload_t*)encryption_payload_create();
default:
return (payload_t*)unknown_payload_create();
}
}
@@ -0,0 +1,279 @@
/**
* @file payload.h
*
* @brief Interface payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef PAYLOAD_H_
#define PAYLOAD_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/encodings.h>
typedef enum payload_type_t payload_type_t;
/**
* @brief Payload-Types of a IKEv2-Message.
*
* Header and substructures are also defined as
* payload types with values from PRIVATE USE space.
*
* @ingroup payloads
*/
enum payload_type_t{
/**
* End of payload list in next_payload
*/
NO_PAYLOAD = 0,
/**
* The security association (SA) payload containing proposals.
*/
SECURITY_ASSOCIATION = 33,
/**
* The key exchange (KE) payload containing diffie-hellman values.
*/
KEY_EXCHANGE = 34,
/**
* Identification for the original initiator (IDi).
*/
ID_INITIATOR = 35,
/**
* Identification for the original responder (IDr).
*/
ID_RESPONDER = 36,
/**
* Certificate payload with certificates (CERT).
*/
CERTIFICATE = 37,
/**
* Certificate request payload (CERTREQ).
*/
CERTIFICATE_REQUEST = 38,
/**
* Authentication payload contains auth data (AUTH).
*/
AUTHENTICATION = 39,
/**
* Nonces, for initator and responder (Ni, Nr, N)
*/
NONCE = 40,
/**
* Notif paylaod (N).
*/
NOTIFY = 41,
/**
* Delete payload (D)
*/
DELETE = 42,
/**
* Vendor id paylpoad (V).
*/
VENDOR_ID = 43,
/**
* Traffic selector for the original initiator (TSi).
*/
TRAFFIC_SELECTOR_INITIATOR = 44,
/**
* Traffic selector for the original responser (TSr).
*/
TRAFFIC_SELECTOR_RESPONDER = 45,
/**
* Encryption payload, contains other payloads (E).
*/
ENCRYPTED = 46,
/**
* Configuration payload (CP).
*/
CONFIGURATION = 47,
/**
* Extensible authentication payload (EAP).
*/
EXTENSIBLE_AUTHENTICATION = 48,
/**
* Header has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle IKEv2-Header like a payload.
*/
HEADER = 140,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a proposal substructure like a payload.
*/
PROPOSAL_SUBSTRUCTURE = 141,
/**
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform substructure like a payload.
*/
TRANSFORM_SUBSTRUCTURE = 142,
/**
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform attribute like a payload.
*/
TRANSFORM_ATTRIBUTE = 143,
/**
* TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform selector like a payload.
*/
TRAFFIC_SELECTOR_SUBSTRUCTURE = 144,
/**
* CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform attribute like a payload.
*/
CONFIGURATION_ATTRIBUTE = 145,
/**
* A unknown payload has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a unknown payload.
*/
UNKNOWN_PAYLOAD = 146,
};
/**
* String mappings for payload_type_t.
*/
extern mapping_t payload_type_m[];
typedef struct payload_t payload_t;
/**
* @brief Generic interface for all payload types (incl.header and substructures).
*
* To handle all kinds of payloads on a generic way, this interface must
* be implemented by every payload. This allows parser_t/generator_t a simple
* handling of all payloads.
*
* @b Constructors:
* - payload_create() with the payload to instanciate.
*
* @ingroup payloads
*/
struct payload_t {
/**
* @brief Get encoding rules for this payload.
*
* @param this calling object
* @param[out] rules location to store pointer of first rule
* @param[out] rule_count location to store number of rules
*/
void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
/**
* @brief Get type of payload.
*
* @param this calling object
* @return type of this payload
*/
payload_type_t (*get_type) (payload_t *this);
/**
* @brief Get type of next payload or NO_PAYLOAD (0) if this is the last one.
*
* @param this calling object
* @return type of next payload
*/
payload_type_t (*get_next_type) (payload_t *this);
/**
* @brief Set type of next payload.
*
* @param this calling object
* @param type type of next payload
*/
void (*set_next_type) (payload_t *this,payload_type_t type);
/**
* @brief Get length of payload.
*
* @param this calling object
* @return length of this payload
*/
size_t (*get_length) (payload_t *this);
/**
* @brief Verifies payload structure and makes consistence check.
*
* @param this calling object
* @return
* - SUCCESS
* - FAILED if consistence not given
*/
status_t (*verify) (payload_t *this);
/**
* @brief Destroys a payload and all included substructures.
*
* @param this payload to destroy
*/
void (*destroy) (payload_t *this);
};
/**
* @brief Create an empty payload.
*
* Useful for the parser, who wants a generic constructor for all payloads.
* It supports all payload_t methods. If a payload type is not known,
* an unknwon_paylod is created with the chunk of data in it.
*
* @param type type of the payload to create
* @return payload_t object
*/
payload_t *payload_create(payload_type_t type);
#endif /*PAYLOAD_H_*/
@@ -0,0 +1,629 @@
/**
* @file proposal_substructure.h
*
* @brief Implementation of proposal_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "proposal_substructure.h"
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/transform_substructure.h>
#include <types.h>
#include <utils/linked_list.h>
/**
* IKEv1 Value for a proposal payload.
*/
#define PROPOSAL_TYPE_VALUE 2
typedef struct private_proposal_substructure_t private_proposal_substructure_t;
/**
* Private data of an proposal_substructure_t object.
*
*/
struct private_proposal_substructure_t {
/**
* Public proposal_substructure_t interface.
*/
proposal_substructure_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Length of this payload.
*/
u_int16_t proposal_length;
/**
* Proposal number.
*/
u_int8_t proposal_number;
/**
* Protocol ID.
*/
u_int8_t protocol_id;
/**
* SPI size of the following SPI.
*/
u_int8_t spi_size;
/**
* Number of transforms.
*/
u_int8_t transforms_count;
/**
* SPI is stored as chunk.
*/
chunk_t spi;
/**
* Transforms are stored in a linked_list_t.
*/
linked_list_t * transforms;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_proposal_substructure_t object
*/
void (*compute_length) (private_proposal_substructure_t *this);
};
/**
* Encoding rules to parse or generate a Proposal substructure.
*
* The defined offsets are the positions in a object of type
* private_proposal_substructure_t.
*
*/
encoding_rule_t proposal_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole proposal substructure payload*/
{ PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
/* proposal number is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
/* protocol ID is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
/* SPI Size has its own type */
{ SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
/* Number of transforms is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
/* SPI is a chunk of variable size*/
{ SPI, offsetof(private_proposal_substructure_t, spi) },
/* Transforms are stored in a transform substructure,
offset points to a linked_list_t pointer */
{ TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 2 ! RESERVED ! Proposal Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ SPI (variable) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Transforms> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_proposal_substructure_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2))
{
/* must be 0 or 2 */
return FAILED;
}
if (this->transforms_count != this->transforms->get_count(this->transforms))
{
/* must be the same! */
return FAILED;
}
if ((this->protocol_id == 0) || (this->protocol_id >= 4))
{
/* reserved are not supported */
return FAILED;
}
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_transform;
iterator->current(iterator,(void **)&current_transform);
status = current_transform->verify(current_transform);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
/* proposal number is checked in SA payload */
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = proposal_substructure_encodings;
*rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_proposal_substructure_t *this)
{
return PROPOSAL_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_proposal_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_proposal_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_proposal_substructure_t *this)
{
this->compute_length(this);
return this->proposal_length;
}
/**
* Implementation of proposal_substructure_t.create_transform_substructure_iterator.
*/
static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward)
{
return (this->transforms->create_iterator(this->transforms,forward));
}
/**
* Implementation of proposal_substructure_t.add_transform_substructure.
*/
static void add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform)
{
status_t status;
if (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *last_transform;
status = this->transforms->get_last(this->transforms,(void **) &last_transform);
/* last transform is now not anymore last one */
last_transform->set_is_last_transform(last_transform,FALSE);
}
transform->set_is_last_transform(transform,TRUE);
this->transforms->insert_last(this->transforms,(void *) transform);
this->compute_length(this);
}
/**
* Implementation of proposal_substructure_t.proposal_substructure_t.
*/
static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last)
{
this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE;
}
/**
* Implementation of proposal_substructure_t.set_proposal_number.
*/
static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
{
this->proposal_number = proposal_number;
}
/**
* Implementation of proposal_substructure_t.get_proposal_number.
*/
static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
{
return (this->proposal_number);
}
/**
* Implementation of proposal_substructure_t.set_protocol_id.
*/
static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of proposal_substructure_t.get_protocol_id.
*/
static u_int8_t get_protocol_id (private_proposal_substructure_t *this)
{
return (this->protocol_id);
}
/**
* Implementation of proposal_substructure_t.set_spi.
*/
static void set_spi (private_proposal_substructure_t *this, chunk_t spi)
{
/* first delete already set spi value */
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
this->compute_length(this);
}
this->spi.ptr = clalloc(spi.ptr,spi.len);
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
}
/**
* Implementation of proposal_substructure_t.get_spi.
*/
static chunk_t get_spi (private_proposal_substructure_t *this)
{
chunk_t spi;
spi.ptr = this->spi.ptr;
spi.len = this->spi.len;
return spi;
}
/**
* Implementation of proposal_substructure_t.get_info_for_transform_type.
*/
static status_t get_info_for_transform_type (private_proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length)
{
iterator_t *iterator;
status_t status;
u_int16_t found_transform_id;
u_int16_t found_key_length;
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while (iterator->has_next(iterator))
{
transform_substructure_t *current_transform;
status = iterator->current(iterator,(void **) &current_transform);
if (status != SUCCESS)
{
break;
}
if (current_transform->get_transform_type(current_transform) == type)
{
/* now get data for specific type */
found_transform_id = current_transform->get_transform_id(current_transform);
status = current_transform->get_key_length(current_transform,&found_key_length);
*transform_id = found_transform_id;
*key_length = found_key_length;
iterator->destroy(iterator);
return status;
}
}
iterator->destroy(iterator);
return NOT_FOUND;
}
/**
* Implementation of private_proposal_substructure_t.compute_length.
*/
static void compute_length (private_proposal_substructure_t *this)
{
iterator_t *iterator;
size_t transforms_count = 0;
size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_transform;
iterator->current(iterator,(void **) &current_transform);
length += current_transform->get_length(current_transform);
transforms_count++;
}
iterator->destroy(iterator);
length += this->spi.len;
this->transforms_count = transforms_count;
this->proposal_length = length;
}
/**
* Implementation of proposal_substructure_t.get_transform_count.
*/
static size_t get_transform_count (private_proposal_substructure_t *this)
{
return this->transforms->get_count(this->transforms);
}
/**
* Implementation of proposal_substructure_t.get_spi_size.
*/
static size_t get_spi_size (private_proposal_substructure_t *this)
{
return this->spi.len;
}
/**
* Implementation of proposal_substructure_t.add_to_proposal.
*/
void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal)
{
iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE);
u_int32_t spi;
while (iterator->has_next(iterator))
{
transform_substructure_t *transform;
transform_type_t transform_type;
u_int16_t transform_id;
u_int16_t key_length = 0;
iterator->current(iterator, (void**)&transform);
transform_type = transform->get_transform_type(transform);
transform_id = transform->get_transform_id(transform);
transform->get_key_length(transform, &key_length);
proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length);
}
iterator->destroy(iterator);
spi = *((u_int32_t*)this->spi.ptr);
proposal->set_spi(proposal, this->protocol_id, spi);
}
/**
* Implementation of proposal_substructure_t.clone.
*/
static private_proposal_substructure_t* clone(private_proposal_substructure_t *this)
{
private_proposal_substructure_t * new_clone;
iterator_t *transforms;
new_clone = (private_proposal_substructure_t *) proposal_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->proposal_number = this->proposal_number;
new_clone->protocol_id = this->protocol_id;
new_clone->spi_size = this->spi_size;
if (this->spi.ptr != NULL)
{
new_clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len);
new_clone->spi.len = this->spi.len;
}
transforms = this->transforms->create_iterator(this->transforms,FALSE);
while (transforms->has_next(transforms))
{
transform_substructure_t *current_transform;
transform_substructure_t *current_transform_clone;
transforms->current(transforms,(void **) &current_transform);
current_transform_clone = current_transform->clone(current_transform);
new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone);
}
transforms->destroy(transforms);
return new_clone;
}
/**
* Implements payload_t's and proposal_substructure_t's destroy function.
* See #payload_s.destroy or proposal_substructure_s.destroy for description.
*/
static status_t destroy(private_proposal_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *current_transform;
if (this->transforms->remove_last(this->transforms,(void **)&current_transform) != SUCCESS)
{
break;
}
current_transform->destroy(current_transform);
}
this->transforms->destroy(this->transforms);
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
}
free(this);
return SUCCESS;
}
/*
* Described in header.
*/
proposal_substructure_t *proposal_substructure_create()
{
private_proposal_substructure_t *this = malloc_thing(private_proposal_substructure_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator;
this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
this->public.set_proposal_number = (void (*) (proposal_substructure_t *,u_int8_t))set_proposal_number;
this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number;
this->public.set_protocol_id = (void (*) (proposal_substructure_t *,u_int8_t))set_protocol_id;
this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id;
this->public.get_info_for_transform_type = (status_t (*) (proposal_substructure_t *,transform_type_t,u_int16_t *, u_int16_t *))get_info_for_transform_type;
this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal;
this->public.add_to_proposal = (void (*) (proposal_substructure_t*,proposal_t*))add_to_proposal;
this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi;
this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count;
this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size;
this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone;
this->public.destroy = (void (*) (proposal_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->proposal_length = 0;
this->proposal_number = 0;
this->protocol_id = 0;
this->transforms_count = 0;
this->spi_size = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->transforms = linked_list_create();
return (&(this->public));
}
/*
* Described in header.
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto)
{
private_proposal_substructure_t *this = (private_proposal_substructure_t*)proposal_substructure_create();
iterator_t *iterator;
algorithm_t *algo;
transform_substructure_t *transform;
/* encryption algorithm is only availble in ESP */
iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* integrity algorithms */
iterator = proposal->create_algorithm_iterator(proposal, proto, INTEGRITY_ALGORITHM);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* prf algorithms */
iterator = proposal->create_algorithm_iterator(proposal, proto, PSEUDO_RANDOM_FUNCTION);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* dh groups */
iterator = proposal->create_algorithm_iterator(proposal, proto, DIFFIE_HELLMAN_GROUP);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* extended sequence numbers */
iterator = proposal->create_algorithm_iterator(proposal, proto, EXTENDED_SEQUENCE_NUMBERS);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, algo->algorithm, 0);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* take over general infos */
this->spi_size = proto == PROTO_IKE ? 8 : 4;
this->spi.len = this->spi_size;
this->spi.ptr = malloc(this->spi_size);
*((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto);
this->proposal_number = proposal->get_number(proposal);
this->protocol_id = proto;
return &(this->public);
}
@@ -0,0 +1,231 @@
/**
* @file proposal_substructure.h
*
* @brief Interface of proposal_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef PROPOSAL_SUBSTRUCTURE_H_
#define PROPOSAL_SUBSTRUCTURE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <config/proposal.h>
#include <utils/linked_list.h>
/**
* Length of the proposal substructure header (without spi).
*
* @ingroup payloads
*/
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
typedef struct proposal_substructure_t proposal_substructure_t;
/**
* @brief Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
*
* The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
*
* @b Constructors:
* - proposal_substructure_create()
*
* @ingroup payloads
*/
struct proposal_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
* When deleting any transform over this iterator, call
* get_size to make sure the length and number values are ok.
*
* @param this calling proposal_substructure_t object
* @param forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t * (*create_transform_substructure_iterator) (proposal_substructure_t *this, bool forward);
/**
* @brief Adds a transform_substructure_t object to this object.
*
* @warning The added transform_substructure_t object is
* getting destroyed in destroy function of proposal_substructure_t.
*
* @param this calling proposal_substructure_t object
* @param transform transform_substructure_t object to add
*/
void (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform);
/**
* @brief Sets the proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id proposal number to set
*/
void (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number);
/**
* @brief get proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @return proposal number of current proposal substructure.
*/
u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
/**
* @brief get the number of transforms in current proposal.
*
* @param this calling proposal_substructure_t object
* @return transform count in current proposal
*/
size_t (*get_transform_count) (proposal_substructure_t *this);
/**
* @brief get size of the set spi in bytes.
*
* @param this calling proposal_substructure_t object
* @return size of the spi in bytes
*/
size_t (*get_spi_size) (proposal_substructure_t *this);
/**
* @brief Sets the protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id protocol id to set
*/
void (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id);
/**
* @brief get protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @return protocol id of current proposal substructure.
*/
u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
/**
* @brief Get informations for a specific transform type.
*
* @param this calling proposal_substructure_t object
* @param type type to get informations for
* @param transform_id transform id of the specific type
* @param key_length key length of the specific key length transform attribute
* @return
* - SUCCESS if transform type is part of this proposal and
* all data (incl. key length) could be fetched
* - NOT_FOUND if transform type is not part of this proposal
*/
status_t (*get_info_for_transform_type) (proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length);
/**
* @brief Sets the next_payload field of this substructure
*
* If this is the last proposal, next payload field is set to 0,
* otherwise to 2
*
* @param this calling proposal_substructure_t object
* @param is_last When TRUE, next payload field is set to 0, otherwise to 2
*/
void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last);
/**
* @brief Returns the currently set SPI of this proposal.
*
* @warning Returned data are not copied
*
* @param this calling proposal_substructure_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (proposal_substructure_t *this);
/**
* @brief Sets the SPI of the current proposal.
*
* @warning SPI is getting copied
*
* @param this calling proposal_substructure_t object
* @param spi chunk_t pointing to the value to set
*/
void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
/**
* @brief Add this proposal_substructure to a proposal.
*
* Since a proposal_t may contain the data of multiple
* proposal_sbustructure_t's, it may be necessary to call
* the function multiple times with the same proposal.
*
* @param this calling proposal_substructure_t object
* @param proposal proposal where the data should be added
*/
void (*add_to_proposal) (proposal_substructure_t *this, proposal_t *proposal);
/**
* @brief Clones an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to clone
* @return cloned object
*/
proposal_substructure_t* (*clone) (proposal_substructure_t *this);
/**
* @brief Destroys an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to destroy
*/
void (*destroy) (proposal_substructure_t *this);
};
/**
* @brief Creates an empty proposal_substructure_t object
*
* @return proposal_substructure_t object
*
* @ingroup payloads
*/
proposal_substructure_t *proposal_substructure_create();
/**
* @brief Creates a proposal substructure from a proposal.
*
* Since a child proposal may contain data for both AH and ESP,
* the protocol must be specified. If the proposal does not contain
* data for proto, NULL is returned. Call twice, once with AH, once
* with ESP, with the same proposal to build the two substructures
* for it.
*
* @param proposal proposal to build a substruct out of it
* @param proto for which protocol the substructure should be built
* @return proposal_substructure_t object, or NULL
*
* @ingroup payloads
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto);
#endif /*PROPOSAL_SUBSTRUCTURE_H_*/
@@ -0,0 +1,390 @@
/**
* @file sa_payload.c
*
* @brief Implementation of sa_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "sa_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
typedef struct private_sa_payload_t private_sa_payload_t;
/**
* Private data of an sa_payload_t object.
*
*/
struct private_sa_payload_t {
/**
* Public sa_payload_t interface.
*/
sa_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Proposals in this payload are stored in a linked_list_t.
*/
linked_list_t * proposals;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_sa_payload_t object
*/
void (*compute_length) (private_sa_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-SA Payload
*
* The defined offsets are the positions in a object of type
* private_sa_payload_t.
*
*/
encoding_rule_t sa_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ PROPOSALS, offsetof(private_sa_payload_t, proposals) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Proposals> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_sa_payload_t *this)
{
int proposal_number = 1;
status_t status = SUCCESS;
iterator_t *iterator;
bool first = TRUE;
/* check proposal numbering */
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while(iterator->has_next(iterator))
{
proposal_substructure_t *current_proposal;
iterator->current(iterator,(void **)&current_proposal);
if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
{
if (first)
{
/* first number must be 1 */
status = FAILED;
break;
}
if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
{
/* must be only one more then previous proposal */
status = FAILED;
break;
}
}
else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
{
/* must not be smaller then proceeding one */
status = FAILED;
break;
}
status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface));
if (status != SUCCESS)
{
break;
}
first = FALSE;
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of payload_t.destroy and sa_payload_t.destroy.
*/
static status_t destroy(private_sa_payload_t *this)
{
/* all proposals are getting destroyed */
while (this->proposals->get_count(this->proposals) > 0)
{
proposal_substructure_t *current_proposal;
this->proposals->remove_last(this->proposals,(void **)&current_proposal);
current_proposal->destroy(current_proposal);
}
this->proposals->destroy(this->proposals);
free(this);
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = sa_payload_encodings;
*rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_sa_payload_t *this)
{
return SECURITY_ASSOCIATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_sa_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_sa_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_sa_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of sa_payload_t.create_proposal_substructure_iterator.
*/
static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward)
{
return this->proposals->create_iterator(this->proposals,forward);
}
/**
* Implementation of sa_payload_t.add_proposal_substructure.
*/
static void add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal)
{
status_t status;
if (this->proposals->get_count(this->proposals) > 0)
{
proposal_substructure_t *last_proposal;
status = this->proposals->get_last(this->proposals,(void **) &last_proposal);
/* last transform is now not anymore last one */
last_proposal->set_is_last_proposal(last_proposal,FALSE);
}
proposal->set_is_last_proposal(proposal,TRUE);
this->proposals->insert_last(this->proposals,(void *) proposal);
this->compute_length(this);
}
/**
* Implementation of sa_payload_t.add_proposal.
*/
static void add_proposal(private_sa_payload_t *this, proposal_t *proposal)
{
proposal_substructure_t *substructure;
protocol_id_t proto[2];
u_int i;
/* build the substructures for every protocol */
proposal->get_protocols(proposal, proto);
for (i = 0; i<2; i++)
{
if (proto[i] != PROTO_NONE)
{
substructure = proposal_substructure_create_from_proposal(proposal, proto[i]);
add_proposal_substructure(this, substructure);
}
}
}
/**
* Implementation of sa_payload_t.get_proposals.
*/
static linked_list_t *get_proposals(private_sa_payload_t *this)
{
int proposal_struct_number = 0;
iterator_t *iterator;
proposal_t *proposal;
linked_list_t *proposal_list;
/* this list will hold our proposals */
proposal_list = linked_list_create();
/* iterate over structures, one OR MORE structures will result in a proposal */
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while (iterator->has_next(iterator))
{
proposal_substructure_t *proposal_struct;
iterator->current(iterator,(void **)&(proposal_struct));
if (proposal_struct->get_proposal_number(proposal_struct) > proposal_struct_number)
{
/* here starts a new proposal, create a new one and add it to the list */
proposal_struct_number = proposal_struct->get_proposal_number(proposal_struct);
proposal = proposal_create(proposal_struct_number);
proposal_list->insert_last(proposal_list, proposal);
}
/* proposal_substructure_t does the dirty work and builds up the proposal */
proposal_struct->add_to_proposal(proposal_struct, proposal);
}
iterator->destroy(iterator);
return proposal_list;
}
/**
* Implementation of private_sa_payload_t.compute_length.
*/
static void compute_length (private_sa_payload_t *this)
{
iterator_t *iterator;
size_t length = SA_PAYLOAD_HEADER_LENGTH;
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while (iterator->has_next(iterator))
{
payload_t *current_proposal;
iterator->current(iterator,(void **) &current_proposal);
length += current_proposal->get_length(current_proposal);
}
iterator->destroy(iterator);
this->payload_length = length;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create()
{
private_sa_payload_t *this = malloc_thing(private_sa_payload_t);
/* public interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator;
this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals;
this->public.destroy = (void (*) (sa_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
this->proposals = linked_list_create();
return (&(this->public));
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
{
iterator_t *iterator;
proposal_t *proposal;
sa_payload_t *sa_payload = sa_payload_create();
/* add every payload from the list */
iterator = proposals->create_iterator(proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&proposal);
add_proposal((private_sa_payload_t*)sa_payload, proposal);
}
iterator->destroy(iterator);
return sa_payload;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
{
sa_payload_t *sa_payload = sa_payload_create();
add_proposal((private_sa_payload_t*)sa_payload, proposal);
return sa_payload;
}
@@ -0,0 +1,140 @@
/**
* @file sa_payload.h
*
* @brief Interface of sa_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef SA_PAYLOAD_H_
#define SA_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
/**
* SA_PAYLOAD length in bytes without any proposal substructure.
*
* @ingroup payloads
*/
#define SA_PAYLOAD_HEADER_LENGTH 4
typedef struct sa_payload_t sa_payload_t;
/**
* @brief Class representing an IKEv2-SA Payload.
*
* The SA Payload format is described in RFC section 3.3.
*
* @b Constructors:
* - sa_payload_create()
* - sa_payload_create_from_ike_proposals()
* - sa_payload_create_from_proposal()
*
* @todo Add support of algorithms without specified keylength in get_proposals and get_ike_proposals.
*
* @ingroup payloads
*/
struct sa_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored proposal_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an proposal using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling sa_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, bool forward);
/**
* @brief Adds a proposal_substructure_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of sa_payload_t.
*
* @param this calling sa_payload_t object
* @param proposal proposal_substructure_t object to add
*/
void (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal);
/**
* @brief Gets the proposals in this payload as a list.
*
* @return a list containing proposal_t s
*/
linked_list_t *(*get_proposals) (sa_payload_t *this);
/**
* @brief Add a child proposal (AH/ESP) to the payload.
*
* @param proposal child proposal to add to the payload
*/
void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
/**
* @brief Destroys an sa_payload_t object.
*
* @param this sa_payload_t object to destroy
*/
void (*destroy) (sa_payload_t *this);
};
/**
* @brief Creates an empty sa_payload_t object
*
* @return created sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create();
/**
* @brief Creates a sa_payload_t object from a list of proposals.
*
* @param proposals list of proposals to build the payload from
* @return sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
/**
* @brief Creates a sa_payload_t object from a single proposal.
*
* This is only for convenience. Use sa_payload_create_from_proposal_list
* if you want to add more than one proposal.
*
* @param proposal proposal from which the payload should be built.
* @return sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
#endif /*SA_PAYLOAD_H_*/
@@ -0,0 +1,374 @@
/**
* @file traffic_selector_substructure.c
*
* @brief Interface of traffic_selector_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "traffic_selector_substructure.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
/**
* String mappings for ts_type_t.
*/
mapping_t ts_type_m[] = {
{TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"},
{TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"},
{MAPPING_END, NULL}
};
typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
/**
* Private data of an traffic_selector_substructure_t object.
*
*/
struct private_traffic_selector_substructure_t {
/**
* Public traffic_selector_substructure_t interface.
*/
traffic_selector_substructure_t public;
/**
* Type of traffic selector.
*/
u_int8_t ts_type;
/**
* IP Protocol ID.
*/
u_int8_t ip_protocol_id;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Start port number.
*/
u_int16_t start_port;
/**
* End port number.
*/
u_int16_t end_port;
/**
* Starting address.
*/
chunk_t starting_address;
/**
* Ending address.
*/
chunk_t ending_address;
/**
* update length
*/
void (*compute_length) (private_traffic_selector_substructure_t *this);
};
/**
* Encoding rules to parse or generate a TS payload
*
* The defined offsets are the positions in a object of type
* private_traffic_selector_substructure_t.
*
*/
encoding_rule_t traffic_selector_substructure_encodings[] = {
/* 1 Byte next ts type*/
{ TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
/* 1 Byte IP protocol id*/
{ U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
/* 2 Byte start port*/
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
/* 2 Byte end port*/
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
/* starting address is either 4 or 16 byte */
{ ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
/* ending address is either 4 or 16 byte */
{ ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! TS Type !IP Protocol ID*| Selector Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Start Port* | End Port* |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Starting Address* ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Ending Address* ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_traffic_selector_substructure_t *this)
{
if (this->start_port > this->end_port)
{
return FAILED;
}
switch (this->ts_type)
{
case TS_IPV4_ADDR_RANGE:
{
if ((this->starting_address.len != 4) ||
(this->ending_address.len != 4))
{
/* ipv4 address must be 4 bytes long */
return FAILED;
}
break;
}
case TS_IPV6_ADDR_RANGE:
default:
{
/* not supported ts type */
return FAILED;
}
}
return SUCCESS;
}
/**
* Implementation of traffic_selector_substructure_t.get_encoding_rules.
*/
static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = traffic_selector_substructure_encodings;
*rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
{
return TRAFFIC_SELECTOR_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
{
return 0;
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_traffic_selector_substructure_t *this)
{
return this->payload_length;
}
/**
* Implementation of traffic_selector_substructure_t.get_ts_type.
*/
static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this)
{
return this->ts_type;
}
/**
* Implementation of traffic_selector_substructure_t.set_ts_type.
*/
static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type)
{
this->ts_type = ts_type;
}
/**
* Implementation of traffic_selector_substructure_t.get_protocol_id.
*/
static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this)
{
return this->ip_protocol_id;
}
/**
* Implementation of traffic_selector_substructure_t.set_protocol_id.
*/
static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id)
{
this->ip_protocol_id = protocol_id;
}
/**
* Implementation of traffic_selector_substructure_t.get_start_host.
*/
static host_t * get_start_host (private_traffic_selector_substructure_t *this)
{
return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port));
}
/**
* Implementation of traffic_selector_substructure_t.set_start_host.
*/
static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host)
{
this->start_port = start_host->get_port(start_host);
if (this->starting_address.ptr != NULL)
{
chunk_free(&(this->starting_address));
}
this->starting_address = start_host->get_address_as_chunk(start_host);
this->compute_length(this);
}
/**
* Implementation of traffic_selector_substructure_t.get_end_host.
*/
static host_t *get_end_host (private_traffic_selector_substructure_t *this)
{
return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port));
}
/**
* Implementation of traffic_selector_substructure_t.set_end_host.
*/
static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host)
{
this->end_port = end_host->get_port(end_host);
if (this->ending_address.ptr != NULL)
{
chunk_free(&(this->ending_address));
}
this->ending_address = end_host->get_address_as_chunk(end_host);
this->compute_length(this);
}
/**
* Implementation of traffic_selector_substructure_t.get_traffic_selector.
*/
static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
{
traffic_selector_t *ts;
ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
this->starting_address, this->start_port,
this->ending_address, this->end_port);
return ts;
}
/**
* Implementation of private_ts_payload_t.compute_length
*/
void compute_length(private_traffic_selector_substructure_t *this)
{
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->ending_address.len + this->starting_address.len;
}
/**
* Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
*/
static void destroy(private_traffic_selector_substructure_t *this)
{
free(this->starting_address.ptr);
free(this->ending_address.ptr);
free(this);
}
/*
* Described in header
*/
traffic_selector_substructure_t *traffic_selector_substructure_create()
{
private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type;
this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type;
this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id;
this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id;
this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host;
this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host;
this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host;
this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host;
this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
this->start_port = 0;
this->end_port = 0;
this->starting_address = CHUNK_INITIALIZER;
this->ending_address = CHUNK_INITIALIZER;
this->ip_protocol_id = 0;
/* must be set to be valid */
this->ts_type = TS_IPV4_ADDR_RANGE;
return (&(this->public));
}
/*
* Described in header
*/
traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
{
private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
this->ts_type = traffic_selector->get_type(traffic_selector);
this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
this->start_port = traffic_selector->get_from_port(traffic_selector);
this->end_port = traffic_selector->get_to_port(traffic_selector);
this->starting_address = traffic_selector->get_from_address(traffic_selector);
this->ending_address = traffic_selector->get_to_address(traffic_selector);
this->compute_length(this);
return &(this->public);
}
@@ -0,0 +1,171 @@
/**
* @file traffic_selector_substructure.h
*
* @brief Interface of traffic_selector_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <utils/host.h>
#include <config/traffic_selector.h>
/**
* Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
*
* @ingroup payloads
*/
#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
/**
* @brief Class representing an IKEv2 TRAFFIC SELECTOR.
*
* The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
*
* @b Constructors:
* - traffic_selector_substructure_create()
* - traffic_selector_substructure_create_from_traffic_selector()
*
* @ingroup payloads
*/
struct traffic_selector_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the type of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @return type of traffic selector
*
*/
ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
/**
* @brief Set the type of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @param ts_type type of traffic selector
*/
void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type);
/**
* @brief Get the IP protocol ID of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @return type of traffic selector
*
*/
u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this);
/**
* @brief Set the IP protocol ID of Traffic selector
*
* @param this calling traffic_selector_substructure_t object
* @param protocol_id protocol ID of traffic selector
*/
void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id);
/**
* @brief Get the start port and address as host_t object.
*
* Returned host_t object has to get destroyed by the caller.
*
* @param this calling traffic_selector_substructure_t object
* @return start host as host_t object
*
*/
host_t *(*get_start_host) (traffic_selector_substructure_t *this);
/**
* @brief Set the start port and address as host_t object.
*
* @param this calling traffic_selector_substructure_t object
* @param start_host start host as host_t object
*/
void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host);
/**
* @brief Get the end port and address as host_t object.
*
* Returned host_t object has to get destroyed by the caller.
*
* @param this calling traffic_selector_substructure_t object
* @return end host as host_t object
*
*/
host_t *(*get_end_host) (traffic_selector_substructure_t *this);
/**
* @brief Set the end port and address as host_t object.
*
* @param this calling traffic_selector_substructure_t object
* @param end_host end host as host_t object
*/
void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host);
/**
* @brief Get a traffic_selector_t from this substructure.
*
* @warning traffic_selector_t must be destroyed after usage.
*
* @param this calling traffic_selector_substructure_t object
* @return contained traffic_selector_t
*/
traffic_selector_t *(*get_traffic_selector) (traffic_selector_substructure_t *this);
/**
* @brief Destroys an traffic_selector_substructure_t object.
*
* @param this traffic_selector_substructure_t object to destroy
*/
void (*destroy) (traffic_selector_substructure_t *this);
};
/**
* @brief Creates an empty traffic_selector_substructure_t object.
*
* TS type is set to default TS_IPV4_ADDR_RANGE!
*
* @return traffic_selector_substructure_t object
*
* @ingroup payloads
*/
traffic_selector_substructure_t *traffic_selector_substructure_create();
/**
* @brief Creates an initialized traffif selector substructure using
* the values from a traffic_selector_t.
*
* @param traffic_selector traffic_selector_t to use for initialization
* @return traffic_selector_substructure_t object
*
* @ingroup payloads
*/
traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector);
#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ */
@@ -0,0 +1,333 @@
/**
* @file transform_attribute.c
*
* @brief Implementation of transform_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <string.h>
#include <stddef.h>
#include "transform_attribute.h"
#include <encoding/payloads/encodings.h>
#include <types.h>
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
* Private data of an transform_attribute_t object.
*
*/
struct private_transform_attribute_t {
/**
* Public transform_attribute_t interface.
*/
transform_attribute_t public;
/**
* Attribute Format Flag.
*
* - TRUE means value is stored in attribute_length_or_value
* - FALSE means value is stored in attribute_value
*/
bool attribute_format;
/**
* Type of the attribute.
*/
u_int16_t attribute_type;
/**
* Attribute Length if attribute_format is 0, attribute Value otherwise.
*/
u_int16_t attribute_length_or_value;
/**
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
};
/**
* String mappings for transform_attribute_type_t.
*/
mapping_t transform_attribute_type_m[] = {
{ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"},
{KEY_LENGTH, "KEY_LENGTH"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a Transform attribute.
*
* The defined offsets are the positions in a object of type
* private_transform_attribute_t.
*
*/
encoding_rule_t transform_attribute_encodings[] = {
/* Flag defining the format of this payload */
{ ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
/* Length or value, depending on the attribute format flag */
{ ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) },
/* Value of attribute if attribute format flag is zero */
{ ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!A! Attribute Type ! AF=0 Attribute Length !
!F! ! AF=1 Attribute Value !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! AF=0 Attribute Value !
! AF=1 Not Transmitted !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_transform_attribute_t *this)
{
if (this->attribute_type != KEY_LENGTH)
{
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_attribute_encodings;
*rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_transform_attribute_t *this)
{
return (NO_PAYLOAD);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_transform_attribute_t *this,payload_type_t type)
{
}
/**
* Implementation of transform_attribute_t.get_length.
*/
static size_t get_length(private_transform_attribute_t *this)
{
if (this->attribute_format == TRUE)
{
/*Attribute size is only 4 byte */
return 4;
}
return (this->attribute_length_or_value + 4);
}
/**
* Implementation of transform_attribute_t.set_value_chunk.
*/
static void set_value_chunk(private_transform_attribute_t *this, chunk_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
if (value.len > 2)
{
this->attribute_value.ptr = clalloc(value.ptr,value.len);
this->attribute_value.len = value.len;
this->attribute_length_or_value = value.len;
/* attribute has not a fixed length */
this->attribute_format = FALSE;
}
else
{
memcpy(&(this->attribute_length_or_value),value.ptr,value.len);
}
}
/**
* Implementation of transform_attribute_t.set_value.
*/
static void set_value(private_transform_attribute_t *this, u_int16_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
this->attribute_length_or_value = value;
}
/**
* Implementation of transform_attribute_t.get_value_chunk.
*/
static chunk_t get_value_chunk (private_transform_attribute_t *this)
{
chunk_t value;
if (this->attribute_format == FALSE)
{
value.ptr = this->attribute_value.ptr;
value.len = this->attribute_value.len;
}
else
{
value.ptr = (void *) &(this->attribute_length_or_value);
value.len = 2;
}
return value;
}
/**
* Implementation of transform_attribute_t.get_value.
*/
static u_int16_t get_value (private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
/**
* Implementation of transform_attribute_t.set_attribute_type.
*/
static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
/**
* Implementation of transform_attribute_t.get_attribute_type.
*/
static u_int16_t get_attribute_type (private_transform_attribute_t *this)
{
return this->attribute_type;
}
/**
* Implementation of transform_attribute_t.clone.
*/
static transform_attribute_t * clone(private_transform_attribute_t *this)
{
private_transform_attribute_t *new_clone;
new_clone = (private_transform_attribute_t *) transform_attribute_create();
new_clone->attribute_format = this->attribute_format;
new_clone->attribute_type = this->attribute_type;
new_clone->attribute_length_or_value = this->attribute_length_or_value;
if (!new_clone->attribute_format)
{
new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len);
new_clone->attribute_value.len = this->attribute_value.len;
}
return (transform_attribute_t *) new_clone;
}
/**
* Implementation of transform_attribute_t.destroy and payload_t.destroy.
*/
static void destroy(private_transform_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
free(this->attribute_value.ptr);
}
free(this);
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create()
{
private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
this->public.set_value = (void (*) (transform_attribute_t *,u_int16_t)) set_value;
this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value;
this->public.set_attribute_type = (void (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type;
this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type;
this->public.clone = (transform_attribute_t * (*) (transform_attribute_t *)) clone;
this->public.destroy = (void (*) (transform_attribute_t *)) destroy;
/* set default values of the fields */
this->attribute_format = TRUE;
this->attribute_type = 0;
this->attribute_length_or_value = 0;
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
return (&(this->public));
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
{
transform_attribute_t *attribute = transform_attribute_create();
attribute->set_attribute_type(attribute,KEY_LENGTH);
attribute->set_value(attribute,key_length);
return attribute;
}
@@ -0,0 +1,154 @@
/**
* @file transform_attribute.h
*
* @brief Interface of transform_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef TRANSFORM_ATTRIBUTE_H_
#define TRANSFORM_ATTRIBUTE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
typedef enum transform_attribute_type_t transform_attribute_type_t;
/**
* Type of the attribute, as in IKEv2 RFC 3.3.5.
*
* @ingroup payloads
*/
enum transform_attribute_type_t {
ATTRIBUTE_UNDEFINED = 16384,
KEY_LENGTH = 14
};
/**
* String mappings for transform_attribute_type_t.
*
* @ingroup payloads
*/
extern mapping_t transform_attribute_type_m[];
typedef struct transform_attribute_t transform_attribute_t;
/**
* @brief Class representing an IKEv2- TRANSFORM Attribute.
*
* The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
*
* @ingroup payloads
*/
struct transform_attribute_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling transform_attribute_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_value_chunk) (transform_attribute_t *this);
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling transform_attribute_t object
* @return value
*/
u_int16_t (*get_value) (transform_attribute_t *this);
/**
* @brief Sets the value of the attribute.
*
* @warning Value is getting copied.
*
* @param this calling transform_attribute_t object
* @param value chunk_t pointing to the value to set
*/
void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
/**
* @brief Sets the value of the attribute.
*
* @param this calling transform_attribute_t object
* @param value value to set
*/
void (*set_value) (transform_attribute_t *this, u_int16_t value);
/**
* @brief Sets the type of the attribute.
*
* @param this calling transform_attribute_t object
* @param type type to set (most significant bit is set to zero)
*/
void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
/**
* @brief get the type of the attribute.
*
* @param this calling transform_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
/**
* @brief Clones an transform_attribute_t object.
*
* @param this transform_attribute_t object to clone
* @return cloned transform_attribute_t object
*/
transform_attribute_t * (*clone) (transform_attribute_t *this);
/**
* @brief Destroys an transform_attribute_t object.
*
* @param this transform_attribute_t object to destroy
*/
void (*destroy) (transform_attribute_t *this);
};
/**
* @brief Creates an empty transform_attribute_t object.
*
* @return transform_attribute_t object
*
* @ingroup payloads
*/
transform_attribute_t *transform_attribute_create();
/**
* @brief Creates an transform_attribute_t of type KEY_LENGTH.
*
* @param key_length key length in bytes
* @return transform_attribute_t object
*
* @ingroup payloads
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
#endif /*TRANSFORM_ATTRIBUTE_H_*/
@@ -0,0 +1,485 @@
/**
* @file transform_substructure.h
*
* @brief Implementation of transform_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "transform_substructure.h"
#include <encoding/payloads/transform_attribute.h>
#include <encoding/payloads/encodings.h>
#include <types.h>
#include <utils/linked_list.h>
typedef struct private_transform_substructure_t private_transform_substructure_t;
/**
* Private data of an transform_substructure_t object.
*
*/
struct private_transform_substructure_t {
/**
* Public transform_substructure_t interface.
*/
transform_substructure_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Length of this payload.
*/
u_int16_t transform_length;
/**
* Type of the transform.
*/
u_int8_t transform_type;
/**
* Transform ID.
*/
u_int16_t transform_id;
/**
* Transforms Attributes are stored in a linked_list_t.
*/
linked_list_t *attributes;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_transform_substructure_t object
*/
void (*compute_length) (private_transform_substructure_t *this);
};
/**
* Encoding rules to parse or generate a Transform substructure.
*
* The defined offsets are the positions in a object of type
* private_transform_substructure_t.
*
*/
encoding_rule_t transform_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole transform substructure*/
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
/* transform type is a number of 8 bit */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* tranform ID is a number of 8 bit */
{ U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
/* Attributes are stored in a transform attribute,
offset points to a linked_list_t pointer */
{ TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!Transform Type ! RESERVED ! Transform ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_transform_substructure_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3))
{
/* must be 0 or 3 */
return FAILED;
}
switch (this->transform_type)
{
case ENCRYPTION_ALGORITHM:
{
if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
{
return FAILED;
}
break;
}
case PSEUDO_RANDOM_FUNCTION:
{
if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
{
return FAILED;
}
break;
}
case INTEGRITY_ALGORITHM:
{
if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
{
return FAILED;
}
break;
}
case DIFFIE_HELLMAN_GROUP:
{
switch (this->transform_id)
{
case MODP_768_BIT:
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_6144_BIT:
case MODP_8192_BIT:
{
break;
}
default:
{
return FAILED;
}
}
break;
}
case EXTENDED_SEQUENCE_NUMBERS:
{
if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
{
return FAILED;
}
break;
}
default:
{
/* not a supported transform type! */
return FAILED;
}
}
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_attributes;
iterator->current(iterator,(void **)&current_attributes);
status = current_attributes->verify(current_attributes);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
/* proposal number is checked in SA payload */
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_substructure_encodings;
*rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_transform_substructure_t *this)
{
return TRANSFORM_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_transform_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_transform_substructure_t *this)
{
this->compute_length(this);
return this->transform_length;
}
/**
* Implementation of transform_substructure_t.create_transform_attribute_iterator.
*/
static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward)
{
return this->attributes->create_iterator(this->attributes,forward);
}
/**
* Implementation of transform_substructure_t.add_transform_attribute.
*/
static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes,(void *) attribute);
this->compute_length(this);
}
/**
* Implementation of transform_substructure_t.set_is_last_transform.
*/
static void set_is_last_transform (private_transform_substructure_t *this, bool is_last)
{
this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
}
/**
* Implementation of transform_substructure_t.get_is_last_transform.
*/
static bool get_is_last_transform (private_transform_substructure_t *this)
{
return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_transform_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of transform_substructure_t.set_transform_type.
*/
static void set_transform_type (private_transform_substructure_t *this,u_int8_t type)
{
this->transform_type = type;
}
/**
* Implementation of transform_substructure_t.get_transform_type.
*/
static u_int8_t get_transform_type (private_transform_substructure_t *this)
{
return this->transform_type;
}
/**
* Implementation of transform_substructure_t.set_transform_id.
*/
static void set_transform_id (private_transform_substructure_t *this,u_int16_t id)
{
this->transform_id = id;
}
/**
* Implementation of transform_substructure_t.get_transform_id.
*/
static u_int16_t get_transform_id (private_transform_substructure_t *this)
{
return this->transform_id;
}
/**
* Implementation of private_transform_substructure_t.compute_length.
*/
static void compute_length (private_transform_substructure_t *this)
{
iterator_t *iterator;
size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_attribute;
iterator->current(iterator,(void **) &current_attribute);
length += current_attribute->get_length(current_attribute);
}
iterator->destroy(iterator);
this->transform_length = length;
}
/**
* Implementation of transform_substructure_t.clone.
*/
static transform_substructure_t *clone(private_transform_substructure_t *this)
{
private_transform_substructure_t *new_clone;
iterator_t *attributes;
new_clone = (private_transform_substructure_t *) transform_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->transform_type = this->transform_type;
new_clone->transform_id = this->transform_id;
attributes = this->attributes->create_iterator(this->attributes,FALSE);
while (attributes->has_next(attributes))
{
transform_attribute_t *current_attribute;
transform_attribute_t *current_attribute_clone;
attributes->current(attributes,(void **) &current_attribute);
current_attribute_clone = current_attribute->clone(current_attribute);
new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
}
attributes->destroy(attributes);
return &(new_clone->public);
}
/**
* Implementation of transform_substructure_t.get_key_length.
*/
static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
{
iterator_t *attributes;
attributes = this->attributes->create_iterator(this->attributes,TRUE);
while (attributes->has_next(attributes))
{
transform_attribute_t *current_attribute;
attributes->current(attributes,(void **) &current_attribute);
if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
{
*key_length = current_attribute->get_value(current_attribute);
attributes->destroy(attributes);
return SUCCESS;
}
}
attributes->destroy(attributes);
return FAILED;
}
/**
* Implementation of transform_substructure_t.destroy and payload_t.destroy.
*/
static void destroy(private_transform_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->attributes->get_count(this->attributes) > 0)
{
transform_attribute_t *current_attribute;
this->attributes->remove_last(this->attributes,(void **)&current_attribute);
current_attribute->destroy(current_attribute);
}
this->attributes->destroy(this->attributes);
free(this);
}
/*
* Described in header.
*/
transform_substructure_t *transform_substructure_create()
{
private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator;
this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
this->public.set_is_last_transform = (void (*) (transform_substructure_t *,bool)) set_is_last_transform;
this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone;
this->public.destroy = (void (*) (transform_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
this->transform_id = 0;
this->transform_type = 0;
this->attributes = linked_list_create();
return (&(this->public));
}
/*
* Described in header
*/
transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length)
{
transform_substructure_t *transform = transform_substructure_create();
transform->set_transform_type(transform,transform_type);
transform->set_transform_id(transform,transform_id);
/* a keylength attribute is only created for AES encryption */
if (transform_type == ENCRYPTION_ALGORITHM &&
transform_id == ENCR_AES_CBC)
{
transform_attribute_t *attribute = transform_attribute_create_key_length(key_length);
transform->add_transform_attribute(transform,attribute);
}
return transform;
}
@@ -0,0 +1,198 @@
/**
* @file transform_substructure.h
*
* @brief Interface of transform_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef TRANSFORM_SUBSTRUCTURE_H_
#define TRANSFORM_SUBSTRUCTURE_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_attribute.h>
#include <utils/linked_list.h>
#include <crypto/diffie_hellman.h>
#include <crypto/signers/signer.h>
#include <crypto/prfs/prf.h>
#include <crypto/crypters/crypter.h>
#include <config/proposal.h>
/**
* IKEv1 Value for a transform payload.
*
* @ingroup payloads
*/
#define TRANSFORM_TYPE_VALUE 3
/**
* Length of the transform substructure header in bytes.
*
* @ingroup payloads
*/
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
typedef struct transform_substructure_t transform_substructure_t;
/**
* @brief Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
*
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
*
* @ingroup payloads
*/
struct transform_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_attribute_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an transform attribute using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling transform_substructure_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object.
*/
iterator_t * (*create_transform_attribute_iterator) (transform_substructure_t *this, bool forward);
/**
* @brief Adds a transform_attribute_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of transform_substructure_t.
*
* @param this calling transform_substructure_t object
* @param proposal transform_attribute_t object to add
*/
void (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute);
/**
* @brief Sets the next_payload field of this substructure
*
* If this is the last transform, next payload field is set to 0,
* otherwise to 3
*
* @param this calling transform_substructure_t object
* @param is_last When TRUE, next payload field is set to 0, otherwise to 3
*/
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
* @brief Checks if this is the last transform.
*
* @param this calling transform_substructure_t object
* @return TRUE if this is the last Transform, FALSE otherwise
*/
bool (*get_is_last_transform) (transform_substructure_t *this);
/**
* @brief Sets transform type of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param type type value to set
*/
void (*set_transform_type) (transform_substructure_t *this,u_int8_t type);
/**
* @brief get transform type of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform type of current transform substructure.
*/
u_int8_t (*get_transform_type) (transform_substructure_t *this);
/**
* @brief Sets transform id of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param id transform id to set
*/
void (*set_transform_id) (transform_substructure_t *this,u_int16_t id);
/**
* @brief get transform id of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform id of current transform substructure.
*/
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
* @brief get transform id of the current transform.
*
* @param this calling transform_substructure_t object
* @param key_length The key length is written to this location
* @return
* - SUCCESS if a key length attribute is contained
* - FAILED if no key length attribute is part of this
* transform or key length uses more then 16 bit!
*/
status_t (*get_key_length) (transform_substructure_t *this,u_int16_t *key_length);
/**
* @brief Clones an transform_substructure_t object.
*
* @param this transform_substructure_t object to clone
* @return cloned transform_substructure_t object
*/
transform_substructure_t* (*clone) (transform_substructure_t *this);
/**
* @brief Destroys an transform_substructure_t object.
*
* @param this transform_substructure_t object to destroy
*/
void (*destroy) (transform_substructure_t *this);
};
/**
* @brief Creates an empty transform_substructure_t object.
*
* @return created transform_substructure_t object
*
* @ingroup payloads
*/
transform_substructure_t *transform_substructure_create();
/**
* @brief Creates an empty transform_substructure_t object.
*
* The key length is used for the transport types ENCRYPTION_ALGORITHM,
* PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all
* other transport types the key_length parameter is not used
*
* @param transform_type type of transform to create
* @param transform_id transform id specifying the specific algorithm of a transform type
* @param key_length Key length for key lenght attribute
* @return transform_substructure_t object
*
* @ingroup payloads
*/
transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length);
#endif /*TRANSFORM_SUBSTRUCTURE_H_*/
@@ -0,0 +1,365 @@
/**
* @file ts_payload.c
*
* @brief Implementation of ts_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "ts_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
typedef struct private_ts_payload_t private_ts_payload_t;
/**
* Private data of an ts_payload_t object.
*
*/
struct private_ts_payload_t {
/**
* Public ts_payload_t interface.
*/
ts_payload_t public;
/**
* TRUE if this TS payload is of type TSi, FALSE for TSr.
*/
bool is_initiator;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Number of traffic selectors
*/
u_int8_t number_of_traffic_selectors;
/**
* Contains the traffic selectors of type traffic_selector_substructure_t.
*/
linked_list_t *traffic_selectors;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ts_payload_t object
*/
void (*compute_length) (private_ts_payload_t *this);
};
/**
* Encoding rules to parse or generate a TS payload
*
* The defined offsets are the positions in a object of type
* private_ts_payload_t.
*
*/
encoding_rule_t ts_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ts_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_ts_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)},
/* 1 Byte TS type*/
{ U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some ts data bytes, length is defined in PAYLOAD_LENGTH */
{ TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Number of TSs ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Traffic Selectors> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ts_payload_t *this)
{
iterator_t *iterator;
status_t status = SUCCESS;
if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
{
/* must be the same */
return FAILED;
}
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_traffic_selector;
iterator->current(iterator,(void **)&current_traffic_selector);
status = current_traffic_selector->verify(current_traffic_selector);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of ts_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ts_payload_encodings;
*rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_ts_payload_t *this)
{
if (this->is_initiator)
{
return TRAFFIC_SELECTOR_INITIATOR;
}
else
{
return TRAFFIC_SELECTOR_RESPONDER;
}
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_ts_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_ts_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_ts_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of ts_payload_t.get_initiator.
*/
static bool get_initiator (private_ts_payload_t *this)
{
return (this->is_initiator);
}
/**
* Implementation of ts_payload_t.set_initiator.
*/
static void set_initiator (private_ts_payload_t *this,bool is_initiator)
{
this->is_initiator = is_initiator;
}
/**
* Implementation of ts_payload_t.add_traffic_selector_substructure.
*/
static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
{
this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
}
/**
* Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
*/
static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
{
return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
}
/**
* Implementation of ts_payload_t.get_traffic_selectors.
*/
static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
{
traffic_selector_t *ts;
iterator_t *iterator;
linked_list_t *ts_list = linked_list_create();
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
while (iterator->has_next(iterator))
{
traffic_selector_substructure_t *ts_substructure;
iterator->current(iterator, (void**)&ts_substructure);
ts = ts_substructure->get_traffic_selector(ts_substructure);
ts_list->insert_last(ts_list, (void*)ts);
}
iterator->destroy(iterator);
return ts_list;
}
/**
* Implementation of private_ts_payload_t.compute_length.
*/
static void compute_length (private_ts_payload_t *this)
{
iterator_t *iterator;
size_t ts_count = 0;
size_t length = TS_PAYLOAD_HEADER_LENGTH;
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_traffic_selector;
iterator->current(iterator,(void **) &current_traffic_selector);
length += current_traffic_selector->get_length(current_traffic_selector);
ts_count++;
}
iterator->destroy(iterator);
this->number_of_traffic_selectors= ts_count;
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy and ts_payload_t.destroy.
*/
static void destroy(private_ts_payload_t *this)
{
while (this->traffic_selectors->get_count(this->traffic_selectors) > 0)
{
payload_t *current_traffic_selector;
this->traffic_selectors->remove_last(this->traffic_selectors,(void **) &current_traffic_selector);
current_traffic_selector->destroy(current_traffic_selector);
}
this->traffic_selectors->destroy(this->traffic_selectors);
free(this);
}
/*
* Described in header
*/
ts_payload_t *ts_payload_create(bool is_initiator)
{
private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (ts_payload_t *)) destroy;
this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
this->is_initiator = is_initiator;
this->number_of_traffic_selectors = 0;
this->traffic_selectors = linked_list_create();
return &(this->public);
}
/*
* Described in header
*/
ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
{
iterator_t *iterator;
traffic_selector_t *ts;
traffic_selector_substructure_t *ts_substructure;
private_ts_payload_t *this;
this = (private_ts_payload_t*)ts_payload_create(is_initiator);
iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&ts);
ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
}
iterator->destroy(iterator);
return &(this->public);
}
@@ -0,0 +1,152 @@
/**
* @file ts_payload.h
*
* @brief Interface of ts_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef TS_PAYLOAD_H_
#define TS_PAYLOAD_H_
#include <types.h>
#include <utils/linked_list.h>
#include <config/traffic_selector.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/traffic_selector_substructure.h>
/**
* Length of a TS payload without the Traffic selectors.
*
* @ingroup payloads
*/
#define TS_PAYLOAD_HEADER_LENGTH 8
typedef struct ts_payload_t ts_payload_t;
/**
* @brief Class representing an IKEv2 TS payload.
*
* The TS payload format is described in RFC section 3.13.
*
* @b Constructors:
* - ts_payload_create()
* - ts_payload_create_from_traffic_selectors()
*
* @ingroup payloads
*/
struct ts_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the type of TSpayload (TSi or TSr).
*
* @param this calling id_payload_t object
* @return
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
*/
bool (*get_initiator) (ts_payload_t *this);
/**
* @brief Set the type of TS payload (TSi or TSr).
*
* @param this calling id_payload_t object
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
*/
void (*set_initiator) (ts_payload_t *this,bool is_initiator);
/**
* @brief Adds a traffic_selector_substructure_t object to this object.
*
* @warning The added traffic_selector_substructure_t object is
* getting destroyed in destroy function of ts_payload_t.
*
* @param this calling ts_payload_t object
* @param traffic_selector traffic_selector_substructure_t object to add
*/
void (*add_traffic_selector_substructure) (ts_payload_t *this,traffic_selector_substructure_t *traffic_selector);
/**
* @brief Creates an iterator of stored traffic_selector_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When removing an traffic_selector_substructure_t object
* using this iterator, the length of this payload
* has to get refreshed by calling payload_t.get_length!
*
* @param this calling ts_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_traffic_selector_substructure_iterator) (ts_payload_t *this, bool forward);
/**
* @brief Get a list of nested traffic selectors as traffic_selector_t.
*
* Resulting list and its traffic selectors must be destroyed after usage
*
* @param this calling ts_payload_t object
* @return list of traffic selectors
*/
linked_list_t *(*get_traffic_selectors) (ts_payload_t *this);
/**
* @brief Destroys an ts_payload_t object.
*
* @param this ts_payload_t object to destroy
*/
void (*destroy) (ts_payload_t *this);
};
/**
* @brief Creates an empty ts_payload_t object.
*
*
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
* @return ts_payload_t object
*
* @ingroup payloads
*/
ts_payload_t *ts_payload_create(bool is_initiator);
/**
* @brief Creates ts_payload with a list of traffic_selector_t
*
*
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
* @param traffic_selectors list of traffic selectors to include
* @return ts_payload_t object
*
* @ingroup payloads
*/
ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors);
#endif /* TS_PAYLOAD_H_ */
@@ -0,0 +1,207 @@
/**
* @file unknown_payload.c
*
* @brief Implementation of unknown_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "unknown_payload.h"
typedef struct private_unknown_payload_t private_unknown_payload_t;
/**
* Private data of an unknown_payload_t object.
*/
struct private_unknown_payload_t {
/**
* Public unknown_payload_t interface.
*/
unknown_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained data.
*/
chunk_t data;
};
/**
* Encoding rules to parse an payload which is not further specified.
*
* The defined offsets are the positions in a object of type
* private_unknown_payload_t.
*
*/
encoding_rule_t unknown_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_unknown_payload_t, next_payload)},
/* the critical bit */
{ FLAG, offsetof(private_unknown_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)},
/* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
{ UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Data of any type ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_unknown_payload_t *this)
{
/* can't do any checks, so we assume its good */
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = unknown_payload_encodings;
*rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_unknown_payload_t *this)
{
return UNKNOWN_PAYLOAD;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_unknown_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_unknown_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_unknown_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of unknown_payload_t.get_data.
*/
static bool is_critical(private_unknown_payload_t *this)
{
return this->critical;
}
/**
* Implementation of unknown_payload_t.get_data.
*/
static chunk_t get_data (private_unknown_payload_t *this)
{
return (this->data);
}
/**
* Implementation of payload_t.destroy and unknown_payload_t.destroy.
*/
static void destroy(private_unknown_payload_t *this)
{
if (this->data.ptr != NULL)
{
chunk_free(&(this->data));
}
free(this);
}
/*
* Described in header
*/
unknown_payload_t *unknown_payload_create()
{
private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (unknown_payload_t *)) destroy;
this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical;
this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH;
this->data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,95 @@
/**
* @file unknown_payload.h
*
* @brief Interface of unknown_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef UNKNOWN_PAYLOAD_H_
#define UNKNOWN_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Header length of the unknown payload.
*
* @ingroup payloads
*/
#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
typedef struct unknown_payload_t unknown_payload_t;
/**
* @brief Payload which can't be processed further.
*
* When the parser finds an unknown payload, he builds an instance of
* this class. This allows further processing of this payload, such as
* a check for the critical bit in the header.
*
* @b Constructors:
* - unknown_payload_create()
*
* @ingroup payloads
*/
struct unknown_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the raw data of this payload, without
* the generic payload header.
*
* Returned data are NOT copied and must not be freed.
*
* @param this calling unknown_payload_t object
* @return data as chunk_t
*/
chunk_t (*get_data) (unknown_payload_t *this);
/**
* @brief Get the critical flag.
*
* @param this calling unknown_payload_t object
* @return TRUE if payload is critical, FALSE if not
*/
bool (*is_critical) (unknown_payload_t *this);
/**
* @brief Destroys an unknown_payload_t object.
*
* @param this unknown_payload_t object to destroy
*/
void (*destroy) (unknown_payload_t *this);
};
/**
* @brief Creates an empty unknown_payload_t object.
*
* @return unknown_payload_t object
*
* @ingroup payloads
*/
unknown_payload_t *unknown_payload_create();
#endif /* UNKNOWN_PAYLOAD_H_ */
@@ -0,0 +1,227 @@
/**
* @file vendor_id_payload.c
*
* @brief Implementation of vendor_id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include "vendor_id_payload.h"
typedef struct private_vendor_id_payload_t private_vendor_id_payload_t;
/**
* Private data of an vendor_id_payload_t object.
*
*/
struct private_vendor_id_payload_t {
/**
* Public vendor_id_payload_t interface.
*/
vendor_id_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained vendor_id data value.
*/
chunk_t vendor_id_data;
};
/**
* Encoding rules to parse or generate a VENDOR ID payload
*
* The defined offsets are the positions in a object of type
* private_vendor_id_payload_t.
*
*/
encoding_rule_t vendor_id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_vendor_id_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)},
/* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
{ VID_DATA, offsetof(private_vendor_id_payload_t, vendor_id_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certificate Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_vendor_id_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of vendor_id_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_vendor_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = vendor_id_payload_encodings;
*rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_vendor_id_payload_t *this)
{
return VENDOR_ID;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_vendor_id_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_vendor_id_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of vendor_id_payload_t.set_data.
*/
static void set_data (private_vendor_id_payload_t *this, chunk_t data)
{
if (this->vendor_id_data.ptr != NULL)
{
chunk_free(&(this->vendor_id_data));
}
this->vendor_id_data.ptr = clalloc(data.ptr,data.len);
this->vendor_id_data.len = data.len;
this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + this->vendor_id_data.len;
}
/**
* Implementation of vendor_id_payload_t.get_data.
*/
static chunk_t get_data (private_vendor_id_payload_t *this)
{
return (this->vendor_id_data);
}
/**
* Implementation of vendor_id_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_vendor_id_payload_t *this)
{
chunk_t cloned_data;
if (this->vendor_id_data.ptr == NULL)
{
return (this->vendor_id_data);
}
cloned_data.ptr = clalloc(this->vendor_id_data.ptr,this->vendor_id_data.len);
cloned_data.len = this->vendor_id_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and vendor_id_payload_t.destroy.
*/
static void destroy(private_vendor_id_payload_t *this)
{
if (this->vendor_id_data.ptr != NULL)
{
chunk_free(&(this->vendor_id_data));
}
free(this);
}
/*
* Described in header
*/
vendor_id_payload_t *vendor_id_payload_create()
{
private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (vendor_id_payload_t *)) destroy;
this->public.set_data = (void (*) (vendor_id_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (vendor_id_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
this->vendor_id_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,103 @@
/**
* @file vendor_id_payload.h
*
* @brief Interface of vendor_id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef VENDOR_ID_PAYLOAD_H_
#define VENDOR_ID_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a VENDOR ID payload without the VID data in bytes.
*
* @ingroup payloads
*/
#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
typedef struct vendor_id_payload_t vendor_id_payload_t;
/**
* @brief Class representing an IKEv2 VENDOR ID payload.
*
* The VENDOR ID payload format is described in RFC section 3.12.
*
* @b Constructors:
* - vendor_id_payload_create()
*
* @ingroup payloads
*/
struct vendor_id_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the VID data.
*
* Data are getting cloned.
*
* @param this calling vendor_id_payload_t object
* @param data VID data as chunk_t
*/
void (*set_data) (vendor_id_payload_t *this, chunk_t data);
/**
* @brief Get the VID data.
*
* Returned data are a copy of the internal one.
*
* @param this calling vendor_id_payload_t object
* @return VID data as chunk_t
*/
chunk_t (*get_data_clone) (vendor_id_payload_t *this);
/**
* @brief Get the VID data.
*
* Returned data are NOT copied.
*
* @param this calling vendor_id_payload_t object
* @return VID data as chunk_t
*/
chunk_t (*get_data) (vendor_id_payload_t *this);
/**
* @brief Destroys an vendor_id_payload_t object.
*
* @param this vendor_id_payload_t object to destroy
*/
void (*destroy) (vendor_id_payload_t *this);
};
/**
* @brief Creates an empty vendor_id_payload_t object.
*
* @return vendor_id_payload_t object
*
* @ingroup payloads
*/
vendor_id_payload_t *vendor_id_payload_create();
#endif /* VENDOR_ID_PAYLOAD_H_ */
@@ -0,0 +1,24 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# 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.
#
NETWORK_DIR= $(CHARON_DIR)network/
CHARON_OBJS+= $(BUILD_DIR)packet.o
$(BUILD_DIR)packet.o : $(NETWORK_DIR)packet.c $(NETWORK_DIR)packet.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)socket.o
$(BUILD_DIR)socket.o : $(NETWORK_DIR)socket.c $(NETWORK_DIR)socket.h
$(CC) $(CFLAGS) -c -o $@ $<
+189
View File
@@ -0,0 +1,189 @@
/**
* @file packet.c
*
* @brief Implementation of packet_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "packet.h"
typedef struct private_packet_t private_packet_t;
/**
* Private data of an packet_t object.
*/
struct private_packet_t {
/**
* Public part of a packet_t object.
*/
packet_t public;
/**
* source address
*/
host_t *source;
/**
* destination address
*/
host_t *destination;
/**
* message data
*/
chunk_t data;
};
/**
* Implements packet_t.get_source
*/
static void set_source(private_packet_t *this, host_t *source)
{
if (this->source)
{
this->source->destroy(this->source);
}
this->source = source;
}
/**
* Implements packet_t.set_destination
*/
static void set_destination(private_packet_t *this, host_t *destination)
{
if (this->destination)
{
this->destination->destroy(this->destination);
}
this->destination = destination;
}
/**
* Implements packet_t.get_source
*/
static host_t *get_source(private_packet_t *this)
{
return this->source;
}
/**
* Implements packet_t.get_destination
*/
static host_t *get_destination(private_packet_t *this)
{
return this->destination;
}
/**
* Implements packet_t.get_data
*/
static chunk_t get_data(private_packet_t *this)
{
return this->data;
}
/**
* Implements packet_t.set_data
*/
static void set_data(private_packet_t *this, chunk_t data)
{
free(this->data.ptr);
this->data = data;
}
/**
* Implements packet_t.destroy.
*/
static void destroy(private_packet_t *this)
{
if (this->source != NULL)
{
this->source->destroy(this->source);
}
if (this->destination != NULL)
{
this->destination->destroy(this->destination);
}
free(this->data.ptr);
free(this);
}
/**
* Implements packet_t.clone.
*/
static packet_t *clone(private_packet_t *this)
{
private_packet_t *other = (private_packet_t*)packet_create();
if (this->destination != NULL)
{
other->destination = this->destination->clone(this->destination);
}
else
{
other->destination = NULL;
}
if (this->source != NULL)
{
other->source = this->source->clone(this->source);
}
else
{
other->source = NULL;
}
/* only clone existing chunks :-) */
if (this->data.ptr != NULL)
{
other->data.ptr = clalloc(this->data.ptr,this->data.len);
other->data.len = this->data.len;
}
else
{
other->data = CHUNK_INITIALIZER;
}
return &(other->public);
}
/*
* Documented in header
*/
packet_t *packet_create()
{
private_packet_t *this = malloc_thing(private_packet_t);
this->public.set_data = (void(*) (packet_t *,chunk_t)) set_data;
this->public.get_data = (chunk_t(*) (packet_t *)) get_data;
this->public.set_source = (void(*) (packet_t *,host_t*)) set_source;
this->public.get_source = (host_t*(*) (packet_t *)) get_source;
this->public.set_destination = (void(*) (packet_t *,host_t*)) set_destination;
this->public.get_destination = (host_t*(*) (packet_t *)) get_destination;
this->public.clone = (packet_t*(*) (packet_t *))clone;
this->public.destroy = (void(*) (packet_t *)) destroy;
this->destination = NULL;
this->source = NULL;
this->data = CHUNK_INITIALIZER;
return &(this->public);
}
+135
View File
@@ -0,0 +1,135 @@
/**
* @file packet.h
*
* @brief Interface of packet_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef PACKET_H_
#define PACKET_H_
#include <types.h>
#include <utils/host.h>
typedef struct packet_t packet_t;
/**
* @brief Abstraction of an UDP-Packet, contains data, sender and receiver.
*
* @b Constructors:
* - packet_create()
*
* @ingroup network
*/
struct packet_t {
/**
* @brief Set the source address.
*
* Set host_t is now owned by packet_t, it will destroy
* it if necessary.
*
* @param this calling object
* @param source address to set as source
*/
void (*set_source) (packet_t *packet, host_t *source);
/**
* @brief Set the destination address.
*
* Set host_t is now owned by packet_t, it will destroy
* it if necessary.
*
* @param this calling object
* @param source address to set as destination
*/
void (*set_destination) (packet_t *packet, host_t *destination);
/**
* @brief Get the source address.
*
* Set host_t is still owned by packet_t, clone it
* if needed.
*
* @param this calling object
* @return source address
*/
host_t *(*get_source) (packet_t *packet);
/**
* @brief Get the destination address.
*
* Set host_t is still owned by packet_t, clone it
* if needed.
*
* @param this calling object
* @return destination address
*/
host_t *(*get_destination) (packet_t *packet);
/**
* @brief Get the data from the packet.
*
* The data pointed by the chunk is still owned
* by the packet. Clone it if needed.
*
* @param this calling object
* @return chunk containing the data
*/
chunk_t (*get_data) (packet_t *packet);
/**
* @brief Set the data in the packet.
*
* Supplied chunk data is now owned by the
* packet. It will free it.
*
* @param this calling object
* @param data chunk with data to set
*/
void (*set_data) (packet_t *packet, chunk_t data);
/**
* @brief Clones a packet_t object.
*
* @param packet calling object
* @param clone pointer to a packet_t object pointer where the new object is stored
*/
packet_t* (*clone) (packet_t *packet);
/**
* @brief Destroy the packet, freeing contained data.
*
* @param packet packet to destroy
*/
void (*destroy) (packet_t *packet);
};
/**
* @brief create an empty packet
*
* @return packet_t object
*
* @ingroup network
*/
packet_t *packet_create();
#endif /*PACKET_H_*/
+457
View File
@@ -0,0 +1,457 @@
/**
* @file socket.c
*
* @brief Implementation of socket_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 1997 Angelos D. Keromytis.
*
* Some parts of interface lookup code from pluto.
*
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <linux/filter.h>
#include "socket.h"
#include <daemon.h>
#include <utils/logger_manager.h>
#define IP_HEADER_LENGTH 20
#define UDP_HEADER_LENGTH 8
/**
* This filter code filters out all non-IKEv2 traffic on
* a SOCK_RAW IP_PROTP_UDP socket. Handling of other
* IKE versions is done in pluto.
*/
struct sock_filter ikev2_filter_code[] =
{
/* Protocol must be UDP */
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 7),
/* Destination Port must be 500 */
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 22),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 500, 0, 5),
/* IKE version must be 2.0 */
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 45),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3),
/* packet length is length in IKEv2 header + ip header + udp header */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 52),
BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, IP_HEADER_LENGTH + UDP_HEADER_LENGTH),
BPF_STMT(BPF_RET+BPF_A, 0),
/* packet doesn't match IKEv2, ignore */
BPF_STMT(BPF_RET+BPF_K, 0),
};
/**
* Filter struct to use with setsockopt
*/
struct sock_fprog ikev2_filter = {
sizeof(ikev2_filter_code) / sizeof(struct sock_filter),
ikev2_filter_code
};
typedef struct interface_t interface_t;
/**
* An interface on which we listen.
*/
struct interface_t {
/**
* Name of the interface
*/
char name[IFNAMSIZ];
/**
* Associated socket
*/
int socket_fd;
/**
* Host with listening address
*/
host_t *address;
};
typedef struct private_socket_t private_socket_t;
/**
* Private data of an socket_t object
*/
struct private_socket_t{
/**
* public functions
*/
socket_t public;
/**
* Master socket
*/
int master_fd;
/**
* List of all socket to listen
*/
linked_list_t* interfaces;
/**
* logger for this socket
*/
logger_t *logger;
};
/**
* implementation of socket_t.receive
*/
static status_t receiver(private_socket_t *this, packet_t **packet)
{
char buffer[MAX_PACKET];
chunk_t data;
packet_t *pkt = packet_create();
host_t *source, *dest;
int bytes_read = 0;
while (bytes_read >= 0)
{
int max_fd = 1;
fd_set readfds;
iterator_t *iterator;
int oldstate;
interface_t *interface;
/* build fd_set */
FD_ZERO(&readfds);
iterator = this->interfaces->create_iterator(this->interfaces, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&interface);
FD_SET(interface->socket_fd, &readfds);
if (interface->socket_fd > max_fd)
{
max_fd = interface->socket_fd + 1;
}
}
iterator->destroy(iterator);
/* add packet destroy handler for cancellation, enable cancellation */
pthread_cleanup_push((void(*)(void*))pkt->destroy, (void*)pkt);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
this->logger->log(this->logger, CONTROL|LEVEL1, "waiting on sockets");
bytes_read = select(max_fd, &readfds, NULL, NULL, NULL);
/* reset cancellation, remove packet destroy handler (without executing) */
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(0);
/* read on the first nonblocking socket */
bytes_read = 0;
iterator = this->interfaces->create_iterator(this->interfaces, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&interface);
if (FD_ISSET(interface->socket_fd, &readfds))
{
/* do the read */
bytes_read = recv(interface->socket_fd, buffer, MAX_PACKET, 0);
break;
}
}
iterator->destroy(iterator);
if (bytes_read < 0)
{
this->logger->log(this->logger, ERROR, "error reading from socket: %s", strerror(errno));
continue;
}
if (bytes_read > IP_HEADER_LENGTH + UDP_HEADER_LENGTH)
{
/* read source/dest from raw IP/UDP header */
chunk_t source_chunk = {buffer + 12, 4};
chunk_t dest_chunk = {buffer + 16, 4};
u_int16_t source_port = ntohs(*(u_int16_t*)(buffer + 20));
u_int16_t dest_port = ntohs(*(u_int16_t*)(buffer + 22));
source = host_create_from_chunk(AF_INET, source_chunk, source_port);
dest = host_create_from_chunk(AF_INET, dest_chunk, dest_port);
pkt->set_source(pkt, source);
pkt->set_destination(pkt, dest);
break;
}
this->logger->log(this->logger, ERROR|LEVEL1, "too short packet received");
}
this->logger->log(this->logger, CONTROL, "received packet: from %s:%d to %s:%d",
source->get_address(source), source->get_port(source),
dest->get_address(dest), dest->get_port(dest));
/* fill in packet */
data.len = bytes_read - IP_HEADER_LENGTH - UDP_HEADER_LENGTH;
data.ptr = malloc(data.len);
memcpy(data.ptr, buffer + IP_HEADER_LENGTH + UDP_HEADER_LENGTH, data.len);
pkt->set_data(pkt, data);
/* return packet */
*packet = pkt;
return SUCCESS;
}
/**
* implementation of socket_t.send
*/
status_t sender(private_socket_t *this, packet_t *packet)
{
ssize_t bytes_sent;
chunk_t data;
host_t *src, *dst;
src = packet->get_source(packet);
dst = packet->get_destination(packet);
data = packet->get_data(packet);
this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d",
src->get_address(src), src->get_port(src),
dst->get_address(dst), dst->get_port(dst));
/* send data */
/* TODO: should we send via the interface we received the packet? */
bytes_sent = sendto(this->master_fd, data.ptr, data.len, 0,
dst->get_sockaddr(dst), *(dst->get_sockaddr_len(dst)));
if (bytes_sent != data.len)
{
this->logger->log(this->logger, ERROR, "error writing to socket: %s", strerror(errno));
return FAILED;
}
return SUCCESS;
}
/**
* Find all suitable interfaces, bind them and add them to the list
*/
static status_t build_interface_list(private_socket_t *this, u_int16_t port)
{
int on = TRUE;
int i;
struct sockaddr_in addr;
struct ifconf ifconf;
struct ifreq buf[300];
/* master socket for querying socket for a specific interfaces */
this->master_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (this->master_fd == -1)
{
this->logger->log(this->logger, ERROR, "could not open IPv4 master socket!");
return FAILED;
}
/* allow binding of multiplo sockets */
if (setsockopt(this->master_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
{
this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on master socket!");
return FAILED;
}
/* bind the master socket */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(this->master_fd,(struct sockaddr*)&addr, sizeof(addr)) < 0)
{
this->logger->log(this->logger, ERROR, "unable to bind master socket: %s!", strerror(errno));
return FAILED;
}
/* get all interfaces */
ifconf.ifc_len = sizeof(buf);
ifconf.ifc_buf = (void*) buf;
memset(buf, 0, sizeof(buf));
if (ioctl(this->master_fd, SIOCGIFCONF, &ifconf) == -1)
{
this->logger->log(this->logger, ERROR, "unable to get interfaces!");
return FAILED;
}
/* add every interesting interfaces to our interface list */
for (i = 0; (i+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; i++)
{
struct sockaddr_in *current = (struct sockaddr_in*) &buf[i].ifr_addr;
struct ifreq auxinfo;
int skt;
interface_t *interface;
if (current->sin_family != AF_INET)
{
/* ignore all but AF_INET interfaces */
continue;
}
/* get auxilary info about socket */
memset(&auxinfo, 0, sizeof(auxinfo));
memcpy(auxinfo.ifr_name, buf[i].ifr_name, IFNAMSIZ);
if (ioctl(this->master_fd, SIOCGIFFLAGS, &auxinfo) == -1)
{
this->logger->log(this->logger, ERROR, "unable to SIOCGIFFLAGS master socket!");
continue;
}
if (!(auxinfo.ifr_flags & IFF_UP))
{
/* ignore an interface that isn't up */
continue;
}
if (current->sin_addr.s_addr == 0)
{
/* ignore unconfigured interfaces */
continue;
}
/* set up interface socket */
skt = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (socket < 0)
{
this->logger->log(this->logger, ERROR, "unable to open interface socket!");
continue;
}
if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
{
this->logger->log(this->logger, ERROR, "unable to set SO_REUSEADDR on interface socket!");
close(skt);
continue;
}
current->sin_port = htons(port);
current->sin_family = AF_INET;
if (bind(skt, (struct sockaddr*)current, sizeof(struct sockaddr_in)) < 0)
{
this->logger->log(this->logger, ERROR, "unable to bind interface socket!");
close(skt);
continue;
}
if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER, &ikev2_filter, sizeof(ikev2_filter)) < 0)
{
this->logger->log(this->logger, ERROR, "unable to attack IKEv2 filter to interface socket!");
close(skt);
continue;
}
/* add socket with interface name to list */
interface = malloc_thing(interface_t);
memcpy(interface->name, buf[i].ifr_name, IFNAMSIZ);
interface->name[IFNAMSIZ-1] = '\0';
interface->socket_fd = skt;
interface->address = host_create_from_sockaddr((struct sockaddr*)current);
this->logger->log(this->logger, CONTROL, "listening on %s (%s)",
interface->name, interface->address->get_address(interface->address));
this->interfaces->insert_last(this->interfaces, (void*)interface);
}
if (this->interfaces->get_count(this->interfaces) == 0)
{
this->logger->log(this->logger, ERROR, "unable to find any usable interface!");
return FAILED;
}
return SUCCESS;
}
/**
* implementation of socket_t.is_listening_on
*/
static bool is_listening_on(private_socket_t *this, host_t *host)
{
iterator_t *iterator;
/* listening on 0.0.0.0 is always TRUE */
if (host->is_default_route(host))
{
return TRUE;
}
/* compare host with all interfaces */
iterator = this->interfaces->create_iterator(this->interfaces, TRUE);
while (iterator->has_next(iterator))
{
interface_t *interface;
iterator->current(iterator, (void**)&interface);
if (host->equals(host, interface->address))
{
iterator->destroy(iterator);
return TRUE;
}
}
iterator->destroy(iterator);
return FALSE;
}
/**
* implementation of socket_t.destroy
*/
static void destroy(private_socket_t *this)
{
interface_t *interface;
while (this->interfaces->remove_last(this->interfaces, (void**)&interface) == SUCCESS)
{
interface->address->destroy(interface->address);
close(interface->socket_fd);
free(interface);
}
this->interfaces->destroy(this->interfaces);
close(this->master_fd);
free(this);
}
/*
* See header for description
*/
socket_t *socket_create(u_int16_t port)
{
private_socket_t *this = malloc_thing(private_socket_t);
/* public functions */
this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
this->public.is_listening_on = (bool (*)(socket_t*,host_t*))is_listening_on;
this->public.destroy = (void(*)(socket_t*)) destroy;
this->logger = logger_manager->get_logger(logger_manager, SOCKET);
this->interfaces = linked_list_create();
if (build_interface_list(this, port) != SUCCESS)
{
this->interfaces->destroy(this->interfaces);
free(this);
charon->kill(charon, "could not bind any interface!");
}
return (socket_t*)this;
}
Loaded 100 of 514 files, more files were not shown because too many files have changed in this diff. Show more