Merge branch 'ikev1-clean' into ikev1-master

Conflicts:
	configure.in
	man/ipsec.conf.5.in
	src/libcharon/daemon.c
	src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
	src/libcharon/plugins/eap_radius/eap_radius_accounting.c
	src/libcharon/plugins/eap_radius/eap_radius_forward.c
	src/libcharon/plugins/farp/farp_listener.c
	src/libcharon/sa/ike_sa.c
	src/libcharon/sa/keymat.c
	src/libcharon/sa/task_manager.c
	src/libcharon/sa/trap_manager.c
	src/libstrongswan/plugins/x509/x509_cert.c
	src/libstrongswan/utils.h

Applied lost changes of moved files keymat.c and task_manager.c.
Updated listener_t.message hook signature in new plugins.
This commit is contained in:
Martin Willi 2012-03-20 17:56:18 +01:00
commit b1f2f05c92
295 changed files with 21950 additions and 5446 deletions

25
configure.in Normal file → Executable file
View File

@ -16,7 +16,7 @@ dnl ===========================
dnl initialize & set some vars
dnl ===========================
AC_INIT(strongSwan,4.6.3dr2)
AC_INIT(strongSwan,5.0.0dr1)
AM_INIT_AUTOMAKE(tar-ustar)
AC_CONFIG_MACRO_DIR([m4/config])
PKG_PROG_PKG_CONFIG
@ -130,6 +130,8 @@ ARG_ENABL_SET([eap-ttls], [enable EAP TTLS authentication module.])
ARG_ENABL_SET([eap-peap], [enable EAP PEAP authentication module.])
ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.])
ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.])
ARG_ENABL_SET([xauth-generic], [enable generic XAuth backend.])
ARG_ENABL_SET([xauth-eap], [enable XAuth backend using EAP methods to verify passwords.])
ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module.])
ARG_ENABL_SET([tnc-pdp], [enable TNC policy decision point module.])
ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.])
@ -160,11 +162,13 @@ ARG_ENABL_SET([manager], [enable web management console (proof of concept
ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.])
ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.])
ARG_DISBL_SET([load-warning], [disable the charon/pluto plugin load option warning in starter.])
ARG_DISBL_SET([pluto], [disable the IKEv1 keying daemon pluto.])
ARG_ENABL_SET([pluto], [enable the IKEv1 keying daemon pluto.])
ARG_DISBL_SET([ikev1], [disable IKEv1 protocol support in charon.])
ARG_DISBL_SET([ikev2], [disable IKEv2 protocol support in charon.])
ARG_DISBL_SET([xauth], [disable xauth plugin.])
ARG_DISBL_SET([threads], [disable the use of threads in pluto. Charon always uses threads.])
ARG_DISBL_SET([adns], [disable the use of adns in pluto (disables opportunistic encryption).])
ARG_DISBL_SET([charon], [disable the IKEv2 keying daemon charon.])
ARG_DISBL_SET([charon], [disable the IKEv1/IKEv2 keying daemon charon.])
ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).])
ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).])
ARG_ENABL_SET([conftest], [enforce Suite B conformance test framework.])
@ -871,6 +875,8 @@ ADD_PLUGIN([eap-tls], [c libcharon])
ADD_PLUGIN([eap-ttls], [c libcharon])
ADD_PLUGIN([eap-peap], [c libcharon])
ADD_PLUGIN([eap-tnc], [c libcharon])
ADD_PLUGIN([xauth-generic], [c libcharon])
ADD_PLUGIN([xauth-eap], [c libcharon])
ADD_PLUGIN([tnc-ifmap], [c libcharon])
ADD_PLUGIN([tnc-pdp], [c libcharon])
ADD_PLUGIN([tnc-imc], [c libcharon])
@ -995,6 +1001,8 @@ AM_CONDITIONAL(USE_EAP_TTLS, test x$eap_ttls = xtrue)
AM_CONDITIONAL(USE_EAP_PEAP, test x$eap_peap = xtrue)
AM_CONDITIONAL(USE_EAP_TNC, test x$eap_tnc = xtrue)
AM_CONDITIONAL(USE_EAP_RADIUS, test x$eap_radius = xtrue)
AM_CONDITIONAL(USE_XAUTH_GENERIC, test x$xauth_generic = xtrue)
AM_CONDITIONAL(USE_XAUTH_EAP, test x$xauth_eap = xtrue)
AM_CONDITIONAL(USE_TNC_IFMAP, test x$tnc_ifmap = xtrue)
AM_CONDITIONAL(USE_TNC_PDP, test x$tnc_pdp = xtrue)
AM_CONDITIONAL(USE_TNC_IMC, test x$tnc_imc = xtrue)
@ -1045,6 +1053,8 @@ AM_CONDITIONAL(USE_ME, test x$mediation = xtrue)
AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
AM_CONDITIONAL(USE_LOAD_WARNING, test x$load_warning = xtrue)
AM_CONDITIONAL(USE_PLUTO, test x$pluto = xtrue)
AM_CONDITIONAL(USE_IKEV1, test x$ikev1 = xtrue)
AM_CONDITIONAL(USE_IKEV2, test x$ikev2 = xtrue)
AM_CONDITIONAL(USE_THREADS, test x$threads = xtrue)
AM_CONDITIONAL(USE_ADNS, test x$adns = xtrue)
AM_CONDITIONAL(USE_CHARON, test x$charon = xtrue)
@ -1080,7 +1090,12 @@ fi
if test x$monolithic = xtrue; then
AC_DEFINE(MONOLITHIC)
fi
if test x$ikev1 = xtrue; then
AC_DEFINE(USE_IKEV1)
fi
if test x$ikev2 = xtrue; then
AC_DEFINE(USE_IKEV2)
fi
dnl ==============================
dnl build Makefiles
@ -1174,6 +1189,8 @@ AC_OUTPUT(
src/libcharon/plugins/eap_peap/Makefile
src/libcharon/plugins/eap_tnc/Makefile
src/libcharon/plugins/eap_radius/Makefile
src/libcharon/plugins/xauth_generic/Makefile
src/libcharon/plugins/xauth_eap/Makefile
src/libcharon/plugins/tnc_ifmap/Makefile
src/libcharon/plugins/tnc_pdp/Makefile
src/libcharon/plugins/tnc_imc/Makefile

View File

@ -172,9 +172,9 @@ keying, rekeying, and general control.
The path to control the connection is called 'ISAKMP SA' in IKEv1
and 'IKE SA' in the IKEv2 protocol. That what is being negotiated, the kernel
level data path, is called 'IPsec SA' or 'Child SA'.
strongSwan currently uses two separate keying daemons. \fIpluto\fP handles
all IKEv1 connections, \fIcharon\fP is the daemon handling the IKEv2
protocol.
strongSwan previously used two separate keying daemons, \fIpluto\fP and
\fIcharon\fP. This manual does not discuss \fIpluto\fP options anymore, but
only \fIcharon\fP that since strongSwan 5.0 supports both IKEv1 and IKEv2.
.PP
To avoid trivial editing of the configuration file to suit it to each system
involved in a connection,
@ -237,17 +237,7 @@ identity (such as EAP-TLS), but it does not match the IKEv2 gateway identity.
includes conn section
.BR <name> .
.TP
.BR auth " = " esp " | ah"
whether authentication should be done as part of
ESP encryption, or separately using the AH protocol;
acceptable values are
.B esp
(the default) and
.BR ah .
.br
The IKEv2 daemon currently supports ESP only.
.TP
.BR authby " = " pubkey " | rsasig | ecdsasig | psk | eap | never | xauth..."
.BR authby " = " pubkey " | rsasig | ecdsasig | psk | never | xauthpsk | xauthrsasig"
how the two security gateways should authenticate each other;
acceptable values are
.B psk
@ -268,17 +258,12 @@ IKEv1 additionally supports the values
.B xauthpsk
and
.B xauthrsasig
that will enable eXtended Authentication (XAuth) in addition to IKEv1 main mode
based on shared secrets or digital RSA signatures, respectively.
IKEv2 additionally supports the value
.BR eap ,
which indicates an initiator to request EAP authentication. The EAP method
to use is selected by the server (see
.BR eap ).
This parameter is deprecated for IKEv2 connections, as two peers do not need
to agree on an authentication method. Use the
that will enable eXtended AUTHentication (XAUTH) in addition to IKEv1 main mode
based on shared secrets or digital RSA signatures, respectively.
This parameter is deprecated, as two peers do not need to agree on an
authentication method in IKEv2. Use the
.B leftauth
parameter instead to define authentication methods in IKEv2.
parameter instead to define authentication methods.
.TP
.BR auto " = " ignore " | add | route | start"
what operation, if any, should be done automatically at IPsec startup;
@ -323,7 +308,8 @@ and prefer compressed.
A value of
.B no
prevents IPsec from proposing compression;
a proposal to compress will still be accepted.
a proposal to compress will still be accepted. IPComp is currently not supported
with IKEv1.
.TP
.BR dpdaction " = " none " | clear | hold | restart"
controls the use of the Dead Peer Detection protocol (DPD, RFC 3706) where
@ -341,16 +327,9 @@ put in the hold state
.RB ( hold )
or restarted
.RB ( restart ).
For IKEv1, the default is
The default is
.B none
which disables the active sending of R_U_THERE notifications.
Nevertheless pluto will always send the DPD Vendor ID during connection set up
in order to signal the readiness to act passively as a responder if the peer
wants to use DPD. For IKEv2,
.B none
does't make sense, since all messages are used to detect dead peers. If specified,
it has the same meaning as the default
.RB ( clear ).
which disables the active sending of DPD messages.
.TP
.BR dpddelay " = " 30s " | <time>"
defines the period time interval with which R_U_THERE messages/INFORMATIONAL
@ -359,48 +338,16 @@ received. In IKEv2, a value of 0 sends no additional INFORMATIONAL
messages and uses only standard messages (such as those to rekey) to detect
dead peers.
.TP
.BR dpdtimeout " = " 150s " | <time>"
defines the timeout interval, after which all connections to a peer are deleted
in case of inactivity. This only applies to IKEv1, in IKEv2 the default
retransmission timeout applies, as every exchange is used to detect dead peers.
See
.IR strongswan.conf (5)
for a description of the IKEv2 retransmission timeout.
.TP
.BR closeaction " = " none " | clear | hold | restart"
defines the action to take if the remote peer unexpectedly closes a CHILD_SA
(IKEv2 only, see dpdaction for meaning of values). A closeaction should not be
defines the action to take if the remote peer unexpectedly closes a CHILD_SA.
A closeaction should not be
used if the peer uses reauthentication or uniquids checking, as these events
might trigger a closeaction when not desired.
might trigger a closeaction when not desired. Closeactions are currently
not supported with IKEv1.
.TP
.BR inactivity " = <time>"
defines the timeout interval, after which a CHILD_SA is closed if it did
not send or receive any traffic. Currently supported in IKEv2 connections only.
.TP
.BR eap " = md5 | mschapv2 | radius | ... | <type> | <type>-<vendor>
defines the EAP type to propose as server if the client requests EAP
authentication. Currently supported values are
.B aka
for EAP-AKA,
.B gtc
for EAP-GTC,
.B md5
for EAP-MD5,
.B mschapv2
for EAP-MS-CHAPv2,
.B radius
for the EAP-RADIUS proxy and
.B sim
for EAP-SIM. Additionally, IANA assigned EAP method numbers are accepted, or a
definition in the form
.B eap=type-vendor
(e.g. eap=7-12345) can be used to specify vendor specific EAP types.
This parameter is deprecated in the favour of
.B leftauth.
To forward EAP authentication to a RADIUS server using the EAP-RADIUS plugin,
set
.BR eap=radius .
not send or receive any traffic.
.TP
.BR eap_identity " = <id>"
defines the identity the client uses to reply to a EAP Identity request.
@ -418,15 +365,15 @@ The notation is
.BR encryption-integrity[-dhgroup][-esnmode] .
.br
Defaults to
.BR aes128-sha1,3des-sha1
for IKEv1. The IKEv2 daemon adds its extensive default proposal to this default
.BR aes128-sha1,3des-sha1 .
The daemon adds its extensive default proposal to this default
or the configured value. To restrict it to the configured proposal an
exclamation mark
.RB ( ! )
can be added at the end.
.br
.BR Note :
As a responder both daemons accept the first supported proposal received from
As a responder the daemon accepts the first supported proposal received from
the peer. In order to restrict a responder to only accept specific cipher
suites, the strict flag
.RB ( ! ,
@ -434,8 +381,8 @@ exclamation mark) can be used, e.g: aes256-sha512-modp4096!
.br
If
.B dh-group
is specified, CHILD_SA setup and rekeying include a separate Diffie-Hellman
exchange (IKEv2 only). Valid values for
is specified, CHILD_SA/Quick Mode setup and rekeying include a separate
Diffie-Hellman exchange. Valid values for
.B esnmode
(IKEv2 only) are
.B esn
@ -448,7 +395,7 @@ the default is
.BR forceencaps " = yes | " no
force UDP encapsulation for ESP packets even if no NAT situation is detected.
This may help to surmount restrictive firewalls. In order to force the peer to
encapsulate packets, NAT detection payloads are faked (IKEv2 only).
encapsulate packets, NAT detection payloads are faked.
.TP
.BR ike " = <cipher suites>"
comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms
@ -460,15 +407,15 @@ In IKEv2, multiple algorithms and proposals may be included, such as
aes128-aes256-sha1-modp1536-modp2048,3des-sha1-md5-modp1024.
.br
Defaults to
.B aes128-sha1-modp2048,3des-sha1-modp1536
for IKEv1. The IKEv2 daemon adds its extensive default proposal to this
.B aes128-sha1-modp2048,3des-sha1-modp1536 .
The daemon adds its extensive default proposal to this
default or the configured value. To restrict it to the configured proposal an
exclamation mark
.RB ( ! )
can be added at the end.
.br
.BR Note :
As a responder both daemons accept the first supported proposal received from
As a responder the daemon accepts the first supported proposal received from
the peer. In order to restrict a responder to only accept specific cipher
suites, the strict flag
.BR ( ! ,
@ -479,8 +426,8 @@ how long the keying channel of a connection (ISAKMP or IKE SA)
should last before being renegotiated. Also see EXPIRY/REKEY below.
.TP
.BR installpolicy " = " yes " | no"
decides whether IPsec policies are installed in the kernel by the IKEv2
charon daemon for a given connection. Allows peaceful cooperation e.g. with
decides whether IPsec policies are installed in the kernel by the charon daemon
for a given connection. Allows peaceful cooperation e.g. with
the Mobile IPv6 daemon mip6d who wants to control the kernel policies.
Acceptable values are
.B yes
@ -490,19 +437,8 @@ Acceptable values are
.BR keyexchange " = " ike " | ikev1 | ikev2"
method of key exchange;
which protocol should be used to initialize the connection. Connections marked with
.B ikev1
are initiated with pluto, those marked with
.B ikev2
with charon. An incoming request from the remote peer is handled by the correct
daemon, unaffected from the
.B keyexchange
setting. Starting with strongSwan 4.5 the default value
.B ike
is a synonym for
.BR ikev2 ,
whereas in older strongSwan releases
.B ikev1
was assumed.
use IKEv2 when initiating, but accept any protocol version when responding.
.TP
.BR keyingtries " = " 3 " | <number> | %forever"
how many attempts (a whole number or \fB%forever\fP) should be made to
@ -534,18 +470,8 @@ or
may be
.BR %defaultroute ,
but not both.
The prefix
.B %
in front of a fully-qualified domain name or an IP address will implicitly set
.B leftallowany=yes.
If the domain name cannot be resolved into an IP address at IPsec startup or
update time then
.B left=%any
and
.B leftallowany=no
will be assumed.
In case of an IKEv2 connection, the value
The value
.B %any
for the local endpoint signifies an address to be filled in (by automatic
keying) during negotiation. If the local peer initiates the connection setup
@ -553,9 +479,6 @@ the routing table will be queried to determine the correct local IP address.
In case the local peer is responding to a connection setup then any IP address
that is assigned to a local interface will be accepted.
.br
Note that specifying
.B %any
for the local endpoint is not supported by the IKEv1 pluto daemon.
If
.B %any
@ -565,30 +488,18 @@ Please note that with the usage of wildcards multiple connection descriptions
might match a given incoming connection attempt. The most specific description
is used in that case.
.TP
.BR leftallowany " = yes | " no
a modifier for
.B left
, making it behave as
.B %any
although a concrete IP address has been assigned.
Recommended for dynamic IP addresses that can be resolved by DynDNS at IPsec
startup or update time.
Acceptable values are
.B yes
and
.B no
(the default).
.TP
.BR leftauth " = <auth method>"
Authentication method to use locally (left) or require from the remote (right)
side.
This parameter is supported in IKEv2 only. Acceptable values are
Acceptable values are
.B pubkey
for public key authentication (RSA/ECDSA),
.B psk
for pre-shared key authentication and
for pre-shared key authentication,
.B eap
to (require the) use of the Extensible Authentication Protocol.
to (require the) use of the Extensible Authentication Protocol in IKEv2, and
.B xauth
for IKEv1 eXtended Authentication.
To require a trustchain public key strength for the remote side, specify the
key type followed by the strength in bits (for example
.BR rsa-2048
@ -598,24 +509,37 @@ For
.B eap,
an optional EAP method can be appended. Currently defined methods are
.BR eap-aka ,
.BR eap-sim ,
.BR eap-gtc ,
.BR eap-md5 ,
.BR eap-tls ,
.B eap-mschapv2
and
.BR eap-sim .
.BR eap-radius .
Alternatively, IANA assigned EAP method numbers are accepted. Vendor specific
EAP methods are defined in the form
.B eap-type-vendor
.RB "(e.g. " eap-7-12345 ).
For
.B xauth,
a XAuth authentication backend can be specified, such as
.B xauth-generic
or
.B xauth-eap .
If XAuth is used in
.BR leftauth ,
Hybrid authentication is used. For traditional XAuth authentication, define
XAuth in
.BR lefauth2 .
.TP
.BR leftauth2 " = <auth method>"
Same as
.BR leftauth ,
but defines an additional authentication exchange. IKEv2 supports multiple
but defines an additional authentication exchange. In IKEv1, only XAuth can be
used in the second authentication round. IKEv2 supports multiple complete
authentication rounds using "Multiple Authentication Exchanges" defined
in RFC4739. This allows, for example, separated authentication
of host and user (IKEv2 only).
of host and user.
.TP
.BR leftca " = <issuer dn> | %same"
the distinguished name of a certificate authority which is required to
@ -674,8 +598,7 @@ tunnels established with IPsec are exempted from it
so that packets can flow unchanged through the tunnels.
(This means that all subnets connected in this manner must have
distinct, non-overlapping subnet address blocks.)
This is done by the default \fBipsec _updown\fR script (see
.IR pluto (8)).
This is done by the default \fBipsec _updown\fR script.
In situations calling for more control,
it may be preferable for the user to supply his own
@ -687,12 +610,7 @@ which makes the appropriate adjustments for his system.
a comma separated list of group names. If the
.B leftgroups
parameter is present then the peer must be a member of at least one
of the groups defined by the parameter. Group membership must be certified
by a valid attribute certificate stored in \fI/etc/ipsec.d/acerts/\fP thas has
been issued to the peer by a trusted Authorization Authority stored in
\fI/etc/ipsec.d/aacerts/\fP.
.br
Attribute certificates are not supported in IKEv2 yet.
of the groups defined by the parameter.
.TP
.BR lefthostaccess " = yes | " no
inserts a pair of INPUT and OUTPUT iptables rules using the default
@ -719,8 +637,8 @@ identity to use for a second authentication for the left participant
.BR leftid .
.TP
.BR leftikeport " = <port>"
UDP port the left participant uses for IKE communication. Currently supported in
IKEv2 connections only. If unspecified, port 500 is used with the port floating
UDP port the left participant uses for IKE communication.
If unspecified, port 500 is used with the port floating
to 4500 if a NAT is detected or MOBIKE is enabled. Specifying a local IKE port
different from the default additionally requires a socket implementation that
listens to this port.
@ -742,29 +660,6 @@ or
or
.B leftprotoport=udp
.TP
.BR leftrsasigkey " = " %cert " | <raw rsa public key>"
the left participant's
public key for RSA signature authentication,
in RFC 2537 format using
.IR ttodata (3)
encoding.
The magic value
.B %none
means the same as not specifying a value (useful to override a default).
The value
.B %cert
(the default)
means that the key is extracted from a certificate.
The identity used for the left participant
must be a specific host, not
.B %any
or another magic value.
.B Caution:
if two connection descriptions
specify different public keys for the same
.BR leftid ,
confusion and madness will ensue.
.TP
.BR leftsendcert " = never | no | " ifasked " | always | yes"
Accepted values are
.B never
@ -786,8 +681,7 @@ value is one of the synonyms
.BR %modeconfig ,
or
.BR %modecfg ,
an address is requested from the peer. In IKEv2, a statically defined address
is also requested, since the server may change it.
an address is requested from the peer.
.TP
.BR rightsourceip " = %config | <network>/<netmask> | %poolname"
The internal source IP to use in a tunnel for the remote peer. If the
@ -804,16 +698,11 @@ private subnet behind the left participant, expressed as
\fInetwork\fB/\fInetmask\fR;
if omitted, essentially assumed to be \fIleft\fB/32\fR,
signifying that the left end of the connection goes to the left participant
only. When using IKEv2, the configured subnet of the peers may differ, the
protocol narrows it to the greatest common subnet. Further, IKEv2 supports
multiple subnets separated by commas. IKEv1 only interprets the first subnet
of such a definition.
.TP
.BR leftsubnetwithin " = <ip subnet>"
the peer can propose any subnet or single IP address that fits within the
range defined by
.BR leftsubnetwithin.
Not relevant for IKEv2, as subnets are narrowed.
only. Configured subnet of the peers may differ, the protocol narrows it to
the greatest common subnet. In IKEv1, this may lead to problems with other
implementations, make sure to configure identical subnets in such
configurations. IKEv2 supports multiple subnets separated by commas, IKEv1 only
interprets the first subnet of such a definition.
.TP
.BR leftupdown " = <path>"
what ``updown'' script to run to adjust routing and/or firewalling
@ -823,20 +712,15 @@ changes (default
May include positional parameters separated by white space
(although this requires enclosing the whole string in quotes);
including shell metacharacters is unwise.
See
.IR pluto (8)
for details.
Relevant only locally, other end need not agree on it. IKEv2 uses the updown
Relevant only locally, other end need not agree on it. Charon uses the updown
script to insert firewall rules only, since routing has been implemented
directly into charon.
directly into the daemon.
.TP
.BR lifebytes " = <number>"
the number of bytes transmitted over an IPsec SA before it expires (IKEv2
only).
the number of bytes transmitted over an IPsec SA before it expires.
.TP
.BR lifepackets " = <number>"
the number of packets transmitted over an IPsec SA before it expires (IKEv2
only).
the number of packets transmitted over an IPsec SA before it expires.
.TP
.BR lifetime " = " 1h " | <time>"
how long a particular instance of a connection
@ -868,12 +752,12 @@ which thinks the lifetime is longer. Also see EXPIRY/REKEY below.
.BR marginbytes " = <number>"
how many bytes before IPsec SA expiry (see
.BR lifebytes )
should attempts to negotiate a replacement begin (IKEv2 only).
should attempts to negotiate a replacement begin.
.TP
.BR marginpackets " = <number>"
how many packets before IPsec SA expiry (see
.BR lifepackets )
should attempts to negotiate a replacement begin (IKEv2 only).
should attempts to negotiate a replacement begin.
.TP
.BR margintime " = " 9m " | <time>"
how long before connection expiry or keying-channel expiry
@ -912,7 +796,7 @@ enables the IKEv2 MOBIKE protocol defined by RFC 4555. Accepted values are
.BR no .
If set to
.BR no ,
the IKEv2 charon daemon will not actively propose MOBIKE as initiator and
the charon daemon will not actively propose MOBIKE as initiator and
ignore the MOBIKE_SUPPORTED notify as responder.
.TP
.BR modeconfig " = push | " pull
@ -922,29 +806,8 @@ Accepted values are
and
.B pull
(the default).
Currently relevant for IKEv1 only since IKEv2 always uses the configuration
payload in pull mode. Cisco VPN gateways usually operate in
.B push
mode.
.TP
.BR pfs " = " yes " | no"
whether Perfect Forward Secrecy of keys is desired on the connection's
keying channel
(with PFS, penetration of the key-exchange protocol
does not compromise keys negotiated earlier);
acceptable values are
.B yes
(the default)
and
.BR no.
IKEv2 always uses PFS for IKE_SA rekeying whereas for CHILD_SA rekeying
PFS is enforced by defining a Diffie-Hellman modp group in the
.B esp
parameter.
.TP
.BR pfsgroup " = <modp group>"
defines a Diffie-Hellman group for perfect forward secrecy in IKEv1 Quick Mode
differing from the DH group used for IKEv1 Main Mode (IKEv1 only).
Push mode is currently not supported in charon, hence this parameter has no
effect.
.TP
.BR reauth " = " yes " | no"
whether rekeying of an IKE_SA should also reauthenticate the peer. In IKEv1,
@ -964,7 +827,7 @@ and
.BR no .
The two ends need not agree, but while a value of
.B no
prevents pluto/charon from requesting renegotiation,
prevents charon from requesting renegotiation,
it does not prevent responding to renegotiation requested from the other end,
so
.B no
@ -1026,11 +889,7 @@ signifying the special Mobile IPv6 transport proxy mode;
.BR passthrough ,
signifying that no IPsec processing should be done at all;
.BR drop ,
signifying that packets should be discarded; and
.BR reject ,
signifying that packets should be discarded and a diagnostic ICMP returned
.RB ( reject
is currently not supported by the NETKEY stack of the Linux 2.6 kernel).
signifying that packets should be discarded.
.TP
.BR xauth " = " client " | server"
specifies the role in the XAuth protocol if activated by
@ -1107,8 +966,6 @@ synonym for
.BR crluri2 " = <uri>"
defines an alternative CRL distribution point (ldap, http, or file URI)
.TP
.BR ldaphost " = <hostname>"
defines an ldap host. Currently used by IKEv1 only.
.TP
.BR ocspuri " = <uri>"
defines an OCSP URI.
@ -1118,7 +975,7 @@ synonym for
.B ocspuri.
.TP
.BR ocspuri2 " = <uri>"
defines an alternative OCSP URI. Currently used by IKEv2 only.
defines an alternative OCSP URI.
.TP
.BR certuribase " = <uri>"
defines the base URI for the Hash and URL feature supported by IKEv2.
@ -1131,48 +988,12 @@ At present, the only
section known to the IPsec software is the one named
.BR setup ,
which contains information used when the software is being started.
Here's an example:
.PP
.ne 8
.nf
.ft B
.ta 1c
config setup
plutodebug=all
crlcheckinterval=10m
strictcrlpolicy=yes
.ft
.fi
.PP
Parameters are optional unless marked ``(required)''.
The currently-accepted
.I parameter
names in a
.B config
.B setup
section affecting both daemons are:
.TP
.BR cachecrls " = yes | " no
certificate revocation lists (CRLs) fetched via http or ldap will be cached in
\fI/etc/ipsec.d/crls/\fR under a unique file name derived from the certification
authority's public key.
Accepted values are
.B yes
and
.B no
(the default). Only relevant for IKEv1, as CRLs are always cached in IKEv2.
.TP
.BR charonstart " = " yes " | no"
whether to start the IKEv2 charon daemon or not.
The default is
.B yes
if starter was compiled with IKEv2 support.
.TP
.BR plutostart " = " yes " | no"
whether to start the IKEv1 pluto daemon or not.
The default is
.B yes
if starter was compiled with IKEv1 support.
section are:
.TP
.BR strictcrlpolicy " = yes | ifuri | " no
defines if a fresh CRL must be available in order for the peer authentication
@ -1198,116 +1019,13 @@ and
Participant IDs normally \fIare\fR unique,
so a new (automatically-keyed) connection using the same ID is
almost invariably intended to replace an old one.
The IKEv2 daemon also accepts the value
The daemon also accepts the value
.B replace
which is identical to
.B yes
and the value
.B keep
to reject new IKE_SA setups and keep the duplicate established earlier.
.PP
The following
.B config section
parameters are used by the IKEv1 Pluto daemon only:
.TP
.BR crlcheckinterval " = " 0s " | <time>"
interval in seconds. CRL fetching is enabled if the value is greater than zero.
Asynchronous, periodic checking for fresh CRLs is currently done by the
IKEv1 Pluto daemon only.
.TP
.BR keep_alive " = " 20s " | <time>"
interval in seconds between NAT keep alive packets, the default being 20 seconds.
.TP
.BR nat_traversal " = yes | " no
activates NAT traversal by accepting source ISAKMP ports different from udp/500 and
being able of floating to udp/4500 if a NAT situation is detected.
Accepted values are
.B yes
and
.B no
(the default).
Used by IKEv1 only, NAT traversal is always being active in IKEv2.
.TP
.BR nocrsend " = yes | " no
no certificate request payloads will be sent.
.TP
.BR pkcs11initargs " = <args>"
non-standard argument string for PKCS#11 C_Initialize() function;
required by NSS softoken.
.TP
.BR pkcs11module " = <args>"
defines the path to a dynamically loadable PKCS #11 library.
.TP
.BR pkcs11keepstate " = yes | " no
PKCS #11 login sessions will be kept during the whole lifetime of the keying
daemon. Useful with pin-pad smart card readers.
Accepted values are
.B yes
and
.B no
(the default).
.TP
.BR pkcs11proxy " = yes | " no
Pluto will act as a PKCS #11 proxy accessible via the whack interface.
Accepted values are
.B yes
and
.B no
(the default).
.TP
.BR plutodebug " = " none " | <debug list> | all"
how much pluto debugging output should be logged.
An empty value,
or the magic value
.BR none ,
means no debugging output (the default).
The magic value
.B all
means full output.
Otherwise only the specified types of output
(a quoted list, names without the
.B \-\-debug\-
prefix,
separated by white space) are enabled;
for details on available debugging types, see
.IR pluto (8).
.TP
.BR plutostderrlog " = <file>"
Pluto will not use syslog, but rather log to stderr, and redirect stderr
to <file>.
.TP
.BR postpluto " = <command>"
shell command to run after starting pluto
(e.g., to remove a decrypted copy of the
.I ipsec.secrets
file).
It's run in a very simple way;
complexities like I/O redirection are best hidden within a script.
Any output is redirected for logging,
so running interactive commands is difficult unless they use
.I /dev/tty
or equivalent for their interaction.
Default is none.
.TP
.BR prepluto " = <command>"
shell command to run before starting pluto
(e.g., to decrypt an encrypted copy of the
.I ipsec.secrets
file).
It's run in a very simple way;
complexities like I/O redirection are best hidden within a script.
Any output is redirected for logging,
so running interactive commands is difficult unless they use
.I /dev/tty
or equivalent for their interaction.
Default is none.
.TP
.BR virtual_private " = <networks>"
defines private networks using a wildcard notation.
.PP
The following
.B config section
parameters are used by the IKEv2 charon daemon only:
.TP
.BR charondebug " = <debug list>"
how much charon debugging output should be logged.
@ -1324,7 +1042,7 @@ is set to
for all types. For more flexibility see LOGGER CONFIGURATION in
.IR strongswan.conf (5).
.SH IKEv2 EXPIRY/REKEY
.SH SA EXPIRY/REKEY
The IKE SAs and IPsec SAs negotiated by the daemon can be configured to expire
after a specific amount of time. For IPsec SAs this can also happen after a
specified number of transmitted packets or transmitted bytes. The following
@ -1410,7 +1128,7 @@ time equals zero and, thus, rekeying gets disabled.
/etc/ipsec.d/crls
.SH SEE ALSO
strongswan.conf(5), ipsec.secrets(5), ipsec(8), pluto(8)
strongswan.conf(5), ipsec.secrets(5), ipsec(8)
.SH HISTORY
Originally written for the FreeS/WAN project by Henry Spencer.
Updated and extended for the strongSwan project <http://www.strongswan.org> by

View File

@ -251,8 +251,8 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
uintptr_t strength;
ike_cfg = load_ike_config(this, settings, config);
peer_cfg = peer_cfg_create(config, 2, ike_cfg, CERT_ALWAYS_SEND,
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, 0,
peer_cfg = peer_cfg_create(config, IKEV2, ike_cfg, CERT_ALWAYS_SEND,
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0,
NULL, NULL, FALSE, NULL, NULL);
auth = auth_cfg_create();

View File

@ -60,9 +60,9 @@ struct private_add_notify_t {
METHOD(listener_t, message, bool,
private_add_notify_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@ -89,7 +89,7 @@ METHOD(listener_t, message, bool,
{
data = chunk_clone(chunk_create(this->data, strlen(this->data)));
}
notify = notify_payload_create_from_protocol_and_type(
notify = notify_payload_create_from_protocol_and_type(NOTIFY,
this->esp ? PROTO_ESP : PROTO_IKE, type);
notify->set_spi(notify, this->spi);
if (data.len)

View File

@ -62,9 +62,9 @@ struct private_add_payload_t {
METHOD(listener_t, message, bool,
private_add_payload_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -111,9 +111,9 @@ static linked_list_t* load_proposals(private_custom_proposal_t *this,
METHOD(listener_t, message, bool,
private_custom_proposal_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@ -145,7 +145,7 @@ METHOD(listener_t, message, bool,
proposal->get_protocol(proposal),
proposal->get_spi(proposal));
DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props);
new = sa_payload_create_from_proposal_list(new_props);
new = sa_payload_create_from_proposals_v2(new_props);
message->add_payload(message, (payload_t*)new);
new_props->destroy_offset(new_props, offsetof(proposal_t, destroy));
}

View File

@ -32,9 +32,9 @@ struct private_force_cookie_t {
METHOD(listener_t, message, bool,
private_force_cookie_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming && message->get_request(message) &&
if (incoming && plain && message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
enumerator_t *enumerator;
@ -68,7 +68,7 @@ METHOD(listener_t, message, bool,
chunk_t data = chunk_from_thing("COOKIE test data");
DBG1(DBG_CFG, "sending COOKIE: %#B", &data);
response = message_create();
response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
dst = message->get_source(message);
src = message->get_destination(message);
response->set_source(response, src->clone(src));

View File

@ -45,9 +45,9 @@ struct private_ignore_message_t {
METHOD(listener_t, message, bool,
private_ignore_message_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming == this->in &&
if (incoming == this->in && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -51,7 +51,10 @@ struct private_ike_auth_fill_t {
/** size of non ESP-Marker */
#define NON_ESP_MARKER_LEN 4
/** length of fixed encryption payload header */
#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
/** length of fixed cert payload header */
#define CERT_PAYLOAD_HEADER_LENGTH 5
/**
* Calculate packet size on wire (without ethernet/IP header)
*/
@ -89,9 +92,9 @@ static size_t calculate_wire_size(message_t *message, ike_sa_t *ike_sa)
METHOD(listener_t, message, bool,
private_ike_auth_fill_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@ -105,7 +108,7 @@ METHOD(listener_t, message, bool,
diff = this->bytes - size - CERT_PAYLOAD_HEADER_LENGTH;
data = chunk_alloc(diff);
memset(data.ptr, 0x12, data.len);
pld = cert_payload_create_custom(201, data);
pld = cert_payload_create_custom(CERTIFICATE, 201, data);
message->add_payload(message, &pld->payload_interface);
DBG1(DBG_CFG, "inserting %d dummy bytes certificate payload", diff);
}

View File

@ -32,9 +32,9 @@ struct private_log_id_t {
METHOD(listener_t, message, bool,
private_log_id_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming)
if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;

View File

@ -32,9 +32,9 @@ struct private_log_ke_t {
METHOD(listener_t, message, bool,
private_log_ke_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming)
if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;

View File

@ -32,9 +32,9 @@ struct private_log_proposals_t {
METHOD(listener_t, message, bool,
private_log_proposals_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming)
if (incoming && plain)
{
enumerator_t *enumerator, *proposals;
payload_t *payload;

View File

@ -32,9 +32,9 @@ struct private_log_ts_t {
METHOD(listener_t, message, bool,
private_log_ts_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming)
if (incoming && plain)
{
enumerator_t *enumerator;
payload_t *payload;

View File

@ -15,6 +15,7 @@
#include "hook.h"
#include <sa/ikev2/keymat_v2.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/auth_payload.h>
@ -135,7 +136,7 @@ static void process_auth_request(private_pretend_auth_t *this,
static void process_init_response(private_pretend_auth_t *this,
ike_sa_t *ike_sa, message_t *message)
{
this->ike_init = message->get_packet_data(message);
this->ike_init = chunk_clone(message->get_packet_data(message));
}
/**
@ -153,7 +154,7 @@ static void build_certs(private_pretend_auth_t *this,
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (cert)
{
payload = cert_payload_create_from_cert(cert);
payload = cert_payload_create_from_cert(CERTIFICATE, cert);
if (payload)
{
DBG1(DBG_IKE, "pretending end entity cert \"%Y\"",
@ -166,7 +167,7 @@ static void build_certs(private_pretend_auth_t *this,
{
if (type == AUTH_RULE_IM_CERT)
{
payload = cert_payload_create_from_cert(cert);
payload = cert_payload_create_from_cert(CERTIFICATE, cert);
if (payload)
{
DBG1(DBG_IKE, "pretending issuer cert \"%Y\"",
@ -190,7 +191,7 @@ static bool build_auth(private_pretend_auth_t *this,
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
keymat_t *keymat;
keymat_v2_t *keymat;
auth = auth_cfg_create();
private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, this->id, auth);
@ -235,7 +236,7 @@ static bool build_auth(private_pretend_auth_t *this,
key_type_names, private->get_type(private));
return FALSE;
}
keymat = ike_sa->get_keymat(ike_sa);
keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
octets = keymat->get_auth_octets(keymat, TRUE, this->ike_init,
this->nonce, this->id, this->reserved);
if (!private->sign(private, scheme, octets, &auth_data))
@ -294,7 +295,7 @@ static void process_auth_response(private_pretend_auth_t *this,
if (this->proposal)
{
message->add_payload(message, (payload_t*)
sa_payload_create_from_proposal(this->proposal));
sa_payload_create_from_proposal_v2(this->proposal));
}
if (this->tsi)
{
@ -310,35 +311,38 @@ static void process_auth_response(private_pretend_auth_t *this,
METHOD(listener_t, message, bool,
private_pretend_auth_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (incoming)
if (plain)
{
if (!message->get_request(message))
if (incoming)
{
if (message->get_exchange_type(message) == IKE_SA_INIT)
if (!message->get_request(message))
{
process_init_response(this, ike_sa, message);
}
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_message_id(message) == 1)
{
process_auth_response(this, ike_sa, message);
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
process_init_response(this, ike_sa, message);
}
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_message_id(message) == 1)
{
process_auth_response(this, ike_sa, message);
}
}
}
}
else
{
if (message->get_request(message))
else
{
if (message->get_exchange_type(message) == IKE_SA_INIT)
if (message->get_request(message))
{
process_init_request(this, ike_sa, message);
}
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_message_id(message) == 1)
{
process_auth_request(this, ike_sa, message);
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
process_init_request(this, ike_sa, message);
}
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_message_id(message) == 1)
{
process_auth_request(this, ike_sa, message);
}
}
}
}

View File

@ -15,6 +15,7 @@
#include "hook.h"
#include <sa/ikev2/keymat_v2.h>
#include <encoding/generator.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/auth_payload.h>
@ -57,12 +58,11 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
enumerator_t *enumerator;
chunk_t octets, auth_data;
private_key_t *private;
auth_cfg_t *auth;
payload_t *payload;
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
keymat_t *keymat;
keymat_v2_t *keymat;
identification_t *id;
char reserved[3];
generator_t *generator;
@ -90,10 +90,8 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
id = identification_create_from_encoding(data.ptr[4], chunk_skip(data, 8));
generator->destroy(generator);
auth = auth_cfg_create();
private = lib->credmgr->get_private(lib->credmgr, KEY_ANY,
this->id ?: id, auth);
auth->destroy(auth);
this->id ?: id, NULL);
if (private == NULL)
{
DBG1(DBG_CFG, "no private key found for '%Y' to rebuild AUTH",
@ -137,7 +135,7 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
id->destroy(id);
return FALSE;
}
keymat = ike_sa->get_keymat(ike_sa);
keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
octets = keymat->get_auth_octets(keymat, FALSE, this->ike_init,
this->nonce, id, reserved);
if (!private->sign(private, scheme, octets, &auth_data))
@ -174,34 +172,37 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
METHOD(listener_t, message, bool,
private_rebuild_auth_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming && message->get_message_id(message) == 1)
if (plain)
{
rebuild_auth(this, ike_sa, message);
}
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
if (incoming)
if (!incoming && message->get_message_id(message) == 1)
{
nonce_payload_t *nonce;
nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
if (nonce)
{
free(this->nonce.ptr);
this->nonce = nonce->get_nonce(nonce);
}
rebuild_auth(this, ike_sa, message);
}
else
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
packet_t *packet;
if (message->generate(message, NULL, &packet) == SUCCESS)
if (incoming)
{
free(this->ike_init.ptr);
this->ike_init = chunk_clone(packet->get_data(packet));
packet->destroy(packet);
nonce_payload_t *nonce;
nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
if (nonce)
{
free(this->nonce.ptr);
this->nonce = nonce->get_nonce(nonce);
}
}
else
{
packet_t *packet;
if (message->generate(message, NULL, &packet) == SUCCESS)
{
free(this->ike_init.ptr);
this->ike_init = chunk_clone(packet->get_data(packet));
packet->destroy(packet);
}
}
}
}

View File

@ -47,9 +47,9 @@ struct private_set_critical_t {
METHOD(listener_t, message, bool,
private_set_critical_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -42,9 +42,9 @@ struct private_set_ike_initiator_t {
METHOD(listener_t, message, bool,
private_set_ike_initiator_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -42,9 +42,9 @@ struct private_set_ike_request_t {
METHOD(listener_t, message, bool,
private_set_ike_request_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -52,9 +52,9 @@ struct private_set_ike_spi_t {
METHOD(listener_t, message, bool,
private_set_ike_spi_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -57,9 +57,9 @@ struct private_set_ike_version_t {
METHOD(listener_t, message, bool,
private_set_ike_version_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -50,9 +50,9 @@ struct private_set_length_t {
METHOD(listener_t, message, bool,
private_set_length_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@ -76,11 +76,10 @@ METHOD(listener_t, message, bool,
if (type == payload->get_type(payload))
{
encoding_rule_t *rules;
size_t count;
u_int16_t *len;
int i;
int i, count;
payload->get_encoding_rules(payload, &rules, &count);
count = payload->get_encoding_rules(payload, &rules);
for (i = 0; i < count; i++)
{
if (rules[i].type == PAYLOAD_LENGTH)

View File

@ -69,9 +69,9 @@ static void copy_proposal_algs(proposal_t *from, proposal_t *to,
METHOD(listener_t, message, bool,
private_set_proposal_number_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{
@ -121,7 +121,7 @@ METHOD(listener_t, message, bool,
}
enumerator->destroy(enumerator);
}
sa = sa_payload_create_from_proposal_list(updated);
sa = sa_payload_create_from_proposals_v2(updated);
list->destroy_offset(list, offsetof(proposal_t, destroy));
updated->destroy_offset(updated, offsetof(proposal_t, destroy));
message->add_payload(message, (payload_t*)sa);

View File

@ -163,9 +163,9 @@ static void set_byte(private_set_reserved_t *this, message_t *message,
METHOD(listener_t, message, bool,
private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

View File

@ -84,7 +84,7 @@ METHOD(listener_t, ike_updown, bool,
{
data = chunk_clone(chunk_create(this->data, strlen(this->data)));
}
notify = notify_payload_create_from_protocol_and_type(
notify = notify_payload_create_from_protocol_and_type(NOTIFY,
this->esp ? PROTO_ESP : PROTO_IKE, type);
notify->set_spi(notify, this->spi);
if (data.len)
@ -95,7 +95,7 @@ METHOD(listener_t, ike_updown, bool,
DBG1(DBG_CFG, "injecting unencrypted INFORMATIONAL message");
message = message_create();
message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
message->set_message_id(message, this->id);
message->set_ike_sa_id(message, ike_sa->get_id(ike_sa));
message->set_exchange_type(message, INFORMATIONAL);

View File

@ -45,9 +45,9 @@ struct private_unsort_message_t {
METHOD(listener_t, message, bool,
private_unsort_message_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming)
bool incoming, bool plain)
{
if (!incoming &&
if (!incoming && plain &&
message->get_request(message) == this->req &&
message->get_message_id(message) == this->id)
{

103
src/libcharon/Makefile.am Normal file → Executable file
View File

@ -38,6 +38,7 @@ encoding/payloads/transform_substructure.c encoding/payloads/transform_substruct
encoding/payloads/ts_payload.c encoding/payloads/ts_payload.h \
encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
kernel/kernel_handler.c kernel/kernel_handler.h \
network/receiver.c network/receiver.h network/sender.c network/sender.h \
network/packet.c network/packet.h network/socket.c network/socket.h \
@ -56,37 +57,70 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \
processing/jobs/roam_job.c processing/jobs/roam_job.h \
processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \
processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \
sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \
sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \
sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \
sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \
sa/eap/eap_method.c sa/eap/eap_method.h \
sa/eap/eap_manager.c sa/eap/eap_manager.h \
sa/xauth/xauth_method.c sa/xauth/xauth_method.h \
sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \
sa/authenticator.c sa/authenticator.h \
sa/child_sa.c sa/child_sa.h \
sa/ike_sa.c sa/ike_sa.h \
sa/ike_sa_id.c sa/ike_sa_id.h \
sa/keymat.h sa/keymat.c \
sa/ike_sa_manager.c sa/ike_sa_manager.h \
sa/task_manager.c sa/task_manager.h \
sa/keymat.c sa/keymat.h \
sa/task_manager.h sa/task_manager.c \
sa/shunt_manager.c sa/shunt_manager.h \
sa/trap_manager.c sa/trap_manager.h \
sa/tasks/child_create.c sa/tasks/child_create.h \
sa/tasks/child_delete.c sa/tasks/child_delete.h \
sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
sa/tasks/ike_config.c sa/tasks/ike_config.h \
sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
sa/tasks/ike_init.c sa/tasks/ike_init.h \
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
sa/tasks/task.c sa/tasks/task.h
sa/task.c sa/task.h
if USE_IKEV2
libcharon_la_SOURCES += \
sa/ikev2/keymat_v2.c sa/ikev2/keymat_v2.h \
sa/ikev2/task_manager_v2.c sa/ikev2/task_manager_v2.h \
sa/ikev2/authenticators/eap_authenticator.c sa/ikev2/authenticators/eap_authenticator.h \
sa/ikev2/authenticators/psk_authenticator.c sa/ikev2/authenticators/psk_authenticator.h \
sa/ikev2/authenticators/pubkey_authenticator.c sa/ikev2/authenticators/pubkey_authenticator.h \
sa/ikev2/tasks/child_create.c sa/ikev2/tasks/child_create.h \
sa/ikev2/tasks/child_delete.c sa/ikev2/tasks/child_delete.h \
sa/ikev2/tasks/child_rekey.c sa/ikev2/tasks/child_rekey.h \
sa/ikev2/tasks/ike_auth.c sa/ikev2/tasks/ike_auth.h \
sa/ikev2/tasks/ike_cert_pre.c sa/ikev2/tasks/ike_cert_pre.h \
sa/ikev2/tasks/ike_cert_post.c sa/ikev2/tasks/ike_cert_post.h \
sa/ikev2/tasks/ike_config.c sa/ikev2/tasks/ike_config.h \
sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
endif
if USE_IKEV1
libcharon_la_SOURCES += \
sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
sa/ikev1/authenticators/hybrid_authenticator.c sa/ikev1/authenticators/hybrid_authenticator.h \
sa/ikev1/phase1.c sa/ikev1/phase1.h \
sa/ikev1/tasks/main_mode.c sa/ikev1/tasks/main_mode.h \
sa/ikev1/tasks/aggressive_mode.c sa/ikev1/tasks/aggressive_mode.h \
sa/ikev1/tasks/informational.c sa/ikev1/tasks/informational.h \
sa/ikev1/tasks/isakmp_cert_pre.c sa/ikev1/tasks/isakmp_cert_pre.h \
sa/ikev1/tasks/isakmp_cert_post.c sa/ikev1/tasks/isakmp_cert_post.h \
sa/ikev1/tasks/isakmp_natd.c sa/ikev1/tasks/isakmp_natd.h \
sa/ikev1/tasks/isakmp_vendor.c sa/ikev1/tasks/isakmp_vendor.h \
sa/ikev1/tasks/isakmp_delete.c sa/ikev1/tasks/isakmp_delete.h \
sa/ikev1/tasks/isakmp_dpd.c sa/ikev1/tasks/isakmp_dpd.h \
sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \
sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \
sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \
sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \
processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
endif
daemon.lo : $(top_builddir)/config.status
@ -112,9 +146,9 @@ if USE_ME
libcharon_la_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
sa/connect_manager.c sa/connect_manager.h \
sa/mediation_manager.c sa/mediation_manager.h \
sa/tasks/ike_me.c sa/tasks/ike_me.h
sa/ikev2/connect_manager.c sa/ikev2/connect_manager.h \
sa/ikev2/mediation_manager.c sa/ikev2/mediation_manager.h \
sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
endif
if USE_LIBCAP
@ -508,3 +542,16 @@ if MONOLITHIC
endif
endif
if USE_XAUTH_GENERIC
SUBDIRS += plugins/xauth_generic
if MONOLITHIC
libcharon_la_LIBADD += plugins/xauth_generic/libstrongswan-xauth-generic.la
endif
endif
if USE_XAUTH_EAP
SUBDIRS += plugins/xauth_eap
if MONOLITHIC
libcharon_la_LIBADD += plugins/xauth_eap/libstrongswan-xauth-eap.la
endif
endif

View File

@ -406,7 +406,7 @@ METHOD(bus_t, child_state_change, void,
}
METHOD(bus_t, message, void,
private_bus_t *this, message_t *message, bool incoming)
private_bus_t *this, message_t *message, bool incoming, bool plain)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@ -425,7 +425,7 @@ METHOD(bus_t, message, void,
}
entry->calling++;
keep = entry->listener->message(entry->listener, ike_sa,
message, incoming);
message, incoming, plain);
entry->calling--;
if (!keep)
{
@ -438,7 +438,8 @@ METHOD(bus_t, message, void,
METHOD(bus_t, ike_keys, void,
private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
ike_sa_t *rekey, shared_key_t *shared)
{
enumerator_t *enumerator;
entry_t *entry;
@ -453,8 +454,8 @@ METHOD(bus_t, ike_keys, void,
continue;
}
entry->calling++;
keep = entry->listener->ike_keys(entry->listener, ike_sa, dh,
nonce_i, nonce_r, rekey);
keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
nonce_i, nonce_r, rekey, shared);
entry->calling--;
if (!keep)
{

View File

@ -235,10 +235,15 @@ struct bus_t {
/**
* Message send/receive hook.
*
* The hook is invoked twice for each message: Once with plain, parsed data
* and once encoded and encrypted.
*
* @param message message to send/receive
* @param incoming TRUE for incoming messages, FALSE for outgoing
* @param plain TRUE if message is parsed and decrypted, FALSE it not
* @param
*/
void (*message)(bus_t *this, message_t *message, bool incoming);
void (*message)(bus_t *this, message_t *message, bool incoming, bool plain);
/**
* IKE_SA authorization hook.
@ -264,12 +269,15 @@ struct bus_t {
*
* @param ike_sa IKE_SA this keymat belongs to
* @param dh diffie hellman shared secret
* @param dh_other others DH public value (IKEv1 only)
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
* @param rekey IKE_SA we are rekeying, if any
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
* @param shared shared key used for key derivation (IKEv1-PSK only)
*/
void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
ike_sa_t *rekey, shared_key_t *shared);
/**
* CHILD_SA keymat hook.
*

View File

@ -84,26 +84,33 @@ struct listener_t {
/**
* Hook called for received/sent messages of an IKE_SA.
*
* The hook is invoked twice for each message: Once with plain, parsed data
* and once encoded and encrypted.
*
* @param ike_sa IKE_SA sending/receiving a message
* @param message message object
* @param incoming TRUE for incoming messages, FALSE for outgoing
* @param plain TRUE if message is parsed and decrypted, FALSE it not
* @return TRUE to stay registered, FALSE to unregister
*/
bool (*message)(listener_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming);
bool incoming, bool plain);
/**
* Hook called with IKE_SA key material.
*
* @param ike_sa IKE_SA this keymat belongs to
* @param dh diffie hellman shared secret
* @param dh_other others DH public value (IKEv1 only)
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
* @param rekey IKE_SA we are rekeying, if any
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
* @param shared shared key used for key derivation (IKEv1-PSK only)
* @return TRUE to stay registered, FALSE to unregister
*/
bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
ike_sa_t *rekey, shared_key_t *shared);
/**
* Hook called with CHILD_SA key material.

View File

@ -146,10 +146,11 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
ike_cfg_match_t match, best = MATCH_ANY;
ike_data_t *data;
data = malloc_thing(ike_data_t);
data->this = this;
data->me = me;
data->other = other;
INIT(data,
.this = this,
.me = me,
.other = other,
);
DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other);
@ -160,7 +161,7 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
while (enumerator->enumerate(enumerator, (void**)&current))
{
match = get_ike_match(current, me, other);
DBG3(DBG_CFG, "ike config match: %d (%H %H)", match, me, other);
if (match)
{
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
@ -195,9 +196,13 @@ static id_match_t get_peer_match(identification_t *id,
auth_cfg_t *auth;
identification_t *candidate;
id_match_t match = ID_MATCH_NONE;
char *where = local ? "local" : "remote";
chunk_t data;
if (!id)
{
DBG3(DBG_CFG, "peer config match %s: %d (%N)",
where, ID_MATCH_ANY, id_type_names, ID_ANY);
return ID_MATCH_ANY;
}
@ -221,9 +226,29 @@ static id_match_t get_peer_match(identification_t *id,
}
}
enumerator->destroy(enumerator);
data = id->get_encoding(id);
DBG3(DBG_CFG, "peer config match %s: %d (%N -> %#B)",
where, match, id_type_names, id->get_type(id), &data);
return match;
}
/**
* Get match quality of IKE version
*/
static int get_version_match(ike_version_t cfg, ike_version_t req)
{
if (req == IKE_ANY || cfg == IKE_ANY)
{
return 1;
}
if (req == cfg)
{
return 2;
}
return 0;
}
/**
* data to pass nested peer enumerator
*/
@ -317,17 +342,18 @@ static void insert_sorted(match_entry_t *entry, linked_list_t *list,
METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
private_backend_manager_t *this, host_t *me, host_t *other,
identification_t *my_id, identification_t *other_id)
identification_t *my_id, identification_t *other_id, ike_version_t version)
{
enumerator_t *enumerator;
peer_data_t *data;
peer_cfg_t *cfg;
linked_list_t *configs, *helper;
data = malloc_thing(peer_data_t);
data->lock = this->lock;
data->me = my_id;
data->other = other_id;
INIT(data,
.lock = this->lock,
.me = my_id,
.other = other_id,
);
/* create a sorted list with all matches */
this->lock->read_lock(this->lock);
@ -340,9 +366,6 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
return enumerator;
}
DBG1(DBG_CFG, "looking for peer configs matching %H[%Y]...%H[%Y]",
me, my_id, other, other_id);
configs = linked_list_create();
/* only once allocated helper list for sorting */
helper = linked_list_create();
@ -350,29 +373,26 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
{
id_match_t match_peer_me, match_peer_other;
ike_cfg_match_t match_ike;
int match_version;
match_entry_t *entry;
chunk_t data;
match_peer_me = get_peer_match(my_id, cfg, TRUE);
data = my_id->get_encoding(my_id);
DBG3(DBG_CFG, "match_peer_me: %d (%N -> %#B)", match_peer_me,
id_type_names, my_id->get_type(my_id), &data);
match_peer_other = get_peer_match(other_id, cfg, FALSE);
data = other_id->get_encoding(other_id);
DBG3(DBG_CFG, "match_peer_other: %d (%N -> %#B)", match_peer_other,
id_type_names, other_id->get_type(other_id), &data);
match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other);
DBG3(DBG_CFG, "match_ike: %d (%H %H)", match_ike, me, other);
match_version = get_version_match(cfg->get_ike_version(cfg), version);
DBG3(DBG_CFG, "ike config match: %d (%H %H)", match_ike, me, other);
if (match_peer_me && match_peer_other && match_ike)
if (match_peer_me && match_peer_other && match_ike && match_version)
{
DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)",
cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike);
DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d/%d "
"(me/other/ike/version)", cfg->get_name(cfg),
match_peer_me, match_peer_other, match_ike, match_version);
entry = malloc_thing(match_entry_t);
entry->match_peer = match_peer_me + match_peer_other;
entry->match_ike = match_ike;
entry->cfg = cfg->get_ref(cfg);
INIT(entry,
.match_peer = match_peer_me + match_peer_other,
.match_ike = match_ike,
.cfg = cfg->get_ref(cfg),
);
insert_sorted(entry, configs, helper);
}
}

View File

@ -56,6 +56,7 @@ struct backend_manager_t {
*
* @param my_host address of own host
* @param other_host address of remote host
* @param version IKE version to get a config for
* @return matching ike_config, or NULL if none found
*/
ike_cfg_t* (*get_ike_cfg)(backend_manager_t *this,
@ -79,11 +80,12 @@ struct backend_manager_t {
* @param other remote address
* @param my_id IDr in first authentication round
* @param other_id IDi in first authentication round
* @param version IKE version to get a config for
* @return enumerator over peer_cfg_t
*/
enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this,
host_t *me, host_t *other, identification_t *my_id,
identification_t *other_id);
identification_t *other_id, ike_version_t version);
/**
* Register a backend on the manager.
*

View File

@ -25,6 +25,12 @@
#include <utils/linked_list.h>
#include <utils/identification.h>
ENUM(ike_version_names, IKE_ANY, IKEV2,
"IKEv1/2",
"IKEv1",
"IKEv2",
);
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"CERT_ALWAYS_SEND",
"CERT_SEND_IF_ASKED",
@ -62,7 +68,7 @@ struct private_peer_cfg_t {
/**
* IKE version to use for initiation
*/
u_int ike_version;
ike_version_t ike_version;
/**
* IKE config associated to this peer config
@ -99,6 +105,11 @@ struct private_peer_cfg_t {
*/
bool use_mobike;
/**
* Use aggressive mode?
*/
bool aggressive;
/**
* Time before starting rekeying
*/
@ -169,7 +180,7 @@ METHOD(peer_cfg_t, get_name, char*,
return this->name;
}
METHOD(peer_cfg_t, get_ike_version, u_int,
METHOD(peer_cfg_t, get_ike_version, ike_version_t,
private_peer_cfg_t *this)
{
return this->ike_version;
@ -336,13 +347,13 @@ METHOD(peer_cfg_t, get_keyingtries, u_int32_t,
}
METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
private_peer_cfg_t *this)
private_peer_cfg_t *this, bool jitter)
{
if (this->rekey_time == 0)
{
return 0;
}
if (this->jitter_time == 0)
if (this->jitter_time == 0 || !jitter)
{
return this->rekey_time;
}
@ -350,13 +361,13 @@ METHOD(peer_cfg_t, get_rekey_time, u_int32_t,
}
METHOD(peer_cfg_t, get_reauth_time, u_int32_t,
private_peer_cfg_t *this)
private_peer_cfg_t *this, bool jitter)
{
if (this->reauth_time == 0)
{
return 0;
}
if (this->jitter_time == 0)
if (this->jitter_time == 0 || !jitter)
{
return this->reauth_time;
}
@ -375,6 +386,12 @@ METHOD(peer_cfg_t, use_mobike, bool,
return this->use_mobike;
}
METHOD(peer_cfg_t, use_aggressive, bool,
private_peer_cfg_t *this)
{
return this->aggressive;
}
METHOD(peer_cfg_t, get_dpd, u_int32_t,
private_peer_cfg_t *this)
{
@ -563,14 +580,14 @@ METHOD(peer_cfg_t, destroy, void,
/*
* Described in header-file
*/
peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
cert_policy_t cert_policy, unique_policy_t unique,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t dpd,
host_t *virtual_ip, char *pool,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id)
peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
unique_policy_t unique, u_int32_t keyingtries,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
host_t *virtual_ip, char *pool, bool mediation,
peer_cfg_t *mediated_by, identification_t *peer_id)
{
private_peer_cfg_t *this;
@ -599,6 +616,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
.get_reauth_time = _get_reauth_time,
.get_over_time = _get_over_time,
.use_mobike = _use_mobike,
.use_aggressive = _use_aggressive,
.get_dpd = _get_dpd,
.get_virtual_ip = _get_virtual_ip,
.get_pool = _get_pool,
@ -626,6 +644,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
.jitter_time = jitter_time,
.over_time = over_time,
.use_mobike = mobike,
.aggressive = aggressive,
.dpd = dpd,
.virtual_ip = virtual_ip,
.pool = strdupnull(pool),

View File

@ -23,6 +23,7 @@
#ifndef PEER_CFG_H_
#define PEER_CFG_H_
typedef enum ike_version_t ike_version_t;
typedef enum cert_policy_t cert_policy_t;
typedef enum unique_policy_t unique_policy_t;
typedef struct peer_cfg_t peer_cfg_t;
@ -34,10 +35,25 @@ typedef struct peer_cfg_t peer_cfg_t;
#include <config/proposal.h>
#include <config/ike_cfg.h>
#include <config/child_cfg.h>
#include <sa/authenticators/authenticator.h>
#include <sa/authenticators/eap/eap_method.h>
#include <credentials/auth_cfg.h>
/**
* IKE version.
*/
enum ike_version_t {
/** any version */
IKE_ANY = 0,
/** IKE version 1 */
IKEV1 = 1,
/** IKE version 2 */
IKEV2 = 2,
};
/**
* enum strings fro ike_version_t
*/
extern enum_name_t *ike_version_names;
/**
* Certificate sending policy. This is also used for certificate
* requests when using this definition for the other peer. If
@ -130,7 +146,7 @@ struct peer_cfg_t {
*
* @return IKE major version
*/
u_int (*get_ike_version)(peer_cfg_t *this);
ike_version_t (*get_ike_version)(peer_cfg_t *this);
/**
* Get the IKE config to use for initiaton.
@ -211,18 +227,20 @@ struct peer_cfg_t {
u_int32_t (*get_keyingtries) (peer_cfg_t *this);
/**
* Get a time to start rekeying (is randomized with jitter).
* Get a time to start rekeying.
*
* @param jitter remove a jitter value to randomize time
* @return time in s when to start rekeying, 0 disables rekeying
*/
u_int32_t (*get_rekey_time)(peer_cfg_t *this);
u_int32_t (*get_rekey_time)(peer_cfg_t *this, bool jitter);
/**
* Get a time to start reauthentication (is randomized with jitter).
* Get a time to start reauthentication.
*
* @param jitter remove a jitter value to randomize time
* @return time in s when to start reauthentication, 0 disables it
*/
u_int32_t (*get_reauth_time)(peer_cfg_t *this);
u_int32_t (*get_reauth_time)(peer_cfg_t *this, bool jitter);
/**
* Get the timeout of a rekeying/reauthenticating SA.
@ -238,6 +256,13 @@ struct peer_cfg_t {
*/
bool (*use_mobike) (peer_cfg_t *this);
/**
* Use/Accept aggressive mode with IKEv1?.
*
* @return TRUE to use aggressive mode
*/
bool (*use_aggressive)(peer_cfg_t *this);
/**
* Get the DPD check interval.
*
@ -339,6 +364,7 @@ struct peer_cfg_t {
* @param jitter_time timerange to randomly subtract from rekey/reauth time
* @param over_time maximum overtime before closing a rekeying/reauth SA
* @param mobike use MOBIKE (RFC4555) if peer supports it
* @param aggressive use/accept aggressive mode with IKEv1
* @param dpd DPD check interval, 0 to disable
* @param virtual_ip virtual IP for local host, or NULL
* @param pool pool name to get configuration attributes from, or NULL
@ -347,13 +373,13 @@ struct peer_cfg_t {
* @param peer_id ID that identifies our peer at the mediation server
* @return peer_cfg_t object
*/
peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
cert_policy_t cert_policy, unique_policy_t unique,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t dpd,
host_t *virtual_ip, char *pool,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id);
peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
ike_cfg_t *ike_cfg, cert_policy_t cert_policy,
unique_policy_t unique, u_int32_t keyingtries,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
host_t *virtual_ip, char *pool, bool mediation,
peer_cfg_t *mediated_by, identification_t *peer_id);
#endif /** PEER_CFG_H_ @}*/

View File

@ -217,6 +217,17 @@ METHOD(job_t, initiate_execute, void,
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
if (!ike_sa)
{
listener->child_cfg->destroy(listener->child_cfg);
peer_cfg->destroy(peer_cfg);
/* trigger down event to release listener */
listener->ike_sa = charon->ike_sa_manager->checkout_new(
charon->ike_sa_manager, IKE_ANY, TRUE);
DESTROY_IF(listener->ike_sa);
listener->status = FAILED;
return;
}
listener->ike_sa = ike_sa;
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
@ -357,7 +368,7 @@ METHOD(job_t, terminate_child_execute, void,
charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE)) != DESTROY_ME)
child_sa->get_spi(child_sa, TRUE), FALSE) != DESTROY_ME)
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
listener->status = SUCCESS;

View File

@ -128,6 +128,7 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.ike_sa_manager);
DESTROY_IF(this->public.controller);
DESTROY_IF(this->public.eap);
DESTROY_IF(this->public.xauth);
DESTROY_IF(this->public.backends);
DESTROY_IF(this->public.socket);
@ -272,6 +273,7 @@ private_daemon_t *daemon_create()
charon = &this->public;
this->public.controller = controller_create();
this->public.eap = eap_manager_create();
this->public.xauth = xauth_manager_create();
this->public.backends = backend_manager_create();
this->public.socket = socket_manager_create();
this->public.traps = trap_manager_create();

View File

@ -148,11 +148,12 @@ typedef struct daemon_t daemon_t;
#include <sa/trap_manager.h>
#include <sa/shunt_manager.h>
#include <config/backend_manager.h>
#include <sa/authenticators/eap/eap_manager.h>
#include <sa/eap/eap_manager.h>
#include <sa/xauth/xauth_manager.h>
#ifdef ME
#include <sa/connect_manager.h>
#include <sa/mediation_manager.h>
#include <sa/ikev2/connect_manager.h>
#include <sa/ikev2/mediation_manager.h>
#endif /* ME */
/**
@ -235,6 +236,11 @@ struct daemon_t {
*/
eap_manager_t *eap;
/**
* XAuth manager to maintain registered XAuth methods
*/
xauth_manager_t *xauth;
#ifdef ME
/**
* Connect manager

View File

@ -1,4 +1,5 @@
/*
* Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@ -108,6 +109,11 @@ struct private_generator_t {
* to hold the length of the transform attribute in bytes.
*/
u_int16_t attribute_length;
/**
* TRUE, if debug messages should be logged during generation.
*/
bool debug;
};
/**
@ -155,8 +161,11 @@ static void make_space_available(private_generator_t *this, int bits)
new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
out_position_offset = this->out_position - this->buffer;
DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
old_buffer_size, new_buffer_size);
if (this->debug)
{
DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
old_buffer_size, new_buffer_size);
}
this->buffer = realloc(this->buffer,new_buffer_size);
this->out_position = (this->buffer + out_position_offset);
@ -205,7 +214,7 @@ static void generate_u_int_type(private_generator_t *this,
break;
case U_INT_16:
case PAYLOAD_LENGTH:
case CONFIGURATION_ATTRIBUTE_LENGTH:
case ATTRIBUTE_LENGTH:
number_of_bits = 16;
break;
case U_INT_32:
@ -244,7 +253,10 @@ static void generate_u_int_type(private_generator_t *this,
low = *(this->out_position) & 0x0F;
/* high is set, low_val is not changed */
*(this->out_position) = high | low;
DBG3(DBG_ENC, " => %d", *(this->out_position));
if (this->debug)
{
DBG3(DBG_ENC, " => %d", *(this->out_position));
}
/* write position is not changed, just bit position is moved */
this->current_bit = 4;
}
@ -255,7 +267,10 @@ static void generate_u_int_type(private_generator_t *this,
/* low of current byte in buffer has to be set to the new value*/
low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
*(this->out_position) = high | low;
DBG3(DBG_ENC, " => %d", *(this->out_position));
if (this->debug)
{
DBG3(DBG_ENC, " => %d", *(this->out_position));
}
this->out_position++;
this->current_bit = 0;
}
@ -274,7 +289,10 @@ static void generate_u_int_type(private_generator_t *this,
{
/* 8 bit values are written as they are */
*this->out_position = *((u_int8_t *)(this->data_struct + offset));
DBG3(DBG_ENC, " => %d", *(this->out_position));
if (this->debug)
{
DBG3(DBG_ENC, " => %d", *(this->out_position));
}
this->out_position++;
break;
}
@ -299,7 +317,10 @@ static void generate_u_int_type(private_generator_t *this,
val |= 0x8000;
}
val = htons(val);
DBG3(DBG_ENC, " => %d", val);
if (this->debug)
{
DBG3(DBG_ENC, " => %d", val);
}
/* write bytes to buffer (set bit is overwritten) */
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
this->current_bit = 0;
@ -308,17 +329,23 @@ static void generate_u_int_type(private_generator_t *this,
}
case U_INT_16:
case PAYLOAD_LENGTH:
case CONFIGURATION_ATTRIBUTE_LENGTH:
case ATTRIBUTE_LENGTH:
{
u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
if (this->debug)
{
DBG3(DBG_ENC, " %b", &val, sizeof(u_int16_t));
}
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
break;
}
case U_INT_32:
{
u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
if (this->debug)
{
DBG3(DBG_ENC, " %b", &val, sizeof(u_int32_t));
}
write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
break;
}
@ -327,8 +354,11 @@ static void generate_u_int_type(private_generator_t *this,
/* 64 bit are written as-is, no host order conversion */
write_bytes_to_buffer(this, this->data_struct + offset,
sizeof(u_int64_t));
DBG3(DBG_ENC, " => %b", this->data_struct + offset,
sizeof(u_int64_t));
if (this->debug)
{
DBG3(DBG_ENC, " %b", this->data_struct + offset,
sizeof(u_int64_t));
}
break;
}
default:
@ -361,7 +391,10 @@ static void generate_flag(private_generator_t *this, u_int32_t offset)
}
*(this->out_position) = *(this->out_position) | flag;
DBG3(DBG_ENC, " => %d", *this->out_position);
if (this->debug)
{
DBG3(DBG_ENC, " => %d", *this->out_position);
}
this->current_bit++;
if (this->current_bit >= 8)
@ -380,12 +413,16 @@ static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
if (this->current_bit != 0)
{
DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
DBG1(DBG_ENC, "can not generate a chunk at bitpos %d",
this->current_bit);
return ;
}
value = (chunk_t *)(this->data_struct + offset);
DBG3(DBG_ENC, " => %B", value);
if (this->debug)
{
DBG3(DBG_ENC, " %B", value);
}
write_bytes_to_buffer(this, value->ptr, value->len);
}
@ -397,15 +434,17 @@ METHOD(generator_t, get_chunk, chunk_t,
*lenpos = (u_int32_t*)(this->buffer + this->header_length_offset);
data = chunk_create(this->buffer, get_length(this));
DBG3(DBG_ENC, "generated data of this generator %B", &data);
if (this->debug)
{
DBG3(DBG_ENC, "generated data of this generator %B", &data);
}
return data;
}
METHOD(generator_t, generate_payload, void,
private_generator_t *this,payload_t *payload)
{
int i, offset_start;
size_t rule_count;
int i, offset_start, rule_count;
encoding_rule_t *rules;
payload_type_t payload_type;
@ -414,17 +453,23 @@ METHOD(generator_t, generate_payload, void,
offset_start = this->out_position - this->buffer;
DBG2(DBG_ENC, "generating payload of type %N",
payload_type_names, payload_type);
if (this->debug)
{
DBG2(DBG_ENC, "generating payload of type %N",
payload_type_names, payload_type);
}
/* each payload has its own encoding rules */
payload->get_encoding_rules(payload, &rules, &rule_count);
rule_count = payload->get_encoding_rules(payload, &rules);
for (i = 0; i < rule_count;i++)
{
DBG2(DBG_ENC, " generating rule %d %N",
i, encoding_type_names, rules[i].type);
switch (rules[i].type)
if (this->debug)
{
DBG2(DBG_ENC, " generating rule %d %N",
i, encoding_type_names, rules[i].type);
}
switch ((int)rules[i].type)
{
case U_INT_4:
case U_INT_8:
@ -436,7 +481,7 @@ METHOD(generator_t, generate_payload, void,
case SPI_SIZE:
case TS_TYPE:
case ATTRIBUTE_TYPE:
case CONFIGURATION_ATTRIBUTE_LENGTH:
case ATTRIBUTE_LENGTH:
generate_u_int_type(this, rules[i].type, rules[i].offset);
break;
case RESERVED_BIT:
@ -449,26 +494,19 @@ METHOD(generator_t, generate_payload, void,
break;
case ADDRESS:
case SPI:
case KEY_EXCHANGE_DATA:
case NOTIFICATION_DATA:
case NONCE_DATA:
case ID_DATA:
case AUTH_DATA:
case CERT_DATA:
case CERTREQ_DATA:
case SPIS:
case CONFIGURATION_ATTRIBUTE_VALUE:
case VID_DATA:
case EAP_DATA:
case CHUNK_DATA:
case ENCRYPTED_DATA:
case UNKNOWN_DATA:
generate_from_chunk(this, rules[i].offset);
break;
case PROPOSALS:
case TRANSFORMS:
case TRANSFORM_ATTRIBUTES:
case CONFIGURATION_ATTRIBUTES:
case TRAFFIC_SELECTORS:
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
{
linked_list_t *proposals;
enumerator_t *enumerator;
@ -507,7 +545,10 @@ METHOD(generator_t, generate_payload, void,
{
if (!this->attribute_format)
{
DBG2(DBG_ENC, "attribute value has not fixed size");
if (this->debug)
{
DBG2(DBG_ENC, "attribute value has not fixed size");
}
/* the attribute value is generated */
generate_from_chunk(this, rules[i].offset);
}
@ -519,11 +560,14 @@ METHOD(generator_t, generate_payload, void,
return;
}
}
DBG2(DBG_ENC, "generating %N payload finished",
payload_type_names, payload_type);
DBG3(DBG_ENC, "generated data for this payload %b",
this->buffer + offset_start,
this->out_position - this->buffer - offset_start);
if (this->debug)
{
DBG2(DBG_ENC, "generating %N payload finished",
payload_type_names, payload_type);
DBG3(DBG_ENC, "generated data for this payload %b",
this->buffer + offset_start,
this->out_position - this->buffer - offset_start);
}
}
METHOD(generator_t, destroy, void,
@ -547,6 +591,7 @@ generator_t *generator_create()
.destroy = _destroy,
},
.buffer = malloc(GENERATOR_DATA_BUFFER_SIZE),
.debug = TRUE,
);
this->out_position = this->buffer;
@ -555,3 +600,14 @@ generator_t *generator_create()
return &this->public;
}
/*
* Described in header
*/
generator_t *generator_create_no_dbg()
{
private_generator_t *this = (private_generator_t*)generator_create();
this->debug = FALSE;
return &this->public;
}

View File

@ -72,4 +72,12 @@ struct generator_t {
*/
generator_t *generator_create(void);
/**
* Constructor to create a generator that does not log any debug messages > 1.
*
* @return generator_t object.
*/
generator_t *generator_create_no_dbg(void);
#endif /** GENERATOR_H_ @}*/

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006-2011 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@ -27,15 +27,15 @@
typedef struct message_t message_t;
#include <library.h>
#include <sa/ike_sa_id.h>
#include <network/packet.h>
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/notify_payload.h>
#include <sa/keymat.h>
#include <sa/ike_sa_id.h>
#include <utils/linked_list.h>
#include <crypto/aead.h>
/**
* This class is used to represent an IKEv2-Message.
* This class is used to represent an IKE-Message.
*
* The message handles parsing and generation of payloads
* via parser_t/generator_t. Encryption is done transparently
@ -182,7 +182,7 @@ struct message_t {
* all payloads to encrypt are added to the encryption payload, which is
* always the last one.
*
* @param payload payload to append
* @param payload payload to append
*/
void (*add_payload) (message_t *this, payload_t *payload);
@ -208,14 +208,14 @@ struct message_t {
/**
* Parses header of message.
*
* Begins parisng of a message created via message_create_from_packet().
* Begins parsing 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.
*
* @return
* - SUCCESS if header could be parsed
* - SUCCESS if header could be parsed
* - PARSE_ERROR if corrupted/invalid data found
* - FAILED if consistence check of header failed
* - FAILED if consistency check of header failed
*/
status_t (*parse_header) (message_t *this);
@ -228,15 +228,15 @@ struct message_t {
* If there are encrypted payloads, they get decrypted and verified using
* the given aead transform (if given).
*
* @param aead aead transform to verify/decrypt message
* @param keymat keymat to verify/decrypt message
* @return
* - SUCCESS if parsing successful
* - SUCCESS if parsing successful
* - PARSE_ERROR if message parsing failed
* - VERIFY_ERROR if message verification failed (bad syntax)
* - FAILED if integrity check failed
* - INVALID_STATE if aead not supplied, but needed
* - VERIFY_ERROR if message verification failed (bad syntax)
* - FAILED if integrity check failed
* - INVALID_STATE if aead not supplied, but needed
*/
status_t (*parse_body) (message_t *this, aead_t *aead);
status_t (*parse_body) (message_t *this, keymat_t *keymat);
/**
* Generates the UDP packet of specific message.
@ -247,15 +247,15 @@ struct message_t {
* Generation is only done once, multiple calls will just return a copy
* of the packet.
*
* @param aead aead transform to encrypt/sign message
* @param keymat keymat to encrypt/sign message
* @param packet copy of generated packet
* @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 aead not supplied but needed.
* - 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 aead not supplied but needed.
*/
status_t (*generate) (message_t *this, aead_t *aead, packet_t **packet);
status_t (*generate) (message_t *this, keymat_t *keymat, packet_t **packet);
/**
* Check if the message has already been encoded using generate().
@ -278,7 +278,7 @@ struct message_t {
* 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.
* message_t.destroy or next call of message_t.set_source.
*
* @param host host_t object representing source host
*/
@ -298,7 +298,7 @@ struct message_t {
* 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.
* message_t.destroy or next call of message_t.set_destination.
*
* @param host host_t object representing destination host
*/
@ -344,9 +344,9 @@ struct message_t {
packet_t * (*get_packet) (message_t *this);
/**
* Returns a clone of the internal stored packet_t data.
* Returns a chunk pointing to internal packet_t data.
*
* @return clone of the internal stored packet_t data.
* @return packet data.
*/
chunk_t (*get_packet_data) (message_t *this);
@ -357,26 +357,27 @@ struct message_t {
};
/**
* Creates an message_t object from a incoming UDP Packet.
* Creates a message_t object from an incoming UDP packet.
*
* The given packet gets owned by the message. The message is uninitialized,
* call parse_header() to populate header fields.
*
* @param packet packet_t object which is assigned to message
* @return message_t object
* @return message_t object
*/
message_t * message_create_from_packet(packet_t *packet);
message_t *message_create_from_packet(packet_t *packet);
/**
* Creates an empty message_t object.
* Creates an empty message_t object for a specific major/minor version.
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
*
* @return message_t object
* @param major major IKE version of this message
* @param minor minor IKE version of this message
* @return message_t object
*/
message_t * message_create(void);
message_t *message_create(int major, int minor);
#endif /** MESSAGE_H_ @}*/

View File

@ -137,7 +137,7 @@ static bool parse_uint4(private_parser_t *this, int rule_number,
}
if (output_pos)
{
DBG3(DBG_ENC, " => %d", *output_pos);
DBG3(DBG_ENC, " => %hhu", *output_pos);
}
return TRUE;
}
@ -159,7 +159,7 @@ static bool parse_uint8(private_parser_t *this, int rule_number,
if (output_pos)
{
*output_pos = *(this->byte_pos);
DBG3(DBG_ENC, " => %d", *output_pos);
DBG3(DBG_ENC, " => %hhu", *output_pos);
}
this->byte_pos++;
return TRUE;
@ -183,7 +183,7 @@ static bool parse_uint15(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
*output_pos = ntohs(*output_pos) & ~0x8000;
DBG3(DBG_ENC, " => %d", *output_pos);
DBG3(DBG_ENC, " => %hu", *output_pos);
}
this->byte_pos += sizeof(u_int16_t);
this->bit_pos = 0;
@ -208,7 +208,7 @@ static bool parse_uint16(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
*output_pos = ntohs(*output_pos);
DBG3(DBG_ENC, " => %d", *output_pos);
DBG3(DBG_ENC, " => %hu", *output_pos);
}
this->byte_pos += sizeof(u_int16_t);
return TRUE;
@ -231,7 +231,7 @@ static bool parse_uint32(private_parser_t *this, int rule_number,
{
memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
*output_pos = ntohl(*output_pos);
DBG3(DBG_ENC, " => %d", *output_pos);
DBG3(DBG_ENC, " => %u", *output_pos);
}
this->byte_pos += sizeof(u_int32_t);
return TRUE;
@ -254,7 +254,7 @@ static bool parse_bytes(private_parser_t *this, int rule_number,
if (output_pos)
{
memcpy(output_pos, this->byte_pos, bytes);
DBG3(DBG_ENC, " => %b", output_pos, bytes);
DBG3(DBG_ENC, " %b", output_pos, bytes);
}
this->byte_pos += bytes;
return TRUE;
@ -352,7 +352,7 @@ static bool parse_chunk(private_parser_t *this, int rule_number,
{
*output_pos = chunk_alloc(length);
memcpy(output_pos->ptr, this->byte_pos, length);
DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
DBG3(DBG_ENC, " %b", output_pos->ptr, length);
}
this->byte_pos += length;
return TRUE;
@ -363,11 +363,10 @@ METHOD(parser_t, parse_payload, status_t,
{
payload_t *pld;
void *output;
size_t rule_count;
int payload_length = 0, spi_size = 0, attribute_length = 0;
int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
u_int16_t ts_type = 0;
bool attribute_format = FALSE;
int rule_number;
int rule_number, rule_count;
encoding_rule_t *rule;
/* create instance of the payload to parse */
@ -381,15 +380,17 @@ METHOD(parser_t, parse_payload, status_t,
/* base pointer for output, avoids casting in every rule */
output = pld;
/* parse the payload with its own rulse */
pld->get_encoding_rules(pld, &this->rules, &rule_count);
rule_count = pld->get_encoding_rules(pld, &this->rules);
for (rule_number = 0; rule_number < rule_count; rule_number++)
{
/* update header length for each rule, as it is dynamic (SPIs) */
header_length = pld->get_header_length(pld);
rule = &(this->rules[rule_number]);
DBG2(DBG_ENC, " parsing rule %d %N",
rule_number, encoding_type_names, rule->type);
switch (rule->type)
switch ((int)rule->type)
{
case U_INT_4:
{
@ -457,7 +458,8 @@ METHOD(parser_t, parse_payload, status_t,
}
/* parsed u_int16 should be aligned */
payload_length = *(u_int16_t*)(output + rule->offset);
if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
/* all payloads must have at least 4 bytes header */
if (payload_length < 4)
{
pld->destroy(pld);
return PARSE_ERROR;
@ -484,49 +486,41 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
case PROPOSALS:
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
{
if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
if (payload_length < header_length ||
!parse_list(this, rule_number, output + rule->offset,
PROPOSAL_SUBSTRUCTURE,
payload_length - SA_PAYLOAD_HEADER_LENGTH))
rule->type - PAYLOAD_LIST,
payload_length - header_length))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case TRANSFORMS:
case CHUNK_DATA:
{
if (payload_length <
spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
!parse_list(this, rule_number, output + rule->offset,
TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
if (payload_length < header_length ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - header_length))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case TRANSFORM_ATTRIBUTES:
case ENCRYPTED_DATA:
{
if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
!parse_list(this, rule_number, output + rule->offset,
TRANSFORM_ATTRIBUTE,
payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case CONFIGURATION_ATTRIBUTES:
{
if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
!parse_list(this, rule_number, output + rule->offset,
CONFIGURATION_ATTRIBUTE,
payload_length - CP_PAYLOAD_HEADER_LENGTH))
if (!parse_chunk(this, rule_number, output + rule->offset,
this->input_roof - this->byte_pos))
{
pld->destroy(pld);
return PARSE_ERROR;
@ -552,7 +546,7 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
case CONFIGURATION_ATTRIBUTE_LENGTH:
case ATTRIBUTE_LENGTH:
{
if (!parse_uint16(this, rule_number, output + rule->offset))
{
@ -583,137 +577,6 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
case NONCE_DATA:
{
if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case ID_DATA:
{
if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - ID_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case AUTH_DATA:
{
if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case CERT_DATA:
{
if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - CERT_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case CERTREQ_DATA:
{
if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case EAP_DATA:
{
if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - EAP_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case SPIS:
{
if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case VID_DATA:
{
if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case CONFIGURATION_ATTRIBUTE_VALUE:
{
if (!parse_chunk(this, rule_number, output + rule->offset,
attribute_length))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case KEY_EXCHANGE_DATA:
{
if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - KE_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case NOTIFICATION_DATA:
{
if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case ENCRYPTED_DATA:
{
if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case TS_TYPE:
{
if (!parse_uint8(this, rule_number, output + rule->offset))
@ -736,29 +599,6 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
case TRAFFIC_SELECTORS:
{
if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
!parse_list(this, rule_number, output + rule->offset,
TRAFFIC_SELECTOR_SUBSTRUCTURE,
payload_length - TS_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case UNKNOWN_DATA:
{
if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
!parse_chunk(this, rule_number, output + rule->offset,
payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
default:
{
DBG1(DBG_ENC, " no rule to parse rule %d %N",

View File

@ -74,7 +74,7 @@ struct private_auth_payload_t {
* The defined offsets are the positions in a object of type
* private_auth_payload_t.
*/
encoding_rule_t auth_payload_encodings[] = {
static encoding_rule_t 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 */
@ -96,7 +96,7 @@ encoding_rule_t auth_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[1]) },
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[2]) },
/* some auth data bytes, length is defined in PAYLOAD_LENGTH */
{ AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
{ CHUNK_DATA, offsetof(private_auth_payload_t, auth_data) }
};
/*
@ -119,11 +119,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_auth_payload_t *this, encoding_rule_t **rules)
{
*rules = auth_payload_encodings;
*rule_count = countof(auth_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_auth_payload_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@ -167,7 +173,7 @@ METHOD(auth_payload_t, set_data, void,
{
free(this->auth_data.ptr);
this->auth_data = chunk_clone(data);
this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
this->payload_length = get_header_length(this) + this->auth_data.len;
}
METHOD(auth_payload_t, get_data, chunk_t,
@ -195,6 +201,7 @@ auth_payload_t *auth_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -208,7 +215,7 @@ auth_payload_t *auth_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = AUTH_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
);
return &this->public;
}

View File

@ -26,12 +26,7 @@ typedef struct auth_payload_t auth_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
#include <sa/authenticators/authenticator.h>
/**
* Length of a auth payload without the auth data in bytes.
*/
#define AUTH_PAYLOAD_HEADER_LENGTH 8
#include <sa/authenticator.h>
/**
* Class representing an IKEv2 AUTH payload.

View File

@ -86,6 +86,11 @@ struct private_cert_payload_t {
* TRUE if the "Hash and URL" data is invalid
*/
bool invalid_hash_and_url;
/**
* The payload type.
*/
payload_type_t type;
};
/**
@ -95,7 +100,7 @@ struct private_cert_payload_t {
* private_cert_payload_t.
*
*/
encoding_rule_t cert_payload_encodings[] = {
static encoding_rule_t 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 */
@ -113,7 +118,7 @@ encoding_rule_t cert_payload_encodings[] = {
/* 1 Byte CERT type*/
{ U_INT_8, offsetof(private_cert_payload_t, encoding) },
/* some cert data bytes, length is defined in PAYLOAD_LENGTH */
{ CERT_DATA, offsetof(private_cert_payload_t, data) }
{ CHUNK_DATA, offsetof(private_cert_payload_t, data) }
};
/*
@ -166,17 +171,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_cert_payload_t *this, encoding_rule_t **rules)
{
*rules = cert_payload_encodings;
*rule_count = countof(cert_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_cert_payload_t *this)
{
return 5;
}
METHOD(payload_t, get_type, payload_type_t,
private_cert_payload_t *this)
{
return CERTIFICATE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -261,7 +272,7 @@ METHOD2(payload_t, cert_payload_t, destroy, void,
/*
* Described in header
*/
cert_payload_t *cert_payload_create()
cert_payload_t *cert_payload_create(payload_type_t type)
{
private_cert_payload_t *this;
@ -270,6 +281,7 @@ cert_payload_t *cert_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -283,7 +295,8 @@ cert_payload_t *cert_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = CERT_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.type = type,
);
return &this->public;
}
@ -291,10 +304,12 @@ cert_payload_t *cert_payload_create()
/*
* Described in header
*/
cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
certificate_t *cert)
{
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
private_cert_payload_t *this;
this = (private_cert_payload_t*)cert_payload_create(type);
switch (cert->get_type(cert))
{
case CERT_X509:
@ -312,7 +327,8 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
free(this);
return NULL;
}
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
this->payload_length = get_header_length(this) + this->data.len;
return &this->public;
}
@ -321,23 +337,29 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
*/
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
{
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
private_cert_payload_t *this;
this = (private_cert_payload_t*)cert_payload_create(CERTIFICATE);
this->encoding = ENC_X509_HASH_AND_URL;
this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
this->payload_length = get_header_length(this) + this->data.len;
return &this->public;
}
/*
* Described in header
*/
cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data)
cert_payload_t *cert_payload_create_custom(payload_type_t type,
cert_encoding_t encoding, chunk_t data)
{
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
private_cert_payload_t *this;
this->encoding = type;
this = (private_cert_payload_t*)cert_payload_create(type);
this->encoding = encoding;
this->data = data;
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
this->payload_length = get_header_length(this) + this->data.len;
return &this->public;
}

View File

@ -30,11 +30,6 @@ typedef enum cert_encoding_t cert_encoding_t;
#include <credentials/certificates/certificate.h>
#include <encoding/payloads/payload.h>
/**
* Length of a cert payload without the cert data in bytes.
*/
#define CERT_PAYLOAD_HEADER_LENGTH 5
/**
* Certifcate encodings, as in RFC4306
*/
@ -60,9 +55,7 @@ enum cert_encoding_t {
extern enum_name_t *cert_encoding_names;
/**
* Class representing an IKEv2 CERT payload.
*
* The CERT payload format is described in RFC section 3.6.
* Class representing an IKEv1/IKEv2 CERT payload.
*/
struct cert_payload_t {
@ -103,7 +96,6 @@ struct cert_payload_t {
*/
char *(*get_url)(cert_payload_t *this);
/**
* Destroys the cert_payload object.
*/
@ -113,23 +105,26 @@ struct cert_payload_t {
/**
* Creates an empty certificate payload.
*
* @param type payload type (for IKEv1 or IKEv2)
* @return cert_payload_t object
*/
cert_payload_t *cert_payload_create(void);
cert_payload_t *cert_payload_create(payload_type_t type);
/**
* Creates a certificate payload with an embedded certificate.
*
* @param type payload type (for IKEv1 or IKEv2)
* @param cert certificate to embed
* @return cert_payload_t object
*/
cert_payload_t *cert_payload_create_from_cert(certificate_t *cert);
cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
certificate_t *cert);
/**
* Creates a certificate payload with hash and URL encoding of a certificate.
* Creates an IKEv2 certificate payload with hash and URL encoding.
*
* @param hash hash of the DER encoded certificate (get's cloned)
* @param url the URL to locate the certificate (get's cloned)
* @param url URL to the certificate
* @return cert_payload_t object
*/
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
@ -137,10 +132,12 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
/**
* Creates a custom certificate payload using type and associated data.
*
* @param type encoding type of certificate
* @param type payload type (for IKEv1 or IKEv2)
* @param encoding encoding type of certificate
* @param data associated data (gets owned)
* @return cert_payload_t object
*/
cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data);
cert_payload_t *cert_payload_create_custom(payload_type_t type,
cert_encoding_t encoding, chunk_t data);
#endif /** CERT_PAYLOAD_H_ @}*/

View File

@ -64,15 +64,17 @@ struct private_certreq_payload_t {
* The contained certreq data value.
*/
chunk_t data;
/**
* Payload type CERTIFICATE_REQUEST or CERTIFICATE_REQUEST_V1
*/
payload_type_t type;
};
/**
* 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 rules for CERTREQ payload.
*/
encoding_rule_t certreq_payload_encodings[] = {
static encoding_rule_t 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 */
@ -90,7 +92,7 @@ encoding_rule_t certreq_payload_encodings[] = {
/* 1 Byte CERTREQ type*/
{ U_INT_8, offsetof(private_certreq_payload_t, encoding) },
/* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
{ CERTREQ_DATA, offsetof(private_certreq_payload_t, data) }
{ CHUNK_DATA, offsetof(private_certreq_payload_t, data) }
};
/*
@ -109,7 +111,8 @@ encoding_rule_t certreq_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_certreq_payload_t *this)
{
if (this->encoding == ENC_X509_SIGNATURE)
if (this->type == CERTIFICATE_REQUEST &&
this->encoding == ENC_X509_SIGNATURE)
{
if (this->data.len < HASH_SIZE_SHA1 ||
this->data.len % HASH_SIZE_SHA1)
@ -122,17 +125,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_certreq_payload_t *this, encoding_rule_t **rules)
{
*rules = certreq_payload_encodings;
*rule_count = countof(certreq_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_certreq_payload_t *this)
{
return 5;
}
METHOD(payload_t, get_type, payload_type_t,
private_certreq_payload_t *this)
{
return CERTIFICATE_REQUEST;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -153,6 +162,16 @@ METHOD(payload_t, get_length, size_t,
return this->payload_length;
}
METHOD(certreq_payload_t, get_dn, identification_t*,
private_certreq_payload_t *this)
{
if (this->data.len)
{
return identification_create_from_encoding(ID_DER_ASN1_DN, this->data);
}
return NULL;
}
METHOD(certreq_payload_t, add_keyid, void,
private_certreq_payload_t *this, chunk_t keyid)
{
@ -200,6 +219,10 @@ METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
{
keyid_enumerator_t *enumerator;
if (this->type == CERTIFICATE_REQUEST_V1)
{
return enumerator_create_empty();
}
INIT(enumerator,
.public = {
.enumerate = (void*)_keyid_enumerate,
@ -232,7 +255,7 @@ METHOD2(payload_t, certreq_payload_t, destroy, void,
/*
* Described in header
*/
certreq_payload_t *certreq_payload_create()
certreq_payload_t *certreq_payload_create(payload_type_t type)
{
private_certreq_payload_t *this;
@ -241,6 +264,7 @@ certreq_payload_t *certreq_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -251,9 +275,11 @@ certreq_payload_t *certreq_payload_create()
.get_cert_type = _get_cert_type,
.add_keyid = _add_keyid,
.destroy = _destroy,
.get_dn = _get_dn,
},
.next_payload = NO_PAYLOAD,
.payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.type = type,
);
return &this->public;
}
@ -263,8 +289,10 @@ certreq_payload_t *certreq_payload_create()
*/
certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
{
private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create();
private_certreq_payload_t *this;
this = (private_certreq_payload_t*)
certreq_payload_create(CERTIFICATE_REQUEST);
switch (type)
{
case CERT_X509:
@ -279,3 +307,19 @@ certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
return &this->public;
}
/*
* Described in header
*/
certreq_payload_t *certreq_payload_create_dn(identification_t *id)
{
private_certreq_payload_t *this;
this = (private_certreq_payload_t*)
certreq_payload_create(CERTIFICATE_REQUEST_V1);
this->encoding = ENC_X509_SIGNATURE;
this->data = chunk_clone(id->get_encoding(id));
this->payload_length = get_header_length(this) + this->data.len;
return &this->public;
}

View File

@ -27,25 +27,20 @@ typedef struct certreq_payload_t certreq_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/cert_payload.h>
#include <utils/identification.h>
/**
* Length of a CERTREQ payload without the CERTREQ data in bytes.
*/
#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
/**
* Class representing an IKEv2 CERTREQ payload.
*
* The CERTREQ payload format is described in RFC section 3.7.
* Class representing an IKEv1/IKEv2 CERTREQ payload.
*/
struct certreq_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* Create an enumerator over contained keyids.
* Create an enumerator over contained keyids (IKEv2 only).
*
* @return enumerator over chunk_t's.
*/
@ -59,13 +54,20 @@ struct certreq_payload_t {
certificate_type_t (*get_cert_type)(certreq_payload_t *this);
/**
* Add a certificates keyid to the payload.
* Add a certificates keyid to the payload (IKEv2 only).
*
* @param keyid keyid of the trusted certifcate
* @return
*/
void (*add_keyid)(certreq_payload_t *this, chunk_t keyid);
/**
* Get the distinguished name of the payload (IKEv1 only).
*
* @return DN as identity, must be destroyed
*/
identification_t* (*get_dn)(certreq_payload_t *this);
/**
* Destroys an certreq_payload_t object.
*/
@ -77,14 +79,22 @@ struct certreq_payload_t {
*
* @return certreq payload
*/
certreq_payload_t *certreq_payload_create(void);
certreq_payload_t *certreq_payload_create(payload_type_t payload_type);
/**
* Creates an empty certreq_payload_t for a kind of certificates.
* Creates an empty IKEv2 certreq_payload_t for a kind of certificates.
*
* @param type type of the added keyids
* @return certreq payload
*/
certreq_payload_t *certreq_payload_create_type(certificate_type_t type);
/**
* Creates a IKEv1 certreq_payload_t for a given distinguished name.
*
* @param id distinguished name, does not get owned
* @return certreq payload
*/
certreq_payload_t *certreq_payload_create_dn(identification_t *id);
#endif /** CERTREQ_PAYLOAD_H_ @}*/

View File

@ -36,41 +36,48 @@ struct private_configuration_attribute_t {
configuration_attribute_t public;
/**
* Reserved bit
* Value encoded in length field?
*/
bool af_flag;
/**
* Reserved bit (af_flag in IKEv2)
*/
bool reserved;
/**
* Type of the attribute.
*/
u_int16_t type;
u_int16_t attr_type;
/**
* Length of the attribute.
* Length of the attribute, value if af_flag set.
*/
u_int16_t length;
u_int16_t length_or_value;
/**
* Attribute value as chunk.
*/
chunk_t value;
/**
* Payload type, CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
*/
payload_type_t type;
};
/**
* 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 rules for a IKEv2 configuration attribute / IKEv1 data attribute
*/
encoding_rule_t configuration_attribute_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 reserved bit */
{ RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved)},
{ RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
/* Length of attribute value */
{ CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
{ ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length_or_value)},
/* Value of attribute if attribute format flag is zero */
{ CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
{ ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
};
/*
@ -85,87 +92,142 @@ encoding_rule_t configuration_attribute_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for a IKEv1 data attribute
*/
static encoding_rule_t encodings_v1[] = {
/* AF Flag */
{ ATTRIBUTE_FORMAT, offsetof(private_configuration_attribute_t, af_flag) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
/* Length of attribute value */
{ ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_configuration_attribute_t, length_or_value)},
/* Value of attribute if attribute format flag is zero */
{ ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!F| Attribute Type ! Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Value ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_configuration_attribute_t *this)
{
bool failed = FALSE;
if (this->length != this->value.len)
switch (this->attr_type)
{
DBG1(DBG_ENC, "invalid attribute length");
return FAILED;
}
switch (this->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:
if (this->length != 0 && this->length != 4)
case INTERNAL_IP4_ADDRESS:
case INTERNAL_IP4_NETMASK:
case INTERNAL_IP4_DNS:
case INTERNAL_IP4_NBNS:
case INTERNAL_ADDRESS_EXPIRY:
case INTERNAL_IP4_DHCP:
if (this->length_or_value != 0 && this->length_or_value != 4)
{
failed = TRUE;
}
break;
case INTERNAL_IP4_SUBNET:
if (this->length != 0 && this->length != 8)
case INTERNAL_IP4_SUBNET:
if (this->length_or_value != 0 && this->length_or_value != 8)
{
failed = TRUE;
}
break;
case INTERNAL_IP6_ADDRESS:
case INTERNAL_IP6_SUBNET:
if (this->length != 0 && this->length != 17)
case INTERNAL_IP6_ADDRESS:
case INTERNAL_IP6_SUBNET:
if (this->length_or_value != 0 && this->length_or_value != 17)
{
failed = TRUE;
}
break;
case INTERNAL_IP6_DNS:
case INTERNAL_IP6_NBNS:
case INTERNAL_IP6_DHCP:
if (this->length != 0 && this->length != 16)
case INTERNAL_IP6_DNS:
case INTERNAL_IP6_NBNS:
case INTERNAL_IP6_DHCP:
if (this->length_or_value != 0 && this->length_or_value != 16)
{
failed = TRUE;
}
break;
case SUPPORTED_ATTRIBUTES:
if (this->length % 2)
case SUPPORTED_ATTRIBUTES:
if (this->length_or_value % 2)
{
failed = TRUE;
}
break;
case APPLICATION_VERSION:
case APPLICATION_VERSION:
case INTERNAL_IP4_SERVER:
case INTERNAL_IP6_SERVER:
case XAUTH_TYPE:
case XAUTH_USER_NAME:
case XAUTH_USER_PASSWORD:
case XAUTH_PASSCODE:
case XAUTH_MESSAGE:
case XAUTH_CHALLENGE:
case XAUTH_DOMAIN:
case XAUTH_STATUS:
case XAUTH_NEXT_PIN:
case XAUTH_ANSWER:
case UNITY_BANNER:
case UNITY_SAVE_PASSWD:
case UNITY_DEF_DOMAIN:
case UNITY_SPLITDNS_NAME:
case UNITY_SPLIT_INCLUDE:
case UNITY_NATT_PORT:
case UNITY_LOCAL_LAN:
case UNITY_PFS:
case UNITY_FW_TYPE:
case UNITY_BACKUP_SERVERS:
case UNITY_DDNS_HOSTNAME:
/* any length acceptable */
break;
default:
default:
DBG1(DBG_ENC, "unknown attribute type %N",
configuration_attribute_type_names, this->type);
configuration_attribute_type_names, this->attr_type);
break;
}
if (failed)
{
DBG1(DBG_ENC, "invalid attribute length %d for %N",
this->length, configuration_attribute_type_names, this->type);
this->length_or_value, configuration_attribute_type_names,
this->attr_type);
return FAILED;
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_configuration_attribute_t *this, encoding_rule_t **rules,
size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_configuration_attribute_t *this, encoding_rule_t **rules)
{
*rules = configuration_attribute_encodings;
*rule_count = countof(configuration_attribute_encodings);
if (this->type == CONFIGURATION_ATTRIBUTE)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_configuration_attribute_t *this)
{
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_configuration_attribute_t *this)
{
return CONFIGURATION_ATTRIBUTE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -182,21 +244,35 @@ METHOD(payload_t, set_next_type, void,
METHOD(payload_t, get_length, size_t,
private_configuration_attribute_t *this)
{
return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
return get_header_length(this) + this->value.len;
}
METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
private_configuration_attribute_t *this)
{
return this->type;
return this->attr_type;
}
METHOD(configuration_attribute_t, get_value, chunk_t,
METHOD(configuration_attribute_t, get_chunk, chunk_t,
private_configuration_attribute_t *this)
{
if (this->af_flag)
{
return chunk_from_thing(this->length_or_value);
}
return this->value;
}
METHOD(configuration_attribute_t, get_value, u_int16_t,
private_configuration_attribute_t *this)
{
if (this->af_flag)
{
return this->length_or_value;
}
return 0;
}
METHOD2(payload_t, configuration_attribute_t, destroy, void,
private_configuration_attribute_t *this)
{
@ -207,7 +283,7 @@ METHOD2(payload_t, configuration_attribute_t, destroy, void,
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create()
configuration_attribute_t *configuration_attribute_create(payload_type_t type)
{
private_configuration_attribute_t *this;
@ -216,16 +292,19 @@ configuration_attribute_t *configuration_attribute_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.get_chunk = _get_chunk,
.get_value = _get_value,
.get_type = _get_cattr_type,
.destroy = _destroy,
},
.type = type
);
return &this->public;
}
@ -233,15 +312,33 @@ configuration_attribute_t *configuration_attribute_create()
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create_value(
configuration_attribute_type_t type, chunk_t value)
configuration_attribute_t *configuration_attribute_create_chunk(
payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk)
{
private_configuration_attribute_t *this;
this = (private_configuration_attribute_t*)configuration_attribute_create();
this->type = ((u_int16_t)type) & 0x7FFF;
this->value = chunk_clone(value);
this->length = value.len;
this = (private_configuration_attribute_t*)
configuration_attribute_create(type);
this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
this->value = chunk_clone(chunk);
this->length_or_value = chunk.len;
return &this->public;
}
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create_value(
configuration_attribute_type_t attr_type, u_int16_t value)
{
private_configuration_attribute_t *this;
this = (private_configuration_attribute_t*)
configuration_attribute_create(CONFIGURATION_ATTRIBUTE_V1);
this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
this->length_or_value = value;
this->af_flag = TRUE;
return &this->public;
}

View File

@ -29,14 +29,7 @@ typedef struct configuration_attribute_t configuration_attribute_t;
#include <encoding/payloads/payload.h>
/**
* Configuration attribute header length in bytes.
*/
#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
/**
* Class representing an IKEv2-CONFIGURATION Attribute.
*
* The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
* Class representing an IKEv2 configuration attribute / IKEv1 data attribute.
*/
struct configuration_attribute_t {
@ -53,11 +46,18 @@ struct configuration_attribute_t {
configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
/**
* Returns the value of the attribute.
* Returns the value of the attribute as chunk.
*
* @return chunk_t pointing to the internal value
*/
chunk_t (*get_value) (configuration_attribute_t *this);
chunk_t (*get_chunk) (configuration_attribute_t *this);
/**
* Returns the 2 byte value of the attribute as u_int16.
*
* @return attribute value
*/
u_int16_t (*get_value) (configuration_attribute_t *this);
/**
* Destroys an configuration_attribute_t object.
@ -68,18 +68,30 @@ struct configuration_attribute_t {
/**
* Creates an empty configuration attribute.
*
* @return created configuration attribute
* @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
* @return created configuration attribute
*/
configuration_attribute_t *configuration_attribute_create();
configuration_attribute_t *configuration_attribute_create(payload_type_t type);
/**
* Creates a configuration attribute with type and value.
*
* @param type type of configuration attribute
* @param value value, gets cloned
* @return created configuration attribute
* @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
* @param attr_type type of configuration attribute
* @param chunk attribute value, gets cloned
* @return created configuration attribute
*/
configuration_attribute_t *configuration_attribute_create_chunk(
payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk);
/**
* Creates a IKEv1 configuration attribute with 2 bytes value (IKEv1 only).
*
* @param attr_type type of configuration attribute
* @param value attribute value, gets cloned
* @return created CONFIGURATION_ATTRIBUTE_V1 configuration attribute
*/
configuration_attribute_t *configuration_attribute_create_value(
configuration_attribute_type_t type, chunk_t value);
configuration_attribute_type_t attr_type, u_int16_t value);
#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/

144
src/libcharon/encoding/payloads/cp_payload.c Normal file → Executable file
View File

@ -44,7 +44,7 @@ struct private_cp_payload_t {
/**
* Next payload type.
*/
u_int8_t next_payload;
u_int8_t next_payload;
/**
* Critical flag.
@ -66,6 +66,11 @@ struct private_cp_payload_t {
*/
u_int16_t payload_length;
/**
* Identifier field, IKEv1 only
*/
u_int16_t identifier;
/**
* List of attributes, as configuration_attribute_t
*/
@ -74,38 +79,40 @@ struct private_cp_payload_t {
/**
* Config Type.
*/
u_int8_t type;
u_int8_t cfg_type;
/**
* CONFIGURATION or CONFIGURATION_V1
*/
payload_type_t type;
};
/**
* 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 rules to for an IKEv2 configuration payload
*/
encoding_rule_t cp_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_cp_payload_t, critical) },
{ FLAG, offsetof(private_cp_payload_t, critical) },
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
/* 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, type) },
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
{ U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
/* 3 reserved bytes */
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
{ CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
/* list of configuration attributes in a list */
{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE,
offsetof(private_cp_payload_t, attributes) },
};
/*
@ -122,6 +129,47 @@ encoding_rule_t cp_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules to for an IKEv1 configuration payload
*/
static encoding_rule_t encodings_v1[] = {
/* 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 */
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
/* Length of the whole CP payload*/
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
{ U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
/* 1 reserved bytes */
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
{ U_INT_16, offsetof(private_cp_payload_t, identifier)},
/* list of configuration attributes in a list */
{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1,
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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! CFG Type ! RESERVED ! Identifier !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Configuration Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_cp_payload_t *this)
{
@ -142,17 +190,28 @@ METHOD(payload_t, verify, status_t,
return status;
}
METHOD(payload_t, get_encoding_rules, void,
private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_cp_payload_t *this, encoding_rule_t **rules)
{
*rules = cp_payload_encodings;
*rule_count = countof(cp_payload_encodings);
if (this->type == CONFIGURATION)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_cp_payload_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_cp_payload_t *this)
{
return CONFIGURATION;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -175,7 +234,7 @@ static void compute_length(private_cp_payload_t *this)
enumerator_t *enumerator;
payload_t *attribute;
this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
this->payload_length = get_header_length(this);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
@ -207,7 +266,18 @@ METHOD(cp_payload_t, add_attribute, void,
METHOD(cp_payload_t, get_config_type, config_type_t,
private_cp_payload_t *this)
{
return this->type;
return this->cfg_type;
}
METHOD(cp_payload_t, get_identifier, u_int16_t,
private_cp_payload_t *this)
{
return this->identifier;
}
METHOD(cp_payload_t, set_identifier, void,
private_cp_payload_t *this, u_int16_t identifier)
{
this->identifier = identifier;
}
METHOD2(payload_t, cp_payload_t, destroy, void,
@ -221,7 +291,7 @@ METHOD2(payload_t, cp_payload_t, destroy, void,
/*
* Described in header.
*/
cp_payload_t *cp_payload_create_type(config_type_t type)
cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type)
{
private_cp_payload_t *this;
@ -230,6 +300,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -239,11 +310,14 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
.create_attribute_enumerator = _create_attribute_enumerator,
.add_attribute = _add_attribute,
.get_type = _get_config_type,
.get_identifier = _get_identifier,
.set_identifier = _set_identifier,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = CP_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.attributes = linked_list_create(),
.cfg_type = cfg_type,
.type = type,
);
return &this->public;
@ -252,7 +326,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
/*
* Described in header.
*/
cp_payload_t *cp_payload_create()
cp_payload_t *cp_payload_create(payload_type_t type)
{
return cp_payload_create_type(CFG_REQUEST);
return cp_payload_create_type(type, CFG_REQUEST);
}

35
src/libcharon/encoding/payloads/cp_payload.h Normal file → Executable file
View File

@ -30,11 +30,6 @@ typedef struct cp_payload_t cp_payload_t;
#include <encoding/payloads/configuration_attribute.h>
#include <utils/enumerator.h>
/**
* CP_PAYLOAD length in bytes without any proposal substructure.
*/
#define CP_PAYLOAD_HEADER_LENGTH 8
/**
* Config Type of an Configuration Payload.
*/
@ -51,9 +46,7 @@ enum config_type_t {
extern enum_name_t *config_type_names;
/**
* Class representing an IKEv2-CP Payload.
*
* The CP Payload format is described in RFC section 3.15.
* Class representing an IKEv2 configuration / IKEv1 attribute payload.
*/
struct cp_payload_t {
@ -84,6 +77,20 @@ struct cp_payload_t {
*/
config_type_t (*get_type) (cp_payload_t *this);
/**
* Set the configuration payload identifier (IKEv1 only).
*
@param identifier identifier to set
*/
void (*set_identifier) (cp_payload_t *this, u_int16_t identifier);
/**
* Get the configuration payload identifier (IKEv1 only).
*
* @return identifier
*/
u_int16_t (*get_identifier) (cp_payload_t *this);
/**
* Destroys an cp_payload_t object.
*/
@ -93,16 +100,18 @@ struct cp_payload_t {
/**
* Creates an empty configuration payload
*
* @return empty configuration payload
* @param type payload type, CONFIGURATION or CONFIGURATION_V1
* @return empty configuration payload
*/
cp_payload_t *cp_payload_create();
cp_payload_t *cp_payload_create(payload_type_t type);
/**
* Creates an cp_payload_t with type and value
*
* @param config_type type of configuration payload to create
* @return created configuration payload
* @param type payload type, CONFIGURATION or CONFIGURATION_V1
* @param cfg_type type of configuration payload to create
* @return created configuration payload
*/
cp_payload_t *cp_payload_create_type(config_type_t config_type);
cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type);
#endif /** CP_PAYLOAD_H_ @}*/

View File

@ -24,9 +24,9 @@ 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.
*/
@ -45,13 +45,18 @@ struct private_delete_payload_t {
/**
* reserved bits
*/
bool reserved[7];
bool reserved[8];
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* IKEv1 Domain of Interpretation
*/
u_int32_t doi;
/**
* Protocol ID.
*/
@ -71,19 +76,21 @@ struct private_delete_payload_t {
* The contained SPI's.
*/
chunk_t spis;
/**
* Payload type, DELETE or DELETE_V1
*/
payload_type_t type;
};
/**
* 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 rules for an IKEv2 delete payload.
*/
encoding_rule_t delete_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_delete_payload_t, critical) },
{ FLAG, offsetof(private_delete_payload_t, critical) },
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
@ -98,7 +105,7 @@ encoding_rule_t delete_payload_encodings[] = {
{ 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) }
{ CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
};
/*
@ -115,6 +122,48 @@ encoding_rule_t delete_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for an IKEv1 delete payload.
*/
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* 8 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) },
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[7]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
/* Domain of interpretation */
{ U_INT_32, offsetof(private_delete_payload_t, doi) },
{ 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 */
{ CHUNK_DATA, 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 !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DOI !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! # of SPIs !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index(es) (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_delete_payload_t *this)
{
@ -129,10 +178,19 @@ METHOD(payload_t, verify, status_t,
break;
case PROTO_IKE:
case 0:
/* IKE deletion has no spi assigned! */
if (this->spi_size != 0)
{
return FAILED;
if (this->type == DELETE)
{ /* IKEv2 deletion has no spi assigned! */
if (this->spi_size != 0)
{
return FAILED;
}
}
else
{ /* IKEv1 uses the two concatenated ISAKMP cookies as SPI */
if (this->spi_size != 16)
{
return FAILED;
}
}
break;
default:
@ -145,17 +203,32 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_delete_payload_t *this, encoding_rule_t **rules)
{
*rules = delete_payload_encodings;
*rule_count = countof(delete_payload_encodings);
if (this->type == DELETE)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_delete_payload_t *this)
{
if (this->type == DELETE)
{
return 8;
}
return 12;
}
METHOD(payload_t, get_payload_type, payload_type_t,
private_delete_payload_t *this)
{
return DELETE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -198,6 +271,16 @@ METHOD(delete_payload_t, add_spi, void,
}
}
METHOD(delete_payload_t, set_ike_spi, void,
private_delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r)
{
free(this->spis.ptr);
this->spis = chunk_cat("cc", chunk_from_thing(spi_i),
chunk_from_thing(spi_r));
this->spi_count = 1;
this->payload_length = get_header_length(this) + this->spi_size;
}
/**
* SPI enumerator implementation
*/
@ -249,7 +332,8 @@ METHOD2(payload_t, delete_payload_t, destroy, void,
/*
* Described in header
*/
delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
delete_payload_t *delete_payload_create(payload_type_t type,
protocol_id_t protocol_id)
{
private_delete_payload_t *this;
@ -258,6 +342,7 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -266,13 +351,27 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
},
.get_protocol_id = _get_protocol_id,
.add_spi = _add_spi,
.set_ike_spi = _set_ike_spi,
.create_spi_enumerator = _create_spi_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = DELETE_PAYLOAD_HEADER_LENGTH,
.protocol_id = protocol_id,
.spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0,
.doi = IKEV1_DOI_IPSEC,
.type = type,
);
this->payload_length = get_header_length(this);
if (protocol_id == PROTO_IKE)
{
if (type == DELETE_V1)
{
this->spi_size = 16;
}
}
else
{
this->spi_size = 4;
}
return &this->public;
}

View File

@ -29,14 +29,7 @@ typedef struct delete_payload_t delete_payload_t;
#include <encoding/payloads/proposal_substructure.h>
/**
* Length of a delete payload without the SPI in bytes.
*/
#define DELETE_PAYLOAD_HEADER_LENGTH 8
/**
* Class representing an IKEv2 DELETE payload.
*
* The DELETE payload format is described in RFC section 3.11.
* Class representing an IKEv1 or a IKEv2 DELETE payload.
*/
struct delete_payload_t {
@ -59,6 +52,14 @@ struct delete_payload_t {
*/
void (*add_spi) (delete_payload_t *this, u_int32_t spi);
/**
* Set the IKE SPIs for an IKEv1 delete.
*
* @param spi_i initiator SPI
* @param spi_r responder SPI
*/
void (*set_ike_spi)(delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r);
/**
* Get an enumerator over the SPIs in network order.
*
@ -75,9 +76,11 @@ struct delete_payload_t {
/**
* Creates an empty delete_payload_t object.
*
* @param type DELETE or DELETE_V1
* @param protocol_id protocol, such as AH|ESP
* @return delete_payload_t object
*/
delete_payload_t *delete_payload_create(protocol_id_t protocol_id);
delete_payload_t *delete_payload_create(payload_type_t type,
protocol_id_t protocol_id);
#endif /** DELETE_PAYLOAD_H_ @}*/

View File

@ -19,6 +19,7 @@
#include "eap_payload.h"
#include <daemon.h>
#include <eap/eap.h>
typedef struct private_eap_payload_t private_eap_payload_t;
@ -65,7 +66,7 @@ struct private_eap_payload_t {
* private_eap_payload_t.
*
*/
static encoding_rule_t eap_payload_encodings[] = {
static encoding_rule_t 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 */
@ -81,7 +82,7 @@ static encoding_rule_t eap_payload_encodings[] = {
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
/* chunt to data, starting at "code" */
{ EAP_DATA, offsetof(private_eap_payload_t, data) },
{ CHUNK_DATA, offsetof(private_eap_payload_t, data) },
};
/*
@ -143,11 +144,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_eap_payload_t *this, encoding_rule_t **rules)
{
*rules = eap_payload_encodings;
*rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_eap_payload_t *this)
{
return 4;
}
METHOD(payload_t, get_payload_type, payload_type_t,
@ -251,6 +258,7 @@ eap_payload_t *eap_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -265,7 +273,7 @@ eap_payload_t *eap_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = EAP_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
);
return &this->public;
}

View File

@ -25,13 +25,8 @@
typedef struct eap_payload_t eap_payload_t;
#include <library.h>
#include <eap/eap.h>
#include <encoding/payloads/payload.h>
#include <sa/authenticators/eap/eap_method.h>
/**
* Length of a EAP payload without the EAP Message in bytes.
*/
#define EAP_PAYLOAD_HEADER_LENGTH 4
/**
* Class representing an IKEv2 EAP payload.

View File

@ -29,30 +29,14 @@ ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA,
"HEADER_LENGTH",
"SPI_SIZE",
"SPI",
"KEY_EXCHANGE_DATA",
"NOTIFICATION_DATA",
"PROPOSALS",
"TRANSFORMS",
"TRANSFORM_ATTRIBUTES",
"CONFIGURATION_ATTRIBUTES",
"CONFIGURATION_ATTRIBUTE_VALUE",
"ATTRIBUTE_FORMAT",
"ATTRIBUTE_TYPE",
"ATTRIBUTE_LENGTH_OR_VALUE",
"CONFIGURATION_ATTRIBUTE_LENGTH",
"ATTRIBUTE_LENGTH",
"ATTRIBUTE_VALUE",
"TRAFFIC_SELECTORS",
"TS_TYPE",
"ADDRESS",
"NONCE_DATA",
"ID_DATA",
"AUTH_DATA",
"CERT_DATA",
"CERTREQ_DATA",
"EAP_DATA",
"SPIS",
"VID_DATA",
"UNKNOWN_DATA",
"CHUNK_DATA",
"IKE_SPI",
"ENCRYPTED_DATA",
);

View File

@ -186,87 +186,6 @@ enum encoding_type_t {
*/
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.
*
@ -279,6 +198,7 @@ enum encoding_type_t {
* is moved 1 bit forward afterwards.
*/
ATTRIBUTE_FORMAT,
/**
* Representing a 15 Bit unsigned int value used as attribute type
* in an attribute transform.
@ -321,7 +241,7 @@ enum encoding_type_t {
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
CONFIGURATION_ATTRIBUTE_LENGTH,
ATTRIBUTE_LENGTH,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
@ -335,19 +255,6 @@ enum encoding_type_t {
*/
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.
*
@ -375,94 +282,9 @@ enum encoding_type_t {
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.
* Representing a variable length byte field.
*/
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_DATA,
/**
* 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,
CHUNK_DATA,
/**
* Representating an IKE_SPI field in an IKEv2 Header.
@ -475,9 +297,20 @@ enum encoding_type_t {
IKE_SPI,
/**
* Representing the encrypted data body of a encryption payload.
* Representating an encrypted IKEv1 message.
*/
ENCRYPTED_DATA,
/**
* Reprensenting a field containing a set of wrapped payloads.
*
* This type is not used directly, but as an offset to the wrapped payloads.
* The type of the wrapped payload is added to this encoding type.
*
* @note As payload types are added to this encoding type, it has
* to be the last in encoding_type_t.
*/
PAYLOAD_LIST = 1000 /* no comma, read above! */
};
/**

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -71,6 +72,11 @@ struct private_encryption_payload_t {
* Contained payloads
*/
linked_list_t *payloads;
/**
* Type of payload, ENCRYPTED or ENCRYPTED_V1
*/
payload_type_t type;
};
/**
@ -79,7 +85,7 @@ struct private_encryption_payload_t {
* The defined offsets are the positions in a object of type
* private_encryption_payload_t.
*/
encoding_rule_t encryption_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
/* Critical and 7 reserved bits, all stored for reconstruction */
@ -87,7 +93,7 @@ encoding_rule_t encryption_payload_encodings[] = {
/* 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) },
{ CHUNK_DATA, offsetof(private_encryption_payload_t, encrypted) },
};
/*
@ -109,24 +115,59 @@ encoding_rule_t encryption_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules to parse or generate a complete encrypted IKEv1 message.
*
* The defined offsets are the positions in a object of type
* private_encryption_payload_t.
*/
static encoding_rule_t encodings_v1[] = {
/* encrypted data, stored in a chunk */
{ 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Encrypted IKE Payloads !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ! Padding (0-255 octets) !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_encryption_payload_t *this)
{
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_encryption_payload_t *this, encoding_rule_t **rules,
size_t *count)
METHOD(payload_t, get_encoding_rules, int,
private_encryption_payload_t *this, encoding_rule_t **rules)
{
*rules = encryption_payload_encodings;
*count = countof(encryption_payload_encodings);
if (this->type == ENCRYPTED)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_encryption_payload_t *this)
{
if (this->type == ENCRYPTED)
{
return 4;
}
return 0;
}
METHOD(payload_t, get_type, payload_type_t,
private_encryption_payload_t *this)
{
return ENCRYPTED;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -138,7 +179,8 @@ METHOD(payload_t, get_next_type, payload_type_t,
METHOD(payload_t, set_next_type, void,
private_encryption_payload_t *this, payload_type_t type)
{
/* the next payload is set during add */
/* the next payload is set during add, still allow this for IKEv1 */
this->next_payload = type;
}
/**
@ -174,7 +216,7 @@ static void compute_length(private_encryption_payload_t *this)
length += this->aead->get_icv_size(this->aead);
}
}
length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
length += get_header_length(this);
this->payload_length = length;
}
@ -335,6 +377,47 @@ METHOD(encryption_payload_t, encrypt, bool,
return TRUE;
}
METHOD(encryption_payload_t, encrypt_v1, bool,
private_encryption_payload_t *this, chunk_t iv)
{
generator_t *generator;
chunk_t plain, padding;
size_t bs;
if (this->aead == NULL)
{
DBG1(DBG_ENC, "encryption failed, transform missing");
chunk_free(&iv);
return FALSE;
}
generator = generator_create();
plain = generate(this, generator);
bs = this->aead->get_block_size(this->aead);
padding.len = bs - (plain.len % bs);
/* prepare data to encrypt:
* | plain | padding | */
free(this->encrypted.ptr);
this->encrypted = chunk_alloc(plain.len + padding.len);
memcpy(this->encrypted.ptr, plain.ptr, plain.len);
plain.ptr = this->encrypted.ptr;
padding.ptr = plain.ptr + plain.len;
memset(padding.ptr, 0, padding.len);
generator->destroy(generator);
DBG3(DBG_ENC, "encrypting payloads:");
DBG3(DBG_ENC, "plain %B", &plain);
DBG3(DBG_ENC, "padding %B", &padding);
this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL);
chunk_free(&iv);
DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
return TRUE;
}
/**
* Parse the payloads after decryption.
*/
@ -349,6 +432,13 @@ static status_t parse(private_encryption_payload_t *this, chunk_t plain)
{
payload_t *payload;
if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
{
DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
payload_type_names, type);
parser->destroy(parser);
return PARSE_ERROR;
}
if (parser->parse_payload(parser, type, &payload) != SUCCESS)
{
parser->destroy(parser);
@ -438,6 +528,36 @@ METHOD(encryption_payload_t, decrypt, status_t,
return parse(this, plain);
}
METHOD(encryption_payload_t, decrypt_v1, status_t,
private_encryption_payload_t *this, chunk_t iv)
{
if (this->aead == NULL)
{
DBG1(DBG_ENC, "decryption failed, transform missing");
chunk_free(&iv);
return INVALID_STATE;
}
/* data must be a multiple of block size */
if (iv.len != this->aead->get_block_size(this->aead) ||
this->encrypted.len < iv.len || this->encrypted.len % iv.len)
{
DBG1(DBG_ENC, "decryption failed, invalid length");
chunk_free(&iv);
return FAILED;
}
DBG3(DBG_ENC, "decrypting payloads:");
DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL);
chunk_free(&iv);
DBG3(DBG_ENC, "plain %B", &this->encrypted);
return parse(this, this->encrypted);
}
METHOD(encryption_payload_t, set_transform, void,
private_encryption_payload_t *this, aead_t* aead)
{
@ -455,7 +575,7 @@ METHOD2(payload_t, encryption_payload_t, destroy, void,
/*
* Described in header
*/
encryption_payload_t *encryption_payload_create()
encryption_payload_t *encryption_payload_create(payload_type_t type)
{
private_encryption_payload_t *this;
@ -464,6 +584,7 @@ encryption_payload_t *encryption_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -479,9 +600,16 @@ encryption_payload_t *encryption_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.payloads = linked_list_create(),
.type = type,
);
if (type == ENCRYPTED_V1)
{
this->public.encrypt = _encrypt_v1;
this->public.decrypt = _decrypt_v1;
}
return &this->public;
}

View File

@ -29,11 +29,6 @@ typedef struct encryption_payload_t encryption_payload_t;
#include <crypto/aead.h>
#include <encoding/payloads/payload.h>
/**
* Encrpytion payload length in bytes without IV and following data.
*/
#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
/**
* The encryption payload as described in RFC section 3.14.
*/
@ -102,8 +97,9 @@ struct encryption_payload_t {
/**
* Creates an empty encryption_payload_t object.
*
* @param type ENCRYPTED or ENCRYPTED_V1
* @return encryption_payload_t object
*/
encryption_payload_t *encryption_payload_create(void);
encryption_payload_t *encryption_payload_create(payload_type_t type);
#endif /** ENCRYPTION_PAYLOAD_H_ @}*/

View File

@ -227,7 +227,7 @@ METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
chunk_t data;
notify_payload_t *notify;
notify = notify_payload_create();
notify = notify_payload_create(NOTIFY);
notify->set_notify_type(notify, ME_ENDPOINT);
data = build_notification_data(this);
notify->set_notification_data(notify, data);

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
* 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 "hash_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_hash_payload_t private_hash_payload_t;
/**
* Private data of an hash_payload_t object.
*/
struct private_hash_payload_t {
/**
* Public hash_payload_t interface.
*/
hash_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Reserved byte
*/
u_int8_t reserved;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained hash value.
*/
chunk_t hash;
/**
* either HASH_V1 or NAT_D_V1
*/
payload_type_t type;
};
/**
* Encoding rules for an IKEv1 hash payload
*/
static encoding_rule_t encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_hash_payload_t, next_payload) },
{ RESERVED_BYTE, offsetof(private_hash_payload_t, reserved) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_hash_payload_t, payload_length) },
/* Hash Data is from variable size */
{ CHUNK_DATA, offsetof(private_hash_payload_t, hash) },
};
/*
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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Hash Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_hash_payload_t *this)
{
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, int,
private_hash_payload_t *this, encoding_rule_t **rules)
{
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_hash_payload_t *this)
{
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_hash_payload_t *this)
{
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
private_hash_payload_t *this)
{
return this->next_payload;
}
METHOD(payload_t, set_next_type, void,
private_hash_payload_t *this, payload_type_t type)
{
this->next_payload = type;
}
METHOD(payload_t, get_length, size_t,
private_hash_payload_t *this)
{
return this->payload_length;
}
METHOD(hash_payload_t, set_hash, void,
private_hash_payload_t *this, chunk_t hash)
{
free(this->hash.ptr);
this->hash = chunk_clone(hash);
this->payload_length = get_header_length(this) + hash.len;
}
METHOD(hash_payload_t, get_hash, chunk_t,
private_hash_payload_t *this)
{
return this->hash;
}
METHOD2(payload_t, hash_payload_t, destroy, void,
private_hash_payload_t *this)
{
free(this->hash.ptr);
free(this);
}
/*
* Described in header
*/
hash_payload_t *hash_payload_create(payload_type_t type)
{
private_hash_payload_t *this;
INIT(this,
.public = {
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.set_hash = _set_hash,
.get_hash = _get_hash,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = get_header_length(this),
.type = type,
);
return &this->public;
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
* 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.
*/
/**
* @defgroup hash_payload hash_payload
* @{ @ingroup payloads
*/
#ifndef HASH_PAYLOAD_H_
#define HASH_PAYLOAD_H_
typedef struct hash_payload_t hash_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
/**
* Object representing an IKEv1 hash payload.
*/
struct hash_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* Set the hash value.
*
* @param hash chunk containing the hash, will be cloned
*/
void (*set_hash) (hash_payload_t *this, chunk_t hash);
/**
* Get the hash value.
*
* @return chunkt to internal hash data
*/
chunk_t (*get_hash) (hash_payload_t *this);
/**
* Destroys an hash_payload_t object.
*/
void (*destroy) (hash_payload_t *this);
};
/**
* Creates an empty hash_payload_t object.
*
* @param type either HASH_V1 or NAT_D_V1
* @return hash_payload_t object
*/
hash_payload_t *hash_payload_create(payload_type_t type);
#endif /** HASH_PAYLOAD_H_ @}*/

View File

@ -1,9 +1,8 @@
/*
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
*
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@ -28,19 +27,14 @@ 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;
/**
* one of ID_INITIATOR, ID_RESPONDER
*/
payload_type_t payload_type;
/**
* Next payload type.
*/
@ -75,19 +69,31 @@ struct private_id_payload_t {
* The contained id data value.
*/
chunk_t id_data;
/**
* Tunneled protocol ID for IKEv1 quick modes.
*/
u_int8_t protocol_id;
/**
* Tunneled port for IKEv1 quick modes.
*/
u_int16_t port;
/**
* one of ID_INITIATOR, ID_RESPONDER, IDv1 and NAT_OA_V1
*/
payload_type_t type;
};
/**
* 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 rules for an IKEv2 ID payload
*/
encoding_rule_t id_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_id_payload_t, critical) },
{ FLAG, offsetof(private_id_payload_t, critical) },
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
@ -97,7 +103,7 @@ encoding_rule_t id_payload_encodings[] = {
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) },
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
{ 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 */
@ -105,7 +111,7 @@ encoding_rule_t id_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])},
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
{ ID_DATA, offsetof(private_id_payload_t, id_data) }
{ CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
};
/*
@ -122,29 +128,92 @@ encoding_rule_t id_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for an IKEv1 ID payload
*/
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[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) },
{ U_INT_8, offsetof(private_id_payload_t, protocol_id) },
{ U_INT_16, offsetof(private_id_payload_t, port) },
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
{ CHUNK_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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ID Type ! Protocol ID ! Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Identification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_id_payload_t *this)
{
if (this->id_type == 0 || this->id_type == 4)
bool bad_length = FALSE;
if (this->type == NAT_OA_V1 &&
this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
{
/* reserved IDs */
DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
this->id_type, payload_type_short_names, this->type);
return FAILED;
}
switch (this->id_type)
{
case ID_IPV4_ADDR_RANGE:
case ID_IPV4_ADDR_SUBNET:
bad_length = this->id_data.len != 8;
break;
case ID_IPV6_ADDR_RANGE:
case ID_IPV6_ADDR_SUBNET:
bad_length = this->id_data.len != 32;
break;
}
if (bad_length)
{
DBG1(DBG_ENC, "invalid %N length (%d bytes)",
id_type_names, this->id_type, this->id_data.len);
return FAILED;
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_id_payload_t *this, encoding_rule_t **rules)
{
*rules = id_payload_encodings;
*rule_count = countof(id_payload_encodings);
if (this->type == ID_V1 || this->type == NAT_OA_V1)
{
*rules = encodings_v1;
return countof(encodings_v1);
}
*rules = encodings_v2;
return countof(encodings_v2);
}
METHOD(payload_t, get_header_length, int,
private_id_payload_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_id_payload_t *this)
{
return this->payload_type;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -171,6 +240,102 @@ METHOD(id_payload_t, get_identification, identification_t*,
return identification_create_from_encoding(this->id_type, this->id_data);
}
/**
* Create a traffic selector from an range ID
*/
static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
ts_type_t type)
{
return traffic_selector_create_from_bytes(this->protocol_id, type,
chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
}
/**
* Create a traffic selector from an subnet ID
*/
static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
ts_type_t type)
{
chunk_t net, netmask;
int i;
net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
netmask = chunk_skip(this->id_data, this->id_data.len / 2);
for (i = 0; i < net.len; i++)
{
netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
}
return traffic_selector_create_from_bytes(this->protocol_id, type,
net, this->port, netmask, this->port ?: 65535);
}
/**
* Create a traffic selector from an IP ID
*/
static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
ts_type_t type)
{
return traffic_selector_create_from_bytes(this->protocol_id, type,
this->id_data, this->port, this->id_data, this->port ?: 65535);
}
METHOD(id_payload_t, get_ts, traffic_selector_t*,
private_id_payload_t *this)
{
switch (this->id_type)
{
case ID_IPV4_ADDR_SUBNET:
if (this->id_data.len == 8)
{
return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
}
break;
case ID_IPV6_ADDR_SUBNET:
if (this->id_data.len == 32)
{
return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
}
break;
case ID_IPV4_ADDR_RANGE:
if (this->id_data.len == 8)
{
return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
}
break;
case ID_IPV6_ADDR_RANGE:
if (this->id_data.len == 32)
{
return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
}
break;
case ID_IPV4_ADDR:
if (this->id_data.len == 4)
{
return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
}
break;
case ID_IPV6_ADDR:
if (this->id_data.len == 16)
{
return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
}
break;
default:
break;
}
return NULL;
}
METHOD(id_payload_t, get_encoded, chunk_t,
private_id_payload_t *this)
{
u_int16_t port = htons(this->port);
return chunk_cat("cccc", chunk_from_thing(this->id_type),
chunk_from_thing(this->protocol_id),
chunk_from_thing(port), this->id_data);
}
METHOD2(payload_t, id_payload_t, destroy, void,
private_id_payload_t *this)
{
@ -181,7 +346,7 @@ METHOD2(payload_t, id_payload_t, destroy, void,
/*
* Described in header.
*/
id_payload_t *id_payload_create(payload_type_t payload_type)
id_payload_t *id_payload_create(payload_type_t type)
{
private_id_payload_t *this;
@ -190,6 +355,7 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -197,11 +363,13 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
.destroy = _destroy,
},
.get_identification = _get_identification,
.get_encoded = _get_encoded,
.get_ts = _get_ts,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = ID_PAYLOAD_HEADER_LENGTH,
.payload_type = payload_type,
.payload_length = get_header_length(this),
.type = type,
);
return &this->public;
}
@ -209,15 +377,89 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
/*
* Described in header.
*/
id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
id_payload_t *id_payload_create_from_identification(payload_type_t type,
identification_t *id)
{
private_id_payload_t *this;
this = (private_id_payload_t*)id_payload_create(payload_type);
this = (private_id_payload_t*)id_payload_create(type);
this->id_data = chunk_clone(id->get_encoding(id));
this->id_type = id->get_type(id);
this->payload_length += this->id_data.len;
return &this->public;
}
/*
* Described in header.
*/
id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
{
private_id_payload_t *this;
u_int8_t mask;
host_t *net;
this = (private_id_payload_t*)id_payload_create(ID_V1);
if (ts->is_host(ts, NULL))
{
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
{
this->id_type = ID_IPV4_ADDR;
}
else
{
this->id_type = ID_IPV6_ADDR;
}
this->id_data = chunk_clone(ts->get_from_address(ts));
}
else if (ts->to_subnet(ts, &net, &mask))
{
u_int8_t netmask[16], len, byte;
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
{
this->id_type = ID_IPV4_ADDR_SUBNET;
len = 4;
}
else
{
this->id_type = ID_IPV6_ADDR_SUBNET;
len = 16;
}
memset(netmask, 0, sizeof(netmask));
for (byte = 0; byte < sizeof(netmask); byte++)
{
if (mask < 8)
{
netmask[byte] = 0xFF << (8 - mask);
break;
}
netmask[byte] = 0xFF;
mask -= 8;
}
this->id_data = chunk_cat("cc", net->get_address(net),
chunk_create(netmask, len));
net->destroy(net);
}
else
{
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
{
this->id_type = ID_IPV4_ADDR_RANGE;
}
else
{
this->id_type = ID_IPV6_ADDR_RANGE;
}
this->id_data = chunk_cat("cc",
ts->get_from_address(ts), ts->get_to_address(ts));
net->destroy(net);
}
this->port = ts->get_from_port(ts);
this->protocol_id = ts->get_protocol(ts);
this->payload_length += this->id_data.len;
return &this->public;
}

View File

@ -28,16 +28,10 @@ typedef struct id_payload_t id_payload_t;
#include <library.h>
#include <utils/identification.h>
#include <encoding/payloads/payload.h>
#include <selectors/traffic_selector.h>
/**
* Length of a id payload without the data in bytes.
*/
#define ID_PAYLOAD_HEADER_LENGTH 8
/**
* Object representing an IKEv2 ID payload.
*
* The ID payload format is described in RFC section 3.5.
* Object representing an IKEv1 or an IKEv2 ID payload.
*/
struct id_payload_t {
@ -53,6 +47,20 @@ struct id_payload_t {
*/
identification_t *(*get_identification) (id_payload_t *this);
/**
* Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity.
*
* @return traffic selector, NULL on failure
*/
traffic_selector_t* (*get_ts)(id_payload_t *this);
/**
* Get encoded payload without fixed payload header (used for IKEv1).
*
* @return encoded payload (gets allocated)
*/
chunk_t (*get_encoded)(id_payload_t *this);
/**
* Destroys an id_payload_t object.
*/
@ -62,19 +70,27 @@ struct id_payload_t {
/**
* Creates an empty id_payload_t object.
*
* @param payload_type one of ID_INITIATOR, ID_RESPONDER
* @return id_payload_t object
* @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
* @return id_payload_t object
*/
id_payload_t *id_payload_create(payload_type_t payload_type);
id_payload_t *id_payload_create(payload_type_t type);
/**
* Creates an id_payload_t from an existing identification_t object.
*
* @param payload_type one of ID_INITIATOR, ID_RESPONDER
* @param identification identification_t object
* @return id_payload_t object
* @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
* @param id identification_t object
* @return id_payload_t object
*/
id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
identification_t *identification);
id_payload_t *id_payload_create_from_identification(payload_type_t type,
identification_t *id);
/**
* Create an IKEv1 ID_ADDR_SUBNET/RANGE identity from a traffic selector.
*
* @param ts traffic selector
* @return ID_V1 id_paylad_t object.
*/
id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts);
#endif /** ID_PAYLOAD_H_ @}*/

View File

@ -81,12 +81,27 @@ struct private_ike_header_t {
* TRUE, if this is a response, FALSE if its a Request.
*/
bool response;
/**
* TRUE, if the packet is encrypted (IKEv1).
*/
bool encryption;
/**
* TRUE, if the commit flag is set (IKEv1).
*/
bool commit;
/**
* TRUE, if the auth only flag is set (IKEv1).
*/
bool authonly;
} flags;
/**
* Reserved bits of IKE header
*/
bool reserved[5];
bool reserved[2];
/**
* Associated Message-ID.
@ -99,9 +114,15 @@ struct private_ike_header_t {
u_int32_t length;
};
ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
"EXCHANGE_TYPE_UNDEFINED");
ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UNDEFINED,
ENUM_BEGIN(exchange_type_names, ID_PROT, TRANSACTION,
"ID_PROT",
"AUTH_ONLY",
"AGGRESSIVE",
"INFORMATIONAL_V1",
"TRANSACTION");
ENUM_NEXT(exchange_type_names, QUICK_MODE, IKE_SESSION_RESUME, TRANSACTION,
"QUICK_MODE",
"NEW_GROUP_MODE",
"IKE_SA_INIT",
"IKE_AUTH",
"CREATE_CHILD_SA",
@ -110,18 +131,23 @@ ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UN
#ifdef ME
ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, IKE_SESSION_RESUME,
"ME_CONNECT");
ENUM_END(exchange_type_names, ME_CONNECT);
ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
EXCHANGE_TYPE_UNDEFINED, ME_CONNECT,
"EXCHANGE_TYPE_UNDEFINED");
#else
ENUM_END(exchange_type_names, IKE_SESSION_RESUME);
ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
EXCHANGE_TYPE_UNDEFINED, IKE_SESSION_RESUME,
"EXCHANGE_TYPE_UNDEFINED");
#endif /* ME */
ENUM_END(exchange_type_names, EXCHANGE_TYPE_UNDEFINED);
/**
* Encoding rules to parse or generate a IKEv2-Header.
* Encoding rules to parse or generate a IKE-Header.
*
* The defined offsets are the positions in a object of type
* ike_header_t.
*/
encoding_rule_t ike_header_encodings[] = {
static encoding_rule_t 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 */
@ -137,22 +163,20 @@ encoding_rule_t ike_header_encodings[] = {
/* 2 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[1]) },
/* 3 Bit flags, stored in the fields response, version and initiator */
/* 6 flags */
{ 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 */
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[4]) },
{ FLAG, offsetof(private_ike_header_t, flags.authonly) },
{ FLAG, offsetof(private_ike_header_t, flags.commit) },
{ FLAG, offsetof(private_ike_header_t, flags.encryption)},
/* 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) },
{ HEADER_LENGTH, offsetof(private_ike_header_t, length) }
};
/* 1 2 3
/* 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 !
@ -172,35 +196,67 @@ encoding_rule_t ike_header_encodings[] = {
METHOD(payload_t, verify, status_t,
private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) ||
((this->exchange_type > INFORMATIONAL)
#ifdef ME
&& (this->exchange_type != ME_CONNECT)
#endif /* ME */
))
switch (this->exchange_type)
{
/* unsupported exchange type */
return FAILED;
case ID_PROT:
case AGGRESSIVE:
if (this->message_id != 0)
{
return FAILED;
}
/* fall */
case AUTH_ONLY:
case INFORMATIONAL_V1:
case TRANSACTION:
case QUICK_MODE:
case NEW_GROUP_MODE:
if (this->maj_version != IKEV1_MAJOR_VERSION)
{
return FAILED;
}
break;
case IKE_SA_INIT:
case IKE_AUTH:
case CREATE_CHILD_SA:
case INFORMATIONAL:
case IKE_SESSION_RESUME:
#ifdef ME
case ME_CONNECT:
#endif /* ME */
if (this->maj_version != IKEV2_MAJOR_VERSION)
{
return FAILED;
}
break;
default:
/* unsupported exchange type */
return FAILED;
}
if (this->initiator_spi == 0
#ifdef ME
/* we allow zero spi for INFORMATIONAL exchanges,
* to allow connectivity checks */
&& this->exchange_type != INFORMATIONAL
#endif /* ME */
)
if (this->initiator_spi == 0)
{
/* initiator spi not set */
return FAILED;
#ifdef ME
if (this->exchange_type != INFORMATIONAL)
/* we allow zero spi for INFORMATIONAL exchanges,
* to allow connectivity checks */
#endif /* ME */
{
return FAILED;
}
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_ike_header_t *this, encoding_rule_t **rules)
{
*rules = ike_header_encodings;
*rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_ike_header_t *this)
{
return IKE_HEADER_LENGTH;
}
METHOD(payload_t, get_type, payload_type_t,
@ -311,6 +367,43 @@ METHOD(ike_header_t, set_initiator_flag, void,
this->flags.initiator = initiator;
}
METHOD(ike_header_t, get_encryption_flag, bool,
private_ike_header_t *this)
{
return this->flags.encryption;
}
METHOD(ike_header_t, set_encryption_flag, void,
private_ike_header_t *this, bool encryption)
{
this->flags.encryption = encryption;
}
METHOD(ike_header_t, get_commit_flag, bool,
private_ike_header_t *this)
{
return this->flags.commit;
}
METHOD(ike_header_t, set_commit_flag, void,
private_ike_header_t *this, bool commit)
{
this->flags.commit = commit;
}
METHOD(ike_header_t, get_authonly_flag, bool,
private_ike_header_t *this)
{
return this->flags.authonly;
}
METHOD(ike_header_t, set_authonly_flag, void,
private_ike_header_t *this, bool authonly)
{
this->flags.authonly = authonly;
}
METHOD(ike_header_t, get_exchange_type, u_int8_t,
private_ike_header_t *this)
{
@ -353,6 +446,7 @@ ike_header_t *ike_header_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -373,21 +467,38 @@ ike_header_t *ike_header_create()
.set_version_flag = _set_version_flag,
.get_initiator_flag = _get_initiator_flag,
.set_initiator_flag = _set_initiator_flag,
.get_encryption_flag = _get_encryption_flag,
.set_encryption_flag = _set_encryption_flag,
.get_commit_flag = _get_commit_flag,
.set_commit_flag = _set_commit_flag,
.get_authonly_flag = _get_authonly_flag,
.set_authonly_flag = _set_authonly_flag,
.get_exchange_type = _get_exchange_type,
.set_exchange_type = _set_exchange_type,
.get_message_id = _get_message_id,
.set_message_id = _set_message_id,
.destroy = _destroy,
},
.maj_version = IKE_MAJOR_VERSION,
.min_version = IKE_MINOR_VERSION,
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
.flags = {
.initiator = TRUE,
.version = HIGHER_VERSION_SUPPORTED_FLAG,
},
.length = IKE_HEADER_LENGTH,
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
);
return &this->public;
}
/*
* Described in header.
*/
ike_header_t *ike_header_create_version(int major, int minor)
{
ike_header_t *this = ike_header_create();
this->set_maj_version(this, major);
this->set_min_version(this, minor);
if (major == IKEV2_MAJOR_VERSION)
{
this->set_initiator_flag(this, TRUE);
}
return this;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -30,19 +30,24 @@ typedef struct ike_header_t ike_header_t;
#include <encoding/payloads/payload.h>
/**
* Major Version of IKEv2.
* Major Version of IKEv1 we implement.
*/
#define IKE_MAJOR_VERSION 2
#define IKEV1_MAJOR_VERSION 1
/**
* Minor Version of IKEv2.
* Minor Version of IKEv1 we implement.
*/
#define IKE_MINOR_VERSION 0
#define IKEV1_MINOR_VERSION 0
/**
* Flag in IKEv2-Header. Always 0.
* Major Version of IKEv2 we implement.
*/
#define HIGHER_VERSION_SUPPORTED_FLAG 0
#define IKEV2_MAJOR_VERSION 2
/**
* Minor Version of IKEv2 we implement.
*/
#define IKEV2_MINOR_VERSION 0
/**
* Length of IKE Header in Bytes.
@ -57,9 +62,39 @@ typedef struct ike_header_t ike_header_t;
enum exchange_type_t{
/**
* EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
* Identity Protection (Main mode).
*/
EXCHANGE_TYPE_UNDEFINED = 255,
ID_PROT = 2,
/**
* Authentication Only.
*/
AUTH_ONLY = 3,
/**
* Aggresive (Aggressive mode)
*/
AGGRESSIVE = 4,
/**
* Informational in IKEv1
*/
INFORMATIONAL_V1 = 5,
/**
* Transaction (ISAKMP Cfg Mode "draft-ietf-ipsec-isakmp-mode-cfg-05")
*/
TRANSACTION = 6,
/**
* Quick Mode
*/
QUICK_MODE = 32,
/**
* New Group Mode
*/
NEW_GROUP_MODE = 33,
/**
* IKE_SA_INIT.
@ -77,7 +112,7 @@ enum exchange_type_t{
CREATE_CHILD_SA = 36,
/**
* INFORMATIONAL.
* INFORMATIONAL in IKEv2.
*/
INFORMATIONAL = 37,
@ -85,12 +120,18 @@ enum exchange_type_t{
* IKE_SESSION_RESUME (RFC 5723).
*/
IKE_SESSION_RESUME = 38,
#ifdef ME
/**
* ME_CONNECT
*/
ME_CONNECT = 240
ME_CONNECT = 240,
#endif /* ME */
/**
* Undefined exchange type, in private space.
*/
EXCHANGE_TYPE_UNDEFINED = 255,
};
/**
@ -99,12 +140,7 @@ enum exchange_type_t{
extern enum_name_t *exchange_type_names;
/**
* 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.
* An object of this type represents an IKE header of either IKEv1 or IKEv2.
*/
struct ike_header_t {
/**
@ -115,7 +151,7 @@ struct ike_header_t {
/**
* Get the initiator spi.
*
* @return initiator_spi
* @return initiator_spi
*/
u_int64_t (*get_initiator_spi) (ike_header_t *this);
@ -129,7 +165,7 @@ struct ike_header_t {
/**
* Get the responder spi.
*
* @return responder_spi
* @return responder_spi
*/
u_int64_t (*get_responder_spi) (ike_header_t *this);
@ -143,7 +179,7 @@ struct ike_header_t {
/**
* Get the major version.
*
* @return major version
* @return major version
*/
u_int8_t (*get_maj_version) (ike_header_t *this);
@ -157,7 +193,7 @@ struct ike_header_t {
/**
* Get the minor version.
*
* @return minor version
* @return minor version
*/
u_int8_t (*get_min_version) (ike_header_t *this);
@ -171,7 +207,7 @@ struct ike_header_t {
/**
* Get the response flag.
*
* @return response flag
* @return response flag
*/
bool (*get_response_flag) (ike_header_t *this);
@ -185,7 +221,7 @@ struct ike_header_t {
/**
* Get "higher version supported"-flag.
*
* @return version flag
* @return version flag
*/
bool (*get_version_flag) (ike_header_t *this);
@ -199,7 +235,7 @@ struct ike_header_t {
/**
* Get the initiator flag.
*
* @return initiator flag
* @return initiator flag
*/
bool (*get_initiator_flag) (ike_header_t *this);
@ -210,10 +246,52 @@ struct ike_header_t {
*/
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
/**
* Get the encryption flag.
*
* @return encryption flag
*/
bool (*get_encryption_flag) (ike_header_t *this);
/**
* Set the encryption flag.
*
* @param encryption encryption flag
*/
void (*set_encryption_flag) (ike_header_t *this, bool encryption);
/**
* Get the commit flag.
*
* @return commit flag
*/
bool (*get_commit_flag) (ike_header_t *this);
/**
* Set the commit flag.
*
* @param commit commit flag
*/
void (*set_commit_flag) (ike_header_t *this, bool commit);
/**
* Get the authentication only flag.
*
* @return authonly flag
*/
bool (*get_authonly_flag) (ike_header_t *this);
/**
* Set the authentication only flag.
*
* @param authonly authonly flag
*/
void (*set_authonly_flag) (ike_header_t *this, bool authonly);
/**
* Get the exchange type.
*
* @return exchange type
* @return exchange type
*/
u_int8_t (*get_exchange_type) (ike_header_t *this);
@ -227,7 +305,7 @@ struct ike_header_t {
/**
* Get the message id.
*
* @return message id
* @return message id
*/
u_int32_t (*get_message_id) (ike_header_t *this);
@ -245,10 +323,17 @@ struct ike_header_t {
};
/**
* Create an ike_header_t object
* Create an empty ike_header_t object.
*
* @return ike_header_t object
*/
ike_header_t *ike_header_create(void);
/**
* Create an ike_header_t object for a specific major/minor version
*
* @return ike_header_t object
*/
ike_header_t *ike_header_create_version(int major, int minor);
#endif /** IKE_HEADER_H_ @}*/

View File

@ -67,15 +67,17 @@ struct private_ke_payload_t {
* Key Exchange Data of this KE payload.
*/
chunk_t key_exchange_data;
/**
* Payload type, KEY_EXCHANGE or KEY_EXCHANGE_V1
*/
payload_type_t type;
};
/**
* 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 rules for IKEv2 key exchange payload.
*/
encoding_rule_t ke_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
@ -96,7 +98,7 @@ encoding_rule_t ke_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])},
/* Key Exchange Data is from variable size */
{ KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
{ CHUNK_DATA, offsetof(private_ke_payload_t, key_exchange_data)},
};
/*
@ -113,23 +115,62 @@ encoding_rule_t ke_payload_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* Reserved Byte */
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
/* Key Exchange Data is from variable size */
{ CHUNK_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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Key Exchange Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_ke_payload_t *this)
{
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_ke_payload_t *this, encoding_rule_t **rules)
{
*rules = ke_payload_encodings;
*rule_count = countof(ke_payload_encodings);
if (this->type == KEY_EXCHANGE)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_ke_payload_t *this)
{
if (this->type == KEY_EXCHANGE)
{
return 8;
}
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_ke_payload_t *this)
{
return KEY_EXCHANGE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -172,7 +213,7 @@ METHOD2(payload_t, ke_payload_t, destroy, void,
/*
* Described in header
*/
ke_payload_t *ke_payload_create()
ke_payload_t *ke_payload_create(payload_type_t type)
{
private_ke_payload_t *this;
@ -181,6 +222,7 @@ ke_payload_t *ke_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -192,22 +234,24 @@ ke_payload_t *ke_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = KE_PAYLOAD_HEADER_LENGTH,
.dh_group_number = MODP_NONE,
.type = type,
);
this->payload_length = get_header_length(this);
return &this->public;
}
/*
* Described in header
*/
ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
diffie_hellman_t *dh)
{
private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type);
dh->get_my_public_value(dh, &this->key_exchange_data);
this->dh_group_number = dh->get_dh_group(dh);
this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH;
this->payload_length += this->key_exchange_data.len;
return &this->public;
}

View File

@ -31,16 +31,10 @@ typedef struct ke_payload_t ke_payload_t;
#include <crypto/diffie_hellman.h>
/**
* KE payload length in bytes without any key exchange data.
*/
#define KE_PAYLOAD_HEADER_LENGTH 8
/**
* Class representing an IKEv2-KE Payload.
*
* The KE Payload format is described in RFC section 3.4.
* Class representing an IKEv1 or IKEv2 key exchange payload.
*/
struct ke_payload_t {
/**
* The payload_t interface.
*/
@ -54,32 +48,34 @@ struct ke_payload_t {
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
* Gets the Diffie-Hellman Group Number of this KE payload.
* Gets the Diffie-Hellman Group Number of this KE payload (IKEv2 only).
*
* @return DH Group Number of this payload
*/
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
* Destroys an ke_payload_t object.
* Destroys a ke_payload_t object.
*/
void (*destroy) (ke_payload_t *this);
};
/**
* Creates an empty ke_payload_t object
* Creates an empty ke_payload_t object.
*
* @return ke_payload_t object
* @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
* @return ke_payload_t object
*/
ke_payload_t *ke_payload_create(void);
ke_payload_t *ke_payload_create(payload_type_t type);
/**
* Creates a ke_payload_t from a diffie_hellman_t
* Creates a ke_payload_t from a diffie_hellman_t.
*
* @param diffie_hellman diffie hellman object containing group and key
* @return ke_payload_t object
* @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
* @param dh diffie hellman object containing group and key
* @return ke_payload_t object
*/
ke_payload_t *ke_payload_create_from_diffie_hellman(
diffie_hellman_t *diffie_hellman);
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
diffie_hellman_t *dh);
#endif /** KE_PAYLOAD_H_ @}*/

View File

@ -19,6 +19,7 @@
#include "nonce_payload.h"
#include <daemon.h>
#include <encoding/payloads/encodings.h>
typedef struct private_nonce_payload_t private_nonce_payload_t;
@ -57,6 +58,11 @@ struct private_nonce_payload_t {
* The contained nonce value.
*/
chunk_t nonce;
/**
* Payload type, NONCE or NONCE_V1
*/
payload_type_t type;
};
/**
@ -65,7 +71,7 @@ struct private_nonce_payload_t {
* The defined offsets are the positions in a object of type
* private_nonce_payload_t.
*/
encoding_rule_t nonce_payload_encodings[] = {
static encoding_rule_t 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 */
@ -81,7 +87,7 @@ encoding_rule_t nonce_payload_encodings[] = {
/* 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) },
{ CHUNK_DATA, offsetof(private_nonce_payload_t, nonce) },
};
/* 1 2 3
@ -98,24 +104,48 @@ encoding_rule_t nonce_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_nonce_payload_t *this)
{
if (this->nonce.len < 16 || this->nonce.len > 256)
bool bad_length = FALSE;
if (this->nonce.len > 256)
{
bad_length = TRUE;
}
if (this->type == NONCE &&
this->nonce.len < 16)
{
bad_length = TRUE;
}
if (this->type == NONCE_V1 &&
this->nonce.len < 8)
{
bad_length = TRUE;
}
if (bad_length)
{
DBG1(DBG_ENC, "%N payload has invalid length (%d bytes)",
payload_type_names, this->type, this->nonce.len);
return FAILED;
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_nonce_payload_t *this, encoding_rule_t **rules)
{
*rules = nonce_payload_encodings;
*rule_count = countof(nonce_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_nonce_payload_t *this)
{
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_nonce_payload_t *this)
{
return NONCE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -140,7 +170,7 @@ METHOD(nonce_payload_t, set_nonce, void,
private_nonce_payload_t *this, chunk_t nonce)
{
this->nonce = chunk_clone(nonce);
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
this->payload_length = get_header_length(this) + nonce.len;
}
METHOD(nonce_payload_t, get_nonce, chunk_t,
@ -159,7 +189,7 @@ METHOD2(payload_t, nonce_payload_t, destroy, void,
/*
* Described in header
*/
nonce_payload_t *nonce_payload_create()
nonce_payload_t *nonce_payload_create(payload_type_t type)
{
private_nonce_payload_t *this;
@ -168,6 +198,7 @@ nonce_payload_t *nonce_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -179,7 +210,8 @@ nonce_payload_t *nonce_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = NONCE_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.type = type,
);
return &this->public;
}

View File

@ -33,14 +33,7 @@ typedef struct nonce_payload_t nonce_payload_t;
#define NONCE_SIZE 32
/**
* Length of a nonce payload without a nonce in bytes.
*/
#define NONCE_PAYLOAD_HEADER_LENGTH 4
/**
* Object representing an IKEv2 Nonce payload.
*
* The Nonce payload format is described in RFC section 3.3.
* Object representing an IKEv1/IKEv2 Nonce payload.
*/
struct nonce_payload_t {
/**
@ -71,8 +64,9 @@ struct nonce_payload_t {
/**
* Creates an empty nonce_payload_t object
*
* @return nonce_payload_t object
* @param type NONCE or NONCE_V1
* @return nonce_payload_t object
*/
nonce_payload_t *nonce_payload_create(void);
nonce_payload_t *nonce_payload_create(payload_type_t type);
#endif /** NONCE_PAYLOAD_H_ @}*/

284
src/libcharon/encoding/payloads/notify_payload.c Normal file → Executable file
View File

@ -36,11 +36,18 @@ ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYN
"INVALID_MESSAGE_ID");
ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
"INVALID_SPI");
ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
ENUM_NEXT(notify_type_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
"ATTRIBUTES_NOT_SUPPORTED",
"NO_PROPOSAL_CHOSEN");
ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
"INVALID_KE_PAYLOAD");
ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
ENUM_NEXT(notify_type_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
"PAYLOAD_MALFORMED",
"INVALID_KE_PAYLOAD",
"INVALID_ID_INFORMATION",
"INVALID_CERT_ENCODING",
"INVALID_CERTIFICATE",
"CERT_TYPE_UNSUPPORTED",
"INVALID_CERT_AUTHORITY",
"INVALID_HASH_INFORMATION",
"AUTHENTICATION_FAILED");
ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
"SINGLE_PAIR_REQUIRED",
@ -99,7 +106,14 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTI
"IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
"IKEV2_MESSAGE_ID_SYNC",
"IPSEC_REPLAY_COUNTER_SYNC");
ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC,
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
"DPD_R_U_THERE_ACK");
ENUM_NEXT(notify_type_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
"UNITY_LOAD_BALANCE");
ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
"USE_BEET_MODE");
ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
"ME_MEDIATION",
@ -124,11 +138,18 @@ ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVAL
"INVAL_MID");
ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
"INVAL_SPI");
ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
ENUM_NEXT(notify_type_short_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
"ATTR_UNSUP",
"NO_PROP");
ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
"INVAL_KE");
ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
ENUM_NEXT(notify_type_short_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
"PLD_MAL",
"INVAL_KE",
"INVAL_ID",
"INVAL_CERTEN",
"INVAL_CERT",
"CERT_UNSUP",
"INVAL_CA",
"INVAL_HASH",
"AUTH_FAILED");
ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
"SINGLE_PAIR",
@ -187,7 +208,14 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, M
"RPL_CTR_SYN_SUP",
"MSG_ID_SYN",
"RPL_CTR_SYN");
ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC,
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
"DPD_ACK");
ENUM_NEXT(notify_type_short_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
"UNITY_LB");
ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
"BEET_MODE");
ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
"ME_MED",
@ -226,13 +254,18 @@ struct private_notify_payload_t {
/**
* reserved bits
*/
bool reserved[7];
bool reserved[8];
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Domain of interpretation, IKEv1 only.
*/
u_int32_t doi;
/**
* Protocol id.
*/
@ -256,40 +289,42 @@ struct private_notify_payload_t {
/**
* Notification data.
*/
chunk_t notification_data;
chunk_t notify_data;
/**
* Type of payload, NOTIFY or NOTIFY_V1
*/
payload_type_t type;
};
/**
* 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 rules for an IKEv2 notification payload
*/
encoding_rule_t notify_payload_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_notify_payload_t, critical) },
{ FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
{ 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) },
{ 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) },
{ 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_type) },
{ U_INT_16, offsetof(private_notify_payload_t, notify_type) },
/* SPI as variable length field*/
{ SPI, offsetof(private_notify_payload_t, spi) },
{ SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
{ NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) }
{ CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
};
/*
@ -309,6 +344,57 @@ encoding_rule_t notify_payload_encodings[] = {
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for an IKEv1 notification payload
*/
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* 8 reserved bits */
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[7]) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
/* DOI as 32 bit field*/
{ U_INT_32, offsetof(private_notify_payload_t, doi) },
/* 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_type) },
/* SPI as variable length field*/
{ SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
{ CHUNK_DATA, offsetof(private_notify_payload_t, notify_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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DOI !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! Notify Message Type !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Notification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_notify_payload_t *this)
@ -331,7 +417,7 @@ METHOD(payload_t, verify, status_t,
{
case INVALID_KE_PAYLOAD:
{
if (this->notification_data.len != 2)
if (this->type == NOTIFY && this->notify_data.len != 2)
{
bad_length = TRUE;
}
@ -341,7 +427,7 @@ METHOD(payload_t, verify, status_t,
case NAT_DETECTION_DESTINATION_IP:
case ME_CONNECTAUTH:
{
if (this->notification_data.len != HASH_SIZE_SHA1)
if (this->notify_data.len != HASH_SIZE_SHA1)
{
bad_length = TRUE;
}
@ -351,7 +437,7 @@ METHOD(payload_t, verify, status_t,
case INVALID_MAJOR_VERSION:
case NO_PROPOSAL_CHOSEN:
{
if (this->notification_data.len != 0)
if (this->type == NOTIFY && this->notify_data.len != 0)
{
bad_length = TRUE;
}
@ -359,7 +445,7 @@ METHOD(payload_t, verify, status_t,
}
case ADDITIONAL_IP4_ADDRESS:
{
if (this->notification_data.len != 4)
if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@ -367,7 +453,7 @@ METHOD(payload_t, verify, status_t,
}
case ADDITIONAL_IP6_ADDRESS:
{
if (this->notification_data.len != 16)
if (this->notify_data.len != 16)
{
bad_length = TRUE;
}
@ -375,7 +461,7 @@ METHOD(payload_t, verify, status_t,
}
case AUTH_LIFETIME:
{
if (this->notification_data.len != 4)
if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@ -383,30 +469,37 @@ METHOD(payload_t, verify, status_t,
}
case IPCOMP_SUPPORTED:
{
if (this->notification_data.len != 3)
if (this->notify_data.len != 3)
{
bad_length = TRUE;
}
break;
}
case ME_ENDPOINT:
if (this->notification_data.len != 8 &&
this->notification_data.len != 12 &&
this->notification_data.len != 24)
if (this->notify_data.len != 8 &&
this->notify_data.len != 12 &&
this->notify_data.len != 24)
{
bad_length = TRUE;
}
break;
case ME_CONNECTID:
if (this->notification_data.len < 4 ||
this->notification_data.len > 16)
if (this->notify_data.len < 4 ||
this->notify_data.len > 16)
{
bad_length = TRUE;
}
break;
case ME_CONNECTKEY:
if (this->notification_data.len < 16 ||
this->notification_data.len > 32)
if (this->notify_data.len < 16 ||
this->notify_data.len > 32)
{
bad_length = TRUE;
}
break;
case DPD_R_U_THERE:
case DPD_R_U_THERE_ACK:
if (this->notify_data.len != 4)
{
bad_length = TRUE;
}
@ -419,23 +512,38 @@ METHOD(payload_t, verify, status_t,
{
DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
notify_type_names, this->notify_type,
this->notification_data.len);
this->notify_data.len);
return FAILED;
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_notify_payload_t *this, encoding_rule_t **rules)
{
*rules = notify_payload_encodings;
*rule_count = countof(notify_payload_encodings);
if (this->type == NOTIFY)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_notify_payload_t *this)
{
if (this->type == NOTIFY)
{
return 8 + this->spi_size;
}
return 12 + this->spi_size;
}
METHOD(payload_t, get_type, payload_type_t,
private_notify_payload_t *this)
{
return NOTIFY;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -453,19 +561,9 @@ METHOD(payload_t, set_next_type, void,
/**
* recompute the payloads length.
*/
static void compute_length (private_notify_payload_t *this)
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;
this->payload_length = get_header_length(this) + this->notify_data.len;
}
METHOD(payload_t, get_length, size_t,
@ -533,24 +631,55 @@ METHOD(notify_payload_t, set_spi, void,
compute_length(this);
}
METHOD(notify_payload_t, get_spi_data, chunk_t,
private_notify_payload_t *this)
{
switch (this->protocol_id)
{
case PROTO_IKE:
if (this->spi.len == 16)
{
return this->spi;
}
default:
break;
}
return chunk_empty;
}
METHOD(notify_payload_t, set_spi_data, void,
private_notify_payload_t *this, chunk_t spi)
{
chunk_free(&this->spi);
switch (this->protocol_id)
{
case PROTO_IKE:
this->spi = chunk_clone(spi);
default:
break;
}
this->spi_size = this->spi.len;
compute_length(this);
}
METHOD(notify_payload_t, get_notification_data, chunk_t,
private_notify_payload_t *this)
{
return this->notification_data;
return this->notify_data;
}
METHOD(notify_payload_t, set_notification_data, void,
private_notify_payload_t *this, chunk_t data)
{
free(this->notification_data.ptr);
this->notification_data = chunk_clone(data);
free(this->notify_data.ptr);
this->notify_data = chunk_clone(data);
compute_length(this);
}
METHOD2(payload_t, notify_payload_t, destroy, void,
private_notify_payload_t *this)
{
free(this->notification_data.ptr);
free(this->notify_data.ptr);
free(this->spi.ptr);
free(this);
}
@ -558,7 +687,7 @@ METHOD2(payload_t, notify_payload_t, destroy, void,
/*
* Described in header
*/
notify_payload_t *notify_payload_create()
notify_payload_t *notify_payload_create(payload_type_t type)
{
private_notify_payload_t *this;
@ -567,6 +696,7 @@ notify_payload_t *notify_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -579,13 +709,17 @@ notify_payload_t *notify_payload_create()
.set_notify_type = _set_notify_type,
.get_spi = _get_spi,
.set_spi = _set_spi,
.get_spi_data = _get_spi_data,
.set_spi_data = _set_spi_data,
.get_notification_data = _get_notification_data,
.set_notification_data = _set_notification_data,
.destroy = _destroy,
},
.doi = IKEV1_DOI_IPSEC,
.next_payload = NO_PAYLOAD,
.payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH,
.type = type,
);
compute_length(this);
return &this->public;
}
@ -593,12 +727,12 @@ notify_payload_t *notify_payload_create()
* Described in header.
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(
protocol_id_t protocol_id, notify_type_t notify_type)
payload_type_t type, protocol_id_t protocol, notify_type_t notify)
{
notify_payload_t *notify = notify_payload_create();
notify_payload_t *this = notify_payload_create(type);
notify->set_notify_type(notify, notify_type);
notify->set_protocol_id(notify, protocol_id);
this->set_notify_type(this, notify);
this->set_protocol_id(this, protocol);
return notify;
return this;
}

62
src/libcharon/encoding/payloads/notify_payload.h Normal file → Executable file
View File

@ -33,25 +33,36 @@ typedef struct notify_payload_t notify_payload_t;
#include <utils/linked_list.h>
/**
* Notify payload length in bytes without any spi and notification data.
*/
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
/**
* Notify message types.
*
* See IKEv2 RFC 3.10.1.
* Notify message types for IKEv2, and a subset for IKEv1.
*/
enum notify_type_t {
/* notify error messages */
UNSUPPORTED_CRITICAL_PAYLOAD = 1,
/* IKEv1 alias */
INVALID_PAYLOAD_TYPE = 1,
INVALID_IKE_SPI = 4,
INVALID_MAJOR_VERSION = 5,
INVALID_SYNTAX = 7,
/* IKEv1 alias */
INVALID_EXCHANGE_TYPE = 7,
INVALID_MESSAGE_ID = 9,
INVALID_SPI = 11,
/* IKEv1 only */
ATTRIBUTES_NOT_SUPPORTED = 13,
/* IKEv1 alias */
NO_PROPOSAL_CHOSEN = 14,
/* IKEv1 only */
PAYLOAD_MALFORMED = 16,
INVALID_KE_PAYLOAD = 17,
/* IKEv1 alias */
INVALID_KEY_INFORMATION = 17,
/* IKEv1 only */
INVALID_ID_INFORMATION = 18,
INVALID_CERT_ENCODING = 19,
INVALID_CERTIFICATE = 20,
CERT_TYPE_UNSUPPORTED = 21,
INVALID_CERT_AUTHORITY = 22,
INVALID_HASH_INFORMATION = 23,
AUTHENTICATION_FAILED = 24,
SINGLE_PAIR_REQUIRED = 34,
NO_ADDITIONAL_SAS = 35,
@ -127,6 +138,13 @@ enum notify_type_t {
IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED = 16421,
IKEV2_MESSAGE_ID_SYNC = 16422,
IPSEC_REPLAY_COUNTER_SYNC = 16423,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
DPD_R_U_THERE = 36136,
DPD_R_U_THERE_ACK = 36137,
/* IKEv1 Cisco High Availability */
UNITY_LOAD_BALANCE = 40501,
/* BEET mode, not even a draft yet. private use */
USE_BEET_MODE = 40961,
/* IKE-ME, private use */
@ -208,6 +226,24 @@ struct notify_payload_t {
*/
void (*set_spi) (notify_payload_t *this, u_int32_t spi);
/**
* Returns the currently set spi of this payload.
*
* This is only valid for notifys with protocol ISAKMP
*
* @return SPI value
*/
chunk_t (*get_spi_data) (notify_payload_t *this);
/**
* Sets the spi of this payload.
*
* This is only valid for notifys with protocol ISAKMP
*
* @param spi SPI value
*/
void (*set_spi_data) (notify_payload_t *this, chunk_t spi);
/**
* Returns the currently set notification data of payload.
*
@ -236,18 +272,20 @@ struct notify_payload_t {
/**
* Creates an empty notify_payload_t object
*
* @param type payload type, NOTIFY or NOTIFY_V1
* @return created notify_payload_t object
*/
notify_payload_t *notify_payload_create(void);
notify_payload_t *notify_payload_create(payload_type_t type);
/**
* Creates an notify_payload_t object of specific type for specific protocol id.
*
* @param protocol_id protocol id (IKE, AH or ESP)
* @param type notify type (see notify_type_t)
* @param type payload type, NOTIFY or NOTIFY_V1
* @param protocol protocol id (IKE, AH or ESP)
* @param notify type of notify
* @return notify_payload_t object
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(
protocol_id_t protocol_id, notify_type_t type);
payload_type_t type, protocol_id_t protocol, notify_type_t notify);
#endif /** NOTIFY_PAYLOAD_H_ @}*/

View File

@ -20,6 +20,7 @@
#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>
@ -34,12 +35,30 @@
#include <encoding/payloads/cp_payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/hash_payload.h>
#include <encoding/payloads/unknown_payload.h>
ENUM_BEGIN(payload_type_names, NO_PAYLOAD, NO_PAYLOAD,
"NO_PAYLOAD");
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
"SECURITY_ASSOCIATION_V1",
"PROPOSAL_V1",
"TRANSFORM_V1",
"KEY_EXCHANGE_V1",
"ID_V1",
"CERTIFICATE_V1",
"CERTIFICATE_REQUEST_V1",
"HASH_V1",
"SIGNATURE_V1",
"NONCE_V1",
"NOTIFY_V1",
"DELETE_V1",
"VENDOR_ID_V1",
"CONFIGURATION_V1");
ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT_D_V1",
"NAT_OA_V1");
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
"SECURITY_ASSOCIATION",
"KEY_EXCHANGE",
"ID_INITIATOR",
@ -59,28 +78,56 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
#ifdef ME
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"ID_PEER");
ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"PROPOSAL_SUBSTRUCTURE_V1",
"TRANSFORM_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE_V1",
"TRANSFORM_ATTRIBUTE",
"TRANSFORM_ATTRIBUTE_V1",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
"CONFIGURATION_ATTRIBUTE");
"CONFIGURATION_ATTRIBUTE",
"CONFIGURATION_ATTRIBUTE_V1",
"ENCRYPTED_V1");
#else
ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION,
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"PROPOSAL_SUBSTRUCTURE_V1",
"TRANSFORM_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE_V1",
"TRANSFORM_ATTRIBUTE",
"TRANSFORM_ATTRIBUTE_V1",
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
"CONFIGURATION_ATTRIBUTE");
"CONFIGURATION_ATTRIBUTE",
"CONFIGURATION_ATTRIBUTE_V1",
"ENCRYPTED_V1");
#endif /* ME */
ENUM_END(payload_type_names, CONFIGURATION_ATTRIBUTE);
ENUM_END(payload_type_names, ENCRYPTED_V1);
/* short forms of payload names */
ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
"--");
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NO_PAYLOAD,
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
"SA",
"PROP",
"TRANS",
"KE",
"ID",
"CERT",
"CERTREQ",
"HASH",
"SIG",
"No",
"N",
"D",
"V",
"CP");
ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
"NAT-D",
"NAT-OA");
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, NAT_OA_V1,
"SA",
"KE",
"IDi",
@ -100,23 +147,33 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
#ifdef ME
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"IDp");
ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
"HDR",
"PROP",
"PROP",
"TRANS",
"TRANS",
"TRANSATTR",
"TRANSATTR",
"TSSUB",
"CPATTR");
"CATTR",
"CATTR",
"E");
#else
ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION,
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, EXTENSIBLE_AUTHENTICATION,
"HDR",
"PROP",
"PROP",
"TRANS",
"TRANS",
"TRANSATTR",
"TRANSATTR",
"TSSUB",
"CPATTR");
"CATTR",
"CATTR",
"E");
#endif /* ME */
ENUM_END(payload_type_short_names, CONFIGURATION_ATTRIBUTE);
ENUM_END(payload_type_short_names, ENCRYPTED_V1);
/*
* see header
@ -128,29 +185,36 @@ payload_t *payload_create(payload_type_t type)
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create();
case SECURITY_ASSOCIATION_V1:
return (payload_t*)sa_payload_create(type);
case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create();
case PROPOSAL_SUBSTRUCTURE_V1:
return (payload_t*)proposal_substructure_create(type);
case TRANSFORM_SUBSTRUCTURE:
return (payload_t*)transform_substructure_create();
case TRANSFORM_SUBSTRUCTURE_V1:
return (payload_t*)transform_substructure_create(type);
case TRANSFORM_ATTRIBUTE:
return (payload_t*)transform_attribute_create();
case TRANSFORM_ATTRIBUTE_V1:
return (payload_t*)transform_attribute_create(type);
case NONCE:
return (payload_t*)nonce_payload_create();
case NONCE_V1:
return (payload_t*)nonce_payload_create(type);
case ID_INITIATOR:
return (payload_t*)id_payload_create(ID_INITIATOR);
case ID_RESPONDER:
return (payload_t*)id_payload_create(ID_RESPONDER);
case ID_V1:
case NAT_OA_V1:
#ifdef ME
case ID_PEER:
return (payload_t*)id_payload_create(ID_PEER);
#endif /* ME */
return (payload_t*)id_payload_create(type);
case AUTHENTICATION:
return (payload_t*)auth_payload_create();
case CERTIFICATE:
return (payload_t*)cert_payload_create();
case CERTIFICATE_V1:
return (payload_t*)cert_payload_create(type);
case CERTIFICATE_REQUEST:
return (payload_t*)certreq_payload_create();
case CERTIFICATE_REQUEST_V1:
return (payload_t*)certreq_payload_create(type);
case TRAFFIC_SELECTOR_SUBSTRUCTURE:
return (payload_t*)traffic_selector_substructure_create();
case TRAFFIC_SELECTOR_INITIATOR:
@ -158,21 +222,32 @@ payload_t *payload_create(payload_type_t type)
case TRAFFIC_SELECTOR_RESPONDER:
return (payload_t*)ts_payload_create(FALSE);
case KEY_EXCHANGE:
return (payload_t*)ke_payload_create();
case KEY_EXCHANGE_V1:
return (payload_t*)ke_payload_create(type);
case NOTIFY:
return (payload_t*)notify_payload_create();
case NOTIFY_V1:
return (payload_t*)notify_payload_create(type);
case DELETE:
return (payload_t*)delete_payload_create(0);
case DELETE_V1:
return (payload_t*)delete_payload_create(type, 0);
case VENDOR_ID:
return (payload_t*)vendor_id_payload_create();
case VENDOR_ID_V1:
return (payload_t*)vendor_id_payload_create(type);
case HASH_V1:
case SIGNATURE_V1:
case NAT_D_V1:
return (payload_t*)hash_payload_create(type);
case CONFIGURATION:
return (payload_t*)cp_payload_create();
case CONFIGURATION_V1:
return (payload_t*)cp_payload_create(type);
case CONFIGURATION_ATTRIBUTE:
return (payload_t*)configuration_attribute_create();
case CONFIGURATION_ATTRIBUTE_V1:
return (payload_t*)configuration_attribute_create(type);
case EXTENSIBLE_AUTHENTICATION:
return (payload_t*)eap_payload_create();
case ENCRYPTED:
return (payload_t*)encryption_payload_create();
case ENCRYPTED_V1:
return (payload_t*)encryption_payload_create(type);
default:
return (payload_t*)unknown_payload_create(type);
}
@ -183,8 +258,19 @@ payload_t *payload_create(payload_type_t type)
*/
bool payload_is_known(payload_type_t type)
{
if (type == HEADER ||
(type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION))
if (type == HEADER)
{
return TRUE;
}
if (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION)
{
return TRUE;
}
if (type >= SECURITY_ASSOCIATION_V1 && type <= CONFIGURATION_V1)
{
return TRUE;
}
if (type >= NAT_D_V1 && type <= NAT_OA_V1)
{
return TRUE;
}
@ -203,10 +289,9 @@ bool payload_is_known(payload_type_t type)
void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip)
{
encoding_rule_t *rule;
size_t count;
int i;
int i, count;
payload->get_encoding_rules(payload, &rule, &count);
count = payload->get_encoding_rules(payload, &rule);
for (i = 0; i < count; i++)
{
if (rule[i].type == type && skip-- == 0)

View File

@ -29,20 +29,104 @@ typedef struct payload_t payload_t;
#include <library.h>
#include <encoding/payloads/encodings.h>
/**
* Domain of interpretation used by IPsec/IKEv1
*/
#define IKEV1_DOI_IPSEC 1
/**
* Payload-Types of a IKEv2-Message.
* Payload-Types of an IKE message.
*
* Header and substructures are also defined as
* payload types with values from PRIVATE USE space.
*/
enum payload_type_t{
enum payload_type_t {
/**
* End of payload list in next_payload
*/
NO_PAYLOAD = 0,
/**
* The security association (SA) payload containing proposals.
*/
SECURITY_ASSOCIATION_V1 = 1,
/**
* The proposal payload, containing transforms.
*/
PROPOSAL_V1 = 2,
/**
* The transform payload.
*/
TRANSFORM_V1 = 3,
/**
* The key exchange (KE) payload containing diffie-hellman values.
*/
KEY_EXCHANGE_V1 = 4,
/**
* ID payload.
*/
ID_V1 = 5,
/**
* Certificate payload with certificates (CERT).
*/
CERTIFICATE_V1 = 6,
/**
* Certificate request payload.
*/
CERTIFICATE_REQUEST_V1 = 7,
/**
* Hash payload.
*/
HASH_V1 = 8,
/**
* Signature payload
*/
SIGNATURE_V1 = 9,
/**
* Nonce payload.
*/
NONCE_V1 = 10,
/**
* Notification payload.
*/
NOTIFY_V1 = 11,
/**
* Delete payload.
*/
DELETE_V1 = 12,
/**
* Vendor id payload.
*/
VENDOR_ID_V1 = 13,
/**
* Attribute payload (ISAKMP Mode Config, aka configuration payload.
*/
CONFIGURATION_V1 = 14,
/**
* NAT discovery payload (NAT-D).
*/
NAT_D_V1 = 20,
/**
* NAT original address payload (NAT-OA)
*/
NAT_OA_V1 = 21,
/**
* The security association (SA) payload containing proposals.
*/
@ -134,50 +218,60 @@ enum payload_type_t{
/**
* Header has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle IKEv2-Header like a payload.
* This type and all the following are never sent over wire and are
* used internally only.
*/
HEADER = 256,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a proposal substructure like a payload.
* PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
*/
PROPOSAL_SUBSTRUCTURE = 257,
PROPOSAL_SUBSTRUCTURE,
/**
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a transform substructure like a payload.
* PROPOSAL_SUBSTRUCTURE_V1, IKEv1 proposals in a SA payload.
*/
TRANSFORM_SUBSTRUCTURE = 258,
PROPOSAL_SUBSTRUCTURE_V1,
/**
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a transform attribute like a payload.
* TRANSFORM_SUBSTRUCTURE, IKEv2 transforms in a proposal substructure.
*/
TRANSFORM_ATTRIBUTE = 259,
TRANSFORM_SUBSTRUCTURE,
/**
* TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a transform selector like a payload.
* TRANSFORM_SUBSTRUCTURE_V1, IKEv1 transforms in a proposal substructure.
*/
TRAFFIC_SELECTOR_SUBSTRUCTURE = 260,
TRANSFORM_SUBSTRUCTURE_V1,
/**
* CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a transform attribute like a payload.
* TRANSFORM_ATTRIBUTE, IKEv2 attribute in a transform.
*/
CONFIGURATION_ATTRIBUTE = 261,
TRANSFORM_ATTRIBUTE,
/**
* TRANSFORM_ATTRIBUTE_V1, IKEv1 attribute in a transform.
*/
TRANSFORM_ATTRIBUTE_V1,
/**
* TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic selector in a TS payload.
*/
TRAFFIC_SELECTOR_SUBSTRUCTURE,
/**
* CONFIGURATION_ATTRIBUTE, IKEv2 attribute in a configuration payload.
*/
CONFIGURATION_ATTRIBUTE,
/**
* CONFIGURATION_ATTRIBUTE_V1, IKEv1 attribute in a configuration payload.
*/
CONFIGURATION_ATTRIBUTE_V1,
/**
* This is not really a payload, but rather the complete IKEv1 message.
*/
ENCRYPTED_V1,
};
/**
@ -202,43 +296,50 @@ struct payload_t {
/**
* Get encoding rules for this payload.
*
* @param rules location to store pointer of first rule
* @param rule_count location to store number of rules
* @param rules location to store pointer to rules
* @return number of rules
*/
void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
int (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules);
/**
* Get non-variable header length for a variable length payload.
*
* @return fixed length of the payload
*/
int (*get_header_length)(payload_t *this);
/**
* Get type of payload.
*
* @return type of this payload
* @return type of this payload
*/
payload_type_t (*get_type) (payload_t *this);
/**
* Get type of next payload or NO_PAYLOAD (0) if this is the last one.
*
* @return type of next payload
* @return type of next payload
*/
payload_type_t (*get_next_type) (payload_t *this);
/**
* Set type of next payload.
*
* @param type type of next payload
* @param type type of next payload
*/
void (*set_next_type) (payload_t *this,payload_type_t type);
/**
* Get length of payload.
*
* @return length of this payload
* @return length of this payload
*/
size_t (*get_length) (payload_t *this);
/**
* Verifies payload structure and makes consistence check.
*
* @return SUCCESS, FAILED if consistence not given
* @return SUCCESS, FAILED if consistence not given
*/
status_t (*verify) (payload_t *this);

File diff suppressed because it is too large Load Diff

View File

@ -29,17 +29,11 @@ typedef struct proposal_substructure_t proposal_substructure_t;
#include <encoding/payloads/transform_substructure.h>
#include <config/proposal.h>
#include <utils/linked_list.h>
#include <kernel/kernel_ipsec.h>
#include <sa/authenticator.h>
/**
* Length of the proposal substructure header (without spi).
*/
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
/**
* Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
*
* The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
* Class representing an IKEv1/IKEv2 proposal substructure.
*/
struct proposal_substructure_t {
@ -104,11 +98,11 @@ struct proposal_substructure_t {
void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
/**
* Get a proposal_t from the propsal_substructure_t.
* Get proposals contained in a propsal_substructure_t.
*
* @return proposal_t
* @param list list to add created proposals to
*/
proposal_t * (*get_proposal) (proposal_substructure_t *this);
void (*get_proposals) (proposal_substructure_t *this, linked_list_t *list);
/**
* Create an enumerator over transform substructures.
@ -117,6 +111,35 @@ struct proposal_substructure_t {
*/
enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this);
/**
* Get the (shortest) lifetime of a proposal (IKEv1 only).
*
* @return lifetime, in seconds
*/
u_int32_t (*get_lifetime)(proposal_substructure_t *this);
/**
* Get the (shortest) life duration of a proposal (IKEv1 only).
*
* @return life duration, in bytes
*/
u_int64_t (*get_lifebytes)(proposal_substructure_t *this);
/**
* Get the first authentication method from the proposal (IKEv1 only).
*
* @return auth method, or AUTH_NONE
*/
auth_method_t (*get_auth_method)(proposal_substructure_t *this);
/**
* Get the (first) encapsulation mode from a proposal (IKEv1 only).
*
* @param udp set to TRUE if UDP encapsulation used
* @return ipsec encapsulation mode
*/
ipsec_mode_t (*get_encap_mode)(proposal_substructure_t *this, bool *udp);
/**
* Destroys an proposal_substructure_t object.
*/
@ -126,17 +149,49 @@ struct proposal_substructure_t {
/**
* Creates an empty proposal_substructure_t object
*
* @return proposal_substructure_t object
* @param type PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
* @return proposal_substructure_t object
*/
proposal_substructure_t *proposal_substructure_create(void);
proposal_substructure_t *proposal_substructure_create(payload_type_t type);
/**
* Creates a proposal_substructure_t from a proposal_t.
* Creates an IKEv2 proposal_substructure_t from a proposal_t.
*
* @param proposal proposal to build a substruct out of it
* @return proposal_substructure_t object
* @param proposal proposal to build a substruct out of it
* @return proposal_substructure_t PROPOSAL_SUBSTRUCTURE
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(
proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
proposal_t *proposal);
/**
* Creates an IKEv1 proposal_substructure_t from a proposal_t.
*
* @param proposal proposal to build a substruct out of it
* @param lifetime lifetime in seconds
* @param lifebytes lifebytes, in bytes
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
*
*
* @return proposal_substructure_t object PROPOSAL_SUBSTRUCTURE_V1
*/
proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp);
/**
* Creates an IKEv1 proposal_substructure_t from a list of proposal_t.
*
* @param proposals list of proposal_t to encode in a substructure
* @param lifetime lifetime in seconds
* @param lifebytes lifebytes, in bytes
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
* @return IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
*/
proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp);
#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/

View File

@ -22,6 +22,8 @@
#include <utils/linked_list.h>
#include <daemon.h>
/* IKEv1 situation */
#define SIT_IDENTITY_ONLY 1
typedef struct private_sa_payload_t private_sa_payload_t;
@ -48,7 +50,7 @@ struct private_sa_payload_t {
/**
* Reserved bits
*/
bool reserved[7];
bool reserved[8];
/**
* Length of this payload.
@ -58,21 +60,75 @@ struct private_sa_payload_t {
/**
* Proposals in this payload are stored in a linked_list_t.
*/
linked_list_t * proposals;
linked_list_t *proposals;
/**
* Type of this payload, V1 or V2
*/
payload_type_t type;
/**
* IKEv1 DOI
*/
u_int32_t doi;
/**
* IKEv1 situation
*/
u_int32_t situation;
};
/**
* 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 rules for IKEv1 SA payload
*/
encoding_rule_t sa_payload_encodings[] = {
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* 8 reserved bits */
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[7]) },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* DOI*/
{ U_INT_32, offsetof(private_sa_payload_t, doi) },
/* Situation*/
{ U_INT_32, offsetof(private_sa_payload_t, situation) },
/* Proposals are stored in a proposal substructure list */
{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1,
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 ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DOI !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Situation !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Proposals> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for IKEv2 SA payload
*/
static encoding_rule_t encodings_v2[] = {
/* 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 */
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
@ -82,9 +138,9 @@ encoding_rule_t sa_payload_encodings[] = {
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
/* 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) },
/* Proposals are stored in a proposal substructure list */
{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE,
offsetof(private_sa_payload_t, proposals) },
};
/*
@ -102,11 +158,16 @@ encoding_rule_t sa_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_sa_payload_t *this)
{
int expected_number = 1, current_number;
int expected_number = 0, current_number;
status_t status = SUCCESS;
enumerator_t *enumerator;
proposal_substructure_t *substruct;
if (this->type == SECURITY_ASSOCIATION)
{
expected_number = 1;
}
/* check proposal numbering */
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void**)&substruct))
@ -131,17 +192,32 @@ METHOD(payload_t, verify, status_t,
return status;
}
METHOD(payload_t, get_encoding_rules, void,
private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_sa_payload_t *this, encoding_rule_t **rules)
{
*rules = sa_payload_encodings;
*rule_count = countof(sa_payload_encodings);
if (this->type == SECURITY_ASSOCIATION_V1)
{
*rules = encodings_v1;
return countof(encodings_v1);
}
*rules = encodings_v2;
return countof(encodings_v2);
}
METHOD(payload_t, get_header_length, int,
private_sa_payload_t *this)
{
if (this->type == SECURITY_ASSOCIATION_V1)
{
return 12;
}
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_sa_payload_t *this)
{
return SECURITY_ASSOCIATION;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -163,16 +239,15 @@ static void compute_length(private_sa_payload_t *this)
{
enumerator_t *enumerator;
payload_t *current;
size_t length = SA_PAYLOAD_HEADER_LENGTH;
this->payload_length = get_header_length(this);
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void **)&current))
{
length += current->get_length(current);
this->payload_length += current->get_length(current);
}
enumerator->destroy(enumerator);
this->payload_length = length;
}
METHOD(payload_t, get_length, size_t,
@ -181,14 +256,16 @@ METHOD(payload_t, get_length, size_t,
return this->payload_length;
}
METHOD(sa_payload_t, add_proposal, void,
private_sa_payload_t *this, proposal_t *proposal)
/**
* Create a transform substructure from a proposal, add to payload
*/
static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
{
proposal_substructure_t *substruct, *last;
u_int count;
substruct = proposal_substructure_create_from_proposal_v2(proposal);
count = this->proposals->get_count(this->proposals);
substruct = proposal_substructure_create_from_proposal(proposal);
if (count > 0)
{
this->proposals->get_last(this->proposals, (void**)&last);
@ -215,8 +292,13 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
int ignore_struct_number = 0;
enumerator_t *enumerator;
proposal_substructure_t *substruct;
linked_list_t *list;
proposal_t *proposal;
linked_list_t *list;
if (this->type == SECURITY_ASSOCIATION_V1)
{ /* IKEv1 proposals start with 0 */
struct_number = ignore_struct_number = -1;
}
list = linked_list_create();
/* we do not support proposals split up to two proposal substructures, as
@ -233,18 +315,16 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
if (ignore_struct_number < struct_number)
{
/* remove an already added, if first of series */
list->remove_last(list, (void**)&proposal);
proposal->destroy(proposal);
if (list->remove_last(list, (void**)&proposal) == SUCCESS)
{
proposal->destroy(proposal);
}
ignore_struct_number = struct_number;
}
continue;
}
struct_number++;
proposal = substruct->get_proposal(substruct);
if (proposal)
{
list->insert_last(list, proposal);
}
substruct->get_proposals(substruct, list);
}
enumerator->destroy(enumerator);
return list;
@ -256,18 +336,86 @@ METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
return this->proposals->create_enumerator(this->proposals);
}
METHOD(sa_payload_t, get_lifetime, u_int32_t,
private_sa_payload_t *this)
{
proposal_substructure_t *substruct;
enumerator_t *enumerator;
u_int32_t lifetime = 0;
enumerator = this->proposals->create_enumerator(this->proposals);
if (enumerator->enumerate(enumerator, &substruct))
{
lifetime = substruct->get_lifetime(substruct);
}
enumerator->destroy(enumerator);
return lifetime;
}
METHOD(sa_payload_t, get_lifebytes, u_int64_t,
private_sa_payload_t *this)
{
proposal_substructure_t *substruct;
enumerator_t *enumerator;
u_int64_t lifebytes = 0;
enumerator = this->proposals->create_enumerator(this->proposals);
if (enumerator->enumerate(enumerator, &substruct))
{
lifebytes = substruct->get_lifebytes(substruct);
}
enumerator->destroy(enumerator);
return lifebytes;
}
METHOD(sa_payload_t, get_auth_method, auth_method_t,
private_sa_payload_t *this)
{
proposal_substructure_t *substruct;
enumerator_t *enumerator;
auth_method_t method = AUTH_NONE;
enumerator = this->proposals->create_enumerator(this->proposals);
if (enumerator->enumerate(enumerator, &substruct))
{
method = substruct->get_auth_method(substruct);
}
enumerator->destroy(enumerator);
return method;
}
METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
private_sa_payload_t *this, bool *udp)
{
proposal_substructure_t *substruct;
enumerator_t *enumerator;
ipsec_mode_t mode = MODE_NONE;
enumerator = this->proposals->create_enumerator(this->proposals);
if (enumerator->enumerate(enumerator, &substruct))
{
mode = substruct->get_encap_mode(substruct, udp);
}
enumerator->destroy(enumerator);
return mode;
}
METHOD2(payload_t, sa_payload_t, destroy, void,
private_sa_payload_t *this)
{
this->proposals->destroy_offset(this->proposals,
offsetof(proposal_substructure_t, destroy));
offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create()
sa_payload_t *sa_payload_create(payload_type_t type)
{
private_sa_payload_t *this;
@ -276,38 +424,48 @@ sa_payload_t *sa_payload_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.add_proposal = _add_proposal,
.get_proposals = _get_proposals,
.create_substructure_enumerator = _create_substructure_enumerator,
.get_lifetime = _get_lifetime,
.get_lifebytes = _get_lifebytes,
.get_auth_method = _get_auth_method,
.get_encap_mode = _get_encap_mode,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = SA_PAYLOAD_HEADER_LENGTH,
.proposals = linked_list_create(),
.type = type,
/* for IKEv1 only */
.doi = IKEV1_DOI_IPSEC,
.situation = SIT_IDENTITY_ONLY,
);
compute_length(this);
return &this->public;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
{
private_sa_payload_t *this;
enumerator_t *enumerator;
proposal_t *proposal;
this = (private_sa_payload_t*)sa_payload_create();
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
enumerator = proposals->create_enumerator(proposals);
while (enumerator->enumerate(enumerator, &proposal))
{
add_proposal(this, proposal);
add_proposal_v2(this, proposal);
}
enumerator->destroy(enumerator);
@ -317,12 +475,57 @@ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
{
private_sa_payload_t *this;
this = (private_sa_payload_t*)sa_payload_create();
add_proposal(this, proposal);
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
add_proposal_v2(this, proposal);
return &this->public;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp)
{
proposal_substructure_t *substruct;
private_sa_payload_t *this;
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
/* IKEv1 encodes multiple proposals in a single substructure
* TODO-IKEv1: Encode ESP+AH proposals in two different substructs */
substruct = proposal_substructure_create_from_proposals_v1(proposals,
lifetime, lifebytes, auth, mode, udp);
substruct->set_is_last_proposal(substruct, TRUE);
this->proposals->insert_last(this->proposals, substruct);
compute_length(this);
return &this->public;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp)
{
proposal_substructure_t *substruct;
private_sa_payload_t *this;
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
substruct = proposal_substructure_create_from_proposal_v1(proposal,
lifetime, lifebytes, auth, mode, udp);
substruct->set_is_last_proposal(substruct, TRUE);
this->proposals->insert_last(this->proposals, substruct);
compute_length(this);
return &this->public;
}

View File

@ -28,14 +28,11 @@ typedef struct sa_payload_t sa_payload_t;
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
#include <kernel/kernel_ipsec.h>
#include <sa/authenticator.h>
/**
* SA_PAYLOAD length in bytes without any proposal substructure.
*/
#define SA_PAYLOAD_HEADER_LENGTH 4
/**
* Class representing an IKEv2-SA Payload.
* Class representing an IKEv1 or IKEv2 SA Payload.
*
* The SA Payload format is described in RFC section 3.3.
*/
@ -54,11 +51,33 @@ struct sa_payload_t {
linked_list_t *(*get_proposals) (sa_payload_t *this);
/**
* Add a child proposal (AH/ESP) to the payload.
* Get the (shortest) lifetime of a proposal (IKEv1 only).
*
* @param proposal child proposal to add to the payload
* @return lifetime, in seconds
*/
void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
u_int32_t (*get_lifetime)(sa_payload_t *this);
/**
* Get the (shortest) life duration of a proposal (IKEv1 only).
*
* @return life duration, in bytes
*/
u_int64_t (*get_lifebytes)(sa_payload_t *this);
/**
* Get the first authentication method from the proposal (IKEv1 only).
*
* @return auth method, or AUTH_NONE
*/
auth_method_t (*get_auth_method)(sa_payload_t *this);
/**
* Get the (first) encapsulation mode from a proposal (IKEv1 only).
*
* @param udp set to TRUE if UDP encapsulation used
* @return ipsec encapsulation mode
*/
ipsec_mode_t (*get_encap_mode)(sa_payload_t *this, bool *udp);
/**
* Create an enumerator over all proposal substructures.
@ -76,27 +95,55 @@ struct sa_payload_t {
/**
* Creates an empty sa_payload_t object
*
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @return created sa_payload_t object
*/
sa_payload_t *sa_payload_create(void);
sa_payload_t *sa_payload_create(payload_type_t type);
/**
* Creates a sa_payload_t object from a list of proposals.
* Creates an IKEv2 sa_payload_t object from a list of proposals.
*
* @param proposals list of proposals to build the payload from
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals);
/**
* 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.
* Creates an IKEv2 sa_payload_t object from a single proposal.
*
* @param proposal proposal from which the payload should be built.
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal);
/**
* Creates an IKEv1 sa_payload_t object from a list of proposals.
*
* @param proposals list of proposals to build the payload from
* @param lifetime lifetime in seconds
* @param lifebytes lifebytes, in bytes
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp);
/**
* Creates an IKEv1 sa_payload_t object from a single proposal.
*
* @param proposal proposal from which the payload should be built.
* @param lifetime lifetime in seconds
* @param lifebytes lifebytes, in bytes
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
u_int32_t lifetime, u_int64_t lifebytes,
auth_method_t auth, ipsec_mode_t mode, bool udp);
#endif /** SA_PAYLOAD_H_ @}*/

View File

@ -74,7 +74,7 @@ struct private_traffic_selector_substructure_t {
* The defined offsets are the positions in a object of type
* private_traffic_selector_substructure_t.
*/
encoding_rule_t traffic_selector_substructure_encodings[] = {
static encoding_rule_t encodings[] = {
/* 1 Byte next ts type*/
{ TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
/* 1 Byte IP protocol id*/
@ -148,12 +148,17 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_traffic_selector_substructure_t *this, encoding_rule_t **rules,
size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
{
*rules = traffic_selector_substructure_encodings;
*rule_count = countof(traffic_selector_substructure_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_traffic_selector_substructure_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@ -208,6 +213,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -217,7 +223,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
.get_traffic_selector = _get_traffic_selector,
.destroy = _destroy,
},
.payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
.payload_length = get_header_length(this),
/* must be set to be valid */
.ts_type = TS_IPV4_ADDR_RANGE,
);
@ -239,7 +245,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
this->end_port = ts->get_to_port(ts);
this->starting_address = chunk_clone(ts->get_from_address(ts));
this->ending_address = chunk_clone(ts->get_to_address(ts));
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
this->payload_length = get_header_length(this) +
this->ending_address.len + this->starting_address.len;
return &this->public;

View File

@ -29,11 +29,6 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
#include <selectors/traffic_selector.h>
#include <encoding/payloads/payload.h>
/**
* Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
*/
#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
/**
* Class representing an IKEv2 TRAFFIC SELECTOR.
*

View File

@ -23,6 +23,44 @@
#include <encoding/payloads/encodings.h>
#include <library.h>
ENUM(tattr_ph1_names, TATTR_PH1_ENCRYPTION_ALGORITHM, TATTR_PH1_GROUP_ORDER,
"ENCRYPTION_ALGORITHM",
"HASH_ALGORITHM",
"AUTH_METHOD",
"GROUP",
"GROUP_TYPE",
"GROUP_PRIME",
"GROUP_GENONE",
"GROUP_GENTWO",
"GROUP_CURVE_A",
"GROUP_CURVE_B",
"LIFE_TYPE",
"LIFE_DURATION",
"PRF",
"KEY_LENGTH",
"FIELD_SIZE",
"GROUP_ORDER",
);
ENUM(tattr_ph2_names, TATTR_PH2_SA_LIFE_TYPE, TATTR_PH2_EXT_SEQ_NUMBER,
"SA_LIFE_TYPE",
"SA_LIFE_DURATION",
"GROUP",
"ENCAP_MODE",
"AUTH_ALGORITHM",
"KEY_LENGTH",
"KEY_ROUNDS",
"COMP_DICT_SIZE",
"COMP_PRIV_ALGORITHM",
"ECN_TUNNEL",
"EXT_SEQ_NUMBER",
);
ENUM(tattr_ikev2_names, TATTR_IKEV2_KEY_LENGTH, TATTR_IKEV2_KEY_LENGTH,
"KEY_LENGTH",
);
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
@ -57,22 +95,17 @@ struct private_transform_attribute_t {
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
/**
* Payload type, TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
*/
payload_type_t type;
};
ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
"ATTRIBUTE_UNDEFINED");
ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
"KEY_LENGTH");
ENUM_END(transform_attribute_type_name, KEY_LENGTH);
/**
* 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 rules for IKEv1/IKEv2 transform attributes
*/
encoding_rule_t transform_attribute_encodings[] = {
static encoding_rule_t 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 */
@ -101,18 +134,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_transform_attribute_t *this, encoding_rule_t **rules,
size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_transform_attribute_t *this, encoding_rule_t **rules)
{
*rules = transform_attribute_encodings;
*rule_count = countof(transform_attribute_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_transform_attribute_t *this)
{
return 0;
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -136,31 +174,6 @@ METHOD(payload_t, get_length, size_t,
return this->attribute_length_or_value + 4;
}
METHOD(transform_attribute_t, set_value_chunk, void,
private_transform_attribute_t *this, chunk_t value)
{
chunk_free(&this->attribute_value);
if (value.len != 2)
{
this->attribute_value = chunk_clone(value);
this->attribute_length_or_value = value.len;
this->attribute_format = FALSE;
}
else
{
memcpy(&this->attribute_length_or_value, value.ptr, value.len);
}
}
METHOD(transform_attribute_t, set_value, void,
private_transform_attribute_t *this, u_int16_t value)
{
chunk_free(&this->attribute_value);
this->attribute_length_or_value = value;
this->attribute_format = TRUE;
}
METHOD(transform_attribute_t, get_value_chunk, chunk_t,
private_transform_attribute_t *this)
{
@ -171,16 +184,22 @@ METHOD(transform_attribute_t, get_value_chunk, chunk_t,
return this->attribute_value;
}
METHOD(transform_attribute_t, get_value, u_int16_t,
METHOD(transform_attribute_t, get_value, u_int64_t,
private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
u_int64_t value = 0;
METHOD(transform_attribute_t, set_attribute_type, void,
private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
if (this->attribute_format)
{
return this->attribute_length_or_value;
}
if (this->attribute_value.len > sizeof(value))
{
return UINT64_MAX;
}
memcpy(((char*)&value) + sizeof(value) - this->attribute_value.len,
this->attribute_value.ptr, this->attribute_value.len);
return untoh64((char*)&value);
}
METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
@ -189,24 +208,6 @@ METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
return this->attribute_type;
}
METHOD(transform_attribute_t, clone_, transform_attribute_t*,
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 = chunk_clone(this->attribute_value);
}
return &new_clone->public;
}
METHOD2(payload_t, transform_attribute_t, destroy, void,
private_transform_attribute_t *this)
{
@ -217,7 +218,7 @@ METHOD2(payload_t, transform_attribute_t, destroy, void,
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create()
transform_attribute_t *transform_attribute_create(payload_type_t type)
{
private_transform_attribute_t *this;
@ -226,22 +227,20 @@ transform_attribute_t *transform_attribute_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.set_value_chunk = _set_value_chunk,
.set_value = _set_value,
.get_value_chunk = _get_value_chunk,
.get_value = _get_value,
.set_attribute_type = _set_attribute_type,
.get_attribute_type = _get_attribute_type,
.clone = _clone_,
.destroy = _destroy,
},
.attribute_format = TRUE,
.attribute_format = FALSE,
.type = type,
);
return &this->public;
}
@ -249,10 +248,33 @@ transform_attribute_t *transform_attribute_create()
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
transform_attribute_t *transform_attribute_create_value(payload_type_t type,
transform_attribute_type_t kind, u_int64_t value)
{
transform_attribute_t *attribute = transform_attribute_create();
attribute->set_attribute_type(attribute, KEY_LENGTH);
attribute->set_value(attribute, key_length);
return attribute;
private_transform_attribute_t *this;
this = (private_transform_attribute_t*)transform_attribute_create(type);
this->attribute_type = kind & 0x7FFF;
if (value <= UINT16_MAX)
{
this->attribute_length_or_value = value;
this->attribute_format = TRUE;
}
else if (value <= UINT32_MAX)
{
u_int32_t val32;
val32 = htonl(value);
this->attribute_value = chunk_clone(chunk_from_thing(val32));
this->attribute_length_or_value = sizeof(val32);
}
else
{
htoun64(&value, value);
this->attribute_value = chunk_clone(chunk_from_thing(value));
this->attribute_length_or_value = sizeof(value);
}
return &this->public;
}

View File

@ -28,26 +28,66 @@ typedef struct transform_attribute_t transform_attribute_t;
#include <library.h>
#include <encoding/payloads/payload.h>
/**
* Type of the attribute, as in IKEv2 RFC 3.3.5.
* Type of the attribute.
*/
enum transform_attribute_type_t {
ATTRIBUTE_UNDEFINED = 16384,
KEY_LENGTH = 14
/** IKEv1 Phase 1 attributes */
TATTR_PH1_ENCRYPTION_ALGORITHM = 1,
TATTR_PH1_HASH_ALGORITHM = 2,
TATTR_PH1_AUTH_METHOD = 3,
TATTR_PH1_GROUP = 4,
TATTR_PH1_GROUP_TYPE = 5,
TATTR_PH1_GROUP_PRIME = 6,
TATTR_PH1_GROUP_GENONE = 7,
TATTR_PH1_GROUP_GENTWO = 8,
TATTR_PH1_GROUP_CURVE_A = 9,
TATTR_PH1_GROUP_CURVE_B = 10,
TATTR_PH1_LIFE_TYPE = 11,
TATTR_PH1_LIFE_DURATION = 12,
TATTR_PH1_PRF = 13,
TATTR_PH1_KEY_LENGTH = 14,
TATTR_PH1_FIELD_SIZE = 15,
TATTR_PH1_GROUP_ORDER = 16,
/** IKEv1 Phase 2 attributes */
TATTR_PH2_SA_LIFE_TYPE = 1,
TATTR_PH2_SA_LIFE_DURATION = 2,
TATTR_PH2_GROUP = 3,
TATTR_PH2_ENCAP_MODE = 4,
TATTR_PH2_AUTH_ALGORITHM = 5,
TATTR_PH2_KEY_LENGTH = 6,
TATTR_PH2_KEY_ROUNDS = 7,
TATTR_PH2_COMP_DICT_SIZE = 8,
TATTR_PH2_COMP_PRIV_ALGORITHM = 9,
TATTR_PH2_ECN_TUNNEL = 10,
TATTR_PH2_EXT_SEQ_NUMBER = 11,
/* IKEv2 key length attribute */
TATTR_IKEV2_KEY_LENGTH = 14,
/* undefined, private use attribute */
TATTR_UNDEFINED = 16384,
};
/**
* enum name for transform_attribute_type_t.
* Enum names for IKEv1 Phase 1 transform_attribute_type_t.
*/
extern enum_name_t *transform_attribute_type_names;
extern enum_name_t *tattr_ph1_names;
/**
* Class representing an IKEv2- TRANSFORM Attribute.
*
* The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
* Enum names for IKEv1 Phase 2 transform_attribute_type_t.
*/
extern enum_name_t *tattr_ph2_names;
/**
* Enum names for IKEv2 transform_attribute_type_t.
*/
extern enum_name_t *tattr_ikev2_names;
/**
* Class representing an IKEv1/IKEv2 TRANSFORM Attribute.
*/
struct transform_attribute_t {
/**
* The payload_t interface.
*/
@ -58,7 +98,7 @@ struct transform_attribute_t {
*
* Returned data are not copied.
*
* @return chunk_t pointing to the value
* @return chunk_t pointing to internal value
*/
chunk_t (*get_value_chunk) (transform_attribute_t *this);
@ -69,30 +109,7 @@ struct transform_attribute_t {
*
* @return value
*/
u_int16_t (*get_value) (transform_attribute_t *this);
/**
* Sets the value of the attribute.
*
* Value is getting copied.
*
* @param value chunk_t pointing to the value to set
*/
void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
/**
* Sets the value of the attribute.
*
* @param value value to set
*/
void (*set_value) (transform_attribute_t *this, u_int16_t value);
/**
* Sets the type of the attribute.
*
* @param type type to set (most significant bit is set to zero)
*/
void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
u_int64_t (*get_value) (transform_attribute_t *this);
/**
* get the type of the attribute.
@ -101,13 +118,6 @@ struct transform_attribute_t {
*/
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
/**
* Clones an transform_attribute_t object.
*
* @return cloned transform_attribute_t object
*/
transform_attribute_t * (*clone) (transform_attribute_t *this);
/**
* Destroys an transform_attribute_t object.
*/
@ -117,16 +127,20 @@ struct transform_attribute_t {
/**
* Creates an empty transform_attribute_t object.
*
* @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
* @return transform_attribute_t object
*/
transform_attribute_t *transform_attribute_create(void);
transform_attribute_t *transform_attribute_create(payload_type_t type);
/**
* Creates an transform_attribute_t of type KEY_LENGTH.
* Creates a two byte value or a larger attribute for a given attribute kind.
*
* @param key_length key length in bytes
* @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
* @param kind attribute kind
* @param value fixed two byte value
* @return transform_attribute_t object
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
transform_attribute_t *transform_attribute_create_value(payload_type_t type,
transform_attribute_type_t kind, u_int64_t value);
#endif /** TRANSFORM_ATTRIBUTE_H_ @}*/

View File

@ -41,10 +41,11 @@ struct private_transform_substructure_t {
* Next payload type.
*/
u_int8_t next_payload;
/**
* Reserved bytes
* Reserved byte
*/
u_int8_t reserved[2];
u_int8_t reserved[3];
/**
* Length of this payload.
@ -52,43 +53,72 @@ struct private_transform_substructure_t {
u_int16_t transform_length;
/**
* Type of the transform.
* Type or number, Type of the transform in IKEv2, number in IKEv2.
*/
u_int8_t transform_type;
u_int8_t transform_ton;
/**
* Transform ID.
* Transform ID, as encoded in IKEv1.
*/
u_int16_t transform_id;
u_int8_t transform_id_v1;
/**
* Transform ID, as encoded in IKEv2.
*/
u_int16_t transform_id_v2;
/**
* Transforms Attributes are stored in a linked_list_t.
*/
linked_list_t *attributes;
/**
* Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
*/
payload_type_t type;
};
/**
* 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 rules for TRANSFORM_SUBSTRUCTURE
*/
encoding_rule_t transform_substructure_encodings[] = {
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[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) },
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
/* transform type */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_ton) },
/* transform identifier, as used by IKEv1 */
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
/* transform identifier, as used by IKEv2 */
{ U_INT_16, offsetof(private_transform_substructure_t, transform_id_v2) },
/* Attributes in a transform attribute list */
{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE,
offsetof(private_transform_substructure_t, attributes) }
};
/**
* Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
*/
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* 1 Reserved Byte */
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
/* transform 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) }
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
/* Length of the whole transform substructure*/
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
/* transform number */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_ton)},
/* transform identifier, as used by IKEv1 */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_id_v1) },
/* transform identifier, as used by IKEv2 */
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[2]) },
/* Attributes in a transform attribute list */
{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1,
offsetof(private_transform_substructure_t, attributes) }
};
/*
@ -97,7 +127,7 @@ encoding_rule_t transform_substructure_encodings[] = {
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!Transform Type ! RESERVED ! Transform ID !
! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
@ -118,23 +148,6 @@ METHOD(payload_t, verify, status_t,
return FAILED;
}
switch (this->transform_type)
{
case ENCRYPTION_ALGORITHM:
case PSEUDO_RANDOM_FUNCTION:
case INTEGRITY_ALGORITHM:
case DIFFIE_HELLMAN_GROUP:
case EXTENDED_SEQUENCE_NUMBERS:
/* we don't check transform ID, we want to reply
* cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
break;
default:
{
DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
return FAILED;
}
}
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
@ -151,18 +164,28 @@ METHOD(payload_t, verify, status_t,
return status;
}
METHOD(payload_t, get_encoding_rules, void,
private_transform_substructure_t *this, encoding_rule_t **rules,
size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_transform_substructure_t *this, encoding_rule_t **rules)
{
*rules = transform_substructure_encodings;
*rule_count = countof(transform_substructure_encodings);
if (this->type == TRANSFORM_SUBSTRUCTURE)
{
*rules = encodings_v2;
return countof(encodings_v2);
}
*rules = encodings_v1;
return countof(encodings_v1);
}
METHOD(payload_t, get_header_length, int,
private_transform_substructure_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_substructure_t *this)
{
return TRANSFORM_SUBSTRUCTURE;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -174,12 +197,12 @@ METHOD(payload_t, get_next_type, payload_type_t,
/**
* recompute the length of the payload.
*/
static void compute_length (private_transform_substructure_t *this)
static void compute_length(private_transform_substructure_t *this)
{
enumerator_t *enumerator;
payload_t *attribute;
this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
this->transform_length = get_header_length(this);
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
@ -194,6 +217,13 @@ METHOD(payload_t, get_length, size_t,
return this->transform_length;
}
METHOD(transform_substructure_t, add_transform_attribute, void,
private_transform_substructure_t *this, transform_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes, attribute);
compute_length(this);
}
METHOD(transform_substructure_t, set_is_last_transform, void,
private_transform_substructure_t *this, bool is_last)
{
@ -205,50 +235,40 @@ METHOD(payload_t, set_next_type, void,
{
}
METHOD(transform_substructure_t, get_transform_type, u_int8_t,
METHOD(transform_substructure_t, get_transform_type_or_number, u_int8_t,
private_transform_substructure_t *this)
{
return this->transform_type;
return this->transform_ton;
}
METHOD(transform_substructure_t, get_transform_id, u_int16_t,
private_transform_substructure_t *this)
{
return this->transform_id;
if (this->type == TRANSFORM_SUBSTRUCTURE)
{
return this->transform_id_v2;
}
return this->transform_id_v1;
}
METHOD(transform_substructure_t, get_key_length, status_t,
private_transform_substructure_t *this, u_int16_t *key_length)
METHOD(transform_substructure_t, create_attribute_enumerator, enumerator_t*,
private_transform_substructure_t *this)
{
enumerator_t *enumerator;
transform_attribute_t *attribute;
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
if (attribute->get_attribute_type(attribute) == KEY_LENGTH)
{
*key_length = attribute->get_value(attribute);
enumerator->destroy(enumerator);
return SUCCESS;
}
}
enumerator->destroy(enumerator);
return FAILED;
return this->attributes->create_enumerator(this->attributes);
}
METHOD2(payload_t, transform_substructure_t, destroy, void,
private_transform_substructure_t *this)
{
this->attributes->destroy_offset(this->attributes,
offsetof(transform_attribute_t, destroy));
offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
transform_substructure_t *transform_substructure_create()
transform_substructure_t *transform_substructure_create(payload_type_t type)
{
private_transform_substructure_t *this;
@ -257,21 +277,24 @@ transform_substructure_t *transform_substructure_create()
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.add_transform_attribute = _add_transform_attribute,
.set_is_last_transform = _set_is_last_transform,
.get_transform_type = _get_transform_type,
.get_transform_type_or_number = _get_transform_type_or_number,
.get_transform_id = _get_transform_id,
.get_key_length = _get_key_length,
.create_attribute_enumerator = _create_attribute_enumerator,
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH,
.transform_length = get_header_length(this),
.attributes = linked_list_create(),
.type = type,
);
return &this->public;
}
@ -279,20 +302,21 @@ transform_substructure_t *transform_substructure_create()
/*
* Described in header
*/
transform_substructure_t *transform_substructure_create_type(
transform_type_t type, u_int16_t id, u_int16_t key_length)
transform_substructure_t *transform_substructure_create_type(payload_type_t type,
u_int8_t type_or_number, u_int16_t id)
{
private_transform_substructure_t *this;
this = (private_transform_substructure_t*)transform_substructure_create();
this = (private_transform_substructure_t*)transform_substructure_create(type);
this->transform_type = type;
this->transform_id = id;
if (key_length)
this->transform_ton = type_or_number;
if (type == TRANSFORM_SUBSTRUCTURE)
{
this->attributes->insert_last(this->attributes,
(void*)transform_attribute_create_key_length(key_length));
compute_length(this);
this->transform_id_v2 = id;
}
else
{
this->transform_id_v1 = id;
}
return &this->public;
}

View File

@ -40,14 +40,7 @@ typedef struct transform_substructure_t transform_substructure_t;
#define TRANSFORM_TYPE_VALUE 3
/**
* Length of the transform substructure header in bytes.
*/
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
/**
* Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
*
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
* Class representing an IKEv1/IKEv2 transform substructure.
*/
struct transform_substructure_t {
@ -75,11 +68,11 @@ struct transform_substructure_t {
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
* get transform type of the current transform.
* Get transform type (IKEv2) or the transform number (IKEv1).
*
* @return Transform type of current transform substructure.
*/
u_int8_t (*get_transform_type) (transform_substructure_t *this);
u_int8_t (*get_transform_type_or_number) (transform_substructure_t *this);
/**
* Get transform id of the current transform.
@ -89,16 +82,11 @@ struct transform_substructure_t {
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
* Get transform id of the current transform.
* Create an enumerator over transform attributes.
*
* @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!
* @return enumerator over transform_attribute_t*
*/
status_t (*get_key_length) (transform_substructure_t *this,
u_int16_t *key_length);
enumerator_t* (*create_attribute_enumerator)(transform_substructure_t *this);
/**
* Destroys an transform_substructure_t object.
@ -109,19 +97,20 @@ struct transform_substructure_t {
/**
* Creates an empty transform_substructure_t object.
*
* @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
* @return created transform_substructure_t object
*/
transform_substructure_t *transform_substructure_create(void);
transform_substructure_t *transform_substructure_create(payload_type_t type);
/**
* Creates an empty transform_substructure_t object.
*
* @param type type of transform to create
* @param id transform id specifc for the transform type
* @param key_length key length for key length attribute, 0 to omit
* @return transform_substructure_t object
* @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
* @param type_or_number Type (IKEv2) or number (IKEv1) of transform
* @param id transform id specifc for the transform type
* @return transform_substructure_t object
*/
transform_substructure_t *transform_substructure_create_type(
transform_type_t type, u_int16_t id, u_int16_t key_length);
transform_substructure_t *transform_substructure_create_type(payload_type_t type,
u_int8_t type_or_number, u_int16_t id);
#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/

View File

@ -81,7 +81,7 @@ struct private_ts_payload_t {
* The defined offsets are the positions in a object of type
* private_ts_payload_t.
*/
encoding_rule_t ts_payload_encodings[] = {
static encoding_rule_t 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 */
@ -102,8 +102,9 @@ encoding_rule_t ts_payload_encodings[] = {
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[0])},
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[1])},
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[2])},
/* some ts data bytes, length is defined in PAYLOAD_LENGTH */
{ TRAFFIC_SELECTORS,offsetof(private_ts_payload_t, substrs) }
/* wrapped list of traffic selectors substructures */
{ PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE,
offsetof(private_ts_payload_t, substrs) },
};
/*
@ -145,11 +146,17 @@ METHOD(payload_t, verify, status_t,
return status;
}
METHOD(payload_t, get_encoding_rules, void,
private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_ts_payload_t *this, encoding_rule_t **rules)
{
*rules = ts_payload_encodings;
*rule_count = countof(ts_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_ts_payload_t *this)
{
return 8;
}
METHOD(payload_t, get_type, payload_type_t,
@ -182,7 +189,7 @@ static void compute_length(private_ts_payload_t *this)
enumerator_t *enumerator;
payload_t *subst;
this->payload_length = TS_PAYLOAD_HEADER_LENGTH;
this->payload_length = get_header_length(this);
this->ts_num = 0;
enumerator = this->substrs->create_enumerator(this->substrs);
while (enumerator->enumerate(enumerator, &subst))
@ -250,6 +257,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -262,7 +270,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = TS_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.is_initiator = is_initiator,
.substrs = linked_list_create(),
);

View File

@ -30,11 +30,6 @@ typedef struct ts_payload_t ts_payload_t;
#include <encoding/payloads/payload.h>
#include <encoding/payloads/traffic_selector_substructure.h>
/**
* Length of a TS payload without the Traffic selectors.
*/
#define TS_PAYLOAD_HEADER_LENGTH 8
/**
* Class representing an IKEv2 TS payload.
*

View File

@ -68,7 +68,7 @@ struct private_unknown_payload_t {
* private_unknown_payload_t.
*
*/
encoding_rule_t unknown_payload_encodings[] = {
static encoding_rule_t 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 */
@ -84,7 +84,7 @@ encoding_rule_t unknown_payload_encodings[] = {
/* 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) },
{ CHUNK_DATA, offsetof(private_unknown_payload_t, data) },
};
/*
@ -102,18 +102,20 @@ encoding_rule_t unknown_payload_encodings[] = {
METHOD(payload_t, verify, status_t,
private_unknown_payload_t *this)
{
if (this->payload_length != UNKNOWN_PAYLOAD_HEADER_LENGTH + this->data.len)
{
return FAILED;
}
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_unknown_payload_t *this, encoding_rule_t **rules)
{
*rules = unknown_payload_encodings;
*rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_unknown_payload_t *this)
{
return 4;
}
METHOD(payload_t, get_payload_type, payload_type_t,
@ -171,6 +173,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -182,7 +185,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH,
.payload_length = get_header_length(this),
.type = type,
);
@ -201,7 +204,7 @@ unknown_payload_t *unknown_payload_create_data(payload_type_t type,
this = (private_unknown_payload_t*)unknown_payload_create(type);
this->data = data;
this->critical = critical;
this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH + data.len;
this->payload_length = get_header_length(this) + data.len;
return &this->public;
}

View File

@ -27,11 +27,6 @@ typedef struct unknown_payload_t unknown_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
/**
* Header length of the unknown payload.
*/
#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
/**
* Payload which can't be processed further.
*

View File

@ -55,6 +55,11 @@ struct private_vendor_id_payload_t {
* The contained data.
*/
chunk_t data;
/**
* Either a IKEv1 or a IKEv2 vendor ID payload
*/
payload_type_t type;
};
/**
@ -63,7 +68,7 @@ struct private_vendor_id_payload_t {
* The defined offsets are the positions in a object of type
* private_vendor_id_payload_t.
*/
encoding_rule_t vendor_id_payload_encodings[] = {
static encoding_rule_t 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 */
@ -79,7 +84,7 @@ encoding_rule_t vendor_id_payload_encodings[] = {
/* 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, data) }
{ CHUNK_DATA, offsetof(private_vendor_id_payload_t, data) }
};
/*
@ -100,18 +105,23 @@ METHOD(payload_t, verify, status_t,
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_vendor_id_payload_t *this, encoding_rule_t **rules,
size_t *rule_count)
METHOD(payload_t, get_encoding_rules, int,
private_vendor_id_payload_t *this, encoding_rule_t **rules)
{
*rules = vendor_id_payload_encodings;
*rule_count = countof(vendor_id_payload_encodings);
*rules = encodings;
return countof(encodings);
}
METHOD(payload_t, get_header_length, int,
private_vendor_id_payload_t *this)
{
return 4;
}
METHOD(payload_t, get_type, payload_type_t,
private_vendor_id_payload_t *this)
{
return VENDOR_ID;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -148,7 +158,8 @@ METHOD2(payload_t, vendor_id_payload_t, destroy, void,
/*
* Described in header
*/
vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
chunk_t data)
{
private_vendor_id_payload_t *this;
@ -157,6 +168,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_header_length = _get_header_length,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
@ -167,8 +179,9 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + data.len,
.payload_length = get_header_length(this) + data.len,
.data = data,
.type = type,
);
return &this->public;
}
@ -176,7 +189,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
/*
* Described in header
*/
vendor_id_payload_t *vendor_id_payload_create()
vendor_id_payload_t *vendor_id_payload_create(payload_type_t type)
{
return vendor_id_payload_create_data(chunk_empty);
return vendor_id_payload_create_data(type, chunk_empty);
}

View File

@ -28,12 +28,7 @@ typedef struct vendor_id_payload_t vendor_id_payload_t;
#include <encoding/payloads/payload.h>
/**
* Length of a VENDOR ID payload without the VID data in bytes.
*/
#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
/**
* Class representing an IKEv2 VENDOR ID payload.
* Class representing an IKEv1/IKEv2 VENDOR ID payload.
*
* The VENDOR ID payload format is described in RFC section 3.12.
*/
@ -58,18 +53,21 @@ struct vendor_id_payload_t {
};
/**
* Creates an empty Vendor ID payload.
* Creates an empty Vendor ID payload for IKEv1 or IKEv2.
*
* @@param type VENDOR_ID or VENDOR_ID_V1
* @return vendor ID payload
*/
vendor_id_payload_t *vendor_id_payload_create();
vendor_id_payload_t *vendor_id_payload_create(payload_type_t type);
/**
* Creates a vendor ID payload using a chunk of data
*
* @param type VENDOR_ID or VENDOR_ID_V1
* @param data data to use in vendor ID payload, gets owned by payload
* @return vendor ID payload
*/
vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data);
vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
chunk_t data);
#endif /** VENDOR_ID_PAYLOAD_H_ @}*/

View File

@ -84,7 +84,7 @@ METHOD(kernel_listener_t, expire, bool,
protocol_id_names, proto, ntohl(spi), reqid);
if (hard)
{
job = (job_t*)delete_child_sa_job_create(reqid, proto, spi);
job = (job_t*)delete_child_sa_job_create(reqid, proto, spi, hard);
}
else
{

View File

@ -38,6 +38,8 @@
#define BLOCK_THRESHOLD_DEFAULT 5
/** length of the secret to use for cookie calculation */
#define SECRET_LENGTH 16
/** Length of a notify payload header */
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
typedef struct private_receiver_t private_receiver_t;
@ -134,34 +136,34 @@ struct private_receiver_t {
/**
* send a notify back to the sender
*/
static void send_notify(message_t *request, notify_type_t type, chunk_t data)
static void send_notify(message_t *request, int major, exchange_type_t exchange,
notify_type_t type, chunk_t data)
{
if (request->get_request(request) &&
request->get_exchange_type(request) == IKE_SA_INIT)
{
message_t *response;
host_t *src, *dst;
packet_t *packet;
ike_sa_id_t *ike_sa_id;
ike_sa_id_t *ike_sa_id;
message_t *response;
host_t *src, *dst;
packet_t *packet;
response = message_create();
dst = request->get_source(request);
src = request->get_destination(request);
response->set_source(response, src->clone(src));
response->set_destination(response, dst->clone(dst));
response->set_exchange_type(response, request->get_exchange_type(request));
response = message_create(major, 0);
response->set_exchange_type(response, exchange);
response->add_notify(response, FALSE, type, data);
dst = request->get_source(request);
src = request->get_destination(request);
response->set_source(response, src->clone(src));
response->set_destination(response, dst->clone(dst));
if (major == IKEV2_MAJOR_VERSION)
{
response->set_request(response, FALSE);
response->set_message_id(response, 0);
ike_sa_id = request->get_ike_sa_id(request);
ike_sa_id->switch_initiator(ike_sa_id);
response->set_ike_sa_id(response, ike_sa_id);
response->add_notify(response, FALSE, type, data);
if (response->generate(response, NULL, &packet) == SUCCESS)
{
charon->sender->send(charon->sender, packet);
response->destroy(response);
}
}
response->set_message_id(response, 0);
ike_sa_id = request->get_ike_sa_id(request);
ike_sa_id->switch_initiator(ike_sa_id);
response->set_ike_sa_id(response, ike_sa_id);
if (response->generate(response, NULL, &packet) == SUCCESS)
{
charon->sender->send(charon->sender, packet);
}
response->destroy(response);
}
/**
@ -269,8 +271,9 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
half_open = charon->ike_sa_manager->get_half_open_count(
charon->ike_sa_manager, NULL);
/* check for cookies */
if (this->cookie_threshold && half_open >= this->cookie_threshold &&
/* check for cookies in IKEv2 */
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
this->cookie_threshold && half_open >= this->cookie_threshold &&
!check_cookie(this, message))
{
u_int32_t now = time_monotonic(NULL);
@ -282,7 +285,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
message->get_destination(message));
DBG2(DBG_NET, "sending COOKIE notify to %H",
message->get_source(message));
send_notify(message, COOKIE, cookie);
send_notify(message, IKEV2_MAJOR_VERSION, IKE_SA_INIT, COOKIE, cookie);
chunk_free(&cookie);
if (++this->secret_used > COOKIE_REUSE)
{
@ -290,7 +293,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
DBG1(DBG_NET, "generating new cookie secret after %d uses",
this->secret_used);
memcpy(this->secret_old, this->secret, SECRET_LENGTH);
this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
this->secret_switch = now;
this->secret_used = 0;
}
@ -342,9 +345,11 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
*/
static job_requeue_t receive_packets(private_receiver_t *this)
{
ike_sa_id_t *id;
packet_t *packet;
message_t *message;
status_t status;
bool supported = TRUE;
/* read in a packet */
status = charon->socket->receive(charon->socket, &packet);
@ -371,16 +376,50 @@ static job_requeue_t receive_packets(private_receiver_t *this)
}
/* check IKE major version */
if (message->get_major_version(message) != IKE_MAJOR_VERSION)
switch (message->get_major_version(message))
{
DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, "
"sending INVALID_MAJOR_VERSION", message->get_major_version(message),
case IKEV2_MAJOR_VERSION:
#ifndef USE_IKEV2
if (message->get_exchange_type(message) == IKE_SA_INIT &&
message->get_request(message))
{
send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
INVALID_MAJOR_VERSION, chunk_empty);
supported = FALSE;
}
#endif /* USE_IKEV2 */
break;
case IKEV1_MAJOR_VERSION:
#ifndef USE_IKEV1
if (message->get_exchange_type(message) == ID_PROT ||
message->get_exchange_type(message) == AGGRESSIVE)
{
send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
INVALID_MAJOR_VERSION, chunk_empty);
supported = FALSE;
}
#endif /* USE_IKEV1 */
break;
default:
#ifdef USE_IKEV2
send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
INVALID_MAJOR_VERSION, chunk_empty);
#endif /* USE_IKEV2 */
#ifdef USE_IKEV1
send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
INVALID_MAJOR_VERSION, chunk_empty);
#endif /* USE_IKEV1 */
supported = FALSE;
break;
}
if (!supported)
{
DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, sending "
"INVALID_MAJOR_VERSION", message->get_major_version(message),
message->get_minor_version(message), packet->get_source(packet));
send_notify(message, INVALID_MAJOR_VERSION, chunk_empty);
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
if (message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
@ -390,6 +429,18 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_DIRECT;
}
}
if (message->get_exchange_type(message) == ID_PROT ||
message->get_exchange_type(message) == AGGRESSIVE)
{
id = message->get_ike_sa_id(message);
if (id->get_responder_spi(id) == 0 &&
drop_ike_sa_init(this, message))
{
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
}
if (this->receive_delay)
{
if (this->receive_delay_type == 0 ||

View File

@ -273,11 +273,11 @@ static job_requeue_t initiate(private_android_service_t *this)
hostname, IKEV2_UDP_PORT);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("android", 2, ike_cfg, CERT_SEND_IF_ASKED,
peer_cfg = peer_cfg_create("android", IKEV2, ike_cfg, CERT_SEND_IF_ASKED,
UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, 0, /* mobike, DPD */
TRUE, FALSE, 0, /* mobike, aggressive, DPD */
host_create_from_string("0.0.0.0", 0) /* virt */,
NULL, FALSE, NULL, NULL); /* pool, mediation */
@ -300,12 +300,17 @@ static job_requeue_t initiate(private_android_service_t *this)
0, "255.255.255.255", 65535);
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
/* get an additional reference because initiate consumes one */
child_cfg->get_ref(child_cfg);
/* get us an IKE_SA */
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
peer_cfg);
if (!ike_sa)
{
peer_cfg->destroy(peer_cfg);
send_status(this, VPN_ERROR_CONNECTION_FAILED);
return JOB_REQUEUE_NONE;
}
if (!ike_sa->get_peer_cfg(ike_sa))
{
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
@ -318,6 +323,8 @@ static job_requeue_t initiate(private_android_service_t *this)
/* confirm that we received the request */
send_status(this, i);
/* get an additional reference because initiate consumes one */
child_cfg->get_ref(child_cfg);
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
{
DBG1(DBG_CFG, "failed to initiate tunnel");

View File

@ -176,9 +176,9 @@ METHOD(listener_t, ike_updown, bool,
METHOD(listener_t, message_hook, bool,
private_duplicheck_listener_t *this, ike_sa_t *ike_sa,
message_t *message, bool incoming)
message_t *message, bool incoming, bool plain)
{
if (incoming && !message->get_request(message))
if (incoming && plain && !message->get_request(message))
{
identification_t *id;
entry_t *entry;

View File

@ -23,7 +23,7 @@
typedef struct eap_aka_peer_t eap_aka_peer_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* EAP-AKA peer implementation.

View File

@ -23,7 +23,7 @@
typedef struct eap_aka_server_t eap_aka_server_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* EAP-AKA server implementation.

View File

@ -23,7 +23,7 @@
typedef struct eap_gtc_t eap_gtc_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-GTC.

View File

@ -23,7 +23,7 @@
typedef struct eap_identity_t eap_identity_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP Identity.

View File

@ -23,7 +23,7 @@
typedef struct eap_md5_t eap_md5_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-MD5 (CHAP).

View File

@ -23,7 +23,7 @@
typedef struct eap_mschapv2_t eap_mschapv2_t;
#include <sa/authenticators/eap/eap_method.h>
#include <sa/eap/eap_method.h>
/**
* Implementation of the eap_method_t interface using EAP-MS-CHAPv2.

Some files were not shown because too many files have changed in this diff Show More