diff options
author | Martin Willi <martin@strongswan.org> | 2005-12-06 11:51:13 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2005-12-06 11:51:13 +0000 |
commit | 668f9fcba9cbc67d09410a25e77dc217df45ee2a (patch) | |
tree | 402daf2f88df717cee67afb279a41867f7ceb5c5 /Source/charon/encoding | |
parent | 9affa65c7982d28fe575783679a73fd85755737f (diff) | |
download | strongswan-668f9fcba9cbc67d09410a25e77dc217df45ee2a.tar.bz2 strongswan-668f9fcba9cbc67d09410a25e77dc217df45ee2a.tar.xz |
- better management of unknown_payload, with critical check
- message code cleanup
Diffstat (limited to 'Source/charon/encoding')
-rw-r--r-- | Source/charon/encoding/message.c | 448 | ||||
-rw-r--r-- | Source/charon/encoding/message.h | 90 | ||||
-rw-r--r-- | Source/charon/encoding/parser.c | 25 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/payload.c | 6 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/payload.h | 82 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/unknown_payload.c | 66 | ||||
-rw-r--r-- | Source/charon/encoding/payloads/unknown_payload.h | 57 |
7 files changed, 374 insertions, 400 deletions
diff --git a/Source/charon/encoding/message.c b/Source/charon/encoding/message.c index 8c7969042..8e4f3dd7f 100644 --- a/Source/charon/encoding/message.c +++ b/Source/charon/encoding/message.c @@ -35,6 +35,7 @@ #include <encoding/payloads/encodings.h> #include <encoding/payloads/payload.h> #include <encoding/payloads/encryption_payload.h> +#include <encoding/payloads/unknown_payload.h> /** * Max number of notify payloads per IKEv2 Message @@ -42,13 +43,15 @@ #define MAX_NOTIFY_PAYLOADS 10 -typedef struct supported_payload_entry_t supported_payload_entry_t; +typedef struct payload_rule_t payload_rule_t; /** - * Supported payload entry used in message_rule_t. - * + * A payload rule defines the rules for a payload + * in a specific message rule. It defines if and how + * many times a payload must/can occur in a message + * and if it must be encrypted. */ -struct supported_payload_entry_t { +struct payload_rule_t { /** * Payload type. */ @@ -65,21 +68,24 @@ struct supported_payload_entry_t { size_t max_occurence; /** - * TRUE if payload has to get encrypted + * TRUE if payload must be encrypted */ bool encrypted; /** - * Verifying can stop after checking this payload. + * If this payload occurs, the message rule is + * fullfilled in any case. This applies e.g. to + * notify_payloads. */ - bool can_be_last; + bool sufficient; }; typedef struct message_rule_t message_rule_t; /** - * Message Rule used to find out which payloads - * are supported by each message type. + * A message rule defines the kind of a message, + * if it has encrypted contents and a list + * of payload rules. * */ struct message_rule_t { @@ -98,22 +104,21 @@ struct message_rule_t { */ bool encrypted_content; - /** - * Number of supported payloads. - */ - size_t supported_payloads_count; + /** + * Number of payload rules which will follow + */ + size_t payload_rule_count; /** - * Pointer to first supported payload entry. + * Pointer to first payload rule */ - supported_payload_entry_t *supported_payloads; + payload_rule_t *payload_rules; }; /** * Message rule for IKE_SA_INIT from initiator. */ -static supported_payload_entry_t supported_ike_sa_init_i_payloads[] = -{ +static payload_rule_t ike_sa_init_i_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,FALSE}, {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, {KEY_EXCHANGE,1,1,FALSE,FALSE}, @@ -123,8 +128,7 @@ static supported_payload_entry_t supported_ike_sa_init_i_payloads[] = /** * Message rule for IKE_SA_INIT from responder. */ -static supported_payload_entry_t supported_ike_sa_init_r_payloads[] = -{ +static payload_rule_t ike_sa_init_r_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,TRUE}, {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, {KEY_EXCHANGE,1,1,FALSE,FALSE}, @@ -134,8 +138,7 @@ static supported_payload_entry_t supported_ike_sa_init_r_payloads[] = /** * Message rule for IKE_AUTH from initiator. */ -static supported_payload_entry_t supported_ike_auth_i_payloads[] = -{ +static payload_rule_t ike_auth_i_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, {ID_INITIATOR,1,1,TRUE,FALSE}, {CERTIFICATE,0,1,TRUE,FALSE}, @@ -145,13 +148,13 @@ static supported_payload_entry_t supported_ike_auth_i_payloads[] = {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, }; /** * Message rule for IKE_AUTH from responder. */ -static supported_payload_entry_t supported_ike_auth_r_payloads[] = -{ +static payload_rule_t ike_auth_r_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, {CERTIFICATE,0,1,TRUE,FALSE}, {ID_RESPONDER,1,1,TRUE,FALSE}, @@ -159,33 +162,17 @@ static supported_payload_entry_t supported_ike_auth_r_payloads[] = {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, + {CONFIGURATION,0,1,TRUE,FALSE}, }; /** * Message rules, defines allowed payloads. */ static message_rule_t message_rules[] = { - {IKE_SA_INIT,TRUE,FALSE,(sizeof(supported_ike_sa_init_i_payloads)/sizeof(supported_payload_entry_t)),supported_ike_sa_init_i_payloads}, - {IKE_SA_INIT,FALSE,FALSE,(sizeof(supported_ike_sa_init_r_payloads)/sizeof(supported_payload_entry_t)),supported_ike_sa_init_r_payloads}, - {IKE_AUTH,TRUE,TRUE,(sizeof(supported_ike_auth_i_payloads)/sizeof(supported_payload_entry_t)),supported_ike_auth_i_payloads}, - {IKE_AUTH,FALSE,TRUE,(sizeof(supported_ike_auth_r_payloads)/sizeof(supported_payload_entry_t)),supported_ike_auth_r_payloads} -}; - -typedef struct payload_entry_t payload_entry_t; - -/** - * Entry for a payload in the internal used linked list. - * - */ -struct payload_entry_t { - /** - * Type of payload. - */ - payload_type_t payload_type; - /** - * Data struct holding the data of given payload. - */ - void *data_struct; + {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, + {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, + {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, + {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules} }; @@ -222,8 +209,7 @@ struct private_message_t { exchange_type_t exchange_type; /** - * TRUE if message is request. - * FALSE if message is reply. + * TRUE if message is a request, FALSE if a reply. */ bool is_request; @@ -238,9 +224,7 @@ struct private_message_t { ike_sa_id_t *ike_sa_id; /** - * Assigned UDP packet. - * - * Stores incoming packet or last generated one. + * Assigned UDP packet, stores incoming packet or last generated one. */ packet_t *packet; @@ -255,38 +239,38 @@ struct private_message_t { parser_t *parser; /** + * The message rule for this message instance + */ + message_rule_t *message_rule; + + /** * Assigned logger. */ logger_t *logger; /** - * Gets a list of supported payloads of this message type. + * Sets the private message_rule member to the rule which + * applies to this message. Must be called before get_payload_rule(). * * @param this calling object - * @param[out] message_rule pointer is set to the message_rule - * of current message type - * * @return * - SUCCESS - * - NOT_FOUND if no message rule - * for specific message type could be found + * - NOT_FOUND if no message rule applies to this message. */ - status_t (*get_message_rule) (private_message_t *this, message_rule_t **message_rule); + status_t (*set_message_rule) (private_message_t *this); /** - * Gets the supported_payload_entry_t for a specific message_rule_t and payload type. + * Gets the payload_rule_t for a specific message_rule_t and payload type. * * @param this calling object - * @param message_rule message rule * @param payload_type payload type - * @param[out] payload_entry returned payload_entry_t - * + * @param[out] payload_rule returned payload_rule_t * @return * - SUCCESS - * - NOT_FOUND if no message rule - * for specific message type could be found + * - NOT_FOUND if payload not defined in current message rule + * - INVALID_STATE if message rule is not set via set_message_rule() */ - status_t (*get_supported_payload_entry) (private_message_t *this, message_rule_t *message_rule,payload_type_t payload_type, supported_payload_entry_t **payload_entry); + status_t (*get_payload_rule) (private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule); /** * Encrypts all payloads which has to get encrypted. @@ -296,24 +280,40 @@ struct private_message_t { * @param this calling object * @param crypter crypter_t object * @param signer signer_t object + * @return + * - SUCCESS + * - INVALID_STATE if no crypter/signer supplied but needed */ status_t (*encrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); /** - * Decrypts encrypted contents and also verifies all payloads. + * Decrypts encrypted contents, and checks if a payload is encrypted if it has to be. * * @param this calling object * @param crypter crypter_t object * @param signer signer_t object + * @return + * - SUCCESS + * - FAILED if decryption not successfull + * - INVALID_STATE if no crypter/signer supplied but needed + */ + status_t (*decrypt_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); + + /** + * Verifies the message. Checks for payloads count. + * + * @param calling object + * @return + * - SUCCESS if message valid, or + * - FAILED if message does not align with message rules. */ - status_t (*decrypt_and_verify_payloads) (private_message_t *this,crypter_t *crypter, signer_t* signer); + status_t (*verify) (private_message_t *this); }; /** - * Implementation of private_message_t.get_supported_payloads. + * Implementation of private_message_t.set_message_rule. */ - -static status_t get_message_rule (private_message_t *this, message_rule_t **message_rule) +static status_t set_message_rule(private_message_t *this) { int i; @@ -323,31 +323,31 @@ static status_t get_message_rule (private_message_t *this, message_rule_t **mes (this->is_request == message_rules[i].is_request)) { /* found rule for given exchange_type*/ - *message_rule = &(message_rules[i]); + this->message_rule = &(message_rules[i]); return SUCCESS; } } - *message_rule = NULL; + this->message_rule = NULL; return NOT_FOUND; } /** - * Implementation of private_message_t.get_supported_payload_entry. + * Implementation of private_message_t.get_payload_rule. */ -static status_t get_supported_payload_entry (private_message_t *this, message_rule_t *message_rule,payload_type_t payload_type, supported_payload_entry_t **payload_entry) +static status_t get_payload_rule(private_message_t *this, payload_type_t payload_type, payload_rule_t **payload_rule) { int i; - for (i = 0; i < message_rule->supported_payloads_count;i++) + for (i = 0; i < this->message_rule->payload_rule_count;i++) { - if (message_rule->supported_payloads[i].payload_type == payload_type) + if (this->message_rule->payload_rules[i].payload_type == payload_type) { - *payload_entry = &(message_rule->supported_payloads[i]); + *payload_rule = &(this->message_rule->payload_rules[i]); return SUCCESS; } } - *payload_entry = NULL; + *payload_rule = NULL; return NOT_FOUND; } @@ -541,7 +541,6 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* ike_header_t *ike_header; payload_t *payload, *next_payload; iterator_t *iterator; - message_rule_t *message_rule; status_t status; this->logger->log(this->logger, CONTROL, "Generating message of type %s, contains %d payloads", @@ -550,27 +549,32 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) { - this->logger->log(this->logger, ERROR | MORE, "Exchange type %s is not defined",mapping_find(exchange_type_m,this->exchange_type)); + this->logger->log(this->logger, ERROR | MORE, "Exchange type %s is not defined", + mapping_find(exchange_type_m,this->exchange_type)); return INVALID_STATE; } - status = this->get_message_rule(this, &message_rule); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | MORE, "Message rule could not be found for exchange type %s", - mapping_find(exchange_type_m,this->exchange_type)); - return status; - } - if (this->packet->source == NULL || this->packet->destination == NULL) { - this->logger->log(this->logger, ERROR | MORE, "Source/destination not defined"); + this->logger->log(this->logger, ERROR|MORE, "%s not defined", + !this->packet->source ? "source" : "destination"); return INVALID_STATE; } + /* set the rules for this messge */ + status = this->set_message_rule(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", + mapping_find(exchange_type_m,this->exchange_type), + this->is_request ? "request" : "response"); + return NOT_SUPPORTED; + } + + /* going to encrypt all content which have to be encrypted */ - status = this->encrypt_payloads(this,crypter,signer); + status = this->encrypt_payloads(this, crypter, signer); if (status != SUCCESS) { this->logger->log(this->logger, ERROR | MORE, "Could not encrypt payloads"); @@ -591,9 +595,9 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* payload = (payload_t*)ike_header; - iterator = this->payloads->create_iterator(this->payloads, TRUE); - /* generate every payload expect last one*/ + /* generate every payload expect last one, this is doen later*/ + iterator = this->payloads->create_iterator(this->payloads, TRUE); while(iterator->has_next(iterator)) { iterator->current(iterator, (void**)&next_payload); @@ -634,7 +638,8 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* /* clone packet for caller */ *packet = this->packet->clone(this->packet); - this->logger->log(this->logger, CONTROL, "Message of type %s generated successfully",mapping_find(exchange_type_m,this->exchange_type)); + this->logger->log(this->logger, CONTROL, "Message of type %s generated successfully", + mapping_find(exchange_type_m,this->exchange_type)); return SUCCESS; } @@ -699,11 +704,22 @@ static status_t parse_header(private_message_t *this) this->minor_version = ike_header->get_min_version(ike_header); this->first_payload = ike_header->payload_interface.get_next_type(&(ike_header->payload_interface)); - this->logger->log(this->logger, CONTROL, "Parsed a %s %s", mapping_find(exchange_type_m, this->exchange_type), + this->logger->log(this->logger, CONTROL, "Parsed a %s %s", + mapping_find(exchange_type_m, this->exchange_type), this->is_request ? "request" : "response"); - ike_header->destroy(ike_header); - return SUCCESS; + ike_header->destroy(ike_header); + + /* get the rules for this messge */ + status = this->set_message_rule(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "No message rules specified for a %s %s", + mapping_find(exchange_type_m,this->exchange_type), + this->is_request ? "request" : "response"); + } + + return status; } /** @@ -712,11 +728,14 @@ static status_t parse_header(private_message_t *this) static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t *signer) { status_t status = SUCCESS; - payload_type_t current_payload_type = this->first_payload; + payload_type_t current_payload_type; + + current_payload_type = this->first_payload; this->logger->log(this->logger, CONTROL|MORE, "Parsing body of message, first payload %s", mapping_find(payload_type_m, current_payload_type)); + /* parse payload for payload, while there are more available */ while ((current_payload_type != NO_PAYLOAD)) { payload_t *current_payload; @@ -724,6 +743,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t this->logger->log(this->logger, CONTROL|MOST, "Start parsing payload of type %s", mapping_find(payload_type_m, current_payload_type)); + /* parse current payload */ status = this->parser->parse_payload(this->parser,current_payload_type,(payload_t **) ¤t_payload); if (status != SUCCESS) { @@ -734,6 +754,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t this->logger->log(this->logger, CONTROL|MOST, "Verify payload of type %s", mapping_find(payload_type_m, current_payload_type)); + /* verify it, stop parsig if its invalid */ status = current_payload->verify(current_payload); if (status != SUCCESS) { @@ -747,7 +768,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t mapping_find(payload_type_m, current_payload_type)); this->payloads->insert_last(this->payloads,current_payload); - /* stop if an encryption payload found */ + /* an encryption payload is the last one, so STOP here. decryption is done later */ if (current_payload_type == ENCRYPTED) { this->logger->log(this->logger, CONTROL|MOST, "Payload of type encrypted found. Stop parsing.", @@ -764,78 +785,91 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t this->is_request ? "request" : "response", this->payloads->get_count(this->payloads)); - status = this->decrypt_and_verify_payloads(this,crypter,signer); + /* */ + if (current_payload_type == ENCRYPTED) + status = this->decrypt_payloads(this,crypter,signer); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR, "Could not decrypt and verify payloads"); + this->logger->log(this->logger, ERROR, "Could not decrypt payloads"); return status; } - return SUCCESS; - + status = this->verify(this); + if (status != SUCCESS) + { + this->logger->log(this->logger, ERROR, "Verification of message failed"); + } + return status; } /** - * Implementation of message_t.verify. + * Implementation of private_message_t.verify. */ static status_t verify(private_message_t *this) { int i; - status_t status; iterator_t *iterator; - message_rule_t *message_rule; size_t total_found_payloads = 0; this->logger->log(this->logger, CONTROL|MORE, "Verifying message structure"); - - status = this->get_message_rule(this, &message_rule); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | MORE, "Message rule could not be found for exchange type %s", - mapping_find(exchange_type_m,this->exchange_type)); - return status; - } iterator = this->payloads->create_iterator(this->payloads,TRUE); /* check for payloads with wrong count*/ - for (i = 0; i < message_rule->supported_payloads_count;i++) + for (i = 0; i < this->message_rule->payload_rule_count;i++) { size_t found_payloads = 0; /* check all payloads for specific rule */ iterator->reset(iterator); + while(iterator->has_next(iterator)) { payload_t *current_payload; + payload_type_t current_payload_type; + iterator->current(iterator,(void **)¤t_payload); + current_payload_type = current_payload->get_type(current_payload); - if (current_payload->get_type(current_payload) == message_rule->supported_payloads[i].payload_type) + if (current_payload_type == UNKNOWN_PAYLOAD) + { + /* unknown payloads are ignored, IF they are not critical */ + unknown_payload_t *unknown_payload = (unknown_payload_t*)current_payload; + if (unknown_payload->is_critical(unknown_payload)) + { + this->logger->log(this->logger, ERROR, "%s (%d) is not supported, but its critical!", + mapping_find(payload_type_m, current_payload_type), current_payload_type); + iterator->destroy(iterator); + return NOT_SUPPORTED; + } + } + else if (current_payload_type == this->message_rule->payload_rules[i].payload_type) { found_payloads++; total_found_payloads++; this->logger->log(this->logger, CONTROL | MOST, "Found payload of type %s", - mapping_find(payload_type_m,message_rule->supported_payloads[i].payload_type)); - + mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type)); + /* as soon as ohe payload occures more then specified, the verification fails */ - if (found_payloads > message_rule->supported_payloads[i].max_occurence) + if (found_payloads > this->message_rule->payload_rules[i].max_occurence) { this->logger->log(this->logger, ERROR, "Payload of type %s more than %d times (%d) occured in current message", - mapping_find(payload_type_m,current_payload->get_type(current_payload)), - message_rule->supported_payloads[i].max_occurence,found_payloads); + mapping_find(payload_type_m, current_payload_type), + this->message_rule->payload_rules[i].max_occurence, found_payloads); iterator->destroy(iterator); - return NOT_SUPPORTED; + return FAILED; } } } - if (found_payloads < message_rule->supported_payloads[i].min_occurence) + + if (found_payloads < this->message_rule->payload_rules[i].min_occurence) { this->logger->log(this->logger, ERROR, "Payload of type %s not occured %d times (%d)", - mapping_find(payload_type_m,message_rule->supported_payloads[i].payload_type), - message_rule->supported_payloads[i].min_occurence,found_payloads); + mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type), + this->message_rule->payload_rules[i].min_occurence, found_payloads); iterator->destroy(iterator); - return NOT_SUPPORTED; + return FAILED; } - if ((message_rule->supported_payloads[i].can_be_last) && (this->payloads->get_count(this->payloads) == total_found_payloads)) + if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads)) { iterator->destroy(iterator); return SUCCESS; @@ -849,29 +883,20 @@ static status_t verify(private_message_t *this) /** * Implementation of private_message_t.decrypt_and_verify_payloads. */ -static status_t decrypt_and_verify_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) +static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, signer_t* signer) { bool current_payload_was_encrypted = FALSE; - payload_t *last_payload = NULL; - message_rule_t *message_rule; + payload_t *previous_payload = NULL; int payload_number = 1; iterator_t *iterator; status_t status; - - status = this->get_message_rule(this, &message_rule); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | MORE, "Message rule could not be found for exchange type %s", - mapping_find(exchange_type_m,this->exchange_type)); - return status; - } iterator = this->payloads->create_iterator(this->payloads,TRUE); /* process each payload and decrypt a encryption payload */ while(iterator->has_next(iterator)) { - supported_payload_entry_t *supported_payload_entry; + payload_rule_t *payload_rule; payload_type_t current_payload_type; payload_t *current_payload; @@ -888,28 +913,18 @@ static status_t decrypt_and_verify_payloads (private_message_t *this,crypter_t * encryption_payload_t *encryption_payload; payload_t *current_encrypted_payload; + encryption_payload = (encryption_payload_t*)current_payload; this->logger->log(this->logger, CONTROL | MORE, "Found an encryption payload"); - - if (!message_rule->encrypted_content) - { - this->logger->log(this->logger, ERROR | MORE, "Encrypted payload not allowed for this message type"); - iterator->destroy(iterator); - /* encrypted payload is not last one */ - return FAILED; - } - + if (payload_number != this->payloads->get_count(this->payloads)) { + /* encrypted payload is not last one */ this->logger->log(this->logger, ERROR | MORE, "Encrypted payload is not last payload"); iterator->destroy(iterator); - /* encrypted payload is not last one */ return FAILED; } - - iterator->current(iterator,(void **)&encryption_payload); - - /* encrypt payload */ + /* decrypt */ encryption_payload->set_transforms(encryption_payload, crypter, signer); this->logger->log(this->logger, CONTROL | MORE, "Verify signature of encryption payload"); status = encryption_payload->verify_signature(encryption_payload, this->packet->data); @@ -929,54 +944,37 @@ static status_t decrypt_and_verify_payloads (private_message_t *this,crypter_t * return status; } - /* needed to later find out if a payload has to be encrypted or not */ + /* needed later to find out if a payload was encrypted */ current_payload_was_encrypted = TRUE; - + + /* check if there are payloads contained in the encryption payload */ if (encryption_payload->get_payload_count(encryption_payload) == 0) { - this->logger->log(this->logger, CONTROL | MORE, "Encrypted payload is empty"); + this->logger->log(this->logger, CONTROL | MOST, "Encrypted payload is empty"); + /* remove the encryption payload, is not needed anymore */ iterator->remove(iterator); - encryption_payload->destroy(encryption_payload); /* encrypted payload contains no other payload */ current_payload_type = NO_PAYLOAD; - if (last_payload == NULL) - { - /* encrypted content was the only payload in IKEv2-Message - * Set the first payload to the first payload of encrypted ones */ - this->first_payload = current_payload_type; - } - else - { - /* another payload was here before the encrypted content - * Set the next payload of proceeding payload - * to the first payload of encrypted ones */ - last_payload->set_next_type(last_payload,current_payload_type); - } - break; - } - - this->logger->log(this->logger, CONTROL | MORE, "Encrypted payload is not empty"); - - /* encryption_payload is replaced with first encrypted payload*/ - encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); + else + { + this->logger->log(this->logger, CONTROL | MOST, "Encrypted payload is not empty"); + /* encryption_payload is replaced with first payload contained in encryption_payload */ + encryption_payload->remove_first_payload(encryption_payload, ¤t_encrypted_payload); + iterator->replace(iterator,NULL,(void *) current_encrypted_payload); + current_payload_type = current_encrypted_payload->get_type(current_encrypted_payload); + } - this->logger->log(this->logger, CONTROL | MORE, "Replace encrypted payload with payload of type %s.", - mapping_find(payload_type_m,current_encrypted_payload->get_type(current_encrypted_payload))); - iterator->replace(iterator,NULL,(void *) current_encrypted_payload); - current_payload_type = current_encrypted_payload->get_type(current_encrypted_payload); - if (last_payload == NULL) + /* is the current paylad the first in the message? */ + if (previous_payload == NULL) { - /* encrypted content was the only payload in IKEv2-Message - * Set the first payload to the first payload of encrypted ones */ + /* yes, set the first payload type of the message to the current type */ this->first_payload = current_payload_type; } else { - /* another payload was here before the encrypted content - * Set the next payload of proceeding payload - * to the first payload of encrypted ones */ - last_payload->set_next_type(last_payload,current_payload_type); + /* no, set the next_type of the previous payload to the current type */ + previous_payload->set_next_type(previous_payload, current_payload_type); } /* all encrypted payloads are added to the payload list */ @@ -987,37 +985,41 @@ static status_t decrypt_and_verify_payloads (private_message_t *this,crypter_t * this->payloads->insert_last(this->payloads,current_encrypted_payload); } - /* encryption payload is not needed anymore cause all payloads are - * moved to internal payload list */ - encryption_payload->destroy(encryption_payload); - - + /* encryption payload is processed, payloads are moved. Destroy it. */ + encryption_payload->destroy(encryption_payload); } - status = this->get_supported_payload_entry(this,message_rule,current_payload_type,&supported_payload_entry); - if (status != SUCCESS) + /* we allow unknown payloads of any type and don't bother if it was encrypted. Not our problem. */ + if (current_payload_type != UNKNOWN_PAYLOAD) { - /* payload type not supported */ - this->logger->log(this->logger, ERROR | MORE, "Payload type %s not allowed",mapping_find(payload_type_m,current_payload_type)); - iterator->destroy(iterator); - return status; - } - - if (supported_payload_entry->encrypted != current_payload_was_encrypted) - { - /* payload type not supported */ - this->logger->log(this->logger, ERROR | MORE, "Payload type %s should be %s!", - mapping_find(payload_type_m,current_payload_type), - (supported_payload_entry->encrypted) ? "encrypted": "not encrypted"); - iterator->destroy(iterator); - return status; + /* get the ruleset for found payload */ + status = this->get_payload_rule(this, current_payload_type, &payload_rule); + if (status != SUCCESS) + { + /* payload is not allowed */ + this->logger->log(this->logger, ERROR | MORE, "Payload type %s not allowed",mapping_find(payload_type_m,current_payload_type)); + iterator->destroy(iterator); + return status; + } + + /* check if the payload was encrypted, and if it should been have encrypted */ + if (payload_rule->encrypted != current_payload_was_encrypted) + { + /* payload was not encrypted, but should have been. or vice-versa */ + this->logger->log(this->logger, ERROR | MORE, "Payload type %s should be %s!", + mapping_find(payload_type_m,current_payload_type), + (payload_rule->encrypted) ? "encrypted": "not encrypted"); + iterator->destroy(iterator); + return FAILED; + } } + /* advance to the next payload */ payload_number++; /* is stored to set next payload in case of found encryption payload */ - last_payload = current_payload; + previous_payload = current_payload; } iterator->destroy(iterator); - return this->public.verify(&(this->public)); + return SUCCESS; } /** @@ -1026,19 +1028,10 @@ static status_t decrypt_and_verify_payloads (private_message_t *this,crypter_t * static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) { encryption_payload_t *encryption_payload = NULL; - message_rule_t *message_rule; status_t status; linked_list_t *all_payloads; - status = this->get_message_rule(this, &message_rule); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR | MORE, "Message rule could not be found for exchange type %s", - mapping_find(exchange_type_m,this->exchange_type)); - return status; - } - - if (!message_rule->encrypted_content) + if (!this->message_rule->encrypted_content) { this->logger->log(this->logger, CONTROL | MORE, "Message doesn't have to be encrypted"); /* message contains no content to encrypt */ @@ -1059,17 +1052,17 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si this->logger->log(this->logger, CONTROL | MOST, "Check each payloads if they have to get encrypted"); while (all_payloads->get_count(all_payloads) > 0) { - supported_payload_entry_t *supported_payload_entry; + payload_rule_t *payload_rule; payload_t *current_payload; bool to_encrypt = FALSE; all_payloads->remove_first(all_payloads,(void **)¤t_payload); this->logger->log(this->logger, CONTROL | MOST, "Get rule for payload %s", mapping_find(payload_type_m,current_payload->get_type(current_payload))); - status = this->get_supported_payload_entry(this,message_rule,current_payload->get_type(current_payload),&supported_payload_entry); + status = this->get_payload_rule(this,current_payload->get_type(current_payload),&payload_rule); /* for payload types which are not found in supported payload list, it is presumed * that they don't have to be encrypted */ - if ((status == SUCCESS) && (supported_payload_entry->encrypted)) + if ((status == SUCCESS) && (payload_rule->encrypted)) { this->logger->log(this->logger, CONTROL | MOST, "Payload %s has to get encrypted", mapping_find(payload_type_m,current_payload->get_type(current_payload))); @@ -1125,7 +1118,7 @@ static void destroy (private_message_t *this) { iterator_t *iterator; - this->logger->log(this->logger, CONTROL | MOST, "Going to destroy message_t object"); + this->logger->log(this->logger, CONTROL|ALL, "Going to destroy message_t object"); this->packet->destroy(this->packet); @@ -1139,7 +1132,7 @@ static void destroy (private_message_t *this) { payload_t *payload; iterator->current(iterator, (void**)&payload); - this->logger->log(this->logger, CONTROL|MOST, "Destroying payload of type %s", + this->logger->log(this->logger, CONTROL|ALL, "Destroying payload of type %s", mapping_find(payload_type_m, payload->get_type(payload))); payload->destroy(payload); } @@ -1181,7 +1174,6 @@ message_t *message_create_from_packet(packet_t *packet) this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator; this->public.parse_header = (status_t (*) (message_t *)) parse_header; this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body; - this->public.verify = (status_t (*) (message_t*)) verify; this->public.get_packet = (packet_t * (*) (message_t*)) get_packet; this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data; this->public.destroy = (void(*)(message_t*))destroy; @@ -1194,16 +1186,18 @@ message_t *message_create_from_packet(packet_t *packet) this->message_id = 0; /* private functions */ - this->get_message_rule = get_message_rule; - this->get_supported_payload_entry = get_supported_payload_entry; + this->set_message_rule = set_message_rule; + this->get_payload_rule = get_payload_rule; this->encrypt_payloads = encrypt_payloads; - this->decrypt_and_verify_payloads = decrypt_and_verify_payloads; + this->decrypt_payloads = decrypt_payloads; + this->verify = verify; /* private values */ if (packet == NULL) { packet = packet_create(); } + this->message_rule = NULL; this->packet = packet; this->payloads = linked_list_create(); diff --git a/Source/charon/encoding/message.h b/Source/charon/encoding/message.h index 98f9d8a22..a10f10aea 100644 --- a/Source/charon/encoding/message.h +++ b/Source/charon/encoding/message.h @@ -38,7 +38,15 @@ typedef struct message_t message_t; /** * @brief This class is used to represent an IKEv2-Message. * - * An IKEv2-Message is either a request or response. + * 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 */ @@ -159,6 +167,12 @@ struct message_t { /** * @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 @@ -166,7 +180,11 @@ struct message_t { void (*add_payload) (message_t *this, payload_t *payload); /** - * @brief Parses header of message + * @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 @@ -181,42 +199,53 @@ struct message_t { * * 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. + * 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 unsupported payload are contained in body + * - 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 + * @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 - * - EXCHANGE_TYPE_NOT_SET if exchange type is currently not set - * .... + * - 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); - - /** - * Verifies the structure of the message_t object. - * - * The payloads are checked for the correct occurence count. - * - * @param this message_t object - */ - status_t (*verify) (message_t *this); - + /** - * Gets the source host informations. + * @brief Gets the source host informations. * - * @warning Returned host_t object is not getting cloned. + * @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 @@ -224,7 +253,7 @@ struct message_t { host_t * (*get_source) (message_t *this); /** - * Sets the source host informations. + * @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. @@ -235,9 +264,10 @@ struct message_t { void (*set_source) (message_t *this, host_t *host); /** - * Gets the destination host informations. + * @brief Gets the destination host informations. * - * @warning Returned host_t object is not getting cloned. + * @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 @@ -245,7 +275,7 @@ struct message_t { host_t * (*get_destination) (message_t *this); /** - * Sets the destination host informations. + * @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. @@ -256,10 +286,10 @@ struct message_t { void (*set_destination) (message_t *this, host_t *host); /** - * Returns an iterator on all stored payloads. + * @brief Returns an iterator on all stored payloads. * * @warning Don't insert payloads over this iterator. - * Use message_t.add_payload instead. + * Use add_payload() instead. * * @param this message_t object * @return iterator_t object which has to get destroyd by the caller @@ -292,7 +322,7 @@ struct message_t { }; /** - * Creates an message_t object from a incoming UDP Packet. + * @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. @@ -302,9 +332,9 @@ struct message_t { * - 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 - * + * @param packet packet_t object which is assigned to message * @return created message_t object * * @ingroup encoding @@ -313,7 +343,7 @@ message_t * message_create_from_packet(packet_t *packet); /** - * Creates an empty message_t object. + * @brief Creates an empty message_t object. * * - exchange_type is set to NOT_SET * - original_initiator is set to TRUE @@ -326,7 +356,7 @@ message_t * message_create_from_packet(packet_t *packet); message_t * message_create(); /** - * Creates an message_t object of type reply containing a notify payload. + * @brief Creates an message_t object of type reply containing a notify payload. * * @return created message_t object * diff --git a/Source/charon/encoding/parser.c b/Source/charon/encoding/parser.c index e3d7fa8c5..a6aefa968 100644 --- a/Source/charon/encoding/parser.c +++ b/Source/charon/encoding/parser.c @@ -51,6 +51,7 @@ #include <encoding/payloads/cp_payload.h> #include <encoding/payloads/configuration_attribute.h> #include <encoding/payloads/eap_payload.h> +#include <encoding/payloads/unknown_payload.h> typedef struct private_parser_t private_parser_t; @@ -587,6 +588,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ int rule_number; encoding_rule_t *rule; + /* create instance of the payload to parse */ + pld = payload_create(payload_type); + this->logger->log(this->logger, CONTROL|MORE, "parsing %s payload, %d bytes left", mapping_find(payload_type_m, payload_type), this->input_roof-this->byte_pos); @@ -594,18 +598,17 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ this->logger->log_bytes(this->logger, RAW, "parsing payload from", this->byte_pos, this->input_roof-this->byte_pos); - /* ok, do the parsing */ - pld = payload_create(payload_type); - if (pld == NULL) + if (pld->get_type(pld) == UNKNOWN_PAYLOAD) { - this->logger->log(this->logger, ERROR, " payload %s not supported", mapping_find(payload_type_m, payload_type)); - return NOT_SUPPORTED; + this->logger->log(this->logger, ERROR|MORE, " payload type %d is unknown, handling as %s", + payload_type, mapping_find(payload_type_m, UNKNOWN_PAYLOAD)); } + /* base pointer for output, avoids casting in every rule */ output = pld; + /* parse the payload with its own rulse */ pld->get_encoding_rules(pld, &(this->rules), &rule_count); - for (rule_number = 0; rule_number < rule_count; rule_number++) { rule = &(this->rules[rule_number]); @@ -974,6 +977,16 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } break; } + case UNKNOWN_PAYLOAD: + { + size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH; + if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } default: { this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type); diff --git a/Source/charon/encoding/payloads/payload.c b/Source/charon/encoding/payloads/payload.c index bd94eaa5f..b89e80a53 100644 --- a/Source/charon/encoding/payloads/payload.c +++ b/Source/charon/encoding/payloads/payload.c @@ -1,7 +1,7 @@ /** * @file payload.c * - * @brief Generic payload interface + * @brief Generic constructor to the payload_t interface. * * */ @@ -122,12 +122,10 @@ payload_t *payload_create(payload_type_t type) return (payload_t*)configuration_attribute_create(); case EXTENSIBLE_AUTHENTICATION: return (payload_t*)eap_payload_create(); - case UNKNOWN_PAYLOAD: - return (payload_t*)unknown_payload_create(); case ENCRYPTED: return (payload_t*)encryption_payload_create(); default: - return NULL; + return (payload_t*)unknown_payload_create(); } } diff --git a/Source/charon/encoding/payloads/payload.h b/Source/charon/encoding/payloads/payload.h index 6fbd94969..a3300656b 100644 --- a/Source/charon/encoding/payloads/payload.h +++ b/Source/charon/encoding/payloads/payload.h @@ -1,7 +1,7 @@ /** * @file payload.h * - * @brief Generic payload interface. + * @brief Interface payload_t. * * */ @@ -32,8 +32,7 @@ typedef enum payload_type_t payload_type_t; /** - * Payload-Types of a IKEv2-Message. - * + * @brief Payload-Types of a IKEv2-Message. * * Header and substructures are also defined as * payload types with values from PRIVATE USE space. @@ -43,87 +42,87 @@ typedef enum payload_type_t payload_type_t; enum payload_type_t{ /** - * NO_PAYLOAD + * End of payload list in next_payload */ NO_PAYLOAD = 0, /** - * SA + * The security association (SA) payload containing proposals. */ SECURITY_ASSOCIATION = 33, /** - * KE + * The key exchange (KE) payload containing diffie-hellman values. */ KEY_EXCHANGE = 34, /** - * IDi + * Identification for the original initiator (IDi). */ ID_INITIATOR = 35, /** - * IDr + * Identification for the original responder (IDr). */ ID_RESPONDER = 36, /** - * CERT + * Certificate payload with certificates (CERT). */ CERTIFICATE = 37, /** - * CERTREQ + * Certificate request payload (CERTREQ). */ CERTIFICATE_REQUEST = 38, /** - * AUTH + * Authentication payload contains auth data (AUTH). */ AUTHENTICATION = 39, /** - * Ni, Nr + * Nonces, for initator and responder (Ni, Nr, N) */ NONCE = 40, /** - * N + * Notif paylaod (N). */ NOTIFY = 41, /** - * D + * Delete payload (D) */ DELETE = 42, /** - * V + * Vendor id paylpoad (V). */ VENDOR_ID = 43, /** - * TSi + * Traffic selector for the original initiator (TSi). */ TRAFFIC_SELECTOR_INITIATOR = 44, /** - * TSr + * Traffic selector for the original responser (TSr). */ TRAFFIC_SELECTOR_RESPONDER = 45, /** - * E + * Encryption payload, contains other payloads (E). */ ENCRYPTED = 46, /** - * CP + * Configuration payload (CP). */ CONFIGURATION = 47, /** - * EAP + * Extensible authentication payload (EAP). */ EXTENSIBLE_AUTHENTICATION = 48, @@ -185,8 +184,8 @@ enum payload_type_t{ }; -/* - * Build string mapping array for payload_type_t. +/** + * String mappings for payload_type_t. */ extern mapping_t payload_type_m[]; @@ -194,21 +193,21 @@ extern mapping_t payload_type_m[]; typedef struct payload_t payload_t; /** - * @brief Generic interface for all payload types (inclusive - * header and substructures). + * @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 Destroys a payload and all included substructures. - * - * @param this payload to destroy - */ - void (*destroy) (payload_t *this); /** - * @brief Get encoding rules for this payload + * @brief Get encoding rules for this payload. * * @param this calling object * @param[out] rules location to store pointer of first rule @@ -217,7 +216,7 @@ struct payload_t { void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count); /** - * @brief get type of payload + * @brief Get type of payload. * * @param this calling object * @return type of this payload @@ -225,7 +224,7 @@ struct payload_t { payload_type_t (*get_type) (payload_t *this); /** - * @brief get type of next payload or zero if this is the last one + * @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 @@ -233,7 +232,7 @@ struct payload_t { payload_type_t (*get_next_type) (payload_t *this); /** - * @brief set type of next payload + * @brief Set type of next payload. * * @param this calling object * @param type type of next payload @@ -241,7 +240,7 @@ struct payload_t { void (*set_next_type) (payload_t *this,payload_type_t type); /** - * @brief get length of payload + * @brief Get length of payload. * * @param this calling object * @return length of this payload @@ -249,7 +248,7 @@ struct payload_t { size_t (*get_length) (payload_t *this); /** - * @brief Verifies payload structure and makes consistence check + * @brief Verifies payload structure and makes consistence check. * * @param this calling object * @return @@ -257,18 +256,25 @@ struct payload_t { * - 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. + * 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 created payload */ - payload_t *payload_create(payload_type_t type); #endif /*PAYLOAD_H_*/ diff --git a/Source/charon/encoding/payloads/unknown_payload.c b/Source/charon/encoding/payloads/unknown_payload.c index 3e910ba8d..c162edc30 100644 --- a/Source/charon/encoding/payloads/unknown_payload.c +++ b/Source/charon/encoding/payloads/unknown_payload.c @@ -29,9 +29,9 @@ 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. */ @@ -40,7 +40,7 @@ struct private_unknown_payload_t { /** * Next payload type. */ - u_int8_t next_payload; + u_int8_t next_payload; /** * Critical flag. @@ -53,18 +53,13 @@ struct private_unknown_payload_t { u_int16_t payload_length; /** - * Type of this payload. - */ - payload_type_t payload_type; - - /** * The contained data. */ chunk_t data; }; /** - * Encoding rules to parse or generate a EAP payload. + * 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. @@ -86,7 +81,7 @@ encoding_rule_t unknown_payload_encodings[] = { /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)}, /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */ - { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) } + { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) } }; /* @@ -110,7 +105,7 @@ static status_t verify(private_unknown_payload_t *this) } /** - * Implementation of unknown_payload_t.get_encoding_rules. + * 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) { @@ -143,22 +138,6 @@ static void set_next_type(private_unknown_payload_t *this,payload_type_t type) } /** - * Implementation of unknown_payload_t.set_real_type. - */ -static void set_real_type(private_unknown_payload_t *this,payload_type_t type) -{ - this->payload_type = type; -} - -/** - * Implementation of unknown_payload_t.get_real_type. - */ -static payload_type_t get_real_type(private_unknown_payload_t *this) -{ - return this->payload_type; -} - -/** * Implementation of payload_t.get_length. */ static size_t get_length(private_unknown_payload_t *this) @@ -167,17 +146,11 @@ static size_t get_length(private_unknown_payload_t *this) } /** - * Implementation of unknown_payload_t.set_data. + * Implementation of unknown_payload_t.get_data. */ -static void set_data (private_unknown_payload_t *this, chunk_t data) +static bool is_critical(private_unknown_payload_t *this) { - if (this->data.ptr != NULL) - { - allocator_free_chunk(&(this->data)); - } - this->data.ptr = allocator_clone_bytes(data.ptr,data.len); - this->data.len = data.len; - this->payload_length = DEFAULT_PAYLOAD_HEADER_LENGTH + this->data.len; + return this->critical; } /** @@ -189,21 +162,6 @@ static chunk_t get_data (private_unknown_payload_t *this) } /** - * Implementation of unknown_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_unknown_payload_t *this) -{ - chunk_t cloned_data; - if (this->data.ptr == NULL) - { - return (this->data); - } - cloned_data.ptr = allocator_clone_bytes(this->data.ptr,this->data.len); - cloned_data.len = this->data.len; - return cloned_data; -} - -/** * Implementation of payload_t.destroy and unknown_payload_t.destroy. */ static void destroy(private_unknown_payload_t *this) @@ -234,17 +192,13 @@ unknown_payload_t *unknown_payload_create() /* public functions */ this->public.destroy = (void (*) (unknown_payload_t *)) destroy; - this->public.set_real_type = (void (*) (unknown_payload_t *,payload_type_t)) set_real_type; - this->public.get_real_type = (payload_type_t (*) (unknown_payload_t *)) get_real_type; - this->public.set_data = (void (*) (unknown_payload_t *,chunk_t)) set_data; - this->public.get_data_clone = (chunk_t (*) (unknown_payload_t *)) get_data_clone; + 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_type = NO_PAYLOAD; - this->payload_length = DEFAULT_PAYLOAD_HEADER_LENGTH; + this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH; this->data = CHUNK_INITIALIZER; return (&(this->public)); diff --git a/Source/charon/encoding/payloads/unknown_payload.h b/Source/charon/encoding/payloads/unknown_payload.h index ea365871b..2558ce719 100644 --- a/Source/charon/encoding/payloads/unknown_payload.h +++ b/Source/charon/encoding/payloads/unknown_payload.h @@ -27,73 +27,52 @@ #include <encoding/payloads/payload.h> /** - * Length of a default payload header. + * Header length of the unknown payload. * * @ingroup payloads */ -#define DEFAULT_PAYLOAD_HEADER_LENGTH 4 +#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4 typedef struct unknown_payload_t unknown_payload_t; /** - * Object representing an unknown IKEv2 payload. + * @brief Payload which can't be processed further. * - * @ingroup payloads + * 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 Set the Data of the unknown payload. - * - * Data are getting cloned. - * - * @param this calling unknown_payload_t object - * @param data data following the header as chunk_t - */ - void (*set_data) (unknown_payload_t *this, chunk_t data); - - /** - * @brief Get the data of the message. - * - * Returned data are a copy of the internal one. - * - * @param this calling unknown_payload_t object - * @return data as chunk_t - */ - chunk_t (*get_data_clone) (unknown_payload_t *this); - - /** - * @brief Get the data of the message. + * @brief Get the raw data of this payload, without + * the generic payload header. * - * Returned data are NOT copied. + * 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 Set the real Type of this payload. - * - * @param this calling unknown_payload_t object - * @param type real type of this payload. - */ - - void (*set_real_type) (unknown_payload_t *this,payload_type_t type); /** - * @brief Get the real Type of this payload. + * @brief Get the critical flag. * - * @param this calling unknown_payload_t object - * @return real type of this payload. + * @param this calling unknown_payload_t object + * @return TRUE if payload is critical, FALSE if not */ - payload_type_t (*get_real_type) (unknown_payload_t *this); + bool (*is_critical) (unknown_payload_t *this); /** * @brief Destroys an unknown_payload_t object. |