【18】Strongswan encoding详解 message2
- message是基于packet操作的,packet如下:
struct private_packet_t {//packet_t 操作的接口packet_t public;//源主机地址host_t *source;//目的主机地址host_t *destination;uint8_t dscp;//消息数据chunk_t data;//从 get_data 返回的实际块,在调用 skip_bytes 时进行调整chunk_t adjusted_data;//元数据对象集(如果有)metadata_set_t *metadata;
};
public接口如下:
get_data 返回的是adjusted_data数据;skip_bytes 通过chunk_skip掠过前面指定字节的数据;
get_metadata和set_metadata,操作元数据,元数据另表。
- payload_rule、
它定义有效负载是否必须/可以在消息中出现以及可以出现多少次,以及是否必须加密。
typedef struct {/* 载荷类型 */payload_type_t type;/* 最小出现次数. */size_t min_occurrence;/* 最大出现次数. */size_t max_occurrence;/* 是否加密 */bool encrypted;/* 如果出现 payload,则满足消息规则要求 */bool sufficient;
} payload_rule_t;/*** payload ordering 结构允许我们根据 RFC 对 payload 进行重新排序。*/
typedef struct {/** payload 类型*/payload_type_t type;/** notify 类型, if payload == PLV2_NOTIFY */notify_type_t notify;
} payload_order_t;/*** A message rule defines the kind of a message,* if it has encrypted contents and a list* of payload ordering rules and payload parsing rules.*/
typedef struct {/** 消息类型. */exchange_type_t exchange_type;/** 消息是请求还是回应. */bool is_request;/** 是否包含加密 payloads. */bool encrypted;/** payload rules 个数 */int rule_count;/** 指向第一个 payload rule */payload_rule_t *rules;/** payload order rules个数 */int order_count;/** payload ordering rules */payload_order_t *order;
} message_rule_t;
rule实列:
/*** 来自发起方的 IKE_SA_INIT 的消息规则。*/
static payload_rule_t ike_sa_init_i_rules[] = {
/* payload type min max encr suff */{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},{PLV2_SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},{PLV2_KEY_EXCHANGE, 1, 1, FALSE, FALSE},{PLV2_NONCE, 1, 1, FALSE, FALSE},{PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
};/*** IKE_SA_INIT 发起方的负载顺序*/
static payload_order_t ike_sa_init_i_order[] = {
/* payload type notify type */{PLV2_NOTIFY, COOKIE},{PLV2_SECURITY_ASSOCIATION, 0},{PLV2_KEY_EXCHANGE, 0},{PLV2_NONCE, 0},{PLV2_NOTIFY, NAT_DETECTION_SOURCE_IP},{PLV2_NOTIFY, NAT_DETECTION_DESTINATION_IP},{PLV2_NOTIFY, 0},{PLV2_VENDOR_ID, 0},
};//message rule包含payload rule
static message_rule_t message_rules[] = {{IKE_SA_INIT, TRUE, FALSE,countof(ike_sa_init_i_rules), ike_sa_init_i_rules,countof(ike_sa_init_i_order), ike_sa_init_i_order,},{IKE_SA_INIT, FALSE, FALSE,countof(ike_sa_init_r_rules), ike_sa_init_r_rules,countof(ike_sa_init_r_order), ike_sa_init_r_order,},......
}
方法:
get_message_rule:
根据message的类型和是否请求消息还是回应消息比较,返回上述message_rules的规则。
get_payload_rule:
遍历该message的所有payload rule,比较payload type。
add_payload:
METHOD(message_t, add_payload, void,private_message_t *this, payload_t *payload)
{payload_t *last_payload;//该message的payloads链表为空,则将first_payload 记为当前payload类型,//否则获取链表中最后一个payloads,并将其下一个payload类型设置为当前payload类型//当前payload的下一个payload类型设置PL_NONE//插入message的payloads链表尾部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->first_payload = payload->get_type(payload);}payload->set_next_type(payload, PL_NONE);this->payloads->insert_last(this->payloads, payload);DBG2(DBG_ENC ,"added payload of type %N to message",payload_type_names, payload->get_type(payload));
}
add_notify:
METHOD(message_t, add_notify, void,private_message_t *this, bool flush, notify_type_t type, chunk_t data)
{notify_payload_t *notify;payload_t *payload;//清空已有的payloadif (flush){while (this->payloads->remove_last(this->payloads,(void**)&payload) == SUCCESS){payload->destroy(payload);}}//根据回应消息中的ike版本,创建notify实例,并设置类型和data,然后添加到message的尾部if (this->major_version == IKEV2_MAJOR_VERSION){notify = notify_payload_create(PLV2_NOTIFY);}else{notify = notify_payload_create(PLV1_NOTIFY);}notify->set_notify_type(notify, type);notify->set_notification_data(notify, data);add_payload(this, (payload_t*)notify);
}
get_payload:
遍历message的payloads链表,比较payload的类型,返回匹配的payload。
get_notify:
二级比较,第一级是比较payload的类型,第二级是notify的类型。
enum payload_type_t {/*** End of payload list in next_payload*/PL_NONE = 0,/*** The security association (SA) payload containing proposals.*/PLV1_SECURITY_ASSOCIATION = 1,/*** The proposal payload, containing transforms.*/PLV1_PROPOSAL = 2,/*** The transform payload.*/PLV1_TRANSFORM = 3,/*** The key exchange (KE) payload containing diffie-hellman values.*/PLV1_KEY_EXCHANGE = 4,/*** ID payload.*/PLV1_ID = 5,/*** Certificate payload with certificates (CERT).*/PLV1_CERTIFICATE = 6,/*** Certificate request payload.*/PLV1_CERTREQ = 7,/*** Hash payload.*/PLV1_HASH = 8,/*** Signature payload*/PLV1_SIGNATURE = 9,/*** Nonce payload.*/PLV1_NONCE = 10,/*** Notification payload.*/PLV1_NOTIFY = 11,/*** Delete payload.*/PLV1_DELETE = 12,/*** Vendor id payload.*/PLV1_VENDOR_ID = 13,/*** Attribute payload (ISAKMP Mode Config, aka configuration payload.*/PLV1_CONFIGURATION = 14,/*** NAT discovery payload (NAT-D).*/PLV1_NAT_D = 20,/*** NAT original address payload (NAT-OA).*/PLV1_NAT_OA = 21,....../*** This is not really a payload, but rather the complete IKEv1 message.*/PLV1_ENCRYPTED,
};enum notify_type_t {/* notify error messages */UNSUPPORTED_CRITICAL_PAYLOAD = 1,/* IKEv1 alias */INVALID_PAYLOAD_TYPE = 1,INVALID_IKE_SPI = 4,INVALID_MAJOR_VERSION = 5,INVALID_SYNTAX = 7,....../* notify status messages */INITIAL_CONTACT = 16384,SET_WINDOW_SIZE = 16385,ADDITIONAL_TS_POSSIBLE = 16386,IPCOMP_SUPPORTED = 16387,NAT_DETECTION_SOURCE_IP = 16388,NAT_DETECTION_DESTINATION_IP = 16389,COOKIE = 16390,USE_TRANSPORT_MODE = 16391,HTTP_CERT_LOOKUP_SUPPORTED = 16392,REKEY_SA = 16393,ESP_TFC_PADDING_NOT_SUPPORTED = 16394,NON_FIRST_FRAGMENTS_ALSO = 16395,/* mobike extension, RFC4555 */MOBIKE_SUPPORTED = 16396,ADDITIONAL_IP4_ADDRESS = 16397,ADDITIONAL_IP6_ADDRESS = 16398,NO_ADDITIONAL_ADDRESSES = 16399,UPDATE_SA_ADDRESSES = 16400,COOKIE2 = 16401,NO_NATS_ALLOWED = 16402,/* repeated authentication extension, RFC4478 */AUTH_LIFETIME = 16403,/* multiple authentication exchanges, RFC 4739 */MULTIPLE_AUTH_SUPPORTED = 16404,ANOTHER_AUTH_FOLLOWS = 16405,/* redirect mechanism, RFC 5685 */REDIRECT_SUPPORTED = 16406,REDIRECT = 16407,REDIRECTED_FROM = 16408,/* session resumption, RFC 5723 */TICKET_LT_OPAQUE = 16409,TICKET_REQUEST = 16410,TICKET_ACK = 16411,TICKET_NACK = 16412,TICKET_OPAQUE = 16413,/* IPv6 configuration, RFC 5739 */LINK_ID = 16414,/* wrapped esp, RFC 5840 */USE_WESP_MODE = 16415,/* robust header compression, RFC 5857 */ROHC_SUPPORTED = 16416,/* EAP-only authentication, RFC 5998 */EAP_ONLY_AUTHENTICATION = 16417,/* Childless initiation of IKEv2 SA, RFC 6023 */CHILDLESS_IKEV2_SUPPORTED = 16418,/* Quick crash detection for IKE, RFC 6290 */QUICK_CRASH_DETECTION = 16419,/* High availability of IKEv2/IPsec, RFC 6311 */IKEV2_MESSAGE_ID_SYNC_SUPPORTED = 16420,IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED = 16421,IKEV2_MESSAGE_ID_SYNC = 16422,IPSEC_REPLAY_COUNTER_SYNC = 16423,/* Secure password methods, RFC 6467 */SECURE_PASSWORD_METHOD = 16424,/* PACE, RFC 6631 */PSK_PERSIST = 16425,PSK_CONFIRM = 16426,/* EAP Re-authentication Extension, RFC 6867 */ERX_SUPPORTED = 16427,/* IFOM capability, 3GPP TS 24.303, annex B.2 */IFOM_CAPABILITY = 16428,/* SENDER_REQUEST_ID (draft-yeung-g-ikev2) */SENDER_REQUEST_ID = 16429,/* IKEv2 fragmentation supported, RFC 7383 */FRAGMENTATION_SUPPORTED = 16430,/* Signature Hash Algorithms, RFC 7427 */SIGNATURE_HASH_ALGORITHMS = 16431,/* Use Postquantum Preshared Key, RFC 8784 */USE_PPK = 16435,/* Postquantum Preshared Key Identity, RFC 8784 */PPK_IDENTITY = 16436,/* No Postquantum Preshared Key Auth, RFC 8784 */NO_PPK_AUTH = 16437,/* IKEv2 Intermediate Exchanges, RFC 9242 */INTERMEDIATE_EXCHANGE_SUPPORTED = 16438,/* multiple key exchanges, RFC 9370 */ADDITIONAL_KEY_EXCHANGE = 16441,/* IKEv1 initial contact */INITIAL_CONTACT_IKEV1 = 24578,/* IKEv1 DPD */DPD_R_U_THERE = 36136,DPD_R_U_THERE_ACK = 36137,/* IKEv1 Cisco High Availability */UNITY_LOAD_BALANCE = 40501,/* BEET mode, not even a draft yet. private use */USE_BEET_MODE = 40961,/* IKE-ME, private use */ME_MEDIATION = 40962,ME_ENDPOINT = 40963,ME_CALLBACK = 40964,ME_CONNECTID = 40965,ME_CONNECTKEY = 40966,ME_CONNECTAUTH = 40967,ME_RESPONSE = 40968,/* RADIUS attribute received/to send to a AAA backend */RADIUS_ATTRIBUTE = 40969,
};