Extend sa_payload for IKEv1 support

This commit is contained in:
Martin Willi 2011-11-16 09:29:38 +01:00
parent 8f3aea2f77
commit b0b9d18593
11 changed files with 160 additions and 37 deletions

View File

@ -145,7 +145,8 @@ METHOD(listener_t, message, bool,
proposal->get_protocol(proposal),
proposal->get_spi(proposal));
DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props);
new = sa_payload_create_from_proposal_list(new_props);
new = sa_payload_create_from_proposal_list(
SECURITY_ASSOCIATION, new_props);
message->add_payload(message, (payload_t*)new);
new_props->destroy_offset(new_props, offsetof(proposal_t, destroy));
}

View File

@ -294,7 +294,8 @@ static void process_auth_response(private_pretend_auth_t *this,
if (this->proposal)
{
message->add_payload(message, (payload_t*)
sa_payload_create_from_proposal(this->proposal));
sa_payload_create_from_proposal(SECURITY_ASSOCIATION,
this->proposal));
}
if (this->tsi)
{

View File

@ -121,7 +121,7 @@ METHOD(listener_t, message, bool,
}
enumerator->destroy(enumerator);
}
sa = sa_payload_create_from_proposal_list(updated);
sa = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION, updated);
list->destroy_offset(list, offsetof(proposal_t, destroy));
updated->destroy_offset(updated, offsetof(proposal_t, destroy));
message->add_payload(message, (payload_t*)sa);

View File

@ -496,6 +496,18 @@ METHOD(parser_t, parse_payload, status_t,
}
break;
}
case PROPOSALS_V1:
{
if (payload_length < SA_PAYLOAD_V1_HEADER_LENGTH ||
!parse_list(this, rule_number, output + rule->offset,
PROPOSAL_SUBSTRUCTURE_V1,
payload_length - SA_PAYLOAD_V1_HEADER_LENGTH))
{
pld->destroy(pld);
return PARSE_ERROR;
}
break;
}
case TRANSFORMS:
{
if (payload_length <

View File

@ -219,6 +219,11 @@ enum encoding_type_t {
*/
PROPOSALS,
/**
* Same as PROPOSALS, but for IKEv1 in a SECURITY_ASSOCIATION_V1
*/
PROPOSALS_V1,
/**
* Representating one or more transform substructures.
*

View File

@ -156,7 +156,8 @@ payload_t *payload_create(payload_type_t type)
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create();
case SECURITY_ASSOCIATION_V1:
return (payload_t*)sa_payload_create(type);
case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create();
case TRANSFORM_SUBSTRUCTURE:

View File

@ -29,6 +29,10 @@ typedef struct payload_t payload_t;
#include <library.h>
#include <encoding/payloads/encodings.h>
/**
* Domain of interpretation used by IPsec/IKEv1
*/
#define IKEV1_DOI_IPSEC 1
/**
* Payload-Types of an IKE message.
@ -243,6 +247,14 @@ enum payload_type_t {
* used internally to handle a transform attribute like a payload.
*/
CONFIGURATION_ATTRIBUTE = 261,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
*
* This payload type is not sent over wire and just
* used internally to handle a proposal substructure like a payload.
*/
PROPOSAL_SUBSTRUCTURE_V1 = 262,
};
/**

View File

@ -22,6 +22,8 @@
#include <utils/linked_list.h>
#include <daemon.h>
/* IKEv1 situation */
#define SIT_IDENTITY_ONLY 1
typedef struct private_sa_payload_t private_sa_payload_t;
@ -48,7 +50,7 @@ struct private_sa_payload_t {
/**
* Reserved bits
*/
bool reserved[7];
bool reserved[8];
/**
* Length of this payload.
@ -58,21 +60,75 @@ struct private_sa_payload_t {
/**
* Proposals in this payload are stored in a linked_list_t.
*/
linked_list_t * proposals;
linked_list_t *proposals;
/**
* Type of this payload, V1 or V2
*/
payload_type_t type;
/**
* IKEv1 DOI
*/
u_int32_t doi;
/**
* IKEv1 situation
*/
u_int32_t situation;
};
/**
* Encoding rules to parse or generate a IKEv2-SA Payload
*
* The defined offsets are the positions in a object of type
* private_sa_payload_t.
* Encoding rules for IKEv1 SA payload
*/
encoding_rule_t sa_payload_encodings[] = {
static encoding_rule_t encodings_v1[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* 8 reserved bits */
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[3]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[4]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[5]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[7]) },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* DOI*/
{ U_INT_32, offsetof(private_sa_payload_t, doi) },
/* Situation*/
{ U_INT_32, offsetof(private_sa_payload_t, situation) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ PROPOSALS_V1, offsetof(private_sa_payload_t, proposals) },
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DOI !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Situation !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Proposals> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Encoding rules for IKEv2 SA payload
*/
static encoding_rule_t encodings_v2[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
/* 7 Bit reserved bits */
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
@ -144,14 +200,22 @@ METHOD(payload_t, verify, status_t,
METHOD(payload_t, get_encoding_rules, void,
private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = sa_payload_encodings;
*rule_count = countof(sa_payload_encodings);
if (this->type == SECURITY_ASSOCIATION_V1)
{
*rules = encodings_v1;
*rule_count = countof(encodings_v1);
}
else
{
*rules = encodings_v2;
*rule_count = countof(encodings_v2);
}
}
METHOD(payload_t, get_type, payload_type_t,
private_sa_payload_t *this)
{
return SECURITY_ASSOCIATION;
return this->type;
}
METHOD(payload_t, get_next_type, payload_type_t,
@ -175,6 +239,11 @@ static void compute_length(private_sa_payload_t *this)
payload_t *current;
size_t length = SA_PAYLOAD_HEADER_LENGTH;
if (this->type == SECURITY_ASSOCIATION_V1)
{
length = SA_PAYLOAD_V1_HEADER_LENGTH;
}
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void **)&current))
{
@ -270,14 +339,14 @@ METHOD2(payload_t, sa_payload_t, destroy, void,
private_sa_payload_t *this)
{
this->proposals->destroy_offset(this->proposals,
offsetof(proposal_substructure_t, destroy));
offsetof(payload_t, destroy));
free(this);
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create()
sa_payload_t *sa_payload_create(payload_type_t type)
{
private_sa_payload_t *this;
@ -298,41 +367,49 @@ sa_payload_t *sa_payload_create()
.destroy = _destroy,
},
.next_payload = NO_PAYLOAD,
.payload_length = SA_PAYLOAD_HEADER_LENGTH,
.proposals = linked_list_create(),
.type = type,
/* for IKEv1 only */
.doi = IKEV1_DOI_IPSEC,
.situation = SIT_IDENTITY_ONLY,
);
compute_length(this);
return &this->public;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
sa_payload_t *sa_payload_create_from_proposal_list(payload_type_t type,
linked_list_t *proposals)
{
private_sa_payload_t *this;
sa_payload_t *this;
enumerator_t *enumerator;
proposal_t *proposal;
this = (private_sa_payload_t*)sa_payload_create();
this = sa_payload_create(type);
enumerator = proposals->create_enumerator(proposals);
while (enumerator->enumerate(enumerator, &proposal))
{
add_proposal(this, proposal);
this->add_proposal(this, proposal);
}
enumerator->destroy(enumerator);
return &this->public;
return this;
}
/*
* Described in header.
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
sa_payload_t *sa_payload_create_from_proposal(payload_type_t type,
proposal_t *proposal)
{
private_sa_payload_t *this;
sa_payload_t *this;
this = (private_sa_payload_t*)sa_payload_create();
add_proposal(this, proposal);
this = sa_payload_create(type);
this->add_proposal(this, proposal);
return &this->public;
return this;
}

View File

@ -30,12 +30,17 @@ typedef struct sa_payload_t sa_payload_t;
#include <utils/linked_list.h>
/**
* SA_PAYLOAD length in bytes without any proposal substructure.
* SECURITY_ASSOCIATION length in bytes without any proposal substructure.
*/
#define SA_PAYLOAD_HEADER_LENGTH 4
/**
* Class representing an IKEv2-SA Payload.
* SECURITY_ASSOCIATION_V1 length in bytes without any proposal substructure.
*/
#define SA_PAYLOAD_V1_HEADER_LENGTH 12
/**
* Class representing an IKEv1 or IKEv2 SA Payload.
*
* The SA Payload format is described in RFC section 3.3.
*/
@ -76,17 +81,20 @@ struct sa_payload_t {
/**
* Creates an empty sa_payload_t object
*
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @return created sa_payload_t object
*/
sa_payload_t *sa_payload_create(void);
sa_payload_t *sa_payload_create(payload_type_t type);
/**
* Creates a sa_payload_t object from a list of proposals.
*
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @param proposals list of proposals to build the payload from
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
sa_payload_t *sa_payload_create_from_proposal_list(payload_type_t type,
linked_list_t *proposals);
/**
* Creates a sa_payload_t object from a single proposal.
@ -94,9 +102,11 @@ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
* This is only for convenience. Use sa_payload_create_from_proposal_list
* if you want to add more than one proposal.
*
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @param proposal proposal from which the payload should be built.
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
sa_payload_t *sa_payload_create_from_proposal(payload_type_t type,
proposal_t *proposal);
#endif /** SA_PAYLOAD_H_ @}*/

View File

@ -526,11 +526,13 @@ static void build_payloads(private_child_create_t *this, message_t *message)
/* add SA payload */
if (this->initiator)
{
sa_payload = sa_payload_create_from_proposal_list(this->proposals);
sa_payload = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION,
this->proposals);
}
else
{
sa_payload = sa_payload_create_from_proposal(this->proposal);
sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION,
this->proposal);
}
message->add_payload(message, (payload_t*)sa_payload);

View File

@ -132,7 +132,8 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
enumerator->destroy(enumerator);
}
sa_payload = sa_payload_create_from_proposal_list(proposal_list);
sa_payload = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION,
proposal_list);
proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
}
else
@ -142,7 +143,8 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
/* include SPI of new IKE_SA when we are rekeying */
this->proposal->set_spi(this->proposal, id->get_responder_spi(id));
}
sa_payload = sa_payload_create_from_proposal(this->proposal);
sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION,
this->proposal);
}
message->add_payload(message, (payload_t*)sa_payload);