Extend sa_payload for IKEv1 support

This commit is contained in:
Martin Willi
2012-03-20 17:30:40 +01:00
parent 8f3aea2f77
commit b0b9d18593
11 changed files with 160 additions and 37 deletions
+2 -1
View File
@@ -145,7 +145,8 @@ METHOD(listener_t, message, bool,
proposal->get_protocol(proposal), proposal->get_protocol(proposal),
proposal->get_spi(proposal)); proposal->get_spi(proposal));
DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props); 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); message->add_payload(message, (payload_t*)new);
new_props->destroy_offset(new_props, offsetof(proposal_t, destroy)); new_props->destroy_offset(new_props, offsetof(proposal_t, destroy));
} }
+2 -1
View File
@@ -294,7 +294,8 @@ static void process_auth_response(private_pretend_auth_t *this,
if (this->proposal) if (this->proposal)
{ {
message->add_payload(message, (payload_t*) 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) if (this->tsi)
{ {
+1 -1
View File
@@ -121,7 +121,7 @@ METHOD(listener_t, message, bool,
} }
enumerator->destroy(enumerator); 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)); list->destroy_offset(list, offsetof(proposal_t, destroy));
updated->destroy_offset(updated, offsetof(proposal_t, destroy)); updated->destroy_offset(updated, offsetof(proposal_t, destroy));
message->add_payload(message, (payload_t*)sa); message->add_payload(message, (payload_t*)sa);
+12
View File
@@ -496,6 +496,18 @@ METHOD(parser_t, parse_payload, status_t,
} }
break; 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: case TRANSFORMS:
{ {
if (payload_length < if (payload_length <
@@ -219,6 +219,11 @@ enum encoding_type_t {
*/ */
PROPOSALS, PROPOSALS,
/**
* Same as PROPOSALS, but for IKEv1 in a SECURITY_ASSOCIATION_V1
*/
PROPOSALS_V1,
/** /**
* Representating one or more transform substructures. * Representating one or more transform substructures.
* *
+2 -1
View File
@@ -156,7 +156,8 @@ payload_t *payload_create(payload_type_t type)
case HEADER: case HEADER:
return (payload_t*)ike_header_create(); return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION: case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create(); case SECURITY_ASSOCIATION_V1:
return (payload_t*)sa_payload_create(type);
case PROPOSAL_SUBSTRUCTURE: case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create(); return (payload_t*)proposal_substructure_create();
case TRANSFORM_SUBSTRUCTURE: case TRANSFORM_SUBSTRUCTURE:
+12
View File
@@ -29,6 +29,10 @@ typedef struct payload_t payload_t;
#include <library.h> #include <library.h>
#include <encoding/payloads/encodings.h> #include <encoding/payloads/encodings.h>
/**
* Domain of interpretation used by IPsec/IKEv1
*/
#define IKEV1_DOI_IPSEC 1
/** /**
* Payload-Types of an IKE message. * Payload-Types of an IKE message.
@@ -243,6 +247,14 @@ enum payload_type_t {
* used internally to handle a transform attribute like a payload. * used internally to handle a transform attribute like a payload.
*/ */
CONFIGURATION_ATTRIBUTE = 261, 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,
}; };
/** /**
+101 -24
View File
@@ -22,6 +22,8 @@
#include <utils/linked_list.h> #include <utils/linked_list.h>
#include <daemon.h> #include <daemon.h>
/* IKEv1 situation */
#define SIT_IDENTITY_ONLY 1
typedef struct private_sa_payload_t private_sa_payload_t; typedef struct private_sa_payload_t private_sa_payload_t;
@@ -48,7 +50,7 @@ struct private_sa_payload_t {
/** /**
* Reserved bits * Reserved bits
*/ */
bool reserved[7]; bool reserved[8];
/** /**
* Length of this payload. * Length of this payload.
@@ -58,21 +60,75 @@ struct private_sa_payload_t {
/** /**
* Proposals in this payload are stored in a linked_list_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 * Encoding rules for IKEv1 SA payload
*
* The defined offsets are the positions in a object of type
* private_sa_payload_t.
*/ */
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 */ /* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) }, { U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */ /* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) }, { 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[0]) },
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) }, { 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[2]) },
@@ -144,14 +200,22 @@ METHOD(payload_t, verify, status_t,
METHOD(payload_t, get_encoding_rules, void, METHOD(payload_t, get_encoding_rules, void,
private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count) private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{ {
*rules = sa_payload_encodings; if (this->type == SECURITY_ASSOCIATION_V1)
*rule_count = countof(sa_payload_encodings); {
*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, METHOD(payload_t, get_type, payload_type_t,
private_sa_payload_t *this) private_sa_payload_t *this)
{ {
return SECURITY_ASSOCIATION; return this->type;
} }
METHOD(payload_t, get_next_type, payload_type_t, 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; payload_t *current;
size_t length = SA_PAYLOAD_HEADER_LENGTH; 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); enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, (void **)&current)) while (enumerator->enumerate(enumerator, (void **)&current))
{ {
@@ -270,14 +339,14 @@ METHOD2(payload_t, sa_payload_t, destroy, void,
private_sa_payload_t *this) private_sa_payload_t *this)
{ {
this->proposals->destroy_offset(this->proposals, this->proposals->destroy_offset(this->proposals,
offsetof(proposal_substructure_t, destroy)); offsetof(payload_t, destroy));
free(this); free(this);
} }
/* /*
* Described in header. * Described in header.
*/ */
sa_payload_t *sa_payload_create() sa_payload_t *sa_payload_create(payload_type_t type)
{ {
private_sa_payload_t *this; private_sa_payload_t *this;
@@ -298,41 +367,49 @@ sa_payload_t *sa_payload_create()
.destroy = _destroy, .destroy = _destroy,
}, },
.next_payload = NO_PAYLOAD, .next_payload = NO_PAYLOAD,
.payload_length = SA_PAYLOAD_HEADER_LENGTH,
.proposals = linked_list_create(), .proposals = linked_list_create(),
.type = type,
/* for IKEv1 only */
.doi = IKEV1_DOI_IPSEC,
.situation = SIT_IDENTITY_ONLY,
); );
compute_length(this);
return &this->public; return &this->public;
} }
/* /*
* Described in header. * 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; enumerator_t *enumerator;
proposal_t *proposal; proposal_t *proposal;
this = (private_sa_payload_t*)sa_payload_create(); this = sa_payload_create(type);
enumerator = proposals->create_enumerator(proposals); enumerator = proposals->create_enumerator(proposals);
while (enumerator->enumerate(enumerator, &proposal)) while (enumerator->enumerate(enumerator, &proposal))
{ {
add_proposal(this, proposal); this->add_proposal(this, proposal);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
return &this->public; return this;
} }
/* /*
* Described in header. * 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(); this = sa_payload_create(type);
add_proposal(this, proposal); this->add_proposal(this, proposal);
return &this->public; return this;
} }
+15 -5
View File
@@ -30,12 +30,17 @@ typedef struct sa_payload_t sa_payload_t;
#include <utils/linked_list.h> #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 #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. * 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 * Creates an empty sa_payload_t object
* *
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
* @return created sa_payload_t object * @return created sa_payload_t object
*/ */
sa_payload_t *sa_payload_create(void); sa_payload_t *sa_payload_create(payload_type_t type);
/** /**
* Creates a sa_payload_t object from a list of proposals. * Creates 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 * @param proposals list of proposals to build the payload from
* @return sa_payload_t object * @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. * 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 * This is only for convenience. Use sa_payload_create_from_proposal_list
* if you want to add more than one proposal. * 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. * @param proposal proposal from which the payload should be built.
* @return sa_payload_t object * @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_ @}*/ #endif /** SA_PAYLOAD_H_ @}*/
+4 -2
View File
@@ -526,11 +526,13 @@ static void build_payloads(private_child_create_t *this, message_t *message)
/* add SA payload */ /* add SA payload */
if (this->initiator) 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 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); message->add_payload(message, (payload_t*)sa_payload);
+4 -2
View File
@@ -132,7 +132,8 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
enumerator->destroy(enumerator); 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)); proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy));
} }
else 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 */ /* include SPI of new IKE_SA when we are rekeying */
this->proposal->set_spi(this->proposal, id->get_responder_spi(id)); 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); message->add_payload(message, (payload_t*)sa_payload);