This commit is contained in:
Martin Willi
2006-05-10 08:02:49 +00:00
parent 95806de938
commit b8577029d1
148 changed files with 0 additions and 105 deletions
+30
View File
@@ -0,0 +1,30 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
ENCODING_DIR= $(CHARON_DIR)encoding/
CHARON_OBJS+= $(BUILD_DIR)generator.o
$(BUILD_DIR)generator.o : $(ENCODING_DIR)generator.c $(ENCODING_DIR)generator.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)parser.o
$(BUILD_DIR)parser.o : $(ENCODING_DIR)parser.c $(ENCODING_DIR)parser.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)message.o
$(BUILD_DIR)message.o : $(ENCODING_DIR)message.c $(ENCODING_DIR)message.h
$(CC) $(CFLAGS) -c -o $@ $<
include $(ENCODING_DIR)payloads/Makefile.payloads
File diff suppressed because it is too large Load Diff
+101
View File
@@ -0,0 +1,101 @@
/**
* @file generator.h
*
* @brief Interface of generator_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef GENERATOR_H_
#define GENERATOR_H_
#include <types.h>
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
/**
* Generating is done in a data buffer.
* This is thehe start size of this buffer in bytes.
*
* @ingroup enconding
*/
#define GENERATOR_DATA_BUFFER_SIZE 500
/**
* Number of bytes to increase the buffer, if it is to small.
*
* @ingroup enconding
*/
#define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
typedef struct generator_t generator_t;
/**
* @brief A generator_t class used to generate IKEv2 payloads.
*
* After creation, multiple payloads can be generated with the generate_payload
* method. The generated bytes are appended. After all payloads are added,
* the write_to_chunk method writes out all generated data since
* the creation of the generator. After that, the generator must be destroyed.
* The generater uses a set of encoding rules, which it can get from
* the supplied payload. With this rules, the generater can generate
* the payload and all substructures automatically.
*
* @b Constructor:
* - generator_create()
*
* @ingroup encoding
*/
struct generator_t {
/**
* @brief Generates a specific payload from given payload object.
*
* Remember: Header and substructures are also handled as payloads.
*
* @param this generator_t object
* @param[in] payload interface payload_t implementing object
*/
void (*generate_payload) (generator_t *this,payload_t *payload);
/**
* @brief Writes all generated data of the generator to a chunk.
*
* @param this generator_t object
* @param[out] data chunk to write the data to
*/
void (*write_to_chunk) (generator_t *this,chunk_t *data);
/**
* @brief Destroys a generator_t object.
*
* @param this generator_t object
*/
void (*destroy) (generator_t *this);
};
/**
* @brief Constructor to create a generator.
*
* @return generator_t object.
*
* @ingroup encoding
*/
generator_t *generator_create(void);
#endif /*GENERATOR_H_*/
File diff suppressed because it is too large Load Diff
+367
View File
@@ -0,0 +1,367 @@
/**
* @file message.h
*
* @brief Interface of message_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef MESSAGE_H_
#define MESSAGE_H_
#include <types.h>
#include <sa/ike_sa_id.h>
#include <network/packet.h>
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/notify_payload.h>
#include <utils/linked_list.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
typedef struct message_t message_t;
/**
* @brief This class is used to represent an IKEv2-Message.
*
* The message handles parsing and generation of payloads
* via parser_t/generator_t. Encryption is done transparently
* via the encryption_payload_t. A set of rules for messages
* and payloads does check parsed messages.
*
* @b Constructors:
* - message_create()
* - message_create_from_packet()
* - message_create_notify_reply()
*
* @ingroup encoding
*/
struct message_t {
/**
* @brief Sets the IKE major version of the message.
*
* @param this message_t object
* @param major_version major version to set
*/
void (*set_major_version) (message_t *this,u_int8_t major_version);
/**
* @brief Gets the IKE major version of the message.
*
* @param this message_t object
* @return major version of the message
*/
u_int8_t (*get_major_version) (message_t *this);
/**
* @brief Sets the IKE minor version of the message.
*
* @param this message_t object
* @param minor_version minor version to set
*/
void (*set_minor_version) (message_t *this,u_int8_t minor_version);
/**
* @brief Gets the IKE minor version of the message.
*
* @param this message_t object
* @return minor version of the message
*/
u_int8_t (*get_minor_version) (message_t *this);
/**
* @brief Sets the Message ID of the message.
*
* @param this message_t object
* @param message_id message_id to set
*/
void (*set_message_id) (message_t *this,u_int32_t message_id);
/**
* @brief Gets the Message ID of the message.
*
* @param this message_t object
* @return message_id type of the message
*/
u_int32_t (*get_message_id) (message_t *this);
/**
* @brief Gets the responder SPI of the message.
*
* @param this message_t object
* @return responder spi of the message
*/
u_int64_t (*get_responder_spi) (message_t *this);
/**
* @brief Sets the IKE_SA ID of the message.
*
* @warning ike_sa_id gets cloned internaly and
* so can be destroyed afterwards.
*
* @param this message_t object
* @param ike_sa_id ike_sa_id to set
*/
void (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id);
/**
* @brief Gets the IKE_SA ID of the message.
*
* @warning The returned ike_sa_id is a clone of the internal one.
* So it has to be destroyed by the caller.
*
* @param this message_t object
* @param ike_sa_id pointer to ike_sa_id pointer which will be set
* @return
* - SUCCESS
* - FAILED if no ike_sa_id is set
*/
status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id);
/**
* @brief Sets the exchange type of the message.
*
* @param this message_t object
* @param exchange_type exchange_type to set
*/
void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type);
/**
* @brief Gets the exchange type of the message.
*
* @param this message_t object
* @return exchange type of the message
*/
exchange_type_t (*get_exchange_type) (message_t *this);
/**
* @brief Sets the request flag.
*
* @param this message_t object
* @param original_initiator TRUE if message is a request, FALSE if it is a reply
*/
void (*set_request) (message_t *this,bool request);
/**
* @brief Gets request flag.
*
* @param this message_t object
* @return TRUE if message is a request, FALSE if it is a reply
*/
bool (*get_request) (message_t *this);
/**
* @brief Append a payload to the message.
*
* If the payload must be encrypted is not specified here. Encryption
* of payloads is evaluated via internal rules for the messages and
* is done before generation. The order of payloads may change, since
* all payloads to encrypt are added to the encryption payload, which is
* always the last one.
*
* @param this message_t object
* @param payload payload to append
*/
void (*add_payload) (message_t *this, payload_t *payload);
/**
* @brief Parses header of message.
*
* Begins parisng of a message created via message_create_from_packet().
* The parsing context is stored, so a subsequent call to parse_body()
* will continue the parsing process.
*
* @param this message_t object
* @return
* - SUCCESS if header could be parsed
* - PARSE_ERROR if corrupted/invalid data found
* - FAILED if consistence check of header failed
*/
status_t (*parse_header) (message_t *this);
/**
* @brief Parses body of message.
*
* The body gets not only parsed, but rather it gets verified.
* All payloads are verified if they are allowed to exist in the message
* of this type and if their own structure is ok.
* If there are encrypted payloads, they get decrypted via the supplied
* crypter. Also the message integrity gets verified with the supplied
* signer.
* Crypter/signer can be omitted (by passing NULL) when no encryption
* payload is expected.
*
* @param this message_t object
* @param crypter crypter to decrypt encryption payloads
* @param signer signer to verifiy a message with an encryption payload
* @return
* - SUCCESS if header could be parsed
* - NOT_SUPPORTED if ciritcal unknown payloads found
* - FAILED if message type is not suppported!
* - PARSE_ERROR if corrupted/invalid data found
* - VERIFY_ERROR if verification of some payload failed
* - INVALID_STATE if crypter/signer not supplied, but needed
*/
status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer);
/**
* @brief Generates the UDP packet of specific message.
*
* Payloads which must be encrypted are generated first and added to
* an encryption payload. This encryption payload will get encrypted via
* the supplied crypter. Then all other payloads and the header get generated.
* After that, the checksum is added to the encryption payload over the full
* message.
* Crypter/signer can be omitted (by passing NULL) when no encryption
* payload is expected.
*
* @param this message_t object
* @param crypter crypter to use when a payload must be encrypted
* @param signer signer to build a mac
* @return
* - SUCCESS if packet could be generated
* - INVALID_STATE if exchange type is currently not set
* - NOT_FOUND if no rules found for message generation
* - INVALID_STATE if crypter/signer not supplied but needed.
*/
status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet);
/**
* @brief Gets the source host informations.
*
* @warning Returned host_t object is not getting cloned,
* do not destroy nor modify.
*
* @param this message_t object
* @return host_t object representing source host
*/
host_t * (*get_source) (message_t *this);
/**
* @brief Sets the source host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
* message_t.destroy or next call of message_t.set_source.
*
* @param this message_t object
* @param host host_t object representing source host
*/
void (*set_source) (message_t *this, host_t *host);
/**
* @brief Gets the destination host informations.
*
* @warning Returned host_t object is not getting cloned,
* do not destroy nor modify.
*
* @param this message_t object
* @return host_t object representing destination host
*/
host_t * (*get_destination) (message_t *this);
/**
* @brief Sets the destination host informations.
*
* @warning host_t object is not getting cloned and gets destroyed by
* message_t.destroy or next call of message_t.set_destination.
*
* @param this message_t object
* @param host host_t object representing destination host
*/
void (*set_destination) (message_t *this, host_t *host);
/**
* @brief Returns an iterator on all stored payloads.
*
* @warning Don't insert payloads over this iterator.
* Use add_payload() instead.
*
* @param this message_t object
* @return iterator_t object which has to get destroyd by the caller
*/
iterator_t * (*get_payload_iterator) (message_t *this);
/**
* Returns a clone of the internal stored packet_t object.
*
* @param this message_t object
* @return packet_t object as clone of internal one
*/
packet_t * (*get_packet) (message_t *this);
/**
* Returns a clone of the internal stored packet_t data.
*
* @param this message_t object
* @return clone of the internal stored packet_t data.
*/
chunk_t (*get_packet_data) (message_t *this);
/**
* @brief Destroys a message and all including objects.
*
* @param this message_t object
*/
void (*destroy) (message_t *this);
};
/**
* @brief Creates an message_t object from a incoming UDP Packet.
*
* @warning the given packet_t object is not copied and gets
* destroyed in message_t's destroy call.
*
* @warning Packet is not parsed in here!
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
* Call message_t.parse_header afterwards.
*
* @param packet packet_t object which is assigned to message
* @return message_t object
*
* @ingroup encoding
*/
message_t * message_create_from_packet(packet_t *packet);
/**
* @brief Creates an empty message_t object.
*
* - exchange_type is set to NOT_SET
* - original_initiator is set to TRUE
* - is_request is set to TRUE
*
* @return message_t object
*
* @ingroup encoding
*/
message_t * message_create(void);
/**
* @brief Creates an message_t object of type reply containing a notify payload.
*
* @return message_t object
*
* @ingroup encoding
*/
message_t *message_create_notify_reply(host_t *source, host_t *destination, exchange_type_t exchange_type, bool original_initiator,ike_sa_id_t *ike_sa_id,notify_message_type_t notify_type);
#endif /*MESSAGE_H_*/
File diff suppressed because it is too large Load Diff
+95
View File
@@ -0,0 +1,95 @@
/**
* @file parser.h
*
* @brief Interface of parser_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PARSER_H_
#define PARSER_H_
#include <types.h>
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
typedef struct parser_t parser_t;
/**
* @brief A parser_t class to parse IKEv2 payloads.
*
* A parser is used for parsing one chunk of data. Multiple
* payloads can be parsed out of the chunk using parse_payload.
* The parser remains the state until destroyed.
*
* @b Constructors:
* - parser_create()
*
* @ingroup encoding
*/
struct parser_t {
/**
* @brief Parses the next payload.
*
* @warning Caller is responsible for freeing allocated payload.
*
* Rules for parsing are described in the payload definition.
*
* @param this parser_t bject
* @param payload_type payload type to parse
* @param[out] payload pointer where parsed payload was allocated
* @return
* - SUCCESSFUL if succeeded,
* - PARSE_ERROR if corrupted/invalid data found
*/
status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
/**
* Gets the remaining byte count which is not currently parsed.
*
* @param parser parser_t object
*/
int (*get_remaining_byte_count) (parser_t *this);
/**
* @brief Resets the current parser context.
*
* @param parser parser_t object
*/
void (*reset_context) (parser_t *this);
/**
* @brief Destroys a parser_t object.
*
* @param parser parser_t object
*/
void (*destroy) (parser_t *this);
};
/**
* @brief Constructor to create a parser_t object.
*
* @param data chunk of data to parse with this parser_t object
* @return parser_t object
*
* @ingroup encoding
*/
parser_t *parser_create(chunk_t data);
#endif /*PARSER_H_*/
@@ -0,0 +1,108 @@
# Copyright (C) 2005 Jan Hutter, Martin Willi
# Hochschule fuer Technik Rapperswil
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
PAYLOADS_DIR= $(ENCODING_DIR)payloads/
CHARON_OBJS+= $(BUILD_DIR)encodings.o
$(BUILD_DIR)encodings.o : $(PAYLOADS_DIR)encodings.c $(PAYLOADS_DIR)encodings.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ike_header.o
$(BUILD_DIR)ike_header.o : $(PAYLOADS_DIR)ike_header.c $(PAYLOADS_DIR)ike_header.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ke_payload.o
$(BUILD_DIR)ke_payload.o : $(PAYLOADS_DIR)ke_payload.c $(PAYLOADS_DIR)ke_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)nonce_payload.o
$(BUILD_DIR)nonce_payload.o : $(PAYLOADS_DIR)nonce_payload.c $(PAYLOADS_DIR)nonce_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)notify_payload.o
$(BUILD_DIR)notify_payload.o : $(PAYLOADS_DIR)notify_payload.c $(PAYLOADS_DIR)notify_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)id_payload.o
$(BUILD_DIR)id_payload.o : $(PAYLOADS_DIR)id_payload.c $(PAYLOADS_DIR)id_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)auth_payload.o
$(BUILD_DIR)auth_payload.o : $(PAYLOADS_DIR)auth_payload.c $(PAYLOADS_DIR)auth_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)cert_payload.o
$(BUILD_DIR)cert_payload.o : $(PAYLOADS_DIR)cert_payload.c $(PAYLOADS_DIR)cert_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)certreq_payload.o
$(BUILD_DIR)certreq_payload.o : $(PAYLOADS_DIR)certreq_payload.c $(PAYLOADS_DIR)certreq_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)delete_payload.o
$(BUILD_DIR)delete_payload.o : $(PAYLOADS_DIR)delete_payload.c $(PAYLOADS_DIR)delete_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)vendor_id_payload.o
$(BUILD_DIR)vendor_id_payload.o : $(PAYLOADS_DIR)vendor_id_payload.c $(PAYLOADS_DIR)vendor_id_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)cp_payload.o
$(BUILD_DIR)cp_payload.o : $(PAYLOADS_DIR)cp_payload.c $(PAYLOADS_DIR)cp_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)configuration_attribute.o
$(BUILD_DIR)configuration_attribute.o : $(PAYLOADS_DIR)configuration_attribute.c $(PAYLOADS_DIR)configuration_attribute.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)eap_payload.o
$(BUILD_DIR)eap_payload.o : $(PAYLOADS_DIR)eap_payload.c $(PAYLOADS_DIR)eap_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)unknown_payload.o
$(BUILD_DIR)unknown_payload.o : $(PAYLOADS_DIR)unknown_payload.c $(PAYLOADS_DIR)unknown_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)ts_payload.o
$(BUILD_DIR)ts_payload.o : $(PAYLOADS_DIR)ts_payload.c $(PAYLOADS_DIR)ts_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)traffic_selector_substructure.o
$(BUILD_DIR)traffic_selector_substructure.o : $(PAYLOADS_DIR)traffic_selector_substructure.c $(PAYLOADS_DIR)traffic_selector_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)payload.o
$(BUILD_DIR)payload.o : $(PAYLOADS_DIR)payload.c $(PAYLOADS_DIR)payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)proposal_substructure.o
$(BUILD_DIR)proposal_substructure.o : $(PAYLOADS_DIR)proposal_substructure.c $(PAYLOADS_DIR)proposal_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)sa_payload.o
$(BUILD_DIR)sa_payload.o : $(PAYLOADS_DIR)sa_payload.c $(PAYLOADS_DIR)sa_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)transform_attribute.o
$(BUILD_DIR)transform_attribute.o : $(PAYLOADS_DIR)transform_attribute.c $(PAYLOADS_DIR)transform_attribute.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)transform_substructure.o
$(BUILD_DIR)transform_substructure.o : $(PAYLOADS_DIR)transform_substructure.c $(PAYLOADS_DIR)transform_substructure.h
$(CC) $(CFLAGS) -c -o $@ $<
CHARON_OBJS+= $(BUILD_DIR)encryption_payload.o
$(BUILD_DIR)encryption_payload.o : $(PAYLOADS_DIR)encryption_payload.c $(PAYLOADS_DIR)encryption_payload.h
$(CC) $(CFLAGS) -c -o $@ $<
+265
View File
@@ -0,0 +1,265 @@
/**
* @file auth_payload.h
*
* @brief Implementation of auth_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "auth_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_auth_payload_t private_auth_payload_t;
/**
* Private data of an auth_payload_t object.
*
*/
struct private_auth_payload_t {
/**
* Public auth_payload_t interface.
*/
auth_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Method of the AUTH Data.
*/
u_int8_t auth_method;
/**
* The contained auth data value.
*/
chunk_t auth_data;
};
/**
* Encoding rules to parse or generate a AUTH payload
*
* The defined offsets are the positions in a object of type
* private_auth_payload_t.
*
*/
encoding_rule_t auth_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_auth_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_auth_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)},
/* 1 Byte AUTH type*/
{ U_INT_8, offsetof(private_auth_payload_t, auth_method) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some auth data bytes, length is defined in PAYLOAD_LENGTH */
{ AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Auth Method ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Authentication Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_auth_payload_t *this)
{
if ((this->auth_method == 0) ||
((this->auth_method >= 4) && (this->auth_method <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of auth_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = auth_payload_encodings;
*rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_auth_payload_t *this)
{
return AUTHENTICATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_auth_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_auth_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_auth_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of auth_payload_t.set_auth_method.
*/
static void set_auth_method (private_auth_payload_t *this, auth_method_t method)
{
this->auth_method = method;
}
/**
* Implementation of auth_payload_t.get_auth_method.
*/
static auth_method_t get_auth_method (private_auth_payload_t *this)
{
return (this->auth_method);
}
/**
* Implementation of auth_payload_t.set_data.
*/
static void set_data (private_auth_payload_t *this, chunk_t data)
{
if (this->auth_data.ptr != NULL)
{
chunk_free(&(this->auth_data));
}
this->auth_data.ptr = clalloc(data.ptr,data.len);
this->auth_data.len = data.len;
this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
}
/**
* Implementation of auth_payload_t.get_data.
*/
static chunk_t get_data (private_auth_payload_t *this)
{
return (this->auth_data);
}
/**
* Implementation of auth_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_auth_payload_t *this)
{
chunk_t cloned_data;
if (this->auth_data.ptr == NULL)
{
return (this->auth_data);
}
cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len);
cloned_data.len = this->auth_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and auth_payload_t.destroy.
*/
static void destroy(private_auth_payload_t *this)
{
if (this->auth_data.ptr != NULL)
{
chunk_free(&(this->auth_data));
}
free(this);
}
/*
* Described in header
*/
auth_payload_t *auth_payload_create()
{
private_auth_payload_t *this = malloc_thing(private_auth_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (auth_payload_t *)) destroy;
this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method;
this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method;
this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH;
this->auth_data = CHUNK_INITIALIZER;
return (&(this->public));
}
+122
View File
@@ -0,0 +1,122 @@
/**
* @file auth_payload.h
*
* @brief Interface of auth_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef AUTH_PAYLOAD_H_
#define AUTH_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <config/connections/connection.h>
/**
* Length of a auth payload without the auth data in bytes.
*
* @ingroup payloads
*/
#define AUTH_PAYLOAD_HEADER_LENGTH 8
typedef struct auth_payload_t auth_payload_t;
/**
* @brief Class representing an IKEv2 AUTH payload.
*
* The AUTH payload format is described in RFC section 3.8.
*
* @b Constructors:
* - auth_payload_create()
*
* @ingroup payloads
*/
struct auth_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the AUTH method.
*
* @param this calling auth_payload_t object
* @param method auth_method_t to use
*/
void (*set_auth_method) (auth_payload_t *this, auth_method_t method);
/**
* @brief Get the AUTH method.
*
* @param this calling auth_payload_t object
* @return auth_method_t used
*/
auth_method_t (*get_auth_method) (auth_payload_t *this);
/**
* @brief Set the AUTH data.
*
* Data are getting cloned.
*
* @param this calling auth_payload_t object
* @param data AUTH data as chunk_t
*/
void (*set_data) (auth_payload_t *this, chunk_t data);
/**
* @brief Get the AUTH data.
*
* Returned data are a copy of the internal one.
*
* @param this calling auth_payload_t object
* @return AUTH data as chunk_t
*/
chunk_t (*get_data_clone) (auth_payload_t *this);
/**
* @brief Get the AUTH data.
*
* Returned data are NOT copied
*
* @param this calling auth_payload_t object
* @return AUTH data as chunk_t
*/
chunk_t (*get_data) (auth_payload_t *this);
/**
* @brief Destroys an auth_payload_t object.
*
* @param this auth_payload_t object to destroy
*/
void (*destroy) (auth_payload_t *this);
};
/**
* @brief Creates an empty auth_payload_t object.
*
* @return auth_payload_t object
*
* @ingroup payloads
*/
auth_payload_t *auth_payload_create(void);
#endif /* AUTH_PAYLOAD_H_ */
+279
View File
@@ -0,0 +1,279 @@
/**
* @file cert_payload.c
*
* @brief Implementation of cert_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "cert_payload.h"
/**
* String mappings for cert_encoding_t.
*/
mapping_t cert_encoding_m[] = {
{PKCS7_WRAPPED_X509_CERTIFICATE, "PKCS7_WRAPPED_X509_CERTIFICATE"},
{PGP_CERTIFICATE, "PGP_CERTIFICATE"},
{DNS_SIGNED_KEY, "DNS_SIGNED_KEY"},
{X509_CERTIFICATE_SIGNATURE, "X509_CERTIFICATE_SIGNATURE"},
{KERBEROS_TOKEN, "KERBEROS_TOKEN"},
{CERTIFICATE_REVOCATION_LIST, "CERTIFICATE_REVOCATION_LIST"},
{AUTHORITY_REVOCATION_LIST, "AUTHORITY_REVOCATION_LIST"},
{SPKI_CERTIFICATE, "SPKI_CERTIFICATE"},
{X509_CERTIFICATE_ATTRIBUTE, "X509_CERTIFICATE_ATTRIBUTE"},
{RAW_SA_KEY, "RAW_SA_KEY"},
{HASH_AND_URL_X509_CERTIFICATE, "HASH_AND_URL_X509_CERTIFICATE"},
{HASH_AND_URL_X509_BUNDLE, "HASH_AND_URL_X509_BUNDLE"},
{MAPPING_END, NULL}
};
typedef struct private_cert_payload_t private_cert_payload_t;
/**
* Private data of an cert_payload_t object.
*
*/
struct private_cert_payload_t {
/**
* Public cert_payload_t interface.
*/
cert_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Encoding of the CERT Data.
*/
u_int8_t cert_encoding;
/**
* The contained cert data value.
*/
chunk_t cert_data;
};
/**
* Encoding rules to parse or generate a CERT payload
*
* The defined offsets are the positions in a object of type
* private_cert_payload_t.
*
*/
encoding_rule_t cert_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cert_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_cert_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
/* 1 Byte CERT type*/
{ U_INT_8, offsetof(private_cert_payload_t, cert_encoding) },
/* some cert data bytes, length is defined in PAYLOAD_LENGTH */
{ CERT_DATA, offsetof(private_cert_payload_t, cert_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certificate Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_cert_payload_t *this)
{
if ((this->cert_encoding == 0) ||
((this->cert_encoding >= 14) && (this->cert_encoding <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of cert_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cert_payload_encodings;
*rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_cert_payload_t *this)
{
return CERTIFICATE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_cert_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_cert_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_cert_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of cert_payload_t.set_cert_encoding.
*/
static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding)
{
this->cert_encoding = encoding;
}
/**
* Implementation of cert_payload_t.get_cert_encoding.
*/
static cert_encoding_t get_cert_encoding (private_cert_payload_t *this)
{
return (this->cert_encoding);
}
/**
* Implementation of cert_payload_t.set_data.
*/
static void set_data (private_cert_payload_t *this, chunk_t data)
{
if (this->cert_data.ptr != NULL)
{
chunk_free(&(this->cert_data));
}
this->cert_data.ptr = clalloc(data.ptr,data.len);
this->cert_data.len = data.len;
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len;
}
/**
* Implementation of cert_payload_t.get_data.
*/
static chunk_t get_data (private_cert_payload_t *this)
{
return (this->cert_data);
}
/**
* Implementation of cert_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_cert_payload_t *this)
{
chunk_t cloned_data;
if (this->cert_data.ptr == NULL)
{
return (this->cert_data);
}
cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len);
cloned_data.len = this->cert_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and cert_payload_t.destroy.
*/
static void destroy(private_cert_payload_t *this)
{
if (this->cert_data.ptr != NULL)
{
chunk_free(&(this->cert_data));
}
free(this);
}
/*
* Described in header
*/
cert_payload_t *cert_payload_create()
{
private_cert_payload_t *this = malloc_thing(private_cert_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (cert_payload_t *)) destroy;
this->public.set_cert_encoding = (void (*) (cert_payload_t *,cert_encoding_t)) set_cert_encoding;
this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t *)) get_cert_encoding;
this->public.set_data = (void (*) (cert_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (cert_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (cert_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =CERT_PAYLOAD_HEADER_LENGTH;
this->cert_data = CHUNK_INITIALIZER;
return (&(this->public));
}
+155
View File
@@ -0,0 +1,155 @@
/**
* @file cert_payload.h
*
* @brief Interface of cert_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CERT_PAYLOAD_H_
#define CERT_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a cert payload without the cert data in bytes.
*
* @ingroup payloads
*/
#define CERT_PAYLOAD_HEADER_LENGTH 5
typedef enum cert_encoding_t cert_encoding_t;
/**
* @brief Certificate encoding, as described in IKEv2 RFC section 3.6
*
* @ingroup payloads
*/
enum cert_encoding_t {
PKCS7_WRAPPED_X509_CERTIFICATE = 1,
PGP_CERTIFICATE = 2,
DNS_SIGNED_KEY = 3,
X509_CERTIFICATE_SIGNATURE = 4,
KERBEROS_TOKEN = 6,
CERTIFICATE_REVOCATION_LIST = 7,
AUTHORITY_REVOCATION_LIST = 8,
SPKI_CERTIFICATE = 9,
X509_CERTIFICATE_ATTRIBUTE = 10,
RAW_SA_KEY = 11,
HASH_AND_URL_X509_CERTIFICATE = 12,
HASH_AND_URL_X509_BUNDLE = 13
};
/**
* string mappings for cert_encoding_t.
*
* @ingroup payloads
*/
extern mapping_t cert_encoding_m[];
typedef struct cert_payload_t cert_payload_t;
/**
* @brief Class representing an IKEv2 CERT payload.
*
* The CERT payload format is described in RFC section 3.6.
* This is just a dummy implementation to fullfill the standards
* requirements. A full implementation would offer setters/getters
* for the different encoding types.
*
* @b Constructors:
* - cert_payload_create()
*
* @todo Implement setters/getters for the different certificate encodings.
*
* @ingroup payloads
*/
struct cert_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the CERT encoding.
*
* @param this calling cert_payload_t object
* @param encoding CERT encoding
*/
void (*set_cert_encoding) (cert_payload_t *this, cert_encoding_t encoding);
/**
* @brief Get the CERT encoding.
*
* @param this calling cert_payload_t object
* @return Encoding of the CERT
*/
cert_encoding_t (*get_cert_encoding) (cert_payload_t *this);
/**
* @brief Set the CERT data.
*
* Data are getting cloned.
*
* @param this calling cert_payload_t object
* @param data CERT data as chunk_t
*/
void (*set_data) (cert_payload_t *this, chunk_t data);
/**
* @brief Get the CERT data.
*
* Returned data are a copy of the internal one.
*
* @param this calling cert_payload_t object
* @return CERT data as chunk_t
*/
chunk_t (*get_data_clone) (cert_payload_t *this);
/**
* @brief Get the CERT data.
*
* Returned data are NOT copied.
*
* @param this calling cert_payload_t object
* @return CERT data as chunk_t
*/
chunk_t (*get_data) (cert_payload_t *this);
/**
* @brief Destroys an cert_payload_t object.
*
* @param this cert_payload_t object to destroy
*/
void (*destroy) (cert_payload_t *this);
};
/**
* @brief Creates an empty cert_payload_t object.
*
* @return cert_payload_t object
*
* @ingroup payloads
*/
cert_payload_t *cert_payload_create(void);
#endif /* CERT_PAYLOAD_H_ */
@@ -0,0 +1,259 @@
/**
* @file certreq_payload.c
*
* @brief Implementation of certreq_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "certreq_payload.h"
typedef struct private_certreq_payload_t private_certreq_payload_t;
/**
* Private data of an certreq_payload_t object.
*
*/
struct private_certreq_payload_t {
/**
* Public certreq_payload_t interface.
*/
certreq_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Encoding of the CERT Data.
*/
u_int8_t cert_encoding;
/**
* The contained certreq data value.
*/
chunk_t certreq_data;
};
/**
* Encoding rules to parse or generate a CERTREQ payload
*
* The defined offsets are the positions in a object of type
* private_certreq_payload_t.
*
*/
encoding_rule_t certreq_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_certreq_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)},
/* 1 Byte CERTREQ type*/
{ U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)},
/* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
{ CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certification Authority ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_certreq_payload_t *this)
{
if ((this->cert_encoding == 0) ||
((this->cert_encoding >= 14) && (this->cert_encoding <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of certreq_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = certreq_payload_encodings;
*rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_certreq_payload_t *this)
{
return CERTIFICATE_REQUEST;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_certreq_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_certreq_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_certreq_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of certreq_payload_t.set_cert_encoding.
*/
static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding)
{
this->cert_encoding = encoding;
}
/**
* Implementation of certreq_payload_t.get_cert_encoding.
*/
static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this)
{
return (this->cert_encoding);
}
/**
* Implementation of certreq_payload_t.set_data.
*/
static void set_data (private_certreq_payload_t *this, chunk_t data)
{
if (this->certreq_data.ptr != NULL)
{
chunk_free(&(this->certreq_data));
}
this->certreq_data.ptr = clalloc(data.ptr,data.len);
this->certreq_data.len = data.len;
this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len;
}
/**
* Implementation of certreq_payload_t.get_data.
*/
static chunk_t get_data (private_certreq_payload_t *this)
{
return (this->certreq_data);
}
/**
* Implementation of certreq_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_certreq_payload_t *this)
{
chunk_t cloned_data;
if (this->certreq_data.ptr == NULL)
{
return (this->certreq_data);
}
cloned_data.ptr = clalloc(this->certreq_data.ptr,this->certreq_data.len);
cloned_data.len = this->certreq_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and certreq_payload_t.destroy.
*/
static void destroy(private_certreq_payload_t *this)
{
if (this->certreq_data.ptr != NULL)
{
chunk_free(&(this->certreq_data));
}
free(this);
}
/*
* Described in header
*/
certreq_payload_t *certreq_payload_create()
{
private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (certreq_payload_t *)) destroy;
this->public.set_cert_encoding = (void (*) (certreq_payload_t *,cert_encoding_t)) set_cert_encoding;
this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t *)) get_cert_encoding;
this->public.set_data = (void (*) (certreq_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (certreq_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (certreq_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH;
this->certreq_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,125 @@
/**
* @file certreq_payload.h
*
* @brief Interface of certreq_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CERTREQ_PAYLOAD_H_
#define CERTREQ_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/cert_payload.h>
/**
* Length of a CERTREQ payload without the CERTREQ data in bytes.
*
* @ingroup payloads
*/
#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
typedef struct certreq_payload_t certreq_payload_t;
/**
* @brief Class representing an IKEv2 CERTREQ payload.
*
* The CERTREQ payload format is described in RFC section 3.7.
* This is just a dummy implementation to fullfill the standards
* requirements. A full implementation would offer setters/getters
* for the different encoding types.
*
* @b Constructors:
* - certreq_payload_create()
*
* @todo Implement payload functionality.
*
* @ingroup payloads
*/
struct certreq_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the CERT encoding.
*
* @param this calling certreq_payload_t object
* @param encoding CERT encoding
*/
void (*set_cert_encoding) (certreq_payload_t *this, cert_encoding_t encoding);
/**
* @brief Get the CERT encoding.
*
* @param this calling certreq_payload_t object
* @return Encoding of the CERT
*/
cert_encoding_t (*get_cert_encoding) (certreq_payload_t *this);
/**
* @brief Set the CERTREQ data.
*
* Data are getting cloned.
*
* @param this calling certreq_payload_t object
* @param data CERTREQ data as chunk_t
*/
void (*set_data) (certreq_payload_t *this, chunk_t data);
/**
* @brief Get the CERTREQ data.
*
* Returned data are a copy of the internal one.
*
* @param this calling certreq_payload_t object
* @return CERTREQ data as chunk_t
*/
chunk_t (*get_data_clone) (certreq_payload_t *this);
/**
* @brief Get the CERTREQ data.
*
* Returned data are NOT copied.
*
* @param this calling certreq_payload_t object
* @return CERTREQ data as chunk_t
*/
chunk_t (*get_data) (certreq_payload_t *this);
/**
* @brief Destroys an certreq_payload_t object.
*
* @param this certreq_payload_t object to destroy
*/
void (*destroy) (certreq_payload_t *this);
};
/**
* @brief Creates an empty certreq_payload_t object.
*
* @return certreq_payload_t object
*
* @ingroup payloads
*/
certreq_payload_t *certreq_payload_create(void);
#endif /* CERTREQ_PAYLOAD_H_ */
@@ -0,0 +1,282 @@
/**
* @file configuration_attribute.c
*
* @brief Implementation of configuration_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "configuration_attribute.h"
#include <encoding/payloads/encodings.h>
#include <types.h>
typedef struct private_configuration_attribute_t private_configuration_attribute_t;
/**
* Private data of an configuration_attribute_t object.
*
*/
struct private_configuration_attribute_t {
/**
* Public configuration_attribute_t interface.
*/
configuration_attribute_t public;
/**
* Type of the attribute.
*/
u_int16_t attribute_type;
/**
* Length of the attribute.
*/
u_int16_t attribute_length;
/**
* Attribute value as chunk.
*/
chunk_t attribute_value;
};
/**
* String mappings for configuration_attribute_type_t.
*/
mapping_t configuration_attribute_type_m[] = {
{INTERNAL_IP4_ADDRESS, "INTERNAL_IP4_ADDRESS"},
{INTERNAL_IP4_NETMASK, "INTERNAL_IP4_NETMASK"},
{INTERNAL_IP4_DNS, "INTERNAL_IP4_DNS"},
{INTERNAL_IP4_NBNS, "INTERNAL_IP4_NBNS"},
{INTERNAL_ADDRESS_EXPIRY, "INTERNAL_ADDRESS_EXPIRY"},
{INTERNAL_IP4_DHCP, "INTERNAL_IP4_DHCP"},
{APPLICATION_VERSION, "APPLICATION_VERSION"},
{INTERNAL_IP6_ADDRESS, "INTERNAL_IP6_ADDRESS"},
{INTERNAL_IP6_DNS, "INTERNAL_IP6_DNS"},
{INTERNAL_IP6_NBNS, "INTERNAL_IP6_NBNS"},
{INTERNAL_IP6_DHCP, "INTERNAL_IP6_DHCP"},
{INTERNAL_IP4_SUBNET, "INTERNAL_IP4_SUBNET"},
{SUPPORTED_ATTRIBUTES, "SUPPORTED_ATTRIBUTES"},
{INTERNAL_IP6_SUBNET, "INTERNAL_IP6_SUBNET"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a configuration attribute.
*
* The defined offsets are the positions in a object of type
* private_configuration_attribute_t.
*
*/
encoding_rule_t configuration_attribute_encodings[] = {
{ RESERVED_BIT, 0 },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attribute_type) },
/* Length of attribute value */
{ CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, attribute_length)},
/* Value of attribute if attribute format flag is zero */
{ CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, attribute_value)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!R| Attribute Type ! Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Value ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_configuration_attribute_t *this)
{
switch (this->attribute_type)
{
case INTERNAL_IP4_ADDRESS:
case INTERNAL_IP4_NETMASK:
case INTERNAL_IP4_DNS:
case INTERNAL_IP4_NBNS:
case INTERNAL_ADDRESS_EXPIRY:
case INTERNAL_IP4_DHCP:
case APPLICATION_VERSION:
case INTERNAL_IP6_ADDRESS:
case INTERNAL_IP6_DNS:
case INTERNAL_IP6_NBNS:
case INTERNAL_IP6_DHCP:
case INTERNAL_IP4_SUBNET:
case SUPPORTED_ATTRIBUTES:
case INTERNAL_IP6_SUBNET:
{
/* Attribute types are not checked in here */
break;
}
default:
return FAILED;
}
if (this->attribute_length != this->attribute_value.len)
{
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_configuration_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = configuration_attribute_encodings;
*rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_configuration_attribute_t *this)
{
return CONFIGURATION_ATTRIBUTE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_configuration_attribute_t *this)
{
return (NO_PAYLOAD);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_configuration_attribute_t *this,payload_type_t type)
{
}
/**
* Implementation of configuration_attribute_t.get_length.
*/
static size_t get_length(private_configuration_attribute_t *this)
{
return (this->attribute_value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH);
}
/**
* Implementation of configuration_attribute_t.set_value.
*/
static void set_value(private_configuration_attribute_t *this, chunk_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
chunk_free(&(this->attribute_value));
}
this->attribute_value.ptr = clalloc(value.ptr,value.len);
this->attribute_value.len = value.len;
this->attribute_length = this->attribute_value.len;
}
/**
* Implementation of configuration_attribute_t.get_value.
*/
static chunk_t get_value (private_configuration_attribute_t *this)
{
return this->attribute_value;
}
/**
* Implementation of configuration_attribute_t.set_attribute_type.
*/
static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
/**
* Implementation of configuration_attribute_t.get_attribute_type.
*/
static u_int16_t get_attribute_type (private_configuration_attribute_t *this)
{
return this->attribute_type;
}
/**
* Implementation of configuration_attribute_t.get_attribute_length.
*/
static u_int16_t get_attribute_length (private_configuration_attribute_t *this)
{
return this->attribute_length;
}
/**
* Implementation of configuration_attribute_t.destroy and payload_t.destroy.
*/
static void destroy(private_configuration_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
free(this->attribute_value.ptr);
}
free(this);
}
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create()
{
private_configuration_attribute_t *this = malloc_thing(private_configuration_attribute_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.set_value = (void (*) (configuration_attribute_t *,chunk_t)) set_value;
this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value;
this->public.set_attribute_type = (void (*) (configuration_attribute_t *,u_int16_t type)) set_attribute_type;
this->public.get_attribute_type = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_type;
this->public.get_attribute_length = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_length;
this->public.destroy = (void (*) (configuration_attribute_t *)) destroy;
/* set default values of the fields */
this->attribute_type = 0;
this->attribute_value = CHUNK_INITIALIZER;
this->attribute_length = 0;
return (&(this->public));
}
@@ -0,0 +1,149 @@
/**
* @file configuration_attribute.h
*
* @brief Interface of configuration_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CONFIGURATION_ATTRIBUTE_H_
#define CONFIGURATION_ATTRIBUTE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Configuration attribute header length in bytes.
*
* @ingroup payloads
*/
#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
typedef enum configuration_attribute_type_t configuration_attribute_type_t;
/**
* Type of the attribute, as in IKEv2 RFC 3.15.1.
*
* @ingroup payloads
*/
enum configuration_attribute_type_t {
INTERNAL_IP4_ADDRESS = 1,
INTERNAL_IP4_NETMASK = 2,
INTERNAL_IP4_DNS = 3,
INTERNAL_IP4_NBNS = 4,
INTERNAL_ADDRESS_EXPIRY = 5,
INTERNAL_IP4_DHCP = 6,
APPLICATION_VERSION = 7,
INTERNAL_IP6_ADDRESS = 8,
INTERNAL_IP6_DNS = 10,
INTERNAL_IP6_NBNS = 11,
INTERNAL_IP6_DHCP = 12,
INTERNAL_IP4_SUBNET = 13,
SUPPORTED_ATTRIBUTES = 14,
INTERNAL_IP6_SUBNET = 15
};
/**
* String mappings for configuration_attribute_type_t.
*
* @ingroup payloads
*/
extern mapping_t configuration_attribute_type_m[];
typedef struct configuration_attribute_t configuration_attribute_t;
/**
* @brief Class representing an IKEv2-CONFIGURATION Attribute.
*
* The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
*
* @b Constructors:
* - configuration_attribute_create()
*
* @ingroup payloads
*/
struct configuration_attribute_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling configuration_attribute_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_value) (configuration_attribute_t *this);
/**
* @brief Sets the value of the attribute.
*
* @warning Value is getting copied.
*
* @param this calling configuration_attribute_t object
* @param value chunk_t pointing to the value to set
*/
void (*set_value) (configuration_attribute_t *this, chunk_t value);
/**
* @brief Sets the type of the attribute.
*
* @param this calling configuration_attribute_t object
* @param type type to set (most significant bit is set to zero)
*/
void (*set_attribute_type) (configuration_attribute_t *this, u_int16_t type);
/**
* @brief get the type of the attribute.
*
* @param this calling configuration_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_type) (configuration_attribute_t *this);
/**
* @brief get the length of an attribute.
*
* @param this calling configuration_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_length) (configuration_attribute_t *this);
/**
* @brief Destroys an configuration_attribute_t object.
*
* @param this configuration_attribute_t object to destroy
*/
void (*destroy) (configuration_attribute_t *this);
};
/**
* @brief Creates an empty configuration_attribute_t object.
*
* @return created configuration_attribute_t object
*
* @ingroup payloads
*/
configuration_attribute_t *configuration_attribute_create(void);
#endif /* CONFIGURATION_ATTRIBUTE_H_*/
+305
View File
@@ -0,0 +1,305 @@
/**
* @file cp_payload.c
*
* @brief Implementation of cp_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "cp_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
/**
* String mappings for config_type_t.
*/
mapping_t config_type_m[] = {
{CFG_REQUEST, "CFG_REQUEST"},
{CFG_REPLY, "CFG_REPLY"},
{CFG_SET, "CFG_SET"},
{CFG_ACK, "CFG_ACK"},
{MAPPING_END, NULL}
};
typedef struct private_cp_payload_t private_cp_payload_t;
/**
* Private data of an cp_payload_t object.
*
*/
struct private_cp_payload_t {
/**
* Public cp_payload_t interface.
*/
cp_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Configuration Attributes in this payload are stored in a linked_list_t.
*/
linked_list_t * attributes;
/**
* Config Type.
*/
u_int8_t config_type;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_cp_payload_t object
*/
void (*compute_length) (private_cp_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-CP Payload
*
* The defined offsets are the positions in a object of type
* private_cp_payload_t.
*
*/
encoding_rule_t cp_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_cp_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole CP payload*/
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ U_INT_8, offsetof(private_cp_payload_t, config_type) },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
{ CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! CFG Type ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Configuration Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_cp_payload_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while(iterator->has_next(iterator))
{
configuration_attribute_t *attribute;
iterator->current(iterator,(void **)&attribute);
status = attribute->payload_interface.verify(&(attribute->payload_interface));
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = cp_payload_encodings;
*rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_cp_payload_t *this)
{
return CONFIGURATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_cp_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_cp_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_cp_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of cp_payload_t.create_configuration_attribute_iterator.
*/
static iterator_t *create_configuration_attribute_iterator (private_cp_payload_t *this,bool forward)
{
return this->attributes->create_iterator(this->attributes,forward);
}
/**
* Implementation of cp_payload_t.add_proposal_substructure.
*/
static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes,(void *) attribute);
this->compute_length(this);
}
/**
* Implementation of cp_payload_t.set_config_type.
*/
static void set_config_type (private_cp_payload_t *this,config_type_t config_type)
{
this->config_type = config_type;
}
/**
* Implementation of cp_payload_t.get_config_type.
*/
static config_type_t get_config_type (private_cp_payload_t *this)
{
return this->config_type;
}
/**
* Implementation of private_cp_payload_t.compute_length.
*/
static void compute_length (private_cp_payload_t *this)
{
iterator_t *iterator;
size_t length = CP_PAYLOAD_HEADER_LENGTH;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while (iterator->has_next(iterator))
{
payload_t *current_attribute;
iterator->current(iterator,(void **) &current_attribute);
length += current_attribute->get_length(current_attribute);
}
iterator->destroy(iterator);
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy and cp_payload_t.destroy.
*/
static status_t destroy(private_cp_payload_t *this)
{
/* all attributes are getting destroyed */
while (this->attributes->get_count(this->attributes) > 0)
{
configuration_attribute_t *current_attribute;
this->attributes->remove_last(this->attributes,(void **)&current_attribute);
current_attribute->destroy(current_attribute);
}
this->attributes->destroy(this->attributes);
free(this);
return SUCCESS;
}
/*
* Described in header.
*/
cp_payload_t *cp_payload_create()
{
private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
/* public interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_configuration_attribute_iterator = (iterator_t* (*) (cp_payload_t *,bool)) create_configuration_attribute_iterator;
this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute;
this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type;
this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type;
this->public.destroy = (void (*) (cp_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
this->attributes = linked_list_create();
return (&(this->public));
}
+138
View File
@@ -0,0 +1,138 @@
/**
* @file cp_payload.h
*
* @brief Interface of cp_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef CP_PAYLOAD_H_
#define CP_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <utils/linked_list.h>
/**
* CP_PAYLOAD length in bytes without any proposal substructure.
*
* @ingroup payloads
*/
#define CP_PAYLOAD_HEADER_LENGTH 8
typedef enum config_type_t config_type_t;
/**
* Config Type of an Configuration Payload.
*
* @ingroup payloads
*/
enum config_type_t {
CFG_REQUEST = 1,
CFG_REPLY = 2,
CFG_SET = 3,
CFG_ACK = 4,
};
/**
* string mappings for config_type_t.
*
* @ingroup payloads
*/
extern mapping_t config_type_m[];
typedef struct cp_payload_t cp_payload_t;
/**
* @brief Class representing an IKEv2-CP Payload.
*
* The CP Payload format is described in RFC section 3.15.
*
* @b Constructors:
* - cp_payload_create()
*
* @ingroup payloads
*/
struct cp_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored configuration_attribute_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an attribute using this iterator,
* the length of this configuration_attribute_t has to be refreshed
* by calling get_length()!
*
* @param this calling cp_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_configuration_attribute_iterator) (cp_payload_t *this, bool forward);
/**
* @brief Adds a configuration_attribute_t object to this object.
*
* @warning The added configuration_attribute_t object is
* getting destroyed in destroy function of cp_payload_t.
*
* @param this calling cp_payload_t object
* @param attribute configuration_attribute_t object to add
*/
void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute);
/**
* @brief Set the config type.
*
* @param this calling cp_payload_t object
* @param config_type config_type_t to set
*/
void (*set_config_type) (cp_payload_t *this,config_type_t config_type);
/**
* @brief Get the config type.
*
* @param this calling cp_payload_t object
* @return config_type_t
*/
config_type_t (*get_config_type) (cp_payload_t *this);
/**
* @brief Destroys an cp_payload_t object.
*
* @param this cp_payload_t object to destroy
*/
void (*destroy) (cp_payload_t *this);
};
/**
* @brief Creates an empty cp_payload_t object
*
* @return cp_payload_t object
*
* @ingroup payloads
*/
cp_payload_t *cp_payload_create(void);
#endif /*CP_PAYLOAD_H_*/
@@ -0,0 +1,322 @@
/**
* @file delete_payload.c
*
* @brief Implementation of delete_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "delete_payload.h"
typedef struct private_delete_payload_t private_delete_payload_t;
/**
* Private data of an delete_payload_t object.
*
*/
struct private_delete_payload_t {
/**
* Public delete_payload_t interface.
*/
delete_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Protocol ID.
*/
u_int8_t protocol_id;
/**
* SPI Size.
*/
u_int8_t spi_size;
/**
* Number of SPI's.
*/
u_int16_t spi_count;
/**
* The contained SPI's.
*/
chunk_t spis;
};
/**
* Encoding rules to parse or generate a DELETE payload
*
* The defined offsets are the positions in a object of type
* private_delete_payload_t.
*
*/
encoding_rule_t delete_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_delete_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length)},
{ U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
{ U_INT_8, offsetof(private_delete_payload_t, spi_size) },
{ U_INT_16, offsetof(private_delete_payload_t, spi_count) },
/* some delete data bytes, length is defined in PAYLOAD_LENGTH */
{ SPIS, offsetof(private_delete_payload_t, spis) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! # of SPIs !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index(es) (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_delete_payload_t *this)
{
if ((this->protocol_id == 0) ||
(this->protocol_id > 3))
{
/* reserved IDs */
return FAILED;
}
if (this->spis.len != (this->spi_count * this->spi_size))
{
return FAILED;
}
if ((this->protocol_id == PROTO_IKE) && (this->spis.len != 0))
{
/* IKE deletion has no spi assigned! */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of delete_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = delete_payload_encodings;
*rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_delete_payload_t *this)
{
return DELETE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_delete_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_delete_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_delete_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of delete_payload_t.set_protocol_id.
*/
static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of delete_payload_t.get_protocol_id.
*/
static protocol_id_t get_protocol_id (private_delete_payload_t *this)
{
return (this->protocol_id);
}
/**
* Implementation of delete_payload_t.set_spi_size.
*/
static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size)
{
this->spi_size = spi_size;
}
/**
* Implementation of delete_payload_t.get_spi_size.
*/
static u_int8_t get_spi_size (private_delete_payload_t *this)
{
return (this->spi_size);
}
/**
* Implementation of delete_payload_t.set_spi_count.
*/
static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count)
{
this->spi_count = spi_count;
}
/**
* Implementation of delete_payload_t.get_spi_count.
*/
static u_int16_t get_spi_count (private_delete_payload_t *this)
{
return (this->spi_count);
}
/**
* Implementation of delete_payload_t.set_spis.
*/
static void set_spis (private_delete_payload_t *this, chunk_t spis)
{
if (this->spis.ptr != NULL)
{
chunk_free(&(this->spis));
}
this->spis.ptr = clalloc(spis.ptr,spis.len);
this->spis.len = spis.len;
this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len;
}
/**
* Implementation of delete_payload_t.get_spis.
*/
static chunk_t get_spis (private_delete_payload_t *this)
{
return (this->spis);
}
/**
* Implementation of delete_payload_t.get_spis_clone.
*/
static chunk_t get_spis_clone (private_delete_payload_t *this)
{
chunk_t cloned_spis;
if (this->spis.ptr == NULL)
{
return (this->spis);
}
cloned_spis.ptr = clalloc(this->spis.ptr,this->spis.len);
cloned_spis.len = this->spis.len;
return cloned_spis;
}
/**
* Implementation of payload_t.destroy and delete_payload_t.destroy.
*/
static void destroy(private_delete_payload_t *this)
{
if (this->spis.ptr != NULL)
{
chunk_free(&(this->spis));
}
free(this);
}
/*
* Described in header
*/
delete_payload_t *delete_payload_create()
{
private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (delete_payload_t *)) destroy;
this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id;
this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size;
this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size;
this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count;
this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count;
this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis;
this->public.get_spis_clone = (chunk_t (*) (delete_payload_t *)) get_spis_clone;
this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =DELETE_PAYLOAD_HEADER_LENGTH;
this->protocol_id = PROTO_NONE;
this->spi_size = 0;
this->spi_count = 0;
this->spis = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,156 @@
/**
* @file delete_payload.h
*
* @brief Interface of delete_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef DELETE_PAYLOAD_H_
#define DELETE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
/**
* Length of a delete payload without the SPI in bytes.
*
* @ingroup payloads
*/
#define DELETE_PAYLOAD_HEADER_LENGTH 8
typedef struct delete_payload_t delete_payload_t;
/**
* @brief Class representing an IKEv2 DELETE payload.
*
* The DELETE payload format is described in RFC section 3.11.
*
* @b Constructors:
* - delete_payload_create()
*
* @todo Implement better setter/getters
*
* @ingroup payloads
*/
struct delete_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the protocol ID.
*
* @param this calling delete_payload_t object
* @param protocol_id protocol ID
*/
void (*set_protocol_id) (delete_payload_t *this, protocol_id_t protocol_id);
/**
* @brief Get the protocol ID.
*
* @param this calling delete_payload_t object
* @return protocol ID
*/
protocol_id_t (*get_protocol_id) (delete_payload_t *this);
/**
* @brief Set the SPI size.
*
*
* @param this calling delete_payload_t object
* @param spi_size SPI size
*/
void (*set_spi_size) (delete_payload_t *this, u_int8_t spi_size);
/**
* @brief Get the SPI size.
*
* @param this calling delete_payload_t object
* @return SPI size
*/
u_int8_t (*get_spi_size) (delete_payload_t *this);
/**
* @brief Set the SPI count.
*
* @param this calling delete_payload_t object
* @param spi_count SPI count
*/
void (*set_spi_count) (delete_payload_t *this, u_int16_t spi_count);
/**
* @brief Get the SPI count.
*
* @param this calling delete_payload_t object
* @return Number of SPI's
*/
u_int16_t (*get_spi_count) (delete_payload_t *this);
/**
* @brief Set the SPI's.
*
* Data are getting cloned.
*
* @param this calling delete_payload_t object
* @param data SPI's as chunk_t
*/
void (*set_spis) (delete_payload_t *this, chunk_t spis);
/**
* @brief Get the SPI's.
*
* Returned data are a copy of the internal one.
*
* @param this calling delete_payload_t object
* @return SPI's chunk_t
*/
chunk_t (*get_spis_clone) (delete_payload_t *this);
/**
* @brief Get the SPI's.
*
* Returned data are NOT copied.
*
* @param this calling delete_payload_t object
* @return SPI's as chunk_t
*/
chunk_t (*get_spis) (delete_payload_t *this);
/**
* @brief Destroys an delete_payload_t object.
*
* @param this delete_payload_t object to destroy
*/
void (*destroy) (delete_payload_t *this);
};
/**
* @brief Creates an empty delete_payload_t object.
*
* @return delete_payload_t object
*
* @ingroup payloads
*/
delete_payload_t *delete_payload_create(void);
#endif /* DELETE_PAYLOAD_H_ */
+227
View File
@@ -0,0 +1,227 @@
/**
* @file eap_payload.c
*
* @brief Implementation of eap_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "eap_payload.h"
typedef struct private_eap_payload_t private_eap_payload_t;
/**
* Private data of an eap_payload_t object.
*
*/
struct private_eap_payload_t {
/**
* Public eap_payload_t interface.
*/
eap_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained message.
*/
chunk_t message;
};
/**
* Encoding rules to parse or generate a EAP payload.
*
* The defined offsets are the positions in a object of type
* private_eap_payload_t.
*
*/
encoding_rule_t eap_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_eap_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_eap_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length)},
/* some eap data bytes, length is defined in PAYLOAD_LENGTH */
{ EAP_MESSAGE, offsetof(private_eap_payload_t, message) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ EAP Message ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_eap_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of eap_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = eap_payload_encodings;
*rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_eap_payload_t *this)
{
return EXTENSIBLE_AUTHENTICATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_eap_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_eap_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_eap_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of eap_payload_t.set_message.
*/
static void set_message (private_eap_payload_t *this, chunk_t message)
{
if (this->message.ptr != NULL)
{
chunk_free(&(this->message));
}
this->message.ptr = clalloc(message.ptr,message.len);
this->message.len = message.len;
this->payload_length = EAP_PAYLOAD_HEADER_LENGTH + this->message.len;
}
/**
* Implementation of eap_payload_t.get_message.
*/
static chunk_t get_message (private_eap_payload_t *this)
{
return (this->message);
}
/**
* Implementation of eap_payload_t.get_data_clone.
*/
static chunk_t get_message_clone (private_eap_payload_t *this)
{
chunk_t cloned_message;
if (this->message.ptr == NULL)
{
return (this->message);
}
cloned_message.ptr = clalloc(this->message.ptr,this->message.len);
cloned_message.len = this->message.len;
return cloned_message;
}
/**
* Implementation of payload_t.destroy and eap_payload_t.destroy.
*/
static void destroy(private_eap_payload_t *this)
{
if (this->message.ptr != NULL)
{
chunk_free(&(this->message));
}
free(this);
}
/*
* Described in header
*/
eap_payload_t *eap_payload_create()
{
private_eap_payload_t *this = malloc_thing(private_eap_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (eap_payload_t *)) destroy;
this->public.set_message = (void (*) (eap_payload_t *,chunk_t)) set_message;
this->public.get_message_clone = (chunk_t (*) (eap_payload_t *)) get_message_clone;
this->public.get_message = (chunk_t (*) (eap_payload_t *)) get_message;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = EAP_PAYLOAD_HEADER_LENGTH;
this->message = CHUNK_INITIALIZER;
return (&(this->public));
}
+105
View File
@@ -0,0 +1,105 @@
/**
* @file eap_payload.h
*
* @brief Interface of eap_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef EAP_PAYLOAD_H_
#define EAP_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a EAP payload without the EAP Message in bytes.
*
* @ingroup payloads
*/
#define EAP_PAYLOAD_HEADER_LENGTH 4
typedef struct eap_payload_t eap_payload_t;
/**
* @brief Class representing an IKEv2 EAP payload.
*
* The EAP payload format is described in RFC section 3.16.
*
* @b Constructors:
* - eap_payload_create()
*
* @todo Implement functionality for this payload
*
* @ingroup payloads
*/
struct eap_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the EAP Message.
*
* Data are getting cloned.
*
* @param this calling eap_payload_t object
* @param message EAP message as chunk_t
*/
void (*set_message) (eap_payload_t *this, chunk_t message);
/**
* @brief Get the EAP message.
*
* Returned data are a copy of the internal one.
*
* @param this calling eap_payload_t object
* @return EAP message as chunk_t
*/
chunk_t (*get_message_clone) (eap_payload_t *this);
/**
* @brief Get the EAP message.
*
* Returned data are NOT copied.
*
* @param this calling eap_payload_t object
* @return EAP message as chunk_t
*/
chunk_t (*get_message) (eap_payload_t *this);
/**
* @brief Destroys an eap_payload_t object.
*
* @param this eap_payload_t object to destroy
*/
void (*destroy) (eap_payload_t *this);
};
/**
* @brief Creates an empty eap_payload_t object.
*
* @return eap_payload_t object
*
* @ingroup payloads
*/
eap_payload_t *eap_payload_create(void);
#endif /* EAP_PAYLOAD_H_ */
+68
View File
@@ -0,0 +1,68 @@
/**
* @file encodings.c
*
* @brief String mappings of encoding_type_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "encodings.h"
mapping_t encoding_type_m[] = {
{U_INT_4, "U_INT_4"},
{U_INT_8, "U_INT_8"},
{U_INT_16, "U_INT_16"},
{U_INT_32, "U_INT_32"},
{U_INT_64, "U_INT_64"},
{IKE_SPI, "IKE_SPI"},
{RESERVED_BIT, "RESERVED_BIT"},
{RESERVED_BYTE, "RESERVED_BYTE"},
{FLAG, "FLAG"},
{PAYLOAD_LENGTH, "PAYLOAD_LENGTH"},
{HEADER_LENGTH, "HEADER_LENGTH"},
{SPI_SIZE, "SPI_SIZE"},
{SPI, "SPI"},
{KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"},
{NOTIFICATION_DATA, "NOTIFICATION_DATA"},
{PROPOSALS, "PROPOSALS"},
{TRANSFORMS, "TRANSFORMS"},
{TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"},
{ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"},
{ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"},
{ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"},
{ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"},
{NONCE_DATA, "NONCE_DATA"},
{ID_DATA, "ID_DATA"},
{AUTH_DATA, "AUTH_DATA"},
{ENCRYPTED_DATA, "ENCRYPTED_DATA"},
{TS_TYPE, "TS_TYPE"},
{ADDRESS, "ADDRESS"},
{TRAFFIC_SELECTORS, "TRAFFIC_SELECTORS"},
{CERT_DATA, "CERT_DATA"},
{CERTREQ_DATA, "CERTREQ_DATA"},
{SPIS, "SPIS"},
{VID_DATA, "VID_DATA"},
{VID_DATA, "VID_DATA"},
{CONFIGURATION_ATTRIBUTES, "CONFIGURATION_ATTRIBUTES"},
{CONFIGURATION_ATTRIBUTE_LENGTH, "CONFIGURATION_ATTRIBUTE_LENGTH"},
{CONFIGURATION_ATTRIBUTE_VALUE, "CONFIGURATION_ATTRIBUTE_VALUE"},
{EAP_MESSAGE, "EAP_MESSAGE"},
{UNKNOWN_DATA,"UNKNOWN_DATA"},
{MAPPING_END, NULL}
};
+540
View File
@@ -0,0 +1,540 @@
/**
* @file encodings.h
*
* @brief Definition of encoding_type_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ENCODINGS_H_
#define ENCODINGS_H_
#include <types.h>
#include <definitions.h>
typedef enum encoding_type_t encoding_type_t;
/**
* @brief All different kinds of encoding types.
*
* Each field of an IKEv2-Message (in header or payload)
* which has to be parsed or generated differently has its own
* type defined here.
*
* Header is parsed like a payload and gets its one payload_id
* from PRIVATE USE space. Also the substructures
* of specific payload types get their own payload_id
* from PRIVATE_USE space. See IKEv2-Draft for more informations.
*
* @ingroup payloads
*/
enum encoding_type_t {
/**
* Representing a 4 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 4 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 4 bit forward afterwards.
*/
U_INT_4,
/**
* Representing a 8 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
U_INT_8,
/**
* Representing a 16 Bit unsigned int value.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
U_INT_16,
/**
* Representing a 32 Bit unsigned int value.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
U_INT_32,
/**
* Representing a 64 Bit unsigned int value.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 64 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 64 bit forward afterwards.
*/
U_INT_64,
/**
* @brief represents a RESERVED_BIT used in FLAG-Bytes.
*
* When generating, the next bit is set to zero and the current write
* position is moved one bit forward.
* No value is read from the associated data struct.
* The current write position is moved 1 bit forward afterwards.
*
* When parsing, the current read pointer is moved one bit forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 bit forward afterwards.
*/
RESERVED_BIT,
/**
* @brief represents a RESERVED_BYTE.
*
* When generating, the next byte is set to zero and the current write
* position is moved one byte forward.
* No value is read from the associated data struct.
* The current write position is moved 1 byte forward afterwards.
*
* When parsing, the current read pointer is moved one byte forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 byte forward afterwards.
*/
RESERVED_BYTE,
/**
* Representing a 1 Bit flag.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards
*/
FLAG,
/**
* Representating a length field of a payload.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
PAYLOAD_LENGTH,
/**
* Representating a length field of a header.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
HEADER_LENGTH,
/**
* Representating a spi size field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
SPI_SIZE,
/**
* Representating a spi field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
SPI,
/**
* Representating a Key Exchange Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
KEY_EXCHANGE_DATA,
/**
* Representating a Notification field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
*/
NOTIFICATION_DATA,
/**
* Representating one or more proposal substructures.
*
* The offset points to a linked_list_t pointer.
*
* When generating the proposal_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed proposal_substructure_t objects have
* to be stored in the pointed linked_list.
*/
PROPOSALS,
/**
* Representating one or more transform substructures.
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_substructure_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORMS,
/**
* Representating one or more Attributes of a transform substructure.
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_attribute_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_attribute_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORM_ATTRIBUTES,
/**
* Representating one or more Attributes of a configuration payload.
*
* The offset points to a linked_list_t pointer.
*
* When generating the configuration_attribute_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed configuration_attribute_t objects have
* to be stored in the pointed linked_list.
*/
CONFIGURATION_ATTRIBUTES,
/**
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
CONFIGURATION_ATTRIBUTE_VALUE,
/**
* Representing a 1 Bit flag specifying the format of a transform attribute.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards.
*/
ATTRIBUTE_FORMAT,
/**
* Representing a 15 Bit unsigned int value used as attribute type
* in an attribute transform.
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 15 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 15 bit forward afterwards.
*/
ATTRIBUTE_TYPE,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
* this field contains the length or the value of an transform attribute.
* Its stored in a 16 unsigned integer field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
ATTRIBUTE_LENGTH_OR_VALUE,
/**
* This field contains the length or the value of an configuration attribute.
* Its stored in a 16 unsigned integer field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
CONFIGURATION_ATTRIBUTE_LENGTH,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
* this field is available or missing and so parsed/generated
* or not parsed/not generated.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
ATTRIBUTE_VALUE,
/**
* Representating one or more Traffic selectors of a TS payload.
*
* The offset points to a linked_list_t pointer.
*
* When generating the traffic_selector_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed traffic_selector_substructure_t objects have
* to be stored in the pointed linked_list.
*/
TRAFFIC_SELECTORS,
/**
* Representating a Traffic selector type field.
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
TS_TYPE,
/**
* Representating an address field in a traffic selector.
*
* Depending on the last field of type TS_TYPE
* this field is either 4 or 16 byte long.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing 4 or 16 bytes are read and written into the chunk pointing to.
*/
ADDRESS,
/**
* Representating a Nonce Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
NONCE_DATA,
/**
* Representating a ID Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
ID_DATA,
/**
* Representating a AUTH Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
AUTH_DATA,
/**
* Representating a CERT Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
*/
CERT_DATA,
/**
* Representating a CERTREQ Data field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
*/
CERTREQ_DATA,
/**
* Representating an EAP message field.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
EAP_MESSAGE,
/**
* Representating the SPIS field in a DELETE payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
SPIS,
/**
* Representating the VID DATA field in a VENDOR ID payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
VID_DATA,
/**
* Representating the DATA of an unknown payload.
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
UNKNOWN_DATA,
/**
* Representating an IKE_SPI field in an IKEv2 Header.
*
* When generating the value of the u_int64_t pointing to
* is written (host and networ order is not changed).
*
* When parsing 8 bytes are read and written into the u_int64_t pointing to.
*/
IKE_SPI,
/**
* Representing the encrypted data body of a encryption payload.
*/
ENCRYPTED_DATA,
};
/**
* mappings to map encoding_type_t's to strings
*
* @ingroup payloads
*/
extern mapping_t encoding_type_m[];
typedef struct encoding_rule_t encoding_rule_t;
/**
* An encoding rule is a mapping of a specific encoding type to
* a location in the data struct where the current field is stored to
* or read from.
*
* For examples see files in this directory.
*
* This rules are used by parser and generator.
*
* @ingroup payloads
*/
struct encoding_rule_t {
/**
* Encoding type.
*/
encoding_type_t type;
/**
* Offset in the data struct.
*
* When parsing, data are written to this offset of the
* data struct.
*
* When generating, data are read from this offset in the
* data struct.
*/
u_int32_t offset;
};
#endif /*ENCODINGS_H_*/
@@ -0,0 +1,702 @@
/**
* @file encryption_payload.c
*
* @brief Implementation of encryption_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include <string.h>
#include "encryption_payload.h"
#include <daemon.h>
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
#include <utils/logger.h>
#include <encoding/generator.h>
#include <encoding/parser.h>
#include <utils/iterator.h>
#include <utils/randomizer.h>
#include <crypto/signers/signer.h>
typedef struct private_encryption_payload_t private_encryption_payload_t;
/**
* Private data of an encryption_payload_t' Object.
*
*/
struct private_encryption_payload_t {
/**
* Public encryption_payload_t interface.
*/
encryption_payload_t public;
/**
* There is no next payload for an encryption payload,
* since encryption payload MUST be the last one.
* next_payload means here the first payload of the
* contained, encrypted payload.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* Chunk containing the iv, data, padding,
* and (an eventually not calculated) signature.
*/
chunk_t encrypted;
/**
* Chunk containing the data in decrypted (unpadded) form.
*/
chunk_t decrypted;
/**
* Signer set by set_signer.
*/
signer_t *signer;
/**
* Crypter, supplied by encrypt/decrypt
*/
crypter_t *crypter;
/**
* Contained payloads of this encrpytion_payload.
*/
linked_list_t *payloads;
/**
* logger for this payload, uses MESSAGE context
*/
logger_t *logger;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_encryption_payload_t object
*/
void (*compute_length) (private_encryption_payload_t *this);
/**
* @brief Generate payloads (unencrypted) in chunk decrypted.
*
* @param this calling private_encryption_payload_t object
*/
void (*generate) (private_encryption_payload_t *this);
/**
* @brief Parse payloads from a (unencrypted) chunk.
*
* @param this calling private_encryption_payload_t object
*/
status_t (*parse) (private_encryption_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-Encryption Payload.
*
* The defined offsets are the positions in a object of type
* private_encryption_payload_t.
*
*/
encoding_rule_t encryption_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_encryption_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole encryption payload*/
{ PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
/* encrypted data, stored in a chunk. contains iv, data, padding */
{ ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initialization Vector !
! (length is block size for encryption algorithm) !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Encrypted IKE Payloads !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ! Padding (0-255 octets) !
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
! ! Pad Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Integrity Checksum Data ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_encryption_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = encryption_payload_encodings;
*rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_encryption_payload_t *this)
{
return ENCRYPTED;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_encryption_payload_t *this)
{
/* returns first contained payload here */
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_encryption_payload_t *this, payload_type_t type)
{
/* set next type is not allowed, since this payload MUST be the last one
* and so nothing is done in here*/
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_encryption_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of payload_t.create_payload_iterator.
*/
static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward)
{
return (this->payloads->create_iterator(this->payloads, forward));
}
/**
* Implementation of payload_t.add_payload.
*/
static void add_payload(private_encryption_payload_t *this, payload_t *payload)
{
payload_t *last_payload;
if (this->payloads->get_count(this->payloads) > 0)
{
this->payloads->get_last(this->payloads,(void **) &last_payload);
last_payload->set_next_type(last_payload, payload->get_type(payload));
}
else
{
this->next_payload = payload->get_type(payload);
}
payload->set_next_type(payload, NO_PAYLOAD);
this->payloads->insert_last(this->payloads, (void*)payload);
this->compute_length(this);
}
/**
* Implementation of encryption_payload_t.remove_first_payload.
*/
static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload)
{
return this->payloads->remove_first(this->payloads, (void**)payload);
}
/**
* Implementation of encryption_payload_t.get_payload_count.
*/
static size_t get_payload_count(private_encryption_payload_t *this)
{
return this->payloads->get_count(this->payloads);
}
/**
* Implementation of encryption_payload_t.encrypt.
*/
static status_t encrypt(private_encryption_payload_t *this)
{
chunk_t iv, padding, to_crypt, result;
randomizer_t *randomizer;
status_t status;
size_t block_size;
if (this->signer == NULL || this->crypter == NULL)
{
this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set");
return INVALID_STATE;
}
/* for random data in iv and padding */
randomizer = randomizer_create();
/* build payload chunk */
this->generate(this);
this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads");
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted);
/* build padding */
block_size = this->crypter->get_block_size(this->crypter);
padding.len = block_size - ((this->decrypted.len + 1) % block_size);
status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding);
if (status != SUCCESS)
{
randomizer->destroy(randomizer);
return status;
}
/* concatenate payload data, padding, padding len */
to_crypt.len = this->decrypted.len + padding.len + 1;
to_crypt.ptr = malloc(to_crypt.len);
memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len);
memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len);
*(to_crypt.ptr + to_crypt.len - 1) = padding.len;
/* build iv */
iv.len = block_size;
status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv);
randomizer->destroy(randomizer);
if (status != SUCCESS)
{
chunk_free(&to_crypt);
chunk_free(&padding);
return status;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt);
/* encrypt to_crypt chunk */
free(this->encrypted.ptr);
status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result);
free(padding.ptr);
free(to_crypt.ptr);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed");
free(iv.ptr);
return status;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result);
/* build encrypted result with iv and signature */
this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
free(this->encrypted.ptr);
this->encrypted.ptr = malloc(this->encrypted.len);
/* fill in result, signature is left out */
memcpy(this->encrypted.ptr, iv.ptr, iv.len);
memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len);
free(result.ptr);
free(iv.ptr);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted);
return SUCCESS;
}
/**
* Implementation of encryption_payload_t.encrypt.
*/
static status_t decrypt(private_encryption_payload_t *this)
{
chunk_t iv, concatenated;
u_int8_t padding_length;
status_t status;
this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload");
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted);
if (this->signer == NULL || this->crypter == NULL)
{
this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set");
return INVALID_STATE;
}
/* get IV */
iv.len = this->crypter->get_block_size(this->crypter);
iv.ptr = this->encrypted.ptr;
/* point concatenated to data + padding + padding_length*/
concatenated.ptr = this->encrypted.ptr + iv.len;
concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer);
/* check the size of input:
* concatenated must be at least on block_size of crypter
*/
if (concatenated.len < iv.len)
{
this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input");
return FAILED;
}
/* free previus data, if any */
free(this->decrypted.ptr);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated);
status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted));
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed");
return FAILED;
}
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted);
/* get padding length, sits just bevore signature */
padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
/* add one byte to the padding length, since the padding_length field is not included */
padding_length++;
this->decrypted.len -= padding_length;
/* check size again */
if (padding_length > concatenated.len || this->decrypted.len < 0)
{
this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?");
/* decryption failed :-/ */
return FAILED;
}
/* free padding */
this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len);
this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted);
this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content");
return (this->parse(this));
}
/**
* Implementation of encryption_payload_t.set_transforms.
*/
static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer)
{
this->signer = signer;
this->crypter = crypter;
}
/**
* Implementation of encryption_payload_t.build_signature.
*/
static status_t build_signature(private_encryption_payload_t *this, chunk_t data)
{
chunk_t data_without_sig = data;
chunk_t sig;
if (this->signer == NULL)
{
this->logger->log(this->logger, ERROR, "unable to build signature, no signer set");
return INVALID_STATE;
}
sig.len = this->signer->get_block_size(this->signer);
data_without_sig.len -= sig.len;
sig.ptr = data.ptr + data_without_sig.len;
this->logger->log(this->logger, CONTROL|LEVEL2, "building signature");
this->signer->get_signature(this->signer, data_without_sig, sig.ptr);
return SUCCESS;
}
/**
* Implementation of encryption_payload_t.verify_signature.
*/
static status_t verify_signature(private_encryption_payload_t *this, chunk_t data)
{
chunk_t sig, data_without_sig;
bool valid;
if (this->signer == NULL)
{
this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set");
return INVALID_STATE;
}
/* find signature in data chunk */
sig.len = this->signer->get_block_size(this->signer);
if (data.len <= sig.len)
{
this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input");
return FAILED;
}
sig.ptr = data.ptr + data.len - sig.len;
/* verify it */
data_without_sig.len = data.len - sig.len;
data_without_sig.ptr = data.ptr;
valid = this->signer->verify_signature(this->signer, data_without_sig, sig);
if (!valid)
{
this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed");
return FAILED;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful");
return SUCCESS;
}
/**
* Implementation of private_encryption_payload_t.generate.
*/
static void generate(private_encryption_payload_t *this)
{
payload_t *current_payload, *next_payload;
generator_t *generator;
iterator_t *iterator;
/* recalculate length before generating */
this->compute_length(this);
/* create iterator */
iterator = this->payloads->create_iterator(this->payloads, TRUE);
/* get first payload */
if (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&current_payload);
this->next_payload = current_payload->get_type(current_payload);
}
else
{
/* no paylads? */
this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available");
free(this->decrypted.ptr);
this->decrypted = CHUNK_INITIALIZER;
iterator->destroy(iterator);
return;
}
generator = generator_create();
/* build all payload, except last */
while(iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&next_payload);
current_payload->set_next_type(current_payload, next_payload->get_type(next_payload));
generator->generate_payload(generator, current_payload);
current_payload = next_payload;
}
iterator->destroy(iterator);
/* build last payload */
current_payload->set_next_type(current_payload, NO_PAYLOAD);
generator->generate_payload(generator, current_payload);
/* free already generated data */
free(this->decrypted.ptr);
generator->write_to_chunk(generator, &(this->decrypted));
generator->destroy(generator);
this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload");
}
/**
* Implementation of private_encryption_payload_t.parse.
*/
static status_t parse(private_encryption_payload_t *this)
{
parser_t *parser;
status_t status;
payload_type_t current_payload_type;
/* check if there is decrypted data */
if (this->decrypted.ptr == NULL)
{
this->logger->log(this->logger, ERROR, "unable to parse, no input!");
return INVALID_STATE;
}
/* build a parser on the decrypted data */
parser = parser_create(this->decrypted);
current_payload_type = this->next_payload;
/* parse all payloads */
while (current_payload_type != NO_PAYLOAD)
{
payload_t *current_payload;
status = parser->parse_payload(parser, current_payload_type, (payload_t**)&current_payload);
if (status != SUCCESS)
{
parser->destroy(parser);
return PARSE_ERROR;
}
status = current_payload->verify(current_payload);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s",
mapping_find(payload_type_m,current_payload->get_type(current_payload)),
mapping_find(status_m, status));
current_payload->destroy(current_payload);
parser->destroy(parser);
return VERIFY_ERROR;
}
/* get next payload type */
current_payload_type = current_payload->get_next_type(current_payload);
this->payloads->insert_last(this->payloads,current_payload);
}
parser->destroy(parser);
this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload");
return SUCCESS;
}
/**
* Implementation of private_encryption_payload_t.compute_length.
*/
static void compute_length(private_encryption_payload_t *this)
{
iterator_t *iterator;
size_t block_size, length = 0;
iterator = this->payloads->create_iterator(this->payloads, TRUE);
/* count payload length */
while (iterator->has_next(iterator))
{
payload_t *current_payload;
iterator->current(iterator, (void **) &current_payload);
length += current_payload->get_length(current_payload);
}
iterator->destroy(iterator);
if (this->crypter && this->signer)
{
/* append one byte for padding length */
length++;
/* append padding */
block_size = this->crypter->get_block_size(this->crypter);
length += block_size - length % block_size;
/* add iv */
length += block_size;
/* add signature */
length += this->signer->get_block_size(this->signer);
}
length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy.
*/
static void destroy(private_encryption_payload_t *this)
{
/* all proposals are getting destroyed */
while (this->payloads->get_count(this->payloads) > 0)
{
payload_t *current_payload;
this->payloads->remove_last(this->payloads,(void **)&current_payload);
current_payload->destroy(current_payload);
}
this->payloads->destroy(this->payloads);
free(this->encrypted.ptr);
free(this->decrypted.ptr);
free(this);
}
/*
* Described in header
*/
encryption_payload_t *encryption_payload_create()
{
private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t);
/* payload_t interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator;
this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload;
this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload;
this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count;
this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt;
this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt;
this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms;
this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature;
this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature;
this->public.destroy = (void (*) (encryption_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
this->generate = generate;
this->parse = parse;
this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD);
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH;
this->encrypted = CHUNK_INITIALIZER;
this->decrypted = CHUNK_INITIALIZER;
this->signer = NULL;
this->crypter = NULL;
this->payloads = linked_list_create();
return (&(this->public));
}
@@ -0,0 +1,196 @@
/**
* @file encryption_payload.h
*
* @brief Interface of encryption_payload_t.
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ENCRYPTION_PAYLOAD_H_
#define ENCRYPTION_PAYLOAD_H_
#include <types.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <encoding/payloads/payload.h>
#include <utils/linked_list.h>
/**
* Encrpytion payload length in bytes without IV and following data.
*
* @ingroup payloads
*/
#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
typedef struct encryption_payload_t encryption_payload_t;
/**
* @brief The encryption payload as described in RFC section 3.14.
*
* Before any crypt/decrypt/sign/verify operation can occur,
* the transforms must be set. After that, a parsed encryption payload
* can be decrypted, which also will parse the contained payloads.
* Encryption is done the same way, added payloads will get generated
* and then encrypted.
* For signature building, there is the FULL packet needed. Meaning it
* must be builded after generation of all payloads and the encryption
* of the encryption payload.
* Signature verificatin is done before decryption.
*
* @b Constructors:
* - encryption_payload_create()
*
* @ingroup payloads
*/
struct encryption_payload_t {
/**
* Implements payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator for all contained payloads.
*
* @warning iterator_t object has to get destroyed by the caller.
*
* @param this calling encryption_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* return created iterator_t object
*/
iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward);
/**
* @brief Adds a payload to this encryption payload.
*
* @param this calling encryption_payload_t object
* @param payload payload_t object to add
*/
void (*add_payload) (encryption_payload_t *this, payload_t *payload);
/**
* @brief Reove the last payload in the contained payload list.
*
* @param this calling encryption_payload_t object
* @param[out] payload removed payload
* @return
* - SUCCESS, or
* - NOT_FOUND if list empty
*/
status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload);
/**
* @brief Get the number of payloads.
*
* @param this calling encryption_payload_t object
* @return number of contained payloads
*/
size_t (*get_payload_count) (encryption_payload_t *this);
/**
* @brief Set transforms to use.
*
* To decryption, encryption, signature building and verifying,
* the payload needs a crypter and a signer object.
*
* @warning Do NOT call this function again after encryption, since
* the signer must be the same while encrypting and signature building!
*
* @param this calling encryption_payload_t
* @param crypter crypter_t to use for data de-/encryption
* @param signer signer_t to use for data signing/verifying
*/
void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer);
/**
* @brief Generate and encrypt contained payloads.
*
* This function generates the content for added payloads
* and encrypts them. Signature is not built, since we need
* additional data (the full message).
*
* @param this calling encryption_payload_t
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set
*/
status_t (*encrypt) (encryption_payload_t *this);
/**
* @brief Decrypt and parse contained payloads.
*
* This function decrypts the contained data. After,
* the payloads are parsed internally and are accessible
* via the iterator.
*
* @param this calling encryption_payload_t
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set, or
* - FAILED if data is invalid
*/
status_t (*decrypt) (encryption_payload_t *this);
/**
* @brief Build the signature.
*
* The signature is built over the FULL message, so the header
* and every payload (inclusive this one) must already be generated.
* The generated message is supplied via the data paramater.
*
* @param this calling encryption_payload_t
* @param data chunk contains the already generated message
* @return
* - SUCCESS, or
* - INVALID_STATE if transforms not set
*/
status_t (*build_signature) (encryption_payload_t *this, chunk_t data);
/**
* @brief Verify the signature.
*
* Since the signature is built over the full message, we need
* this data to do the verification. The message data
* is supplied via the data argument.
*
* @param this calling encryption_payload_t
* @param data chunk contains the message
* @return
* - SUCCESS, or
* - FAILED if signature invalid, or
* - INVALID_STATE if transforms not set
*/
status_t (*verify_signature) (encryption_payload_t *this, chunk_t data);
/**
* @brief Destroys an encryption_payload_t object.
*
* @param this encryption_payload_t object to destroy
*/
void (*destroy) (encryption_payload_t *this);
};
/**
* @brief Creates an empty encryption_payload_t object.
*
* @return encryption_payload_t object
*
* @ingroup payloads
*/
encryption_payload_t *encryption_payload_create(void);
#endif /*ENCRYPTION_PAYLOAD_H_*/
+320
View File
@@ -0,0 +1,320 @@
/**
* @file id_payload.h
*
* @brief Interface of id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "id_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_id_payload_t private_id_payload_t;
/**
* Private data of an id_payload_t object.
*
*/
struct private_id_payload_t {
/**
* Public id_payload_t interface.
*/
id_payload_t public;
/**
* TRUE if this ID payload is of type IDi, FALSE for IDr.
*/
bool is_initiator;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Type of the ID Data.
*/
u_int8_t id_type;
/**
* The contained id data value.
*/
chunk_t id_data;
};
/**
* Encoding rules to parse or generate a ID payload
*
* The defined offsets are the positions in a object of type
* private_id_payload_t.
*
*/
encoding_rule_t id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_id_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
/* 1 Byte ID type*/
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
{ ID_DATA, offsetof(private_id_payload_t, id_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ID Type ! RESERVED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Identification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_id_payload_t *this)
{
if ((this->id_type == 0) ||
(this->id_type == 4) ||
((this->id_type >= 6) && (this->id_type <= 8)) ||
((this->id_type >= 12) && (this->id_type <= 200)))
{
/* reserved IDs */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of id_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = id_payload_encodings;
*rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_id_payload_t *this)
{
if (this->is_initiator)
{
return ID_INITIATOR;
}
else
{
return ID_RESPONDER;
}
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_id_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_id_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_id_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of id_payload_t.set_type.
*/
static void set_id_type (private_id_payload_t *this, id_type_t type)
{
this->id_type = type;
}
/**
* Implementation of id_payload_t.get_id_type.
*/
static id_type_t get_id_type (private_id_payload_t *this)
{
return (this->id_type);
}
/**
* Implementation of id_payload_t.set_data.
*/
static void set_data (private_id_payload_t *this, chunk_t data)
{
if (this->id_data.ptr != NULL)
{
chunk_free(&(this->id_data));
}
this->id_data.ptr = clalloc(data.ptr,data.len);
this->id_data.len = data.len;
this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len;
}
/**
* Implementation of id_payload_t.get_data_clone.
*/
static chunk_t get_data (private_id_payload_t *this)
{
return (this->id_data);
}
/**
* Implementation of id_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_id_payload_t *this)
{
chunk_t cloned_data;
if (this->id_data.ptr == NULL)
{
return (this->id_data);
}
cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len);
cloned_data.len = this->id_data.len;
return cloned_data;
}
/**
* Implementation of id_payload_t.get_initiator.
*/
static bool get_initiator (private_id_payload_t *this)
{
return (this->is_initiator);
}
/**
* Implementation of id_payload_t.set_initiator.
*/
static void set_initiator (private_id_payload_t *this,bool is_initiator)
{
this->is_initiator = is_initiator;
}
/**
* Implementation of id_payload_t.get_identification.
*/
static identification_t *get_identification (private_id_payload_t *this)
{
return identification_create_from_encoding(this->id_type,this->id_data);
}
/**
* Implementation of payload_t.destroy and id_payload_t.destroy.
*/
static void destroy(private_id_payload_t *this)
{
if (this->id_data.ptr != NULL)
{
chunk_free(&(this->id_data));
}
free(this);
}
/*
* Described in header.
*/
id_payload_t *id_payload_create(bool is_initiator)
{
private_id_payload_t *this = malloc_thing(private_id_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (id_payload_t *)) destroy;
this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type;
this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type;
this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data;
this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data;
this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone;
this->public.get_initiator = (bool (*) (id_payload_t *)) get_initiator;
this->public.set_initiator = (void (*) (id_payload_t *,bool)) set_initiator;
this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =ID_PAYLOAD_HEADER_LENGTH;
this->id_data = CHUNK_INITIALIZER;
this->is_initiator = is_initiator;
return (&(this->public));
}
/*
* Described in header.
*/
id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification)
{
id_payload_t *this= id_payload_create(is_initiator);
this->set_data(this,identification->get_encoding(identification));
this->set_id_type(this,identification->get_type(identification));
return this;
}
+172
View File
@@ -0,0 +1,172 @@
/**
* @file id_payload.h
*
* @brief Interface of id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ID_PAYLOAD_H_
#define ID_PAYLOAD_H_
#include <types.h>
#include <utils/identification.h>
#include <encoding/payloads/payload.h>
/**
* Length of a id payload without the data in bytes.
*
* @ingroup payloads
*/
#define ID_PAYLOAD_HEADER_LENGTH 8
typedef struct id_payload_t id_payload_t;
/**
* Object representing an IKEv2 ID payload.
*
* The ID payload format is described in RFC section 3.5.
*
* @b Constructors:
* - id_payload_create_from_identification()
* - id_payload_create()
*
* @ingroup payloads
*/
struct id_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the ID type.
*
* @param this calling id_payload_t object
* @param type Type of ID
*/
void (*set_id_type) (id_payload_t *this, id_type_t type);
/**
* @brief Get the ID type.
*
* @param this calling id_payload_t object
* @return type of the ID
*/
id_type_t (*get_id_type) (id_payload_t *this);
/**
* @brief Set the ID data.
*
* Data are getting cloned.
*
* @param this calling id_payload_t object
* @param data ID data as chunk_t
*/
void (*set_data) (id_payload_t *this, chunk_t data);
/**
* @brief Get the ID data.
*
* Returned data are a copy of the internal one
*
* @param this calling id_payload_t object
* @return ID data as chunk_t
*/
chunk_t (*get_data_clone) (id_payload_t *this);
/**
* @brief Get the ID data.
*
* Returned data are NOT copied.
*
* @param this calling id_payload_t object
* @return ID data as chunk_t
*/
chunk_t (*get_data) (id_payload_t *this);
/**
* @brief Creates an identification object of this id payload.
*
* Returned object has to get destroyed by the caller.
*
* @param this calling id_payload_t object
* @return identification_t object
*/
identification_t *(*get_identification) (id_payload_t *this);
/**
* @brief Get the type of ID payload (IDi or IDr).
*
* @param this calling id_payload_t object
* @return
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
*/
bool (*get_initiator) (id_payload_t *this);
/**
* @brief Set the type of ID payload (IDi or IDr).
*
* @param this calling id_payload_t object
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
*/
void (*set_initiator) (id_payload_t *this,bool is_initiator);
/**
* @brief Destroys an id_payload_t object.
*
* @param this id_payload_t object to destroy
*/
void (*destroy) (id_payload_t *this);
};
/**
* @brief Creates an empty id_payload_t object.
*
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
*
* @return id_payload_t object
*
* @ingroup payloads
*/
id_payload_t *id_payload_create(bool is_initiator);
/**
* @brief Creates an id_payload_t from an existing identification_t object.
*
* @param is_initiator
* - TRUE if this payload is of type IDi
* - FALSE if this payload is of type IDr
* @param identification identification_t object
* @return id_payload_t object
*
* @ingroup payloads
*/
id_payload_t *id_payload_create_from_identification(bool is_initiator,identification_t *identification);
#endif /* ID_PAYLOAD_H_ */
+408
View File
@@ -0,0 +1,408 @@
/**
* @file ike_header.c
*
* @brief Implementation of ike_header_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "ike_header.h"
#include <encoding/payloads/encodings.h>
typedef struct private_ike_header_t private_ike_header_t;
/**
* Private data of an ike_header_t object.
*
*/
struct private_ike_header_t {
/**
* Public interface.
*/
ike_header_t public;
/**
* SPI of the initiator.
*/
u_int64_t initiator_spi;
/**
* SPI of the responder.
*/
u_int64_t responder_spi;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* IKE major version.
*/
u_int8_t maj_version;
/**
* IKE minor version.
*/
u_int8_t min_version;
/**
* Exchange type .
*/
u_int8_t exchange_type;
/**
* Flags of the Message.
*
*/
struct {
/**
* Sender is initiator of the associated IKE_SA_INIT-Exchange.
*/
bool initiator;
/**
* Is protocol supporting higher version?
*/
bool version;
/**
* TRUE, if this is a response, FALSE if its a Request.
*/
bool response;
} flags;
/**
* Associated Message-ID.
*/
u_int32_t message_id;
/**
* Length of the whole IKEv2-Message (header and all payloads).
*/
u_int32_t length;
};
/**
* Mappings used to get strings for exchange_type_t.
*/
mapping_t exchange_type_m[] = {
{EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"},
{IKE_SA_INIT, "IKE_SA_INIT"},
{IKE_AUTH, "IKE_AUTH"},
{CREATE_CHILD_SA, "CREATE_CHILD_SA"},
{INFORMATIONAL, "INFORMATIONAL"}
};
/**
* Encoding rules to parse or generate a IKEv2-Header.
*
* The defined offsets are the positions in a object of type
* ike_header_t.
*
*/
encoding_rule_t ike_header_encodings[] = {
/* 8 Byte SPI, stored in the field initiator_spi */
{ IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
/* 8 Byte SPI, stored in the field responder_spi */
{ IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ike_header_t, next_payload) },
/* 4 Bit major version, stored in the field maj_version */
{ U_INT_4, offsetof(private_ike_header_t, maj_version) },
/* 4 Bit minor version, stored in the field min_version */
{ U_INT_4, offsetof(private_ike_header_t, min_version) },
/* 8 Bit for the exchange type */
{ U_INT_8, offsetof(private_ike_header_t, exchange_type) },
/* 2 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 3 Bit flags, stored in the fields response, version and initiator */
{ FLAG, offsetof(private_ike_header_t, flags.response) },
{ FLAG, offsetof(private_ike_header_t, flags.version) },
{ FLAG, offsetof(private_ike_header_t, flags.initiator) },
/* 3 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 4 Byte message id, stored in the field message_id */
{ U_INT_32, offsetof(private_ike_header_t, message_id) },
/* 4 Byte length fied, stored in the field length */
{ HEADER_LENGTH, offsetof(private_ike_header_t, length) }
};
/* 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Initiator's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Responder's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Message ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL))
{
/* unsupported exchange type */
return FAILED;
}
if (this->initiator_spi == 0)
{
/* initiator spi not set */
return FAILED;
}
/* verification of version is not done in here */
return SUCCESS;
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(payload_t *this,payload_type_t type)
{
((private_ike_header_t *)this)->next_payload = type;
}
/**
* Implementation of ike_header_t.get_initiator_spi.
*/
static u_int64_t get_initiator_spi(private_ike_header_t *this)
{
return this->initiator_spi;
}
/**
* Implementation of ike_header_t.set_initiator_spi.
*/
static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
/**
* Implementation of ike_header_t.get_responder_spi.
*/
static u_int64_t get_responder_spi(private_ike_header_t *this)
{
return this->responder_spi;
}
/**
* Implementation of ike_header_t.set_responder_spi.
*/
static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
{
this->responder_spi = responder_spi;
}
/**
* Implementation of ike_header_t.get_maj_version.
*/
static u_int8_t get_maj_version(private_ike_header_t *this)
{
return this->maj_version;
}
/**
* Implementation of ike_header_t.get_min_version.
*/
static u_int8_t get_min_version(private_ike_header_t *this)
{
return this->min_version;
}
/**
* Implementation of ike_header_t.get_response_flag.
*/
static bool get_response_flag(private_ike_header_t *this)
{
return this->flags.response;
}
/**
* Implementation of ike_header_t.set_response_flag.
*/
static void set_response_flag(private_ike_header_t *this, bool response)
{
this->flags.response = response;
}
/**
* Implementation of ike_header_t.get_version_flag.
*/
static bool get_version_flag(private_ike_header_t *this)
{
return this->flags.version;
}
/**
* Implementation of ike_header_t.get_initiator_flag.
*/
static bool get_initiator_flag(private_ike_header_t *this)
{
return this->flags.initiator;
}
/**
* Implementation of ike_header_t.set_initiator_flag.
*/
static void set_initiator_flag(private_ike_header_t *this, bool initiator)
{
this->flags.initiator = initiator;
}
/**
* Implementation of ike_header_t.get_exchange_type.
*/
static u_int8_t get_exchange_type(private_ike_header_t *this)
{
return this->exchange_type;
}
/**
* Implementation of ike_header_t.set_exchange_type.
*/
static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
{
this->exchange_type = exchange_type;
}
/**
* Implements ike_header_t's get_message_id function.
* See #ike_header_t.get_message_id for description.
*/
static u_int32_t get_message_id(private_ike_header_t *this)
{
return this->message_id;
}
/**
* Implementation of ike_header_t.set_message_id.
*/
static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
{
this->message_id = message_id;
}
/**
* Implementation of ike_header_t.destroy and payload_t.destroy.
*/
static void destroy(ike_header_t *this)
{
free(this);
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ike_header_encodings;
*rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(payload_t *this)
{
return HEADER;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(payload_t *this)
{
return (((private_ike_header_t*)this)->next_payload);
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(payload_t *this)
{
return (((private_ike_header_t*)this)->length);
}
/*
* Described in header.
*/
ike_header_t *ike_header_create()
{
private_ike_header_t *this = malloc_thing(private_ike_header_t);
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = get_encoding_rules;
this->public.payload_interface.get_length = get_length;
this->public.payload_interface.get_next_type = get_next_type;
this->public.payload_interface.set_next_type = set_next_type;
this->public.payload_interface.get_type = get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
this->public.destroy = destroy;
this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
/* set default values of the fields */
this->initiator_spi = 0;
this->responder_spi = 0;
this->next_payload = 0;
this->maj_version = IKE_MAJOR_VERSION;
this->min_version = IKE_MINOR_VERSION;
this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
this->flags.initiator = TRUE;
this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
this->flags.response = FALSE;
this->message_id = 0;
this->length = IKE_HEADER_LENGTH;
return (ike_header_t*)this;
}
+261
View File
@@ -0,0 +1,261 @@
/**
* @file ike_header.h
*
* @brief Interface of ike_header_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef IKE_HEADER_H_
#define IKE_HEADER_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Major Version of IKEv2.
*
* @ingroup payloads
*/
#define IKE_MAJOR_VERSION 2
/**
* Minor Version of IKEv2.
*
* @ingroup payloads
*/
#define IKE_MINOR_VERSION 0
/**
* Flag in IKEv2-Header. Always 0.
*
* @ingroup payloads
*/
#define HIGHER_VERSION_SUPPORTED_FLAG 0
/**
* Length of IKE Header in Bytes.
*
* @ingroup payloads
*/
#define IKE_HEADER_LENGTH 28
typedef enum exchange_type_t exchange_type_t;
/**
* @brief Different types of IKE-Exchanges.
*
* See Draft for different types.
*
* @ingroup payloads
*/
enum exchange_type_t{
/**
* EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
*/
EXCHANGE_TYPE_UNDEFINED = 240,
/**
* IKE_SA_INIT.
*/
IKE_SA_INIT = 34,
/**
* IKE_AUTH.
*/
IKE_AUTH = 35,
/**
* CREATE_CHILD_SA.
*/
CREATE_CHILD_SA = 36,
/**
* INFORMATIONAL.
*/
INFORMATIONAL = 37
};
/**
* string mappings for exchange_type_t
*
* @ingroup payloads
*/
extern mapping_t exchange_type_m[];
typedef struct ike_header_t ike_header_t;
/**
* @brief An object of this type represents an IKEv2 header and is used to
* generate and parse IKEv2 headers.
*
* The header format of an IKEv2-Message is compatible to the
* ISAKMP-Header format to allow implementations supporting
* both versions of the IKE-protocol.
*
* @b Constructors:
* - ike_header_create()
*
* @ingroup payloads
*/
struct ike_header_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the initiator spi.
*
* @param this ike_header_t object
* @return initiator_spi
*/
u_int64_t (*get_initiator_spi) (ike_header_t *this);
/**
* @brief Set the initiator spi.
*
* @param this ike_header_t object
* @param initiator_spi initiator_spi
*/
void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
/**
* @brief Get the responder spi.
*
* @param this ike_header_t object
* @return responder_spi
*/
u_int64_t (*get_responder_spi) (ike_header_t *this);
/**
* @brief Set the responder spi.
*
* @param this ike_header_t object
* @param responder_spi responder_spi
*/
void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
/**
* @brief Get the major version.
*
* @param this ike_header_t object
* @return major version
*/
u_int8_t (*get_maj_version) (ike_header_t *this);
/**
* @brief Get the minor version.
*
* @param this ike_header_t object
* @return minor version
*/
u_int8_t (*get_min_version) (ike_header_t *this);
/**
* @brief Get the response flag.
*
* @param this ike_header_t object
* @return response flag
*/
bool (*get_response_flag) (ike_header_t *this);
/**
* @brief Set the response flag-
*
* @param this ike_header_t object
* @param response response flag
*
*/
void (*set_response_flag) (ike_header_t *this, bool response);
/**
* @brief Get "higher version supported"-flag.
*
* @param this ike_header_t object
* @return version flag
*/
bool (*get_version_flag) (ike_header_t *this);
/**
* @brief Get the initiator flag.
*
* @param this ike_header_t object
* @return initiator flag
*/
bool (*get_initiator_flag) (ike_header_t *this);
/**
* @brief Set the initiator flag.
*
* @param this ike_header_t object
* @param initiator initiator flag
*
*/
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
/**
* @brief Get the exchange type.
*
* @param this ike_header_t object
* @return exchange type
*/
u_int8_t (*get_exchange_type) (ike_header_t *this);
/**
* @brief Set the exchange type.
*
* @param this ike_header_t object
* @param exchange_type exchange type
*/
void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
/**
* @brief Get the message id.
*
* @param this ike_header_t object
* @return message id
*/
u_int32_t (*get_message_id) (ike_header_t *this);
/**
* @brief Set the message id.
*
* @param this ike_header_t object
* @param initiator_spi message id
*/
void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
/**
* @brief Destroys a ike_header_t object.
*
* @param this ike_header_t object to destroy
*/
void (*destroy) (ike_header_t *this);
};
/**
* @brief Create an ike_header_t object
*
* @return ike_header_t object
*
* @ingroup payloads
*/
ike_header_t *ike_header_create(void);
#endif /*IKE_HEADER_H_*/
+276
View File
@@ -0,0 +1,276 @@
/**
* @file ke_payload.c
*
* @brief Implementation of ke_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "ke_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_ke_payload_t private_ke_payload_t;
/**
* Private data of an ke_payload_t object.
*
*/
struct private_ke_payload_t {
/**
* Public ke_payload_t interface.
*/
ke_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* DH Group Number.
*/
diffie_hellman_group_t dh_group_number;
/**
* Key Exchange Data of this KE payload.
*/
chunk_t key_exchange_data;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
*/
void (*compute_length) (private_ke_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-KE Payload.
*
* The defined offsets are the positions in a object of type
* private_ke_payload_t.
*
*/
encoding_rule_t ke_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_ke_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
/* DH Group number as 16 bit field*/
{ U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* Key Exchange Data is from variable size */
{ KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DH Group # ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Key Exchange Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ke_payload_t *this)
{
/* dh group is not verified in here */
return SUCCESS;
}
/**
* Implementation of payload_t.destroy.
*/
static void destroy(private_ke_payload_t *this)
{
if (this->key_exchange_data.ptr != NULL)
{
free(this->key_exchange_data.ptr);
}
free(this);
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ke_payload_encodings;
*rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_ke_payload_t *this)
{
return KEY_EXCHANGE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_ke_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_ke_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_ke_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_ke_payload_t.compute_length.
*/
static void compute_length (private_ke_payload_t *this)
{
size_t length = KE_PAYLOAD_HEADER_LENGTH;
if (this->key_exchange_data.ptr != NULL)
{
length += this->key_exchange_data.len;
}
this->payload_length = length;
}
/**
* Implementation of ke_payload_t.get_key_exchange_data.
*/
static chunk_t get_key_exchange_data(private_ke_payload_t *this)
{
return (this->key_exchange_data);
}
/**
* Implementation of ke_payload_t.set_key_exchange_data.
*/
static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
{
/* destroy existing data first */
if (this->key_exchange_data.ptr != NULL)
{
/* free existing value */
free(this->key_exchange_data.ptr);
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
}
this->key_exchange_data.ptr = clalloc(key_exchange_data.ptr,key_exchange_data.len);
this->key_exchange_data.len = key_exchange_data.len;
this->compute_length(this);
}
/**
* Implementation of ke_payload_t.get_dh_group_number.
*/
static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
{
return this->dh_group_number;
}
/**
* Implementation of ke_payload_t.set_dh_group_number.
*/
static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
{
this->dh_group_number = dh_group_number;
}
/*
* Described in header
*/
ke_payload_t *ke_payload_create()
{
private_ke_payload_t *this = malloc_thing(private_ke_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
this->public.set_key_exchange_data = (void (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
this->public.set_dh_group_number =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
this->public.destroy = (void (*) (ke_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
this->dh_group_number = 0;
return (&(this->public));
}
+110
View File
@@ -0,0 +1,110 @@
/**
* @file ke_payload.h
*
* @brief Interface of ke_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef KE_PAYLOAD_H_
#define KE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <utils/linked_list.h>
/**
* KE payload length in bytes without any key exchange data.
*
* @ingroup payloads
*/
#define KE_PAYLOAD_HEADER_LENGTH 8
typedef struct ke_payload_t ke_payload_t;
/**
* @brief Class representing an IKEv2-KE Payload.
*
* The KE Payload format is described in RFC section 3.4.
*
* @b Constructors:
* - ke_payload_create()
*
* @ingroup payloads
*/
struct ke_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set key exchange data of this KE payload.
*
* @warning Returned data are not copied.
*
* @param this calling ke_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
* @brief Sets the key exchange data of this KE payload.
*
* @warning Value is getting copied.
*
* @param this calling ke_payload_t object
* @param key_exchange_data chunk_t pointing to the value to set
*/
void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
/**
* @brief Gets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @return DH Group Number of this payload
*/
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
* @brief Sets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @param dh_group_number DH Group to set
*/
void (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number);
/**
* @brief Destroys an ke_payload_t object.
*
* @param this ke_payload_t object to destroy
*/
void (*destroy) (ke_payload_t *this);
};
/**
* @brief Creates an empty ke_payload_t object
*
* @return ke_payload_t object
*
* @ingroup payloads
*/
ke_payload_t *ke_payload_create(void);
#endif /*KE_PAYLOAD_H_*/
@@ -0,0 +1,241 @@
/**
* @file nonce_payload.h
*
* @brief Implementation of nonce_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "nonce_payload.h"
#include <encoding/payloads/encodings.h>
typedef struct private_nonce_payload_t private_nonce_payload_t;
/**
* Private data of an nonce_payload_t object.
*
*/
struct private_nonce_payload_t {
/**
* Public nonce_payload_t interface.
*/
nonce_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained nonce value.
*/
chunk_t nonce;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_nonce_payload_t object
*/
void (*compute_length) (private_nonce_payload_t *this);
};
/**
* Encoding rules to parse or generate a nonce payload
*
* The defined offsets are the positions in a object of type
* private_nonce_payload_t.
*
*/
encoding_rule_t nonce_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_nonce_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole nonce payload*/
{ PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
/* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
{ NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }
};
/* 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Nonce Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_nonce_payload_t *this)
{
if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
{
/* nonce length is wrong */
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of nonce_payload_t.set_nonce.
*/
static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
{
this->nonce.ptr = clalloc(nonce.ptr, nonce.len);
this->nonce.len = nonce.len;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
return SUCCESS;
}
/**
* Implementation of nonce_payload_t.get_nonce.
*/
static chunk_t get_nonce(private_nonce_payload_t *this)
{
chunk_t nonce;
nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len);
nonce.len = this->nonce.len;
return nonce;
}
/**
* Implementation of nonce_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = nonce_payload_encodings;
*rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_nonce_payload_t *this)
{
return NONCE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_nonce_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_nonce_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_nonce_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_id_payload_t.compute_length.
*/
static void compute_length(private_nonce_payload_t *this)
{
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len;
}
/**
* Implementation of payload_t.destroy and nonce_payload_t.destroy.
*/
static void destroy(private_nonce_payload_t *this)
{
if (this->nonce.ptr != NULL)
{
free(this->nonce.ptr);
}
free(this);
}
/*
* Described in header
*/
nonce_payload_t *nonce_payload_create()
{
private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (nonce_payload_t *)) destroy;
this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce;
this->public.get_nonce = (chunk_t (*) (nonce_payload_t *)) get_nonce;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
this->nonce.ptr = NULL;
this->nonce.len = 0;
return (&(this->public));
}
@@ -0,0 +1,89 @@
/**
* @file nonce_payload.h
*
* @brief Interface of nonce_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NONCE_PAYLOAD_H_
#define NONCE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a nonce payload without a nonce in bytes.
*
* @ingroup payloads
*/
#define NONCE_PAYLOAD_HEADER_LENGTH 4
typedef struct nonce_payload_t nonce_payload_t;
/**
* Object representing an IKEv2 Nonce payload.
*
* The Nonce payload format is described in RFC section 3.3.
*
* @b Constructors:
* - nonce_payload_create()
*
* @ingroup payloads
*/
struct nonce_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the nonce value.
*
* @param this calling nonce_payload_t object
* @param nonce chunk containing the nonce, will be cloned
*/
void (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
/**
* @brief Get the nonce value.
*
* @param this calling nonce_payload_t object
* @return a chunk containing the cloned nonce
*/
chunk_t (*get_nonce) (nonce_payload_t *this);
/**
* @brief Destroys an nonce_payload_t object.
*
* @param this nonce_payload_t object to destroy
*/
void (*destroy) (nonce_payload_t *this);
};
/**
* @brief Creates an empty nonce_payload_t object
*
* @return nonce_payload_t object
*
* @ingroup payloads
*/
nonce_payload_t *nonce_payload_create(void);
#endif /*NONCE_PAYLOAD_H_*/
@@ -0,0 +1,441 @@
/**
* @file notify_payload.c
*
* @brief Implementation of notify_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "notify_payload.h"
#include <daemon.h>
#include <encoding/payloads/encodings.h>
/**
* String mappings for notify_message_type_t.
*/
mapping_t notify_message_type_m[] = {
{UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
{INVALID_IKE_SPI, "INVALID_IKE_SPI"},
{INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
{INVALID_SYNTAX, "INVALID_SYNTAX"},
{INVALID_MESSAGE_ID, "INVALID_MESSAGE_ID"},
{INVALID_SPI, "INVALID_SPI"},
{NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN"},
{INVALID_KE_PAYLOAD, "INVALID_KE_PAYLOAD"},
{AUTHENTICATION_FAILED, "AUTHENTICATION_FAILED"},
{SINGLE_PAIR_REQUIRED, "SINGLE_PAIR_REQUIRED"},
{NO_ADDITIONAL_SAS, "NO_ADDITIONAL_SAS"},
{INTERNAL_ADDRESS_FAILURE, "INTERNAL_ADDRESS_FAILURE"},
{FAILED_CP_REQUIRED, "FAILED_CP_REQUIRED"},
{TS_UACCEPTABLE, "TS_UACCEPTABLE"},
{INVALID_SELECTORS, "INVALID_SELECTORS"},
{INITIAL_CONTACT, "INITIAL_CONTACT"},
{SET_WINDOW_SIZE, "SET_WINDOW_SIZE"},
{MAPPING_END, NULL}
};
typedef struct private_notify_payload_t private_notify_payload_t;
/**
* Private data of an notify_payload_t object.
*
*/
struct private_notify_payload_t {
/**
* Public notify_payload_t interface.
*/
notify_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Protocol id.
*/
u_int8_t protocol_id;
/**
* Spi size.
*/
u_int8_t spi_size;
/**
* Notify message type.
*/
u_int16_t notify_message_type;
/**
* Security parameter index (spi).
*/
chunk_t spi;
/**
* Notification data.
*/
chunk_t notification_data;
/**
* Assigned logger
*/
logger_t *logger;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
*/
void (*compute_length) (private_notify_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-Notify Payload.
*
* The defined offsets are the positions in a object of type
* private_notify_payload_t.
*
*/
encoding_rule_t notify_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
/* Protocol ID as 8 bit field*/
{ U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
/* SPI Size as 8 bit field*/
{ SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
/* Notify message type as 16 bit field*/
{ U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
/* SPI as variable length field*/
{ SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
{ NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! Notify Message Type !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Notification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_notify_payload_t *this)
{
if (this->protocol_id > 3)
{
/* reserved for future use */
return FAILED;
}
/* TODO: Check all kinds of notify */
if (this->notify_message_type == INVALID_KE_PAYLOAD)
{
/* check notification data */
diffie_hellman_group_t dh_group;
if (this->notification_data.len != 2)
{
return FAILED;
}
dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
switch (dh_group)
{
case MODP_768_BIT:
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_6144_BIT:
case MODP_8192_BIT:
break;
default:
this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group);
return FAILED;
}
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = notify_payload_encodings;
*rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_notify_payload_t *this)
{
return NOTIFY;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_notify_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_notify_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_notify_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of private_notify_payload_t.compute_length.
*/
static void compute_length (private_notify_payload_t *this)
{
size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
if (this->notification_data.ptr != NULL)
{
length += this->notification_data.len;
}
if (this->spi.ptr != NULL)
{
length += this->spi.len;
}
this->payload_length = length;
}
/**
* Implementation of notify_payload_t.get_protocol_id.
*/
static u_int8_t get_protocol_id(private_notify_payload_t *this)
{
return this->protocol_id;
}
/**
* Implementation of notify_payload_t.set_protocol_id.
*/
static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of notify_payload_t.get_notify_message_type.
*/
static u_int16_t get_notify_message_type(private_notify_payload_t *this)
{
return this->notify_message_type;
}
/**
* Implementation of notify_payload_t.set_notify_message_type.
*/
static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
{
this->notify_message_type = notify_message_type;
}
/**
* Implementation of notify_payload_t.get_spi.
*/
static chunk_t get_spi(private_notify_payload_t *this)
{
return (this->spi);
}
/**
* Implementation of notify_payload_t.set_spi.
*/
static void set_spi(private_notify_payload_t *this, chunk_t spi)
{
/* destroy existing data first */
if (this->spi.ptr != NULL)
{
/* free existing value */
free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
}
this->spi.ptr = clalloc(spi.ptr,spi.len);
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
}
/**
* Implementation of notify_payload_t.get_notification_data.
*/
static chunk_t get_notification_data(private_notify_payload_t *this)
{
return (this->notification_data);
}
/**
* Implementation of notify_payload_t.set_notification_data.
*/
static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
{
/* destroy existing data first */
if (this->notification_data.ptr != NULL)
{
/* free existing value */
free(this->notification_data.ptr);
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
}
this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len);
this->notification_data.len = notification_data.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
*/
static status_t destroy(private_notify_payload_t *this)
{
if (this->notification_data.ptr != NULL)
{
free(this->notification_data.ptr);
}
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
}
free(this);
return SUCCESS;
}
/*
* Described in header
*/
notify_payload_t *notify_payload_create()
{
private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi;
this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
this->public.destroy = (void (*) (notify_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
this->protocol_id = 0;
this->notify_message_type = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->spi_size = 0;
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
this->logger = logger_manager->get_logger(logger_manager, PAYLOAD);
return (&(this->public));
}
/*
* Described in header.
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
{
notify_payload_t *notify = notify_payload_create();
notify->set_notify_message_type(notify,notify_message_type);
notify->set_protocol_id(notify,protocol_id);
return notify;
}
@@ -0,0 +1,200 @@
/**
* @file notify_payload.h
*
* @brief Interface of notify_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NOTIFY_PAYLOAD_H_
#define NOTIFY_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
/**
* Notify payload length in bytes without any spi and notification data.
*
* @ingroup payloads
*/
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
typedef enum notify_message_type_t notify_message_type_t;
/**
* @brief Notify message types.
*
* See IKEv2 RFC 3.10.1.
*
* @ingroup payloads
*/
enum notify_message_type_t {
UNSUPPORTED_CRITICAL_PAYLOAD = 1,
INVALID_IKE_SPI = 4,
INVALID_MAJOR_VERSION = 5,
INVALID_SYNTAX = 7,
INVALID_MESSAGE_ID = 9,
INVALID_SPI = 11,
NO_PROPOSAL_CHOSEN = 14,
INVALID_KE_PAYLOAD = 17,
AUTHENTICATION_FAILED = 24,
SINGLE_PAIR_REQUIRED = 34,
NO_ADDITIONAL_SAS = 35,
INTERNAL_ADDRESS_FAILURE = 36,
FAILED_CP_REQUIRED = 37,
TS_UACCEPTABLE = 38,
INVALID_SELECTORS = 39,
INITIAL_CONTACT = 16384,
SET_WINDOW_SIZE = 16385
};
/**
* String mappings for notify_message_type_t.
*
* @ingroup payloads
*/
extern mapping_t notify_message_type_m[];
typedef struct notify_payload_t notify_payload_t;
/**
* @brief Class representing an IKEv2-Notify Payload.
*
* The Notify Payload format is described in Draft section 3.10.
*
* @b Constructors:
* - notify_payload_create()
* - notify_payload_create_from_protocol_and_type()
*
* @todo Build specified constructor/getter for notify's
*
* @ingroup payloads
*/
struct notify_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Gets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @return protocol id of this payload
*/
u_int8_t (*get_protocol_id) (notify_payload_t *this);
/**
* @brief Sets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @param protocol_id protocol id to set
*/
void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
/**
* @brief Gets the notify message type of this payload.
*
* @param this calling notify_payload_t object
* @return notify message type of this payload
*/
u_int16_t (*get_notify_message_type) (notify_payload_t *this);
/**
* @brief Sets notify message type of this payload.
*
* @param this calling notify_payload_t object
* @param notify_message_type notify message type to set
*/
void (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type);
/**
* @brief Returns the currently set spi of this payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (notify_payload_t *this);
/**
* @brief Sets the spi of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param spi chunk_t pointing to the value to set
*/
void (*set_spi) (notify_payload_t *this, chunk_t spi);
/**
* @brief Returns the currently set notification data of payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_notification_data) (notify_payload_t *this);
/**
* @brief Sets the notification data of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param notification_data chunk_t pointing to the value to set
*/
void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data);
/**
* @brief Destroys an notify_payload_t object.
*
* @param this notify_payload_t object to destroy
*/
void (*destroy) (notify_payload_t *this);
};
/**
* @brief Creates an empty notify_payload_t object
*
* @return created notify_payload_t object
*
* @ingroup payloads
*/
notify_payload_t *notify_payload_create(void);
/**
* @brief Creates an notify_payload_t object of specific type for specific protocol id.
*
* @param protocol_id protocol id (IKE, AH or ESP)
* @param notify_message_type notify type (see notify_message_type_t)
* @return notify_payload_t object
*
* @ingroup payloads
*/
notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type);
#endif /*NOTIFY_PAYLOAD_H_*/
+131
View File
@@ -0,0 +1,131 @@
/**
* @file payload.c
*
* @brief Generic constructor to the payload_t interface.
*
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "payload.h"
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/ke_payload.h>
#include <encoding/payloads/notify_payload.h>
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/certreq_payload.h>
#include <encoding/payloads/encryption_payload.h>
#include <encoding/payloads/ts_payload.h>
#include <encoding/payloads/delete_payload.h>
#include <encoding/payloads/vendor_id_payload.h>
#include <encoding/payloads/cp_payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/unknown_payload.h>
/*
* build the mappings for payload_type_t
*/
mapping_t payload_type_m[] = {
{NO_PAYLOAD, "NO_PAYLOAD"},
{SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"},
{KEY_EXCHANGE, "KEY_EXCHANGE"},
{ID_INITIATOR, "ID_INITIATOR"},
{ID_RESPONDER, "ID_RESPONDER"},
{CERTIFICATE, "CERTIFICATE"},
{CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"},
{AUTHENTICATION, "AUTHENTICATION"},
{NONCE, "NONCE"},
{NOTIFY, "NOTIFY"},
{DELETE, "DELETE"},
{VENDOR_ID, "VENDOR_ID"},
{TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"},
{TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"},
{ENCRYPTED, "ENCRYPTED"},
{CONFIGURATION, "CONFIGURATION"},
{EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"},
{HEADER, "HEADER"},
{PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"},
{TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"},
{TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"},
{TRAFFIC_SELECTOR_SUBSTRUCTURE, "TRAFFIC_SELECTOR_SUBSTRUCTURE"},
{CONFIGURATION_ATTRIBUTE,"CONFIGURATION_ATTRIBUTE"},
{UNKNOWN_PAYLOAD,"UNKNOWN_PAYLOAD"},
{MAPPING_END, NULL}
};
/*
* see header
*/
payload_t *payload_create(payload_type_t type)
{
switch (type)
{
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create();
case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create();
case TRANSFORM_SUBSTRUCTURE:
return (payload_t*)transform_substructure_create();
case TRANSFORM_ATTRIBUTE:
return (payload_t*)transform_attribute_create();
case NONCE:
return (payload_t*)nonce_payload_create();
case ID_INITIATOR:
return (payload_t*)id_payload_create(TRUE);
case ID_RESPONDER:
return (payload_t*)id_payload_create(FALSE);
case AUTHENTICATION:
return (payload_t*)auth_payload_create();
case CERTIFICATE:
return (payload_t*)cert_payload_create();
case CERTIFICATE_REQUEST:
return (payload_t*)certreq_payload_create();
case TRAFFIC_SELECTOR_SUBSTRUCTURE:
return (payload_t*)traffic_selector_substructure_create();
case TRAFFIC_SELECTOR_INITIATOR:
return (payload_t*)ts_payload_create(TRUE);
case TRAFFIC_SELECTOR_RESPONDER:
return (payload_t*)ts_payload_create(FALSE);
case KEY_EXCHANGE:
return (payload_t*)ke_payload_create();
case NOTIFY:
return (payload_t*)notify_payload_create();
case DELETE:
return (payload_t*)delete_payload_create();
case VENDOR_ID:
return (payload_t*)vendor_id_payload_create();
case CONFIGURATION:
return (payload_t*)cp_payload_create();
case CONFIGURATION_ATTRIBUTE:
return (payload_t*)configuration_attribute_create();
case EXTENSIBLE_AUTHENTICATION:
return (payload_t*)eap_payload_create();
case ENCRYPTED:
return (payload_t*)encryption_payload_create();
default:
return (payload_t*)unknown_payload_create();
}
}
+279
View File
@@ -0,0 +1,279 @@
/**
* @file payload.h
*
* @brief Interface payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PAYLOAD_H_
#define PAYLOAD_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/encodings.h>
typedef enum payload_type_t payload_type_t;
/**
* @brief Payload-Types of a IKEv2-Message.
*
* Header and substructures are also defined as
* payload types with values from PRIVATE USE space.
*
* @ingroup payloads
*/
enum payload_type_t{
/**
* End of payload list in next_payload
*/
NO_PAYLOAD = 0,
/**
* The security association (SA) payload containing proposals.
*/
SECURITY_ASSOCIATION = 33,
/**
* The key exchange (KE) payload containing diffie-hellman values.
*/
KEY_EXCHANGE = 34,
/**
* Identification for the original initiator (IDi).
*/
ID_INITIATOR = 35,
/**
* Identification for the original responder (IDr).
*/
ID_RESPONDER = 36,
/**
* Certificate payload with certificates (CERT).
*/
CERTIFICATE = 37,
/**
* Certificate request payload (CERTREQ).
*/
CERTIFICATE_REQUEST = 38,
/**
* Authentication payload contains auth data (AUTH).
*/
AUTHENTICATION = 39,
/**
* Nonces, for initator and responder (Ni, Nr, N)
*/
NONCE = 40,
/**
* Notif paylaod (N).
*/
NOTIFY = 41,
/**
* Delete payload (D)
*/
DELETE = 42,
/**
* Vendor id paylpoad (V).
*/
VENDOR_ID = 43,
/**
* Traffic selector for the original initiator (TSi).
*/
TRAFFIC_SELECTOR_INITIATOR = 44,
/**
* Traffic selector for the original responser (TSr).
*/
TRAFFIC_SELECTOR_RESPONDER = 45,
/**
* Encryption payload, contains other payloads (E).
*/
ENCRYPTED = 46,
/**
* Configuration payload (CP).
*/
CONFIGURATION = 47,
/**
* Extensible authentication payload (EAP).
*/
EXTENSIBLE_AUTHENTICATION = 48,
/**
* Header has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle IKEv2-Header like a payload.
*/
HEADER = 140,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a proposal substructure like a payload.
*/
PROPOSAL_SUBSTRUCTURE = 141,
/**
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform substructure like a payload.
*/
TRANSFORM_SUBSTRUCTURE = 142,
/**
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform attribute like a payload.
*/
TRANSFORM_ATTRIBUTE = 143,
/**
* TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform selector like a payload.
*/
TRAFFIC_SELECTOR_SUBSTRUCTURE = 144,
/**
* CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a transform attribute like a payload.
*/
CONFIGURATION_ATTRIBUTE = 145,
/**
* A unknown payload has a value of PRIVATE USE space.
*
* This payload type is not send over wire and just
* used internally to handle a unknown payload.
*/
UNKNOWN_PAYLOAD = 146,
};
/**
* String mappings for payload_type_t.
*/
extern mapping_t payload_type_m[];
typedef struct payload_t payload_t;
/**
* @brief Generic interface for all payload types (incl.header and substructures).
*
* To handle all kinds of payloads on a generic way, this interface must
* be implemented by every payload. This allows parser_t/generator_t a simple
* handling of all payloads.
*
* @b Constructors:
* - payload_create() with the payload to instanciate.
*
* @ingroup payloads
*/
struct payload_t {
/**
* @brief Get encoding rules for this payload.
*
* @param this calling object
* @param[out] rules location to store pointer of first rule
* @param[out] rule_count location to store number of rules
*/
void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
/**
* @brief Get type of payload.
*
* @param this calling object
* @return type of this payload
*/
payload_type_t (*get_type) (payload_t *this);
/**
* @brief Get type of next payload or NO_PAYLOAD (0) if this is the last one.
*
* @param this calling object
* @return type of next payload
*/
payload_type_t (*get_next_type) (payload_t *this);
/**
* @brief Set type of next payload.
*
* @param this calling object
* @param type type of next payload
*/
void (*set_next_type) (payload_t *this,payload_type_t type);
/**
* @brief Get length of payload.
*
* @param this calling object
* @return length of this payload
*/
size_t (*get_length) (payload_t *this);
/**
* @brief Verifies payload structure and makes consistence check.
*
* @param this calling object
* @return
* - SUCCESS
* - FAILED if consistence not given
*/
status_t (*verify) (payload_t *this);
/**
* @brief Destroys a payload and all included substructures.
*
* @param this payload to destroy
*/
void (*destroy) (payload_t *this);
};
/**
* @brief Create an empty payload.
*
* Useful for the parser, who wants a generic constructor for all payloads.
* It supports all payload_t methods. If a payload type is not known,
* an unknwon_paylod is created with the chunk of data in it.
*
* @param type type of the payload to create
* @return payload_t object
*/
payload_t *payload_create(payload_type_t type);
#endif /*PAYLOAD_H_*/
@@ -0,0 +1,629 @@
/**
* @file proposal_substructure.h
*
* @brief Implementation of proposal_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "proposal_substructure.h"
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/transform_substructure.h>
#include <types.h>
#include <utils/linked_list.h>
/**
* IKEv1 Value for a proposal payload.
*/
#define PROPOSAL_TYPE_VALUE 2
typedef struct private_proposal_substructure_t private_proposal_substructure_t;
/**
* Private data of an proposal_substructure_t object.
*
*/
struct private_proposal_substructure_t {
/**
* Public proposal_substructure_t interface.
*/
proposal_substructure_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Length of this payload.
*/
u_int16_t proposal_length;
/**
* Proposal number.
*/
u_int8_t proposal_number;
/**
* Protocol ID.
*/
u_int8_t protocol_id;
/**
* SPI size of the following SPI.
*/
u_int8_t spi_size;
/**
* Number of transforms.
*/
u_int8_t transforms_count;
/**
* SPI is stored as chunk.
*/
chunk_t spi;
/**
* Transforms are stored in a linked_list_t.
*/
linked_list_t * transforms;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_proposal_substructure_t object
*/
void (*compute_length) (private_proposal_substructure_t *this);
};
/**
* Encoding rules to parse or generate a Proposal substructure.
*
* The defined offsets are the positions in a object of type
* private_proposal_substructure_t.
*
*/
encoding_rule_t proposal_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole proposal substructure payload*/
{ PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
/* proposal number is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
/* protocol ID is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
/* SPI Size has its own type */
{ SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
/* Number of transforms is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
/* SPI is a chunk of variable size*/
{ SPI, offsetof(private_proposal_substructure_t, spi) },
/* Transforms are stored in a transform substructure,
offset points to a linked_list_t pointer */
{ TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 2 ! RESERVED ! Proposal Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ SPI (variable) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Transforms> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_proposal_substructure_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 2))
{
/* must be 0 or 2 */
return FAILED;
}
if (this->transforms_count != this->transforms->get_count(this->transforms))
{
/* must be the same! */
return FAILED;
}
if ((this->protocol_id == 0) || (this->protocol_id >= 4))
{
/* reserved are not supported */
return FAILED;
}
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_transform;
iterator->current(iterator,(void **)&current_transform);
status = current_transform->verify(current_transform);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
/* proposal number is checked in SA payload */
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = proposal_substructure_encodings;
*rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_proposal_substructure_t *this)
{
return PROPOSAL_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_proposal_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_proposal_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_proposal_substructure_t *this)
{
this->compute_length(this);
return this->proposal_length;
}
/**
* Implementation of proposal_substructure_t.create_transform_substructure_iterator.
*/
static iterator_t *create_transform_substructure_iterator (private_proposal_substructure_t *this,bool forward)
{
return (this->transforms->create_iterator(this->transforms,forward));
}
/**
* Implementation of proposal_substructure_t.add_transform_substructure.
*/
static void add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform)
{
status_t status;
if (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *last_transform;
status = this->transforms->get_last(this->transforms,(void **) &last_transform);
/* last transform is now not anymore last one */
last_transform->set_is_last_transform(last_transform,FALSE);
}
transform->set_is_last_transform(transform,TRUE);
this->transforms->insert_last(this->transforms,(void *) transform);
this->compute_length(this);
}
/**
* Implementation of proposal_substructure_t.proposal_substructure_t.
*/
static void set_is_last_proposal (private_proposal_substructure_t *this, bool is_last)
{
this->next_payload = (is_last) ? 0: PROPOSAL_TYPE_VALUE;
}
/**
* Implementation of proposal_substructure_t.set_proposal_number.
*/
static void set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
{
this->proposal_number = proposal_number;
}
/**
* Implementation of proposal_substructure_t.get_proposal_number.
*/
static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
{
return (this->proposal_number);
}
/**
* Implementation of proposal_substructure_t.set_protocol_id.
*/
static void set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
}
/**
* Implementation of proposal_substructure_t.get_protocol_id.
*/
static u_int8_t get_protocol_id (private_proposal_substructure_t *this)
{
return (this->protocol_id);
}
/**
* Implementation of proposal_substructure_t.set_spi.
*/
static void set_spi (private_proposal_substructure_t *this, chunk_t spi)
{
/* first delete already set spi value */
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
this->compute_length(this);
}
this->spi.ptr = clalloc(spi.ptr,spi.len);
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
}
/**
* Implementation of proposal_substructure_t.get_spi.
*/
static chunk_t get_spi (private_proposal_substructure_t *this)
{
chunk_t spi;
spi.ptr = this->spi.ptr;
spi.len = this->spi.len;
return spi;
}
/**
* Implementation of proposal_substructure_t.get_info_for_transform_type.
*/
static status_t get_info_for_transform_type (private_proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length)
{
iterator_t *iterator;
status_t status;
u_int16_t found_transform_id;
u_int16_t found_key_length;
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while (iterator->has_next(iterator))
{
transform_substructure_t *current_transform;
status = iterator->current(iterator,(void **) &current_transform);
if (status != SUCCESS)
{
break;
}
if (current_transform->get_transform_type(current_transform) == type)
{
/* now get data for specific type */
found_transform_id = current_transform->get_transform_id(current_transform);
status = current_transform->get_key_length(current_transform,&found_key_length);
*transform_id = found_transform_id;
*key_length = found_key_length;
iterator->destroy(iterator);
return status;
}
}
iterator->destroy(iterator);
return NOT_FOUND;
}
/**
* Implementation of private_proposal_substructure_t.compute_length.
*/
static void compute_length (private_proposal_substructure_t *this)
{
iterator_t *iterator;
size_t transforms_count = 0;
size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
iterator = this->transforms->create_iterator(this->transforms,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_transform;
iterator->current(iterator,(void **) &current_transform);
length += current_transform->get_length(current_transform);
transforms_count++;
}
iterator->destroy(iterator);
length += this->spi.len;
this->transforms_count = transforms_count;
this->proposal_length = length;
}
/**
* Implementation of proposal_substructure_t.get_transform_count.
*/
static size_t get_transform_count (private_proposal_substructure_t *this)
{
return this->transforms->get_count(this->transforms);
}
/**
* Implementation of proposal_substructure_t.get_spi_size.
*/
static size_t get_spi_size (private_proposal_substructure_t *this)
{
return this->spi.len;
}
/**
* Implementation of proposal_substructure_t.add_to_proposal.
*/
void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal)
{
iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE);
u_int32_t spi;
while (iterator->has_next(iterator))
{
transform_substructure_t *transform;
transform_type_t transform_type;
u_int16_t transform_id;
u_int16_t key_length = 0;
iterator->current(iterator, (void**)&transform);
transform_type = transform->get_transform_type(transform);
transform_id = transform->get_transform_id(transform);
transform->get_key_length(transform, &key_length);
proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length);
}
iterator->destroy(iterator);
spi = *((u_int32_t*)this->spi.ptr);
proposal->set_spi(proposal, this->protocol_id, spi);
}
/**
* Implementation of proposal_substructure_t.clone.
*/
static private_proposal_substructure_t* clone(private_proposal_substructure_t *this)
{
private_proposal_substructure_t * new_clone;
iterator_t *transforms;
new_clone = (private_proposal_substructure_t *) proposal_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->proposal_number = this->proposal_number;
new_clone->protocol_id = this->protocol_id;
new_clone->spi_size = this->spi_size;
if (this->spi.ptr != NULL)
{
new_clone->spi.ptr = clalloc(this->spi.ptr,this->spi.len);
new_clone->spi.len = this->spi.len;
}
transforms = this->transforms->create_iterator(this->transforms,FALSE);
while (transforms->has_next(transforms))
{
transform_substructure_t *current_transform;
transform_substructure_t *current_transform_clone;
transforms->current(transforms,(void **) &current_transform);
current_transform_clone = current_transform->clone(current_transform);
new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone);
}
transforms->destroy(transforms);
return new_clone;
}
/**
* Implements payload_t's and proposal_substructure_t's destroy function.
* See #payload_s.destroy or proposal_substructure_s.destroy for description.
*/
static status_t destroy(private_proposal_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *current_transform;
if (this->transforms->remove_last(this->transforms,(void **)&current_transform) != SUCCESS)
{
break;
}
current_transform->destroy(current_transform);
}
this->transforms->destroy(this->transforms);
if (this->spi.ptr != NULL)
{
free(this->spi.ptr);
}
free(this);
return SUCCESS;
}
/*
* Described in header.
*/
proposal_substructure_t *proposal_substructure_create()
{
private_proposal_substructure_t *this = malloc_thing(private_proposal_substructure_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_substructure_iterator = (iterator_t* (*) (proposal_substructure_t *,bool)) create_transform_substructure_iterator;
this->public.add_transform_substructure = (void (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
this->public.set_proposal_number = (void (*) (proposal_substructure_t *,u_int8_t))set_proposal_number;
this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number;
this->public.set_protocol_id = (void (*) (proposal_substructure_t *,u_int8_t))set_protocol_id;
this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id;
this->public.get_info_for_transform_type = (status_t (*) (proposal_substructure_t *,transform_type_t,u_int16_t *, u_int16_t *))get_info_for_transform_type;
this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal;
this->public.add_to_proposal = (void (*) (proposal_substructure_t*,proposal_t*))add_to_proposal;
this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi;
this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count;
this->public.get_spi_size = (size_t (*) (proposal_substructure_t *)) get_spi_size;
this->public.clone = (proposal_substructure_t * (*) (proposal_substructure_t *)) clone;
this->public.destroy = (void (*) (proposal_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->proposal_length = 0;
this->proposal_number = 0;
this->protocol_id = 0;
this->transforms_count = 0;
this->spi_size = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->transforms = linked_list_create();
return (&(this->public));
}
/*
* Described in header.
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto)
{
private_proposal_substructure_t *this = (private_proposal_substructure_t*)proposal_substructure_create();
iterator_t *iterator;
algorithm_t *algo;
transform_substructure_t *transform;
/* encryption algorithm is only availble in ESP */
iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* integrity algorithms */
iterator = proposal->create_algorithm_iterator(proposal, proto, INTEGRITY_ALGORITHM);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* prf algorithms */
iterator = proposal->create_algorithm_iterator(proposal, proto, PSEUDO_RANDOM_FUNCTION);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, algo->algorithm, algo->key_size);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* dh groups */
iterator = proposal->create_algorithm_iterator(proposal, proto, DIFFIE_HELLMAN_GROUP);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* extended sequence numbers */
iterator = proposal->create_algorithm_iterator(proposal, proto, EXTENDED_SEQUENCE_NUMBERS);
while (iterator->has_next(iterator))
{
algorithm_t *algo;
iterator->current(iterator, (void**)&algo);
transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, algo->algorithm, 0);
this->public.add_transform_substructure(&(this->public), transform);
}
iterator->destroy(iterator);
/* take over general infos */
this->spi_size = proto == PROTO_IKE ? 8 : 4;
this->spi.len = this->spi_size;
this->spi.ptr = malloc(this->spi_size);
*((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto);
this->proposal_number = proposal->get_number(proposal);
this->protocol_id = proto;
return &(this->public);
}
@@ -0,0 +1,231 @@
/**
* @file proposal_substructure.h
*
* @brief Interface of proposal_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PROPOSAL_SUBSTRUCTURE_H_
#define PROPOSAL_SUBSTRUCTURE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <config/proposal.h>
#include <utils/linked_list.h>
/**
* Length of the proposal substructure header (without spi).
*
* @ingroup payloads
*/
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
typedef struct proposal_substructure_t proposal_substructure_t;
/**
* @brief Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
*
* The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
*
* @b Constructors:
* - proposal_substructure_create()
*
* @ingroup payloads
*/
struct proposal_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
* When deleting any transform over this iterator, call
* get_size to make sure the length and number values are ok.
*
* @param this calling proposal_substructure_t object
* @param forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t * (*create_transform_substructure_iterator) (proposal_substructure_t *this, bool forward);
/**
* @brief Adds a transform_substructure_t object to this object.
*
* @warning The added transform_substructure_t object is
* getting destroyed in destroy function of proposal_substructure_t.
*
* @param this calling proposal_substructure_t object
* @param transform transform_substructure_t object to add
*/
void (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform);
/**
* @brief Sets the proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id proposal number to set
*/
void (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number);
/**
* @brief get proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @return proposal number of current proposal substructure.
*/
u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
/**
* @brief get the number of transforms in current proposal.
*
* @param this calling proposal_substructure_t object
* @return transform count in current proposal
*/
size_t (*get_transform_count) (proposal_substructure_t *this);
/**
* @brief get size of the set spi in bytes.
*
* @param this calling proposal_substructure_t object
* @return size of the spi in bytes
*/
size_t (*get_spi_size) (proposal_substructure_t *this);
/**
* @brief Sets the protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id protocol id to set
*/
void (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id);
/**
* @brief get protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @return protocol id of current proposal substructure.
*/
u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
/**
* @brief Get informations for a specific transform type.
*
* @param this calling proposal_substructure_t object
* @param type type to get informations for
* @param transform_id transform id of the specific type
* @param key_length key length of the specific key length transform attribute
* @return
* - SUCCESS if transform type is part of this proposal and
* all data (incl. key length) could be fetched
* - NOT_FOUND if transform type is not part of this proposal
*/
status_t (*get_info_for_transform_type) (proposal_substructure_t *this,transform_type_t type, u_int16_t *transform_id, u_int16_t *key_length);
/**
* @brief Sets the next_payload field of this substructure
*
* If this is the last proposal, next payload field is set to 0,
* otherwise to 2
*
* @param this calling proposal_substructure_t object
* @param is_last When TRUE, next payload field is set to 0, otherwise to 2
*/
void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last);
/**
* @brief Returns the currently set SPI of this proposal.
*
* @warning Returned data are not copied
*
* @param this calling proposal_substructure_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (proposal_substructure_t *this);
/**
* @brief Sets the SPI of the current proposal.
*
* @warning SPI is getting copied
*
* @param this calling proposal_substructure_t object
* @param spi chunk_t pointing to the value to set
*/
void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
/**
* @brief Add this proposal_substructure to a proposal.
*
* Since a proposal_t may contain the data of multiple
* proposal_sbustructure_t's, it may be necessary to call
* the function multiple times with the same proposal.
*
* @param this calling proposal_substructure_t object
* @param proposal proposal where the data should be added
*/
void (*add_to_proposal) (proposal_substructure_t *this, proposal_t *proposal);
/**
* @brief Clones an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to clone
* @return cloned object
*/
proposal_substructure_t* (*clone) (proposal_substructure_t *this);
/**
* @brief Destroys an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to destroy
*/
void (*destroy) (proposal_substructure_t *this);
};
/**
* @brief Creates an empty proposal_substructure_t object
*
* @return proposal_substructure_t object
*
* @ingroup payloads
*/
proposal_substructure_t *proposal_substructure_create(void);
/**
* @brief Creates a proposal substructure from a proposal.
*
* Since a child proposal may contain data for both AH and ESP,
* the protocol must be specified. If the proposal does not contain
* data for proto, NULL is returned. Call twice, once with AH, once
* with ESP, with the same proposal to build the two substructures
* for it.
*
* @param proposal proposal to build a substruct out of it
* @param proto for which protocol the substructure should be built
* @return proposal_substructure_t object, or NULL
*
* @ingroup payloads
*/
proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto);
#endif /*PROPOSAL_SUBSTRUCTURE_H_*/
+390
View File
@@ -0,0 +1,390 @@
/**
* @file sa_payload.c
*
* @brief Implementation of sa_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "sa_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
typedef struct private_sa_payload_t private_sa_payload_t;
/**
* Private data of an sa_payload_t object.
*
*/
struct private_sa_payload_t {
/**
* Public sa_payload_t interface.
*/
sa_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Proposals in this payload are stored in a linked_list_t.
*/
linked_list_t * proposals;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_sa_payload_t object
*/
void (*compute_length) (private_sa_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-SA Payload
*
* The defined offsets are the positions in a object of type
* private_sa_payload_t.
*
*/
encoding_rule_t sa_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ PROPOSALS, offsetof(private_sa_payload_t, proposals) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Proposals> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_sa_payload_t *this)
{
int proposal_number = 1;
status_t status = SUCCESS;
iterator_t *iterator;
bool first = TRUE;
/* check proposal numbering */
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while(iterator->has_next(iterator))
{
proposal_substructure_t *current_proposal;
iterator->current(iterator,(void **)&current_proposal);
if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
{
if (first)
{
/* first number must be 1 */
status = FAILED;
break;
}
if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
{
/* must be only one more then previous proposal */
status = FAILED;
break;
}
}
else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
{
/* must not be smaller then proceeding one */
status = FAILED;
break;
}
status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface));
if (status != SUCCESS)
{
break;
}
first = FALSE;
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of payload_t.destroy and sa_payload_t.destroy.
*/
static status_t destroy(private_sa_payload_t *this)
{
/* all proposals are getting destroyed */
while (this->proposals->get_count(this->proposals) > 0)
{
proposal_substructure_t *current_proposal;
this->proposals->remove_last(this->proposals,(void **)&current_proposal);
current_proposal->destroy(current_proposal);
}
this->proposals->destroy(this->proposals);
free(this);
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = sa_payload_encodings;
*rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_sa_payload_t *this)
{
return SECURITY_ASSOCIATION;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_sa_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_sa_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_sa_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of sa_payload_t.create_proposal_substructure_iterator.
*/
static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t *this,bool forward)
{
return this->proposals->create_iterator(this->proposals,forward);
}
/**
* Implementation of sa_payload_t.add_proposal_substructure.
*/
static void add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal)
{
status_t status;
if (this->proposals->get_count(this->proposals) > 0)
{
proposal_substructure_t *last_proposal;
status = this->proposals->get_last(this->proposals,(void **) &last_proposal);
/* last transform is now not anymore last one */
last_proposal->set_is_last_proposal(last_proposal,FALSE);
}
proposal->set_is_last_proposal(proposal,TRUE);
this->proposals->insert_last(this->proposals,(void *) proposal);
this->compute_length(this);
}
/**
* Implementation of sa_payload_t.add_proposal.
*/
static void add_proposal(private_sa_payload_t *this, proposal_t *proposal)
{
proposal_substructure_t *substructure;
protocol_id_t proto[2];
u_int i;
/* build the substructures for every protocol */
proposal->get_protocols(proposal, proto);
for (i = 0; i<2; i++)
{
if (proto[i] != PROTO_NONE)
{
substructure = proposal_substructure_create_from_proposal(proposal, proto[i]);
add_proposal_substructure(this, substructure);
}
}
}
/**
* Implementation of sa_payload_t.get_proposals.
*/
static linked_list_t *get_proposals(private_sa_payload_t *this)
{
int proposal_struct_number = 0;
iterator_t *iterator;
proposal_t *proposal;
linked_list_t *proposal_list;
/* this list will hold our proposals */
proposal_list = linked_list_create();
/* iterate over structures, one OR MORE structures will result in a proposal */
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while (iterator->has_next(iterator))
{
proposal_substructure_t *proposal_struct;
iterator->current(iterator,(void **)&(proposal_struct));
if (proposal_struct->get_proposal_number(proposal_struct) > proposal_struct_number)
{
/* here starts a new proposal, create a new one and add it to the list */
proposal_struct_number = proposal_struct->get_proposal_number(proposal_struct);
proposal = proposal_create(proposal_struct_number);
proposal_list->insert_last(proposal_list, proposal);
}
/* proposal_substructure_t does the dirty work and builds up the proposal */
proposal_struct->add_to_proposal(proposal_struct, proposal);
}
iterator->destroy(iterator);
return proposal_list;
}
/**
* Implementation of private_sa_payload_t.compute_length.
*/
static void compute_length (private_sa_payload_t *this)
{
iterator_t *iterator;
size_t length = SA_PAYLOAD_HEADER_LENGTH;
iterator = this->proposals->create_iterator(this->proposals,TRUE);
while (iterator->has_next(iterator))
{
payload_t *current_proposal;
iterator->current(iterator,(void **) &current_proposal);
length += current_proposal->get_length(current_proposal);
}
iterator->destroy(iterator);
this->payload_length = length;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create()
{
private_sa_payload_t *this = malloc_thing(private_sa_payload_t);
/* public interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_proposal_substructure_iterator = (iterator_t* (*) (sa_payload_t *,bool)) create_proposal_substructure_iterator;
this->public.add_proposal_substructure = (void (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
this->public.get_proposals = (linked_list_t* (*) (sa_payload_t *)) get_proposals;
this->public.destroy = (void (*) (sa_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
this->proposals = linked_list_create();
return (&(this->public));
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
{
iterator_t *iterator;
proposal_t *proposal;
sa_payload_t *sa_payload = sa_payload_create();
/* add every payload from the list */
iterator = proposals->create_iterator(proposals, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&proposal);
add_proposal((private_sa_payload_t*)sa_payload, proposal);
}
iterator->destroy(iterator);
return sa_payload;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
{
sa_payload_t *sa_payload = sa_payload_create();
add_proposal((private_sa_payload_t*)sa_payload, proposal);
return sa_payload;
}
+140
View File
@@ -0,0 +1,140 @@
/**
* @file sa_payload.h
*
* @brief Interface of sa_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef SA_PAYLOAD_H_
#define SA_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
/**
* SA_PAYLOAD length in bytes without any proposal substructure.
*
* @ingroup payloads
*/
#define SA_PAYLOAD_HEADER_LENGTH 4
typedef struct sa_payload_t sa_payload_t;
/**
* @brief Class representing an IKEv2-SA Payload.
*
* The SA Payload format is described in RFC section 3.3.
*
* @b Constructors:
* - sa_payload_create()
* - sa_payload_create_from_ike_proposals()
* - sa_payload_create_from_proposal()
*
* @todo Add support of algorithms without specified keylength in get_proposals and get_ike_proposals.
*
* @ingroup payloads
*/
struct sa_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored proposal_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an proposal using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling sa_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, bool forward);
/**
* @brief Adds a proposal_substructure_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of sa_payload_t.
*
* @param this calling sa_payload_t object
* @param proposal proposal_substructure_t object to add
*/
void (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal);
/**
* @brief Gets the proposals in this payload as a list.
*
* @return a list containing proposal_t s
*/
linked_list_t *(*get_proposals) (sa_payload_t *this);
/**
* @brief Add a child proposal (AH/ESP) to the payload.
*
* @param proposal child proposal to add to the payload
*/
void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
/**
* @brief Destroys an sa_payload_t object.
*
* @param this sa_payload_t object to destroy
*/
void (*destroy) (sa_payload_t *this);
};
/**
* @brief Creates an empty sa_payload_t object
*
* @return created sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create(void);
/**
* @brief Creates a sa_payload_t object from a list of proposals.
*
* @param proposals list of proposals to build the payload from
* @return sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
/**
* @brief Creates a sa_payload_t object from a single proposal.
*
* This is only for convenience. Use sa_payload_create_from_proposal_list
* if you want to add more than one proposal.
*
* @param proposal proposal from which the payload should be built.
* @return sa_payload_t object
*
* @ingroup payloads
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
#endif /*SA_PAYLOAD_H_*/
@@ -0,0 +1,374 @@
/**
* @file traffic_selector_substructure.c
*
* @brief Interface of traffic_selector_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "traffic_selector_substructure.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
/**
* String mappings for ts_type_t.
*/
mapping_t ts_type_m[] = {
{TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"},
{TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"},
{MAPPING_END, NULL}
};
typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
/**
* Private data of an traffic_selector_substructure_t object.
*
*/
struct private_traffic_selector_substructure_t {
/**
* Public traffic_selector_substructure_t interface.
*/
traffic_selector_substructure_t public;
/**
* Type of traffic selector.
*/
u_int8_t ts_type;
/**
* IP Protocol ID.
*/
u_int8_t ip_protocol_id;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Start port number.
*/
u_int16_t start_port;
/**
* End port number.
*/
u_int16_t end_port;
/**
* Starting address.
*/
chunk_t starting_address;
/**
* Ending address.
*/
chunk_t ending_address;
/**
* update length
*/
void (*compute_length) (private_traffic_selector_substructure_t *this);
};
/**
* Encoding rules to parse or generate a TS payload
*
* The defined offsets are the positions in a object of type
* private_traffic_selector_substructure_t.
*
*/
encoding_rule_t traffic_selector_substructure_encodings[] = {
/* 1 Byte next ts type*/
{ TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
/* 1 Byte IP protocol id*/
{ U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
/* 2 Byte start port*/
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
/* 2 Byte end port*/
{ U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
/* starting address is either 4 or 16 byte */
{ ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
/* ending address is either 4 or 16 byte */
{ ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! TS Type !IP Protocol ID*| Selector Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Start Port* | End Port* |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Starting Address* ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Ending Address* ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_traffic_selector_substructure_t *this)
{
if (this->start_port > this->end_port)
{
return FAILED;
}
switch (this->ts_type)
{
case TS_IPV4_ADDR_RANGE:
{
if ((this->starting_address.len != 4) ||
(this->ending_address.len != 4))
{
/* ipv4 address must be 4 bytes long */
return FAILED;
}
break;
}
case TS_IPV6_ADDR_RANGE:
default:
{
/* not supported ts type */
return FAILED;
}
}
return SUCCESS;
}
/**
* Implementation of traffic_selector_substructure_t.get_encoding_rules.
*/
static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = traffic_selector_substructure_encodings;
*rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
{
return TRAFFIC_SELECTOR_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
{
return 0;
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_traffic_selector_substructure_t *this)
{
return this->payload_length;
}
/**
* Implementation of traffic_selector_substructure_t.get_ts_type.
*/
static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this)
{
return this->ts_type;
}
/**
* Implementation of traffic_selector_substructure_t.set_ts_type.
*/
static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type)
{
this->ts_type = ts_type;
}
/**
* Implementation of traffic_selector_substructure_t.get_protocol_id.
*/
static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this)
{
return this->ip_protocol_id;
}
/**
* Implementation of traffic_selector_substructure_t.set_protocol_id.
*/
static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id)
{
this->ip_protocol_id = protocol_id;
}
/**
* Implementation of traffic_selector_substructure_t.get_start_host.
*/
static host_t * get_start_host (private_traffic_selector_substructure_t *this)
{
return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port));
}
/**
* Implementation of traffic_selector_substructure_t.set_start_host.
*/
static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host)
{
this->start_port = start_host->get_port(start_host);
if (this->starting_address.ptr != NULL)
{
chunk_free(&(this->starting_address));
}
this->starting_address = start_host->get_address_as_chunk(start_host);
this->compute_length(this);
}
/**
* Implementation of traffic_selector_substructure_t.get_end_host.
*/
static host_t *get_end_host (private_traffic_selector_substructure_t *this)
{
return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port));
}
/**
* Implementation of traffic_selector_substructure_t.set_end_host.
*/
static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host)
{
this->end_port = end_host->get_port(end_host);
if (this->ending_address.ptr != NULL)
{
chunk_free(&(this->ending_address));
}
this->ending_address = end_host->get_address_as_chunk(end_host);
this->compute_length(this);
}
/**
* Implementation of traffic_selector_substructure_t.get_traffic_selector.
*/
static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
{
traffic_selector_t *ts;
ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
this->starting_address, this->start_port,
this->ending_address, this->end_port);
return ts;
}
/**
* Implementation of private_ts_payload_t.compute_length
*/
void compute_length(private_traffic_selector_substructure_t *this)
{
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->ending_address.len + this->starting_address.len;
}
/**
* Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
*/
static void destroy(private_traffic_selector_substructure_t *this)
{
free(this->starting_address.ptr);
free(this->ending_address.ptr);
free(this);
}
/*
* Described in header
*/
traffic_selector_substructure_t *traffic_selector_substructure_create()
{
private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type;
this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type;
this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id;
this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id;
this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host;
this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host;
this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host;
this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host;
this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
this->start_port = 0;
this->end_port = 0;
this->starting_address = CHUNK_INITIALIZER;
this->ending_address = CHUNK_INITIALIZER;
this->ip_protocol_id = 0;
/* must be set to be valid */
this->ts_type = TS_IPV4_ADDR_RANGE;
return (&(this->public));
}
/*
* Described in header
*/
traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
{
private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
this->ts_type = traffic_selector->get_type(traffic_selector);
this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
this->start_port = traffic_selector->get_from_port(traffic_selector);
this->end_port = traffic_selector->get_to_port(traffic_selector);
this->starting_address = traffic_selector->get_from_address(traffic_selector);
this->ending_address = traffic_selector->get_to_address(traffic_selector);
this->compute_length(this);
return &(this->public);
}
@@ -0,0 +1,171 @@
/**
* @file traffic_selector_substructure.h
*
* @brief Interface of traffic_selector_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
#define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <utils/host.h>
#include <config/traffic_selector.h>
/**
* Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
*
* @ingroup payloads
*/
#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
/**
* @brief Class representing an IKEv2 TRAFFIC SELECTOR.
*
* The TRAFFIC SELECTOR format is described in RFC section 3.13.1.
*
* @b Constructors:
* - traffic_selector_substructure_create()
* - traffic_selector_substructure_create_from_traffic_selector()
*
* @ingroup payloads
*/
struct traffic_selector_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the type of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @return type of traffic selector
*
*/
ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this);
/**
* @brief Set the type of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @param ts_type type of traffic selector
*/
void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type);
/**
* @brief Get the IP protocol ID of Traffic selector.
*
* @param this calling traffic_selector_substructure_t object
* @return type of traffic selector
*
*/
u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this);
/**
* @brief Set the IP protocol ID of Traffic selector
*
* @param this calling traffic_selector_substructure_t object
* @param protocol_id protocol ID of traffic selector
*/
void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id);
/**
* @brief Get the start port and address as host_t object.
*
* Returned host_t object has to get destroyed by the caller.
*
* @param this calling traffic_selector_substructure_t object
* @return start host as host_t object
*
*/
host_t *(*get_start_host) (traffic_selector_substructure_t *this);
/**
* @brief Set the start port and address as host_t object.
*
* @param this calling traffic_selector_substructure_t object
* @param start_host start host as host_t object
*/
void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host);
/**
* @brief Get the end port and address as host_t object.
*
* Returned host_t object has to get destroyed by the caller.
*
* @param this calling traffic_selector_substructure_t object
* @return end host as host_t object
*
*/
host_t *(*get_end_host) (traffic_selector_substructure_t *this);
/**
* @brief Set the end port and address as host_t object.
*
* @param this calling traffic_selector_substructure_t object
* @param end_host end host as host_t object
*/
void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host);
/**
* @brief Get a traffic_selector_t from this substructure.
*
* @warning traffic_selector_t must be destroyed after usage.
*
* @param this calling traffic_selector_substructure_t object
* @return contained traffic_selector_t
*/
traffic_selector_t *(*get_traffic_selector) (traffic_selector_substructure_t *this);
/**
* @brief Destroys an traffic_selector_substructure_t object.
*
* @param this traffic_selector_substructure_t object to destroy
*/
void (*destroy) (traffic_selector_substructure_t *this);
};
/**
* @brief Creates an empty traffic_selector_substructure_t object.
*
* TS type is set to default TS_IPV4_ADDR_RANGE!
*
* @return traffic_selector_substructure_t object
*
* @ingroup payloads
*/
traffic_selector_substructure_t *traffic_selector_substructure_create(void);
/**
* @brief Creates an initialized traffif selector substructure using
* the values from a traffic_selector_t.
*
* @param traffic_selector traffic_selector_t to use for initialization
* @return traffic_selector_substructure_t object
*
* @ingroup payloads
*/
traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector);
#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ */
@@ -0,0 +1,333 @@
/**
* @file transform_attribute.c
*
* @brief Implementation of transform_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include <stddef.h>
#include "transform_attribute.h"
#include <encoding/payloads/encodings.h>
#include <types.h>
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
* Private data of an transform_attribute_t object.
*
*/
struct private_transform_attribute_t {
/**
* Public transform_attribute_t interface.
*/
transform_attribute_t public;
/**
* Attribute Format Flag.
*
* - TRUE means value is stored in attribute_length_or_value
* - FALSE means value is stored in attribute_value
*/
bool attribute_format;
/**
* Type of the attribute.
*/
u_int16_t attribute_type;
/**
* Attribute Length if attribute_format is 0, attribute Value otherwise.
*/
u_int16_t attribute_length_or_value;
/**
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
};
/**
* String mappings for transform_attribute_type_t.
*/
mapping_t transform_attribute_type_m[] = {
{ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"},
{KEY_LENGTH, "KEY_LENGTH"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a Transform attribute.
*
* The defined offsets are the positions in a object of type
* private_transform_attribute_t.
*
*/
encoding_rule_t transform_attribute_encodings[] = {
/* Flag defining the format of this payload */
{ ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
/* Length or value, depending on the attribute format flag */
{ ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) },
/* Value of attribute if attribute format flag is zero */
{ ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!A! Attribute Type ! AF=0 Attribute Length !
!F! ! AF=1 Attribute Value !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! AF=0 Attribute Value !
! AF=1 Not Transmitted !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_transform_attribute_t *this)
{
if (this->attribute_type != KEY_LENGTH)
{
return FAILED;
}
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_attribute_encodings;
*rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_transform_attribute_t *this)
{
return (NO_PAYLOAD);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_transform_attribute_t *this,payload_type_t type)
{
}
/**
* Implementation of transform_attribute_t.get_length.
*/
static size_t get_length(private_transform_attribute_t *this)
{
if (this->attribute_format == TRUE)
{
/*Attribute size is only 4 byte */
return 4;
}
return (this->attribute_length_or_value + 4);
}
/**
* Implementation of transform_attribute_t.set_value_chunk.
*/
static void set_value_chunk(private_transform_attribute_t *this, chunk_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
if (value.len > 2)
{
this->attribute_value.ptr = clalloc(value.ptr,value.len);
this->attribute_value.len = value.len;
this->attribute_length_or_value = value.len;
/* attribute has not a fixed length */
this->attribute_format = FALSE;
}
else
{
memcpy(&(this->attribute_length_or_value),value.ptr,value.len);
}
}
/**
* Implementation of transform_attribute_t.set_value.
*/
static void set_value(private_transform_attribute_t *this, u_int16_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
this->attribute_length_or_value = value;
}
/**
* Implementation of transform_attribute_t.get_value_chunk.
*/
static chunk_t get_value_chunk (private_transform_attribute_t *this)
{
chunk_t value;
if (this->attribute_format == FALSE)
{
value.ptr = this->attribute_value.ptr;
value.len = this->attribute_value.len;
}
else
{
value.ptr = (void *) &(this->attribute_length_or_value);
value.len = 2;
}
return value;
}
/**
* Implementation of transform_attribute_t.get_value.
*/
static u_int16_t get_value (private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
/**
* Implementation of transform_attribute_t.set_attribute_type.
*/
static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
/**
* Implementation of transform_attribute_t.get_attribute_type.
*/
static u_int16_t get_attribute_type (private_transform_attribute_t *this)
{
return this->attribute_type;
}
/**
* Implementation of transform_attribute_t.clone.
*/
static transform_attribute_t * clone(private_transform_attribute_t *this)
{
private_transform_attribute_t *new_clone;
new_clone = (private_transform_attribute_t *) transform_attribute_create();
new_clone->attribute_format = this->attribute_format;
new_clone->attribute_type = this->attribute_type;
new_clone->attribute_length_or_value = this->attribute_length_or_value;
if (!new_clone->attribute_format)
{
new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len);
new_clone->attribute_value.len = this->attribute_value.len;
}
return (transform_attribute_t *) new_clone;
}
/**
* Implementation of transform_attribute_t.destroy and payload_t.destroy.
*/
static void destroy(private_transform_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
free(this->attribute_value.ptr);
}
free(this);
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create()
{
private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
this->public.set_value = (void (*) (transform_attribute_t *,u_int16_t)) set_value;
this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value;
this->public.set_attribute_type = (void (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type;
this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type;
this->public.clone = (transform_attribute_t * (*) (transform_attribute_t *)) clone;
this->public.destroy = (void (*) (transform_attribute_t *)) destroy;
/* set default values of the fields */
this->attribute_format = TRUE;
this->attribute_type = 0;
this->attribute_length_or_value = 0;
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
return (&(this->public));
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
{
transform_attribute_t *attribute = transform_attribute_create();
attribute->set_attribute_type(attribute,KEY_LENGTH);
attribute->set_value(attribute,key_length);
return attribute;
}
@@ -0,0 +1,154 @@
/**
* @file transform_attribute.h
*
* @brief Interface of transform_attribute_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TRANSFORM_ATTRIBUTE_H_
#define TRANSFORM_ATTRIBUTE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
typedef enum transform_attribute_type_t transform_attribute_type_t;
/**
* Type of the attribute, as in IKEv2 RFC 3.3.5.
*
* @ingroup payloads
*/
enum transform_attribute_type_t {
ATTRIBUTE_UNDEFINED = 16384,
KEY_LENGTH = 14
};
/**
* String mappings for transform_attribute_type_t.
*
* @ingroup payloads
*/
extern mapping_t transform_attribute_type_m[];
typedef struct transform_attribute_t transform_attribute_t;
/**
* @brief Class representing an IKEv2- TRANSFORM Attribute.
*
* The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
*
* @ingroup payloads
*/
struct transform_attribute_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling transform_attribute_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_value_chunk) (transform_attribute_t *this);
/**
* @brief Returns the currently set value of the attribute.
*
* @warning Returned data are not copied.
*
* @param this calling transform_attribute_t object
* @return value
*/
u_int16_t (*get_value) (transform_attribute_t *this);
/**
* @brief Sets the value of the attribute.
*
* @warning Value is getting copied.
*
* @param this calling transform_attribute_t object
* @param value chunk_t pointing to the value to set
*/
void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
/**
* @brief Sets the value of the attribute.
*
* @param this calling transform_attribute_t object
* @param value value to set
*/
void (*set_value) (transform_attribute_t *this, u_int16_t value);
/**
* @brief Sets the type of the attribute.
*
* @param this calling transform_attribute_t object
* @param type type to set (most significant bit is set to zero)
*/
void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
/**
* @brief get the type of the attribute.
*
* @param this calling transform_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
/**
* @brief Clones an transform_attribute_t object.
*
* @param this transform_attribute_t object to clone
* @return cloned transform_attribute_t object
*/
transform_attribute_t * (*clone) (transform_attribute_t *this);
/**
* @brief Destroys an transform_attribute_t object.
*
* @param this transform_attribute_t object to destroy
*/
void (*destroy) (transform_attribute_t *this);
};
/**
* @brief Creates an empty transform_attribute_t object.
*
* @return transform_attribute_t object
*
* @ingroup payloads
*/
transform_attribute_t *transform_attribute_create(void);
/**
* @brief Creates an transform_attribute_t of type KEY_LENGTH.
*
* @param key_length key length in bytes
* @return transform_attribute_t object
*
* @ingroup payloads
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
#endif /*TRANSFORM_ATTRIBUTE_H_*/
@@ -0,0 +1,485 @@
/**
* @file transform_substructure.h
*
* @brief Implementation of transform_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "transform_substructure.h"
#include <encoding/payloads/transform_attribute.h>
#include <encoding/payloads/encodings.h>
#include <types.h>
#include <utils/linked_list.h>
typedef struct private_transform_substructure_t private_transform_substructure_t;
/**
* Private data of an transform_substructure_t object.
*
*/
struct private_transform_substructure_t {
/**
* Public transform_substructure_t interface.
*/
transform_substructure_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Length of this payload.
*/
u_int16_t transform_length;
/**
* Type of the transform.
*/
u_int8_t transform_type;
/**
* Transform ID.
*/
u_int16_t transform_id;
/**
* Transforms Attributes are stored in a linked_list_t.
*/
linked_list_t *attributes;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_transform_substructure_t object
*/
void (*compute_length) (private_transform_substructure_t *this);
};
/**
* Encoding rules to parse or generate a Transform substructure.
*
* The defined offsets are the positions in a object of type
* private_transform_substructure_t.
*
*/
encoding_rule_t transform_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole transform substructure*/
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
/* transform type is a number of 8 bit */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* tranform ID is a number of 8 bit */
{ U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
/* Attributes are stored in a transform attribute,
offset points to a linked_list_t pointer */
{ TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!Transform Type ! RESERVED ! Transform ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_transform_substructure_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3))
{
/* must be 0 or 3 */
return FAILED;
}
switch (this->transform_type)
{
case ENCRYPTION_ALGORITHM:
{
if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
{
return FAILED;
}
break;
}
case PSEUDO_RANDOM_FUNCTION:
{
if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
{
return FAILED;
}
break;
}
case INTEGRITY_ALGORITHM:
{
if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
{
return FAILED;
}
break;
}
case DIFFIE_HELLMAN_GROUP:
{
switch (this->transform_id)
{
case MODP_768_BIT:
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_6144_BIT:
case MODP_8192_BIT:
{
break;
}
default:
{
return FAILED;
}
}
break;
}
case EXTENDED_SEQUENCE_NUMBERS:
{
if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
{
return FAILED;
}
break;
}
default:
{
/* not a supported transform type! */
return FAILED;
}
}
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_attributes;
iterator->current(iterator,(void **)&current_attributes);
status = current_attributes->verify(current_attributes);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
/* proposal number is checked in SA payload */
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_substructure_encodings;
*rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_type(private_transform_substructure_t *this)
{
return TRANSFORM_SUBSTRUCTURE;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_transform_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_transform_substructure_t *this)
{
this->compute_length(this);
return this->transform_length;
}
/**
* Implementation of transform_substructure_t.create_transform_attribute_iterator.
*/
static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward)
{
return this->attributes->create_iterator(this->attributes,forward);
}
/**
* Implementation of transform_substructure_t.add_transform_attribute.
*/
static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes,(void *) attribute);
this->compute_length(this);
}
/**
* Implementation of transform_substructure_t.set_is_last_transform.
*/
static void set_is_last_transform (private_transform_substructure_t *this, bool is_last)
{
this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
}
/**
* Implementation of transform_substructure_t.get_is_last_transform.
*/
static bool get_is_last_transform (private_transform_substructure_t *this)
{
return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_transform_substructure_t *this,payload_type_t type)
{
}
/**
* Implementation of transform_substructure_t.set_transform_type.
*/
static void set_transform_type (private_transform_substructure_t *this,u_int8_t type)
{
this->transform_type = type;
}
/**
* Implementation of transform_substructure_t.get_transform_type.
*/
static u_int8_t get_transform_type (private_transform_substructure_t *this)
{
return this->transform_type;
}
/**
* Implementation of transform_substructure_t.set_transform_id.
*/
static void set_transform_id (private_transform_substructure_t *this,u_int16_t id)
{
this->transform_id = id;
}
/**
* Implementation of transform_substructure_t.get_transform_id.
*/
static u_int16_t get_transform_id (private_transform_substructure_t *this)
{
return this->transform_id;
}
/**
* Implementation of private_transform_substructure_t.compute_length.
*/
static void compute_length (private_transform_substructure_t *this)
{
iterator_t *iterator;
size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_attribute;
iterator->current(iterator,(void **) &current_attribute);
length += current_attribute->get_length(current_attribute);
}
iterator->destroy(iterator);
this->transform_length = length;
}
/**
* Implementation of transform_substructure_t.clone.
*/
static transform_substructure_t *clone(private_transform_substructure_t *this)
{
private_transform_substructure_t *new_clone;
iterator_t *attributes;
new_clone = (private_transform_substructure_t *) transform_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->transform_type = this->transform_type;
new_clone->transform_id = this->transform_id;
attributes = this->attributes->create_iterator(this->attributes,FALSE);
while (attributes->has_next(attributes))
{
transform_attribute_t *current_attribute;
transform_attribute_t *current_attribute_clone;
attributes->current(attributes,(void **) &current_attribute);
current_attribute_clone = current_attribute->clone(current_attribute);
new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
}
attributes->destroy(attributes);
return &(new_clone->public);
}
/**
* Implementation of transform_substructure_t.get_key_length.
*/
static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
{
iterator_t *attributes;
attributes = this->attributes->create_iterator(this->attributes,TRUE);
while (attributes->has_next(attributes))
{
transform_attribute_t *current_attribute;
attributes->current(attributes,(void **) &current_attribute);
if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
{
*key_length = current_attribute->get_value(current_attribute);
attributes->destroy(attributes);
return SUCCESS;
}
}
attributes->destroy(attributes);
return FAILED;
}
/**
* Implementation of transform_substructure_t.destroy and payload_t.destroy.
*/
static void destroy(private_transform_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->attributes->get_count(this->attributes) > 0)
{
transform_attribute_t *current_attribute;
this->attributes->remove_last(this->attributes,(void **)&current_attribute);
current_attribute->destroy(current_attribute);
}
this->attributes->destroy(this->attributes);
free(this);
}
/*
* Described in header.
*/
transform_substructure_t *transform_substructure_create()
{
private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t);
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator;
this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
this->public.set_is_last_transform = (void (*) (transform_substructure_t *,bool)) set_is_last_transform;
this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone;
this->public.destroy = (void (*) (transform_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
this->transform_id = 0;
this->transform_type = 0;
this->attributes = linked_list_create();
return (&(this->public));
}
/*
* Described in header
*/
transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length)
{
transform_substructure_t *transform = transform_substructure_create();
transform->set_transform_type(transform,transform_type);
transform->set_transform_id(transform,transform_id);
/* a keylength attribute is only created for AES encryption */
if (transform_type == ENCRYPTION_ALGORITHM &&
transform_id == ENCR_AES_CBC)
{
transform_attribute_t *attribute = transform_attribute_create_key_length(key_length);
transform->add_transform_attribute(transform,attribute);
}
return transform;
}
@@ -0,0 +1,198 @@
/**
* @file transform_substructure.h
*
* @brief Interface of transform_substructure_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TRANSFORM_SUBSTRUCTURE_H_
#define TRANSFORM_SUBSTRUCTURE_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_attribute.h>
#include <utils/linked_list.h>
#include <crypto/diffie_hellman.h>
#include <crypto/signers/signer.h>
#include <crypto/prfs/prf.h>
#include <crypto/crypters/crypter.h>
#include <config/proposal.h>
/**
* IKEv1 Value for a transform payload.
*
* @ingroup payloads
*/
#define TRANSFORM_TYPE_VALUE 3
/**
* Length of the transform substructure header in bytes.
*
* @ingroup payloads
*/
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
typedef struct transform_substructure_t transform_substructure_t;
/**
* @brief Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
*
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
*
* @ingroup payloads
*/
struct transform_substructure_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_attribute_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an transform attribute using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling transform_substructure_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object.
*/
iterator_t * (*create_transform_attribute_iterator) (transform_substructure_t *this, bool forward);
/**
* @brief Adds a transform_attribute_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of transform_substructure_t.
*
* @param this calling transform_substructure_t object
* @param proposal transform_attribute_t object to add
*/
void (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute);
/**
* @brief Sets the next_payload field of this substructure
*
* If this is the last transform, next payload field is set to 0,
* otherwise to 3
*
* @param this calling transform_substructure_t object
* @param is_last When TRUE, next payload field is set to 0, otherwise to 3
*/
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
* @brief Checks if this is the last transform.
*
* @param this calling transform_substructure_t object
* @return TRUE if this is the last Transform, FALSE otherwise
*/
bool (*get_is_last_transform) (transform_substructure_t *this);
/**
* @brief Sets transform type of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param type type value to set
*/
void (*set_transform_type) (transform_substructure_t *this,u_int8_t type);
/**
* @brief get transform type of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform type of current transform substructure.
*/
u_int8_t (*get_transform_type) (transform_substructure_t *this);
/**
* @brief Sets transform id of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param id transform id to set
*/
void (*set_transform_id) (transform_substructure_t *this,u_int16_t id);
/**
* @brief get transform id of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform id of current transform substructure.
*/
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
* @brief get transform id of the current transform.
*
* @param this calling transform_substructure_t object
* @param key_length The key length is written to this location
* @return
* - SUCCESS if a key length attribute is contained
* - FAILED if no key length attribute is part of this
* transform or key length uses more then 16 bit!
*/
status_t (*get_key_length) (transform_substructure_t *this,u_int16_t *key_length);
/**
* @brief Clones an transform_substructure_t object.
*
* @param this transform_substructure_t object to clone
* @return cloned transform_substructure_t object
*/
transform_substructure_t* (*clone) (transform_substructure_t *this);
/**
* @brief Destroys an transform_substructure_t object.
*
* @param this transform_substructure_t object to destroy
*/
void (*destroy) (transform_substructure_t *this);
};
/**
* @brief Creates an empty transform_substructure_t object.
*
* @return created transform_substructure_t object
*
* @ingroup payloads
*/
transform_substructure_t *transform_substructure_create(void);
/**
* @brief Creates an empty transform_substructure_t object.
*
* The key length is used for the transport types ENCRYPTION_ALGORITHM,
* PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all
* other transport types the key_length parameter is not used
*
* @param transform_type type of transform to create
* @param transform_id transform id specifying the specific algorithm of a transform type
* @param key_length Key length for key lenght attribute
* @return transform_substructure_t object
*
* @ingroup payloads
*/
transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length);
#endif /*TRANSFORM_SUBSTRUCTURE_H_*/
+365
View File
@@ -0,0 +1,365 @@
/**
* @file ts_payload.c
*
* @brief Implementation of ts_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "ts_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/linked_list.h>
typedef struct private_ts_payload_t private_ts_payload_t;
/**
* Private data of an ts_payload_t object.
*
*/
struct private_ts_payload_t {
/**
* Public ts_payload_t interface.
*/
ts_payload_t public;
/**
* TRUE if this TS payload is of type TSi, FALSE for TSr.
*/
bool is_initiator;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* Number of traffic selectors
*/
u_int8_t number_of_traffic_selectors;
/**
* Contains the traffic selectors of type traffic_selector_substructure_t.
*/
linked_list_t *traffic_selectors;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ts_payload_t object
*/
void (*compute_length) (private_ts_payload_t *this);
};
/**
* Encoding rules to parse or generate a TS payload
*
* The defined offsets are the positions in a object of type
* private_ts_payload_t.
*
*/
encoding_rule_t ts_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ts_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_ts_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)},
/* 1 Byte TS type*/
{ U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
/* 3 reserved bytes */
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* some ts data bytes, length is defined in PAYLOAD_LENGTH */
{ TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Number of TSs ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Traffic Selectors> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_ts_payload_t *this)
{
iterator_t *iterator;
status_t status = SUCCESS;
if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
{
/* must be the same */
return FAILED;
}
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
while(iterator->has_next(iterator))
{
payload_t *current_traffic_selector;
iterator->current(iterator,(void **)&current_traffic_selector);
status = current_traffic_selector->verify(current_traffic_selector);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
* Implementation of ts_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ts_payload_encodings;
*rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_ts_payload_t *this)
{
if (this->is_initiator)
{
return TRAFFIC_SELECTOR_INITIATOR;
}
else
{
return TRAFFIC_SELECTOR_RESPONDER;
}
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_ts_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_ts_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_ts_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implementation of ts_payload_t.get_initiator.
*/
static bool get_initiator (private_ts_payload_t *this)
{
return (this->is_initiator);
}
/**
* Implementation of ts_payload_t.set_initiator.
*/
static void set_initiator (private_ts_payload_t *this,bool is_initiator)
{
this->is_initiator = is_initiator;
}
/**
* Implementation of ts_payload_t.add_traffic_selector_substructure.
*/
static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
{
this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
}
/**
* Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
*/
static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
{
return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
}
/**
* Implementation of ts_payload_t.get_traffic_selectors.
*/
static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
{
traffic_selector_t *ts;
iterator_t *iterator;
linked_list_t *ts_list = linked_list_create();
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
while (iterator->has_next(iterator))
{
traffic_selector_substructure_t *ts_substructure;
iterator->current(iterator, (void**)&ts_substructure);
ts = ts_substructure->get_traffic_selector(ts_substructure);
ts_list->insert_last(ts_list, (void*)ts);
}
iterator->destroy(iterator);
return ts_list;
}
/**
* Implementation of private_ts_payload_t.compute_length.
*/
static void compute_length (private_ts_payload_t *this)
{
iterator_t *iterator;
size_t ts_count = 0;
size_t length = TS_PAYLOAD_HEADER_LENGTH;
iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
while (iterator->has_next(iterator))
{
payload_t * current_traffic_selector;
iterator->current(iterator,(void **) &current_traffic_selector);
length += current_traffic_selector->get_length(current_traffic_selector);
ts_count++;
}
iterator->destroy(iterator);
this->number_of_traffic_selectors= ts_count;
this->payload_length = length;
}
/**
* Implementation of payload_t.destroy and ts_payload_t.destroy.
*/
static void destroy(private_ts_payload_t *this)
{
while (this->traffic_selectors->get_count(this->traffic_selectors) > 0)
{
payload_t *current_traffic_selector;
this->traffic_selectors->remove_last(this->traffic_selectors,(void **) &current_traffic_selector);
current_traffic_selector->destroy(current_traffic_selector);
}
this->traffic_selectors->destroy(this->traffic_selectors);
free(this);
}
/*
* Described in header
*/
ts_payload_t *ts_payload_create(bool is_initiator)
{
private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (ts_payload_t *)) destroy;
this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
/* private functions */
this->compute_length = compute_length;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
this->is_initiator = is_initiator;
this->number_of_traffic_selectors = 0;
this->traffic_selectors = linked_list_create();
return &(this->public);
}
/*
* Described in header
*/
ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
{
iterator_t *iterator;
traffic_selector_t *ts;
traffic_selector_substructure_t *ts_substructure;
private_ts_payload_t *this;
this = (private_ts_payload_t*)ts_payload_create(is_initiator);
iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
while (iterator->has_next(iterator))
{
iterator->current(iterator, (void**)&ts);
ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
}
iterator->destroy(iterator);
return &(this->public);
}
+152
View File
@@ -0,0 +1,152 @@
/**
* @file ts_payload.h
*
* @brief Interface of ts_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TS_PAYLOAD_H_
#define TS_PAYLOAD_H_
#include <types.h>
#include <utils/linked_list.h>
#include <config/traffic_selector.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/traffic_selector_substructure.h>
/**
* Length of a TS payload without the Traffic selectors.
*
* @ingroup payloads
*/
#define TS_PAYLOAD_HEADER_LENGTH 8
typedef struct ts_payload_t ts_payload_t;
/**
* @brief Class representing an IKEv2 TS payload.
*
* The TS payload format is described in RFC section 3.13.
*
* @b Constructors:
* - ts_payload_create()
* - ts_payload_create_from_traffic_selectors()
*
* @ingroup payloads
*/
struct ts_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the type of TSpayload (TSi or TSr).
*
* @param this calling id_payload_t object
* @return
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
*/
bool (*get_initiator) (ts_payload_t *this);
/**
* @brief Set the type of TS payload (TSi or TSr).
*
* @param this calling id_payload_t object
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
*/
void (*set_initiator) (ts_payload_t *this,bool is_initiator);
/**
* @brief Adds a traffic_selector_substructure_t object to this object.
*
* @warning The added traffic_selector_substructure_t object is
* getting destroyed in destroy function of ts_payload_t.
*
* @param this calling ts_payload_t object
* @param traffic_selector traffic_selector_substructure_t object to add
*/
void (*add_traffic_selector_substructure) (ts_payload_t *this,traffic_selector_substructure_t *traffic_selector);
/**
* @brief Creates an iterator of stored traffic_selector_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When removing an traffic_selector_substructure_t object
* using this iterator, the length of this payload
* has to get refreshed by calling payload_t.get_length!
*
* @param this calling ts_payload_t object
* @param[in] forward iterator direction (TRUE: front to end)
* @return created iterator_t object
*/
iterator_t *(*create_traffic_selector_substructure_iterator) (ts_payload_t *this, bool forward);
/**
* @brief Get a list of nested traffic selectors as traffic_selector_t.
*
* Resulting list and its traffic selectors must be destroyed after usage
*
* @param this calling ts_payload_t object
* @return list of traffic selectors
*/
linked_list_t *(*get_traffic_selectors) (ts_payload_t *this);
/**
* @brief Destroys an ts_payload_t object.
*
* @param this ts_payload_t object to destroy
*/
void (*destroy) (ts_payload_t *this);
};
/**
* @brief Creates an empty ts_payload_t object.
*
*
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
* @return ts_payload_t object
*
* @ingroup payloads
*/
ts_payload_t *ts_payload_create(bool is_initiator);
/**
* @brief Creates ts_payload with a list of traffic_selector_t
*
*
* @param is_initiator
* - TRUE if this payload is of type TSi
* - FALSE if this payload is of type TSr
* @param traffic_selectors list of traffic selectors to include
* @return ts_payload_t object
*
* @ingroup payloads
*/
ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors);
#endif /* TS_PAYLOAD_H_ */
@@ -0,0 +1,207 @@
/**
* @file unknown_payload.c
*
* @brief Implementation of unknown_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "unknown_payload.h"
typedef struct private_unknown_payload_t private_unknown_payload_t;
/**
* Private data of an unknown_payload_t object.
*/
struct private_unknown_payload_t {
/**
* Public unknown_payload_t interface.
*/
unknown_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained data.
*/
chunk_t data;
};
/**
* Encoding rules to parse an payload which is not further specified.
*
* The defined offsets are the positions in a object of type
* private_unknown_payload_t.
*
*/
encoding_rule_t unknown_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_unknown_payload_t, next_payload)},
/* the critical bit */
{ FLAG, offsetof(private_unknown_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)},
/* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
{ UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Data of any type ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_unknown_payload_t *this)
{
/* can't do any checks, so we assume its good */
return SUCCESS;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = unknown_payload_encodings;
*rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_unknown_payload_t *this)
{
return UNKNOWN_PAYLOAD;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_unknown_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_unknown_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_unknown_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of unknown_payload_t.get_data.
*/
static bool is_critical(private_unknown_payload_t *this)
{
return this->critical;
}
/**
* Implementation of unknown_payload_t.get_data.
*/
static chunk_t get_data (private_unknown_payload_t *this)
{
return (this->data);
}
/**
* Implementation of payload_t.destroy and unknown_payload_t.destroy.
*/
static void destroy(private_unknown_payload_t *this)
{
if (this->data.ptr != NULL)
{
chunk_free(&(this->data));
}
free(this);
}
/*
* Described in header
*/
unknown_payload_t *unknown_payload_create()
{
private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (unknown_payload_t *)) destroy;
this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical;
this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH;
this->data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,95 @@
/**
* @file unknown_payload.h
*
* @brief Interface of unknown_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef UNKNOWN_PAYLOAD_H_
#define UNKNOWN_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Header length of the unknown payload.
*
* @ingroup payloads
*/
#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
typedef struct unknown_payload_t unknown_payload_t;
/**
* @brief Payload which can't be processed further.
*
* When the parser finds an unknown payload, he builds an instance of
* this class. This allows further processing of this payload, such as
* a check for the critical bit in the header.
*
* @b Constructors:
* - unknown_payload_create()
*
* @ingroup payloads
*/
struct unknown_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Get the raw data of this payload, without
* the generic payload header.
*
* Returned data are NOT copied and must not be freed.
*
* @param this calling unknown_payload_t object
* @return data as chunk_t
*/
chunk_t (*get_data) (unknown_payload_t *this);
/**
* @brief Get the critical flag.
*
* @param this calling unknown_payload_t object
* @return TRUE if payload is critical, FALSE if not
*/
bool (*is_critical) (unknown_payload_t *this);
/**
* @brief Destroys an unknown_payload_t object.
*
* @param this unknown_payload_t object to destroy
*/
void (*destroy) (unknown_payload_t *this);
};
/**
* @brief Creates an empty unknown_payload_t object.
*
* @return unknown_payload_t object
*
* @ingroup payloads
*/
unknown_payload_t *unknown_payload_create(void);
#endif /* UNKNOWN_PAYLOAD_H_ */
@@ -0,0 +1,227 @@
/**
* @file vendor_id_payload.c
*
* @brief Implementation of vendor_id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stddef.h>
#include "vendor_id_payload.h"
typedef struct private_vendor_id_payload_t private_vendor_id_payload_t;
/**
* Private data of an vendor_id_payload_t object.
*
*/
struct private_vendor_id_payload_t {
/**
* Public vendor_id_payload_t interface.
*/
vendor_id_payload_t public;
/**
* Next payload type.
*/
u_int8_t next_payload;
/**
* Critical flag.
*/
bool critical;
/**
* Length of this payload.
*/
u_int16_t payload_length;
/**
* The contained vendor_id data value.
*/
chunk_t vendor_id_data;
};
/**
* Encoding rules to parse or generate a VENDOR ID payload
*
* The defined offsets are the positions in a object of type
* private_vendor_id_payload_t.
*
*/
encoding_rule_t vendor_id_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_vendor_id_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)},
/* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
{ VID_DATA, offsetof(private_vendor_id_payload_t, vendor_id_data) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Cert Encoding ! !
+-+-+-+-+-+-+-+-+ !
~ Certificate Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implementation of payload_t.verify.
*/
static status_t verify(private_vendor_id_payload_t *this)
{
return SUCCESS;
}
/**
* Implementation of vendor_id_payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_vendor_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = vendor_id_payload_encodings;
*rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t);
}
/**
* Implementation of payload_t.get_type.
*/
static payload_type_t get_payload_type(private_vendor_id_payload_t *this)
{
return VENDOR_ID;
}
/**
* Implementation of payload_t.get_next_type.
*/
static payload_type_t get_next_type(private_vendor_id_payload_t *this)
{
return (this->next_payload);
}
/**
* Implementation of payload_t.set_next_type.
*/
static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type)
{
this->next_payload = type;
}
/**
* Implementation of payload_t.get_length.
*/
static size_t get_length(private_vendor_id_payload_t *this)
{
return this->payload_length;
}
/**
* Implementation of vendor_id_payload_t.set_data.
*/
static void set_data (private_vendor_id_payload_t *this, chunk_t data)
{
if (this->vendor_id_data.ptr != NULL)
{
chunk_free(&(this->vendor_id_data));
}
this->vendor_id_data.ptr = clalloc(data.ptr,data.len);
this->vendor_id_data.len = data.len;
this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + this->vendor_id_data.len;
}
/**
* Implementation of vendor_id_payload_t.get_data.
*/
static chunk_t get_data (private_vendor_id_payload_t *this)
{
return (this->vendor_id_data);
}
/**
* Implementation of vendor_id_payload_t.get_data_clone.
*/
static chunk_t get_data_clone (private_vendor_id_payload_t *this)
{
chunk_t cloned_data;
if (this->vendor_id_data.ptr == NULL)
{
return (this->vendor_id_data);
}
cloned_data.ptr = clalloc(this->vendor_id_data.ptr,this->vendor_id_data.len);
cloned_data.len = this->vendor_id_data.len;
return cloned_data;
}
/**
* Implementation of payload_t.destroy and vendor_id_payload_t.destroy.
*/
static void destroy(private_vendor_id_payload_t *this)
{
if (this->vendor_id_data.ptr != NULL)
{
chunk_free(&(this->vendor_id_data));
}
free(this);
}
/*
* Described in header
*/
vendor_id_payload_t *vendor_id_payload_create()
{
private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t);
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (void (*) (vendor_id_payload_t *)) destroy;
this->public.set_data = (void (*) (vendor_id_payload_t *,chunk_t)) set_data;
this->public.get_data_clone = (chunk_t (*) (vendor_id_payload_t *)) get_data_clone;
this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
this->vendor_id_data = CHUNK_INITIALIZER;
return (&(this->public));
}
@@ -0,0 +1,103 @@
/**
* @file vendor_id_payload.h
*
* @brief Interface of vendor_id_payload_t.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef VENDOR_ID_PAYLOAD_H_
#define VENDOR_ID_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Length of a VENDOR ID payload without the VID data in bytes.
*
* @ingroup payloads
*/
#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
typedef struct vendor_id_payload_t vendor_id_payload_t;
/**
* @brief Class representing an IKEv2 VENDOR ID payload.
*
* The VENDOR ID payload format is described in RFC section 3.12.
*
* @b Constructors:
* - vendor_id_payload_create()
*
* @ingroup payloads
*/
struct vendor_id_payload_t {
/**
* The payload_t interface.
*/
payload_t payload_interface;
/**
* @brief Set the VID data.
*
* Data are getting cloned.
*
* @param this calling vendor_id_payload_t object
* @param data VID data as chunk_t
*/
void (*set_data) (vendor_id_payload_t *this, chunk_t data);
/**
* @brief Get the VID data.
*
* Returned data are a copy of the internal one.
*
* @param this calling vendor_id_payload_t object
* @return VID data as chunk_t
*/
chunk_t (*get_data_clone) (vendor_id_payload_t *this);
/**
* @brief Get the VID data.
*
* Returned data are NOT copied.
*
* @param this calling vendor_id_payload_t object
* @return VID data as chunk_t
*/
chunk_t (*get_data) (vendor_id_payload_t *this);
/**
* @brief Destroys an vendor_id_payload_t object.
*
* @param this vendor_id_payload_t object to destroy
*/
void (*destroy) (vendor_id_payload_t *this);
};
/**
* @brief Creates an empty vendor_id_payload_t object.
*
* @return vendor_id_payload_t object
*
* @ingroup payloads
*/
vendor_id_payload_t *vendor_id_payload_create(void);
#endif /* VENDOR_ID_PAYLOAD_H_ */