Annotation of embedaddon/strongswan/src/libcharon/encoding/message.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2006-2018 Tobias Brunner
! 3: * Copyright (C) 2005-2010 Martin Willi
! 4: * Copyright (C) 2010 revosec AG
! 5: * Copyright (C) 2006 Daniel Roethlisberger
! 6: * Copyright (C) 2005 Jan Hutter
! 7: * HSR Hochschule fuer Technik Rapperswil
! 8: *
! 9: * This program is free software; you can redistribute it and/or modify it
! 10: * under the terms of the GNU General Public License as published by the
! 11: * Free Software Foundation; either version 2 of the License, or (at your
! 12: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 13: *
! 14: * This program is distributed in the hope that it will be useful, but
! 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 17: * for more details.
! 18: */
! 19:
! 20: #include <stdlib.h>
! 21: #include <string.h>
! 22:
! 23: #include "message.h"
! 24:
! 25: #include <library.h>
! 26: #include <bio/bio_writer.h>
! 27: #include <collections/array.h>
! 28: #include <daemon.h>
! 29: #include <sa/ikev1/keymat_v1.h>
! 30: #include <encoding/generator.h>
! 31: #include <encoding/parser.h>
! 32: #include <encoding/payloads/encodings.h>
! 33: #include <encoding/payloads/payload.h>
! 34: #include <encoding/payloads/hash_payload.h>
! 35: #include <encoding/payloads/encrypted_payload.h>
! 36: #include <encoding/payloads/encrypted_fragment_payload.h>
! 37: #include <encoding/payloads/unknown_payload.h>
! 38: #include <encoding/payloads/cp_payload.h>
! 39: #include <encoding/payloads/fragment_payload.h>
! 40:
! 41: /**
! 42: * Max number of notify payloads per IKEv2 message
! 43: */
! 44: #define MAX_NOTIFY_PAYLOADS 20
! 45:
! 46: /**
! 47: * Max number of delete payloads per IKEv2 message
! 48: */
! 49: #define MAX_DELETE_PAYLOADS 20
! 50:
! 51: /**
! 52: * Max number of certificate payloads per IKEv2 message
! 53: */
! 54: #define MAX_CERT_PAYLOADS 8
! 55:
! 56: /**
! 57: * Max number of vendor ID payloads per IKEv2 message
! 58: */
! 59: #define MAX_VID_PAYLOADS 20
! 60:
! 61: /**
! 62: * Max number of certificate request payloads per IKEv1 message
! 63: */
! 64: #define MAX_CERTREQ_PAYLOADS 20
! 65:
! 66: /**
! 67: * Max number of NAT-D payloads per IKEv1 message
! 68: */
! 69: #define MAX_NAT_D_PAYLOADS 10
! 70:
! 71: /**
! 72: * A payload rule defines the rules for a payload
! 73: * in a specific message rule. It defines if and how
! 74: * many times a payload must/can occur in a message
! 75: * and if it must be encrypted.
! 76: */
! 77: typedef struct {
! 78: /* Payload type */
! 79: payload_type_t type;
! 80: /* Minimal occurrence of this payload. */
! 81: size_t min_occurrence;
! 82: /* Max occurrence of this payload. */
! 83: size_t max_occurrence;
! 84: /* TRUE if payload must be encrypted */
! 85: bool encrypted;
! 86: /* If payload occurs, the message rule is fulfilled */
! 87: bool sufficient;
! 88: } payload_rule_t;
! 89:
! 90: /**
! 91: * payload ordering structure allows us to reorder payloads according to RFC.
! 92: */
! 93: typedef struct {
! 94: /** payload type */
! 95: payload_type_t type;
! 96: /** notify type, if payload == PLV2_NOTIFY */
! 97: notify_type_t notify;
! 98: } payload_order_t;
! 99:
! 100: /**
! 101: * A message rule defines the kind of a message,
! 102: * if it has encrypted contents and a list
! 103: * of payload ordering rules and payload parsing rules.
! 104: */
! 105: typedef struct {
! 106: /** Type of message. */
! 107: exchange_type_t exchange_type;
! 108: /** Is message a request or response. */
! 109: bool is_request;
! 110: /** Message contains encrypted payloads. */
! 111: bool encrypted;
! 112: /** Number of payload rules which will follow */
! 113: int rule_count;
! 114: /** Pointer to first payload rule */
! 115: payload_rule_t *rules;
! 116: /** Number of payload order rules */
! 117: int order_count;
! 118: /** payload ordering rules */
! 119: payload_order_t *order;
! 120: } message_rule_t;
! 121:
! 122: /**
! 123: * Message rule for IKE_SA_INIT from initiator.
! 124: */
! 125: static payload_rule_t ike_sa_init_i_rules[] = {
! 126: /* payload type min max encr suff */
! 127: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 128: {PLV2_SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},
! 129: {PLV2_KEY_EXCHANGE, 1, 1, FALSE, FALSE},
! 130: {PLV2_NONCE, 1, 1, FALSE, FALSE},
! 131: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 132: };
! 133:
! 134: /**
! 135: * payload order for IKE_SA_INIT initiator
! 136: */
! 137: static payload_order_t ike_sa_init_i_order[] = {
! 138: /* payload type notify type */
! 139: {PLV2_NOTIFY, COOKIE},
! 140: {PLV2_SECURITY_ASSOCIATION, 0},
! 141: {PLV2_KEY_EXCHANGE, 0},
! 142: {PLV2_NONCE, 0},
! 143: {PLV2_NOTIFY, NAT_DETECTION_SOURCE_IP},
! 144: {PLV2_NOTIFY, NAT_DETECTION_DESTINATION_IP},
! 145: {PLV2_NOTIFY, 0},
! 146: {PLV2_VENDOR_ID, 0},
! 147: };
! 148:
! 149: /**
! 150: * Message rule for IKE_SA_INIT from responder.
! 151: */
! 152: static payload_rule_t ike_sa_init_r_rules[] = {
! 153: /* payload type min max encr suff */
! 154: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, TRUE},
! 155: {PLV2_SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE},
! 156: {PLV2_KEY_EXCHANGE, 1, 1, FALSE, FALSE},
! 157: {PLV2_NONCE, 1, 1, FALSE, FALSE},
! 158: {PLV2_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
! 159: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 160: };
! 161:
! 162: /**
! 163: * payload order for IKE_SA_INIT responder
! 164: */
! 165: static payload_order_t ike_sa_init_r_order[] = {
! 166: /* payload type notify type */
! 167: {PLV2_SECURITY_ASSOCIATION, 0},
! 168: {PLV2_KEY_EXCHANGE, 0},
! 169: {PLV2_NONCE, 0},
! 170: {PLV2_NOTIFY, NAT_DETECTION_SOURCE_IP},
! 171: {PLV2_NOTIFY, NAT_DETECTION_DESTINATION_IP},
! 172: {PLV2_NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED},
! 173: {PLV2_CERTREQ, 0},
! 174: {PLV2_NOTIFY, 0},
! 175: {PLV2_VENDOR_ID, 0},
! 176: };
! 177:
! 178: /**
! 179: * Message rule for IKE_AUTH from initiator.
! 180: */
! 181: static payload_rule_t ike_auth_i_rules[] = {
! 182: /* payload type min max encr suff */
! 183: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 184: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 185: {PLV2_EAP, 0, 1, TRUE, TRUE},
! 186: {PLV2_AUTH, 0, 1, TRUE, TRUE},
! 187: {PLV2_ID_INITIATOR, 0, 1, TRUE, FALSE},
! 188: {PLV2_CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
! 189: {PLV2_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, TRUE, FALSE},
! 190: {PLV2_ID_RESPONDER, 0, 1, TRUE, FALSE},
! 191: #ifdef ME
! 192: {PLV2_SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
! 193: {PLV2_TS_INITIATOR, 0, 1, TRUE, FALSE},
! 194: {PLV2_TS_RESPONDER, 0, 1, TRUE, FALSE},
! 195: #else
! 196: {PLV2_SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
! 197: {PLV2_TS_INITIATOR, 0, 1, TRUE, FALSE},
! 198: {PLV2_TS_RESPONDER, 0, 1, TRUE, FALSE},
! 199: #endif /* ME */
! 200: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 201: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 202: };
! 203:
! 204: /**
! 205: * payload order for IKE_AUTH initiator
! 206: */
! 207: static payload_order_t ike_auth_i_order[] = {
! 208: /* payload type notify type */
! 209: {PLV2_ID_INITIATOR, 0},
! 210: {PLV2_CERTIFICATE, 0},
! 211: {PLV2_NOTIFY, INITIAL_CONTACT},
! 212: {PLV2_NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED},
! 213: {PLV2_CERTREQ, 0},
! 214: {PLV2_ID_RESPONDER, 0},
! 215: {PLV2_AUTH, 0},
! 216: {PLV2_EAP, 0},
! 217: {PLV2_CONFIGURATION, 0},
! 218: {PLV2_NOTIFY, IPCOMP_SUPPORTED},
! 219: {PLV2_NOTIFY, USE_TRANSPORT_MODE},
! 220: {PLV2_NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
! 221: {PLV2_NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
! 222: {PLV2_SECURITY_ASSOCIATION, 0},
! 223: {PLV2_TS_INITIATOR, 0},
! 224: {PLV2_TS_RESPONDER, 0},
! 225: {PLV2_NOTIFY, MOBIKE_SUPPORTED},
! 226: {PLV2_NOTIFY, ADDITIONAL_IP4_ADDRESS},
! 227: {PLV2_NOTIFY, ADDITIONAL_IP6_ADDRESS},
! 228: {PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES},
! 229: {PLV2_NOTIFY, 0},
! 230: {PLV2_VENDOR_ID, 0},
! 231: {PLV2_FRAGMENT, 0},
! 232: };
! 233:
! 234: /**
! 235: * Message rule for IKE_AUTH from responder.
! 236: */
! 237: static payload_rule_t ike_auth_r_rules[] = {
! 238: /* payload type min max encr suff */
! 239: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 240: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
! 241: {PLV2_EAP, 0, 1, TRUE, TRUE},
! 242: {PLV2_AUTH, 0, 1, TRUE, TRUE},
! 243: {PLV2_CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
! 244: {PLV2_ID_RESPONDER, 0, 1, TRUE, FALSE},
! 245: {PLV2_SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
! 246: {PLV2_TS_INITIATOR, 0, 1, TRUE, FALSE},
! 247: {PLV2_TS_RESPONDER, 0, 1, TRUE, FALSE},
! 248: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 249: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 250: };
! 251:
! 252: /**
! 253: * payload order for IKE_AUTH responder
! 254: */
! 255: static payload_order_t ike_auth_r_order[] = {
! 256: /* payload type notify type */
! 257: {PLV2_ID_RESPONDER, 0},
! 258: {PLV2_CERTIFICATE, 0},
! 259: {PLV2_AUTH, 0},
! 260: {PLV2_EAP, 0},
! 261: {PLV2_CONFIGURATION, 0},
! 262: {PLV2_NOTIFY, IPCOMP_SUPPORTED},
! 263: {PLV2_NOTIFY, USE_TRANSPORT_MODE},
! 264: {PLV2_NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
! 265: {PLV2_NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
! 266: {PLV2_SECURITY_ASSOCIATION, 0},
! 267: {PLV2_TS_INITIATOR, 0},
! 268: {PLV2_TS_RESPONDER, 0},
! 269: {PLV2_NOTIFY, AUTH_LIFETIME},
! 270: {PLV2_NOTIFY, MOBIKE_SUPPORTED},
! 271: {PLV2_NOTIFY, ADDITIONAL_IP4_ADDRESS},
! 272: {PLV2_NOTIFY, ADDITIONAL_IP6_ADDRESS},
! 273: {PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES},
! 274: {PLV2_NOTIFY, 0},
! 275: {PLV2_VENDOR_ID, 0},
! 276: {PLV2_FRAGMENT, 0},
! 277: };
! 278:
! 279: /**
! 280: * Message rule for INFORMATIONAL from initiator.
! 281: */
! 282: static payload_rule_t informational_i_rules[] = {
! 283: /* payload type min max encr suff */
! 284: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 285: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 286: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 287: {PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
! 288: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 289: };
! 290:
! 291: /**
! 292: * payload order for INFORMATIONAL initiator
! 293: */
! 294: static payload_order_t informational_i_order[] = {
! 295: /* payload type notify type */
! 296: {PLV2_NOTIFY, UPDATE_SA_ADDRESSES},
! 297: {PLV2_NOTIFY, NAT_DETECTION_SOURCE_IP},
! 298: {PLV2_NOTIFY, NAT_DETECTION_DESTINATION_IP},
! 299: {PLV2_NOTIFY, COOKIE2},
! 300: {PLV2_NOTIFY, 0},
! 301: {PLV2_DELETE, 0},
! 302: {PLV2_CONFIGURATION, 0},
! 303: {PLV2_FRAGMENT, 0},
! 304: };
! 305:
! 306: /**
! 307: * Message rule for INFORMATIONAL from responder.
! 308: */
! 309: static payload_rule_t informational_r_rules[] = {
! 310: /* payload type min max encr suff */
! 311: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 312: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 313: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 314: {PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
! 315: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 316: };
! 317:
! 318: /**
! 319: * payload order for INFORMATIONAL responder
! 320: */
! 321: static payload_order_t informational_r_order[] = {
! 322: /* payload type notify type */
! 323: {PLV2_NOTIFY, UPDATE_SA_ADDRESSES},
! 324: {PLV2_NOTIFY, NAT_DETECTION_SOURCE_IP},
! 325: {PLV2_NOTIFY, NAT_DETECTION_DESTINATION_IP},
! 326: {PLV2_NOTIFY, COOKIE2},
! 327: {PLV2_NOTIFY, 0},
! 328: {PLV2_DELETE, 0},
! 329: {PLV2_CONFIGURATION, 0},
! 330: {PLV2_FRAGMENT, 0},
! 331: };
! 332:
! 333: /**
! 334: * Message rule for CREATE_CHILD_SA from initiator.
! 335: */
! 336: static payload_rule_t create_child_sa_i_rules[] = {
! 337: /* payload type min max encr suff */
! 338: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 339: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 340: {PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
! 341: {PLV2_NONCE, 1, 1, TRUE, FALSE},
! 342: {PLV2_KEY_EXCHANGE, 0, 1, TRUE, FALSE},
! 343: {PLV2_TS_INITIATOR, 0, 1, TRUE, FALSE},
! 344: {PLV2_TS_RESPONDER, 0, 1, TRUE, FALSE},
! 345: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 346: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 347: };
! 348:
! 349: /**
! 350: * payload order for CREATE_CHILD_SA from initiator.
! 351: */
! 352: static payload_order_t create_child_sa_i_order[] = {
! 353: /* payload type notify type */
! 354: {PLV2_NOTIFY, REKEY_SA},
! 355: {PLV2_NOTIFY, IPCOMP_SUPPORTED},
! 356: {PLV2_NOTIFY, USE_TRANSPORT_MODE},
! 357: {PLV2_NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
! 358: {PLV2_NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
! 359: {PLV2_SECURITY_ASSOCIATION, 0},
! 360: {PLV2_NONCE, 0},
! 361: {PLV2_KEY_EXCHANGE, 0},
! 362: {PLV2_TS_INITIATOR, 0},
! 363: {PLV2_TS_RESPONDER, 0},
! 364: {PLV2_NOTIFY, 0},
! 365: {PLV2_FRAGMENT, 0},
! 366: };
! 367:
! 368: /**
! 369: * Message rule for CREATE_CHILD_SA from responder.
! 370: */
! 371: static payload_rule_t create_child_sa_r_rules[] = {
! 372: /* payload type min max encr suff */
! 373: {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
! 374: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
! 375: {PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
! 376: {PLV2_NONCE, 1, 1, TRUE, FALSE},
! 377: {PLV2_KEY_EXCHANGE, 0, 1, TRUE, FALSE},
! 378: {PLV2_TS_INITIATOR, 0, 1, TRUE, FALSE},
! 379: {PLV2_TS_RESPONDER, 0, 1, TRUE, FALSE},
! 380: {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
! 381: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 382: };
! 383:
! 384: /**
! 385: * payload order for CREATE_CHILD_SA from responder.
! 386: */
! 387: static payload_order_t create_child_sa_r_order[] = {
! 388: /* payload type notify type */
! 389: {PLV2_NOTIFY, IPCOMP_SUPPORTED},
! 390: {PLV2_NOTIFY, USE_TRANSPORT_MODE},
! 391: {PLV2_NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED},
! 392: {PLV2_NOTIFY, NON_FIRST_FRAGMENTS_ALSO},
! 393: {PLV2_SECURITY_ASSOCIATION, 0},
! 394: {PLV2_NONCE, 0},
! 395: {PLV2_KEY_EXCHANGE, 0},
! 396: {PLV2_TS_INITIATOR, 0},
! 397: {PLV2_TS_RESPONDER, 0},
! 398: {PLV2_NOTIFY, ADDITIONAL_TS_POSSIBLE},
! 399: {PLV2_NOTIFY, 0},
! 400: {PLV2_FRAGMENT, 0},
! 401: };
! 402:
! 403: #ifdef ME
! 404: /**
! 405: * Message rule for ME_CONNECT from initiator.
! 406: */
! 407: static payload_rule_t me_connect_i_rules[] = {
! 408: /* payload type min max encr suff */
! 409: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
! 410: {PLV2_ID_PEER, 1, 1, TRUE, FALSE},
! 411: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}
! 412: };
! 413:
! 414: /**
! 415: * payload order for ME_CONNECT from initiator.
! 416: */
! 417: static payload_order_t me_connect_i_order[] = {
! 418: /* payload type notify type */
! 419: {PLV2_NOTIFY, 0},
! 420: {PLV2_ID_PEER, 0},
! 421: {PLV2_VENDOR_ID, 0},
! 422: };
! 423:
! 424: /**
! 425: * Message rule for ME_CONNECT from responder.
! 426: */
! 427: static payload_rule_t me_connect_r_rules[] = {
! 428: /* payload type min max encr suff */
! 429: {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
! 430: {PLV2_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}
! 431: };
! 432:
! 433: /**
! 434: * payload order for ME_CONNECT from responder.
! 435: */
! 436: static payload_order_t me_connect_r_order[] = {
! 437: /* payload type notify type */
! 438: {PLV2_NOTIFY, 0},
! 439: {PLV2_VENDOR_ID, 0},
! 440: };
! 441: #endif /* ME */
! 442:
! 443: #ifdef USE_IKEV1
! 444: /**
! 445: * Message rule for ID_PROT from initiator.
! 446: */
! 447: static payload_rule_t id_prot_i_rules[] = {
! 448: /* payload type min max encr suff */
! 449: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 450: {PLV1_SECURITY_ASSOCIATION, 0, 1, FALSE, FALSE},
! 451: {PLV1_KEY_EXCHANGE, 0, 1, FALSE, FALSE},
! 452: {PLV1_NONCE, 0, 1, FALSE, FALSE},
! 453: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 454: {PLV1_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
! 455: {PLV1_NAT_D, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 456: {PLV1_NAT_D_DRAFT_00_03, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 457: {PLV1_ID, 0, 1, TRUE, FALSE},
! 458: {PLV1_CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
! 459: {PLV1_SIGNATURE, 0, 1, TRUE, FALSE},
! 460: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 461: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 462: };
! 463:
! 464: /**
! 465: * payload order for ID_PROT from initiator.
! 466: */
! 467: static payload_order_t id_prot_i_order[] = {
! 468: /* payload type notify type */
! 469: {PLV1_SECURITY_ASSOCIATION, 0},
! 470: {PLV1_KEY_EXCHANGE, 0},
! 471: {PLV1_NONCE, 0},
! 472: {PLV1_ID, 0},
! 473: {PLV1_CERTIFICATE, 0},
! 474: {PLV1_SIGNATURE, 0},
! 475: {PLV1_HASH, 0},
! 476: {PLV1_CERTREQ, 0},
! 477: {PLV1_NOTIFY, 0},
! 478: {PLV1_VENDOR_ID, 0},
! 479: {PLV1_NAT_D, 0},
! 480: {PLV1_NAT_D_DRAFT_00_03, 0},
! 481: {PLV1_FRAGMENT, 0},
! 482: };
! 483:
! 484: /**
! 485: * Message rule for ID_PROT from responder.
! 486: */
! 487: static payload_rule_t id_prot_r_rules[] = {
! 488: /* payload type min max encr suff */
! 489: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 490: {PLV1_SECURITY_ASSOCIATION, 0, 1, FALSE, FALSE},
! 491: {PLV1_KEY_EXCHANGE, 0, 1, FALSE, FALSE},
! 492: {PLV1_NONCE, 0, 1, FALSE, FALSE},
! 493: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 494: {PLV1_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
! 495: {PLV1_NAT_D, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 496: {PLV1_NAT_D_DRAFT_00_03, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 497: {PLV1_ID, 0, 1, TRUE, FALSE},
! 498: {PLV1_CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
! 499: {PLV1_SIGNATURE, 0, 1, TRUE, FALSE},
! 500: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 501: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 502: };
! 503:
! 504: /**
! 505: * payload order for ID_PROT from responder.
! 506: */
! 507: static payload_order_t id_prot_r_order[] = {
! 508: /* payload type notify type */
! 509: {PLV1_SECURITY_ASSOCIATION, 0},
! 510: {PLV1_KEY_EXCHANGE, 0},
! 511: {PLV1_NONCE, 0},
! 512: {PLV1_ID, 0},
! 513: {PLV1_CERTIFICATE, 0},
! 514: {PLV1_SIGNATURE, 0},
! 515: {PLV1_HASH, 0},
! 516: {PLV1_CERTREQ, 0},
! 517: {PLV1_NOTIFY, 0},
! 518: {PLV1_VENDOR_ID, 0},
! 519: {PLV1_NAT_D, 0},
! 520: {PLV1_NAT_D_DRAFT_00_03, 0},
! 521: {PLV1_FRAGMENT, 0},
! 522: };
! 523:
! 524: /**
! 525: * Message rule for AGGRESSIVE from initiator.
! 526: */
! 527: static payload_rule_t aggressive_i_rules[] = {
! 528: /* payload type min max encr suff */
! 529: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 530: {PLV1_SECURITY_ASSOCIATION, 0, 1, FALSE, FALSE},
! 531: {PLV1_KEY_EXCHANGE, 0, 1, FALSE, FALSE},
! 532: {PLV1_NONCE, 0, 1, FALSE, FALSE},
! 533: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 534: {PLV1_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
! 535: {PLV1_NAT_D, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 536: {PLV1_NAT_D_DRAFT_00_03, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 537: {PLV1_ID, 0, 1, FALSE, FALSE},
! 538: {PLV1_CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE},
! 539: {PLV1_SIGNATURE, 0, 1, TRUE, FALSE},
! 540: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 541: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 542: };
! 543:
! 544: /**
! 545: * payload order for AGGRESSIVE from initiator.
! 546: */
! 547: static payload_order_t aggressive_i_order[] = {
! 548: /* payload type notify type */
! 549: {PLV1_SECURITY_ASSOCIATION, 0},
! 550: {PLV1_KEY_EXCHANGE, 0},
! 551: {PLV1_NONCE, 0},
! 552: {PLV1_ID, 0},
! 553: {PLV1_CERTIFICATE, 0},
! 554: {PLV1_CERTREQ, 0},
! 555: {PLV1_NOTIFY, 0},
! 556: {PLV1_VENDOR_ID, 0},
! 557: {PLV1_HASH, 0},
! 558: {PLV1_NAT_D, 0},
! 559: {PLV1_NAT_D_DRAFT_00_03, 0},
! 560: {PLV1_SIGNATURE, 0},
! 561: {PLV1_FRAGMENT, 0},
! 562: };
! 563:
! 564: /**
! 565: * Message rule for AGGRESSIVE from responder.
! 566: */
! 567: static payload_rule_t aggressive_r_rules[] = {
! 568: /* payload type min max encr suff */
! 569: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 570: {PLV1_SECURITY_ASSOCIATION, 0, 1, FALSE, FALSE},
! 571: {PLV1_KEY_EXCHANGE, 0, 1, FALSE, FALSE},
! 572: {PLV1_NONCE, 0, 1, FALSE, FALSE},
! 573: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE},
! 574: {PLV1_CERTREQ, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE},
! 575: {PLV1_NAT_D, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 576: {PLV1_NAT_D_DRAFT_00_03, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE},
! 577: {PLV1_ID, 0, 1, FALSE, FALSE},
! 578: {PLV1_CERTIFICATE, 0, MAX_CERT_PAYLOADS, FALSE, FALSE},
! 579: {PLV1_SIGNATURE, 0, 1, FALSE, FALSE},
! 580: {PLV1_HASH, 0, 1, FALSE, FALSE},
! 581: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 582: };
! 583:
! 584: /**
! 585: * payload order for AGGRESSIVE from responder.
! 586: */
! 587: static payload_order_t aggressive_r_order[] = {
! 588: /* payload type notify type */
! 589: {PLV1_SECURITY_ASSOCIATION, 0},
! 590: {PLV1_KEY_EXCHANGE, 0},
! 591: {PLV1_NONCE, 0},
! 592: {PLV1_ID, 0},
! 593: {PLV1_CERTIFICATE, 0},
! 594: {PLV1_CERTREQ, 0},
! 595: {PLV1_NOTIFY, 0},
! 596: {PLV1_VENDOR_ID, 0},
! 597: {PLV1_NAT_D, 0},
! 598: {PLV1_NAT_D_DRAFT_00_03, 0},
! 599: {PLV1_SIGNATURE, 0},
! 600: {PLV1_HASH, 0},
! 601: {PLV1_FRAGMENT, 0},
! 602: };
! 603:
! 604: /**
! 605: * Message rule for INFORMATIONAL_V1 from initiator.
! 606: */
! 607: static payload_rule_t informational_i_rules_v1[] = {
! 608: /* payload type min max encr suff */
! 609: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 610: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 611: {PLV1_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
! 612: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 613: };
! 614:
! 615: /**
! 616: * payload order for INFORMATIONAL_V1 from initiator.
! 617: */
! 618: static payload_order_t informational_i_order_v1[] = {
! 619: /* payload type notify type */
! 620: {PLV1_NOTIFY, 0},
! 621: {PLV1_DELETE, 0},
! 622: {PLV1_VENDOR_ID, 0},
! 623: };
! 624:
! 625: /**
! 626: * Message rule for INFORMATIONAL_V1 from responder.
! 627: */
! 628: static payload_rule_t informational_r_rules_v1[] = {
! 629: /* payload type min max encr suff */
! 630: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE},
! 631: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 632: {PLV1_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
! 633: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 634: };
! 635:
! 636: /**
! 637: * payload order for INFORMATIONAL_V1 from responder.
! 638: */
! 639: static payload_order_t informational_r_order_v1[] = {
! 640: /* payload type notify type */
! 641: {PLV1_NOTIFY, 0},
! 642: {PLV1_DELETE, 0},
! 643: {PLV1_VENDOR_ID, 0},
! 644: };
! 645:
! 646: /**
! 647: * Message rule for QUICK_MODE from initiator.
! 648: */
! 649: static payload_rule_t quick_mode_i_rules[] = {
! 650: /* payload type min max encr suff */
! 651: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 652: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 653: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 654: {PLV1_SECURITY_ASSOCIATION, 0, 2, TRUE, FALSE},
! 655: {PLV1_NONCE, 0, 1, TRUE, FALSE},
! 656: {PLV1_KEY_EXCHANGE, 0, 1, TRUE, FALSE},
! 657: {PLV1_ID, 0, 2, TRUE, FALSE},
! 658: {PLV1_NAT_OA, 0, 2, TRUE, FALSE},
! 659: {PLV1_NAT_OA_DRAFT_00_03, 0, 2, TRUE, FALSE},
! 660: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 661: };
! 662:
! 663: /**
! 664: * payload order for QUICK_MODE from initiator.
! 665: */
! 666: static payload_order_t quick_mode_i_order[] = {
! 667: /* payload type notify type */
! 668: {PLV1_NOTIFY, 0},
! 669: {PLV1_VENDOR_ID, 0},
! 670: {PLV1_HASH, 0},
! 671: {PLV1_SECURITY_ASSOCIATION, 0},
! 672: {PLV1_NONCE, 0},
! 673: {PLV1_KEY_EXCHANGE, 0},
! 674: {PLV1_ID, 0},
! 675: {PLV1_NAT_OA, 0},
! 676: {PLV1_NAT_OA_DRAFT_00_03, 0},
! 677: {PLV1_FRAGMENT, 0},
! 678: };
! 679:
! 680: /**
! 681: * Message rule for QUICK_MODE from responder.
! 682: */
! 683: static payload_rule_t quick_mode_r_rules[] = {
! 684: /* payload type min max encr suff */
! 685: {PLV1_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
! 686: {PLV1_VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE},
! 687: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 688: {PLV1_SECURITY_ASSOCIATION, 0, 2, TRUE, FALSE},
! 689: {PLV1_NONCE, 0, 1, TRUE, FALSE},
! 690: {PLV1_KEY_EXCHANGE, 0, 1, TRUE, FALSE},
! 691: {PLV1_ID, 0, 2, TRUE, FALSE},
! 692: {PLV1_NAT_OA, 0, 2, TRUE, FALSE},
! 693: {PLV1_NAT_OA_DRAFT_00_03, 0, 2, TRUE, FALSE},
! 694: {PLV1_FRAGMENT, 0, 1, FALSE, TRUE},
! 695: };
! 696:
! 697: /**
! 698: * payload order for QUICK_MODE from responder.
! 699: */
! 700: static payload_order_t quick_mode_r_order[] = {
! 701: /* payload type notify type */
! 702: {PLV1_NOTIFY, 0},
! 703: {PLV1_VENDOR_ID, 0},
! 704: {PLV1_HASH, 0},
! 705: {PLV1_SECURITY_ASSOCIATION, 0},
! 706: {PLV1_NONCE, 0},
! 707: {PLV1_KEY_EXCHANGE, 0},
! 708: {PLV1_ID, 0},
! 709: {PLV1_NAT_OA, 0},
! 710: {PLV1_NAT_OA_DRAFT_00_03, 0},
! 711: {PLV1_FRAGMENT, 0},
! 712: };
! 713:
! 714: /**
! 715: * Message rule for TRANSACTION.
! 716: */
! 717: static payload_rule_t transaction_payload_rules_v1[] = {
! 718: /* payload type min max encr suff */
! 719: {PLV1_HASH, 0, 1, TRUE, FALSE},
! 720: {PLV1_CONFIGURATION, 1, 1, FALSE, FALSE},
! 721: };
! 722:
! 723: /**
! 724: * Payload order for TRANSACTION.
! 725: */
! 726: static payload_order_t transaction_payload_order_v1[] = {
! 727: /* payload type notify type */
! 728: {PLV1_HASH, 0},
! 729: {PLV1_CONFIGURATION, 0},
! 730: };
! 731:
! 732: #endif /* USE_IKEV1 */
! 733:
! 734: /**
! 735: * Message rules, defines allowed payloads.
! 736: */
! 737: static message_rule_t message_rules[] = {
! 738: {IKE_SA_INIT, TRUE, FALSE,
! 739: countof(ike_sa_init_i_rules), ike_sa_init_i_rules,
! 740: countof(ike_sa_init_i_order), ike_sa_init_i_order,
! 741: },
! 742: {IKE_SA_INIT, FALSE, FALSE,
! 743: countof(ike_sa_init_r_rules), ike_sa_init_r_rules,
! 744: countof(ike_sa_init_r_order), ike_sa_init_r_order,
! 745: },
! 746: {IKE_AUTH, TRUE, TRUE,
! 747: countof(ike_auth_i_rules), ike_auth_i_rules,
! 748: countof(ike_auth_i_order), ike_auth_i_order,
! 749: },
! 750: {IKE_AUTH, FALSE, TRUE,
! 751: countof(ike_auth_r_rules), ike_auth_r_rules,
! 752: countof(ike_auth_r_order), ike_auth_r_order,
! 753: },
! 754: {INFORMATIONAL, TRUE, TRUE,
! 755: countof(informational_i_rules), informational_i_rules,
! 756: countof(informational_i_order), informational_i_order,
! 757: },
! 758: {INFORMATIONAL, FALSE, TRUE,
! 759: countof(informational_r_rules), informational_r_rules,
! 760: countof(informational_r_order), informational_r_order,
! 761: },
! 762: {CREATE_CHILD_SA, TRUE, TRUE,
! 763: countof(create_child_sa_i_rules), create_child_sa_i_rules,
! 764: countof(create_child_sa_i_order), create_child_sa_i_order,
! 765: },
! 766: {CREATE_CHILD_SA, FALSE, TRUE,
! 767: countof(create_child_sa_r_rules), create_child_sa_r_rules,
! 768: countof(create_child_sa_r_order), create_child_sa_r_order,
! 769: },
! 770: #ifdef ME
! 771: {ME_CONNECT, TRUE, TRUE,
! 772: countof(me_connect_i_rules), me_connect_i_rules,
! 773: countof(me_connect_i_order), me_connect_i_order,
! 774: },
! 775: {ME_CONNECT, FALSE, TRUE,
! 776: countof(me_connect_r_rules), me_connect_r_rules,
! 777: countof(me_connect_r_order), me_connect_r_order,
! 778: },
! 779: #endif /* ME */
! 780: #ifdef USE_IKEV1
! 781: {ID_PROT, TRUE, FALSE,
! 782: countof(id_prot_i_rules), id_prot_i_rules,
! 783: countof(id_prot_i_order), id_prot_i_order,
! 784: },
! 785: {ID_PROT, FALSE, FALSE,
! 786: countof(id_prot_r_rules), id_prot_r_rules,
! 787: countof(id_prot_r_order), id_prot_r_order,
! 788: },
! 789: {AGGRESSIVE, TRUE, FALSE,
! 790: countof(aggressive_i_rules), aggressive_i_rules,
! 791: countof(aggressive_i_order), aggressive_i_order,
! 792: },
! 793: {AGGRESSIVE, FALSE, FALSE,
! 794: countof(aggressive_r_rules), aggressive_r_rules,
! 795: countof(aggressive_r_order), aggressive_r_order,
! 796: },
! 797: {INFORMATIONAL_V1, TRUE, TRUE,
! 798: countof(informational_i_rules_v1), informational_i_rules_v1,
! 799: countof(informational_i_order_v1), informational_i_order_v1,
! 800: },
! 801: {INFORMATIONAL_V1, FALSE, TRUE,
! 802: countof(informational_r_rules_v1), informational_r_rules_v1,
! 803: countof(informational_r_order_v1), informational_r_order_v1,
! 804: },
! 805: {QUICK_MODE, TRUE, TRUE,
! 806: countof(quick_mode_i_rules), quick_mode_i_rules,
! 807: countof(quick_mode_i_order), quick_mode_i_order,
! 808: },
! 809: {QUICK_MODE, FALSE, TRUE,
! 810: countof(quick_mode_r_rules), quick_mode_r_rules,
! 811: countof(quick_mode_r_order), quick_mode_r_order,
! 812: },
! 813: {TRANSACTION, TRUE, TRUE,
! 814: countof(transaction_payload_rules_v1), transaction_payload_rules_v1,
! 815: countof(transaction_payload_order_v1), transaction_payload_order_v1,
! 816: },
! 817: {TRANSACTION, FALSE, TRUE,
! 818: countof(transaction_payload_rules_v1), transaction_payload_rules_v1,
! 819: countof(transaction_payload_order_v1), transaction_payload_order_v1,
! 820: },
! 821: /* TODO-IKEv1: define rules for other exchanges */
! 822: #endif /* USE_IKEV1 */
! 823: };
! 824:
! 825: /**
! 826: * Data for fragment reassembly.
! 827: */
! 828: typedef struct {
! 829:
! 830: /**
! 831: * For IKEv1 the number of the last fragment (in case we receive them out
! 832: * of order), since the first one starts with 1 this defines the number of
! 833: * fragments we expect.
! 834: * For IKEv2 we store the total number of fragment we received last.
! 835: */
! 836: uint16_t last;
! 837:
! 838: /**
! 839: * Length of all currently received fragments.
! 840: */
! 841: size_t len;
! 842:
! 843: /**
! 844: * Maximum length of a fragmented packet.
! 845: */
! 846: size_t max_packet;
! 847:
! 848: } fragment_data_t;
! 849:
! 850: typedef struct private_message_t private_message_t;
! 851:
! 852: /**
! 853: * Private data of an message_t object.
! 854: */
! 855: struct private_message_t {
! 856:
! 857: /**
! 858: * Public part of a message_t object.
! 859: */
! 860: message_t public;
! 861:
! 862: /**
! 863: * Minor version of message.
! 864: */
! 865: uint8_t major_version;
! 866:
! 867: /**
! 868: * Major version of message.
! 869: */
! 870: uint8_t minor_version;
! 871:
! 872: /**
! 873: * First Payload in message.
! 874: */
! 875: payload_type_t first_payload;
! 876:
! 877: /**
! 878: * Assigned exchange type.
! 879: */
! 880: exchange_type_t exchange_type;
! 881:
! 882: /**
! 883: * TRUE if message is a request, FALSE if a reply.
! 884: */
! 885: bool is_request;
! 886:
! 887: /**
! 888: * The message is encrypted (IKEv1)
! 889: */
! 890: bool is_encrypted;
! 891:
! 892: /**
! 893: * Higher version supported?
! 894: */
! 895: bool version_flag;
! 896:
! 897: /**
! 898: * Reserved bits in IKE header
! 899: */
! 900: bool reserved[2];
! 901:
! 902: /**
! 903: * Sorting of message disabled?
! 904: */
! 905: bool sort_disabled;
! 906:
! 907: /**
! 908: * Message ID of this message.
! 909: */
! 910: uint32_t message_id;
! 911:
! 912: /**
! 913: * ID of assigned IKE_SA.
! 914: */
! 915: ike_sa_id_t *ike_sa_id;
! 916:
! 917: /**
! 918: * Assigned UDP packet, stores incoming packet or last generated one.
! 919: */
! 920: packet_t *packet;
! 921:
! 922: /**
! 923: * Array of generated fragments (if any), as packet_t*.
! 924: * If defragmenting (i.e. frag != NULL) this contains fragment_t*
! 925: */
! 926: array_t *fragments;
! 927:
! 928: /**
! 929: * Linked List where payload data are stored in.
! 930: */
! 931: linked_list_t *payloads;
! 932:
! 933: /**
! 934: * Assigned parser to parse Header and Body of this message.
! 935: */
! 936: parser_t *parser;
! 937:
! 938: /**
! 939: * The message rule for this message instance
! 940: */
! 941: message_rule_t *rule;
! 942:
! 943: /**
! 944: * Data used to reassemble a fragmented message
! 945: */
! 946: fragment_data_t *frag;
! 947: };
! 948:
! 949: /**
! 950: * Maximum number of fragments we will handle
! 951: */
! 952: #define MAX_FRAGMENTS 255
! 953:
! 954: /**
! 955: * A single fragment within a fragmented message
! 956: */
! 957: typedef struct {
! 958:
! 959: /** fragment number */
! 960: uint8_t num;
! 961:
! 962: /** fragment data */
! 963: chunk_t data;
! 964:
! 965: } fragment_t;
! 966:
! 967: static void fragment_destroy(fragment_t *this)
! 968: {
! 969: chunk_free(&this->data);
! 970: free(this);
! 971: }
! 972:
! 973: static void reset_defrag(private_message_t *this)
! 974: {
! 975: array_destroy_function(this->fragments, (void*)fragment_destroy, NULL);
! 976: this->fragments = NULL;
! 977: this->frag->last = 0;
! 978: this->frag->len = 0;
! 979: }
! 980:
! 981: /**
! 982: * Get the message rule that applies to this message
! 983: */
! 984: static message_rule_t* get_message_rule(private_message_t *this)
! 985: {
! 986: int i;
! 987:
! 988: for (i = 0; i < countof(message_rules); i++)
! 989: {
! 990: if ((this->exchange_type == message_rules[i].exchange_type) &&
! 991: (this->is_request == message_rules[i].is_request))
! 992: {
! 993: return &message_rules[i];
! 994: }
! 995: }
! 996: return NULL;
! 997: }
! 998:
! 999: /**
! 1000: * Look up a payload rule
! 1001: */
! 1002: static payload_rule_t* get_payload_rule(private_message_t *this,
! 1003: payload_type_t type)
! 1004: {
! 1005: int i;
! 1006:
! 1007: for (i = 0; i < this->rule->rule_count;i++)
! 1008: {
! 1009: if (this->rule->rules[i].type == type)
! 1010: {
! 1011: return &this->rule->rules[i];
! 1012: }
! 1013: }
! 1014: return NULL;
! 1015: }
! 1016:
! 1017: METHOD(message_t, set_ike_sa_id, void,
! 1018: private_message_t *this,ike_sa_id_t *ike_sa_id)
! 1019: {
! 1020: DESTROY_IF(this->ike_sa_id);
! 1021: this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
! 1022: }
! 1023:
! 1024: METHOD(message_t, get_ike_sa_id, ike_sa_id_t*,
! 1025: private_message_t *this)
! 1026: {
! 1027: return this->ike_sa_id;
! 1028: }
! 1029:
! 1030: METHOD(message_t, set_message_id, void,
! 1031: private_message_t *this,uint32_t message_id)
! 1032: {
! 1033: this->message_id = message_id;
! 1034: }
! 1035:
! 1036: METHOD(message_t, get_message_id, uint32_t,
! 1037: private_message_t *this)
! 1038: {
! 1039: return this->message_id;
! 1040: }
! 1041:
! 1042: METHOD(message_t, get_initiator_spi, uint64_t,
! 1043: private_message_t *this)
! 1044: {
! 1045: return (this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
! 1046: }
! 1047:
! 1048: METHOD(message_t, get_responder_spi, uint64_t,
! 1049: private_message_t *this)
! 1050: {
! 1051: return (this->ike_sa_id->get_responder_spi(this->ike_sa_id));
! 1052: }
! 1053:
! 1054: METHOD(message_t, set_major_version, void,
! 1055: private_message_t *this, uint8_t major_version)
! 1056: {
! 1057: this->major_version = major_version;
! 1058: }
! 1059:
! 1060: METHOD(message_t, get_major_version, uint8_t,
! 1061: private_message_t *this)
! 1062: {
! 1063: return this->major_version;
! 1064: }
! 1065:
! 1066: METHOD(message_t, set_minor_version, void,
! 1067: private_message_t *this,uint8_t minor_version)
! 1068: {
! 1069: this->minor_version = minor_version;
! 1070: }
! 1071:
! 1072: METHOD(message_t, get_minor_version, uint8_t,
! 1073: private_message_t *this)
! 1074: {
! 1075: return this->minor_version;
! 1076: }
! 1077:
! 1078: METHOD(message_t, set_exchange_type, void,
! 1079: private_message_t *this, exchange_type_t exchange_type)
! 1080: {
! 1081: this->exchange_type = exchange_type;
! 1082: }
! 1083:
! 1084: METHOD(message_t, get_exchange_type, exchange_type_t,
! 1085: private_message_t *this)
! 1086: {
! 1087: return this->exchange_type;
! 1088: }
! 1089:
! 1090: METHOD(message_t, get_first_payload_type, payload_type_t,
! 1091: private_message_t *this)
! 1092: {
! 1093: return this->first_payload;
! 1094: }
! 1095:
! 1096: METHOD(message_t, set_request, void,
! 1097: private_message_t *this, bool request)
! 1098: {
! 1099: this->is_request = request;
! 1100: }
! 1101:
! 1102: METHOD(message_t, get_request, bool,
! 1103: private_message_t *this)
! 1104: {
! 1105: return this->is_request;
! 1106: }
! 1107:
! 1108: METHOD(message_t, set_version_flag, void,
! 1109: private_message_t *this)
! 1110: {
! 1111: this->version_flag = TRUE;
! 1112: }
! 1113:
! 1114: METHOD(message_t, get_reserved_header_bit, bool,
! 1115: private_message_t *this, u_int nr)
! 1116: {
! 1117: if (nr < countof(this->reserved))
! 1118: {
! 1119: return this->reserved[nr];
! 1120: }
! 1121: return FALSE;
! 1122: }
! 1123:
! 1124: METHOD(message_t, set_reserved_header_bit, void,
! 1125: private_message_t *this, u_int nr)
! 1126: {
! 1127: if (nr < countof(this->reserved))
! 1128: {
! 1129: this->reserved[nr] = TRUE;
! 1130: }
! 1131: }
! 1132:
! 1133: METHOD(message_t, is_encoded, bool,
! 1134: private_message_t *this)
! 1135: {
! 1136: return this->packet->get_data(this->packet).ptr != NULL;
! 1137: }
! 1138:
! 1139: METHOD(message_t, is_fragmented, bool,
! 1140: private_message_t *this)
! 1141: {
! 1142: return array_count(this->fragments) > 0;
! 1143: }
! 1144:
! 1145: METHOD(message_t, add_payload, void,
! 1146: private_message_t *this, payload_t *payload)
! 1147: {
! 1148: payload_t *last_payload;
! 1149:
! 1150: if (this->payloads->get_count(this->payloads) > 0)
! 1151: {
! 1152: this->payloads->get_last(this->payloads, (void **)&last_payload);
! 1153: last_payload->set_next_type(last_payload, payload->get_type(payload));
! 1154: }
! 1155: else
! 1156: {
! 1157: this->first_payload = payload->get_type(payload);
! 1158: }
! 1159: payload->set_next_type(payload, PL_NONE);
! 1160: this->payloads->insert_last(this->payloads, payload);
! 1161:
! 1162: DBG2(DBG_ENC ,"added payload of type %N to message",
! 1163: payload_type_names, payload->get_type(payload));
! 1164: }
! 1165:
! 1166: METHOD(message_t, add_notify, void,
! 1167: private_message_t *this, bool flush, notify_type_t type, chunk_t data)
! 1168: {
! 1169: notify_payload_t *notify;
! 1170: payload_t *payload;
! 1171:
! 1172: if (flush)
! 1173: {
! 1174: while (this->payloads->remove_last(this->payloads,
! 1175: (void**)&payload) == SUCCESS)
! 1176: {
! 1177: payload->destroy(payload);
! 1178: }
! 1179: }
! 1180: if (this->major_version == IKEV2_MAJOR_VERSION)
! 1181: {
! 1182: notify = notify_payload_create(PLV2_NOTIFY);
! 1183: }
! 1184: else
! 1185: {
! 1186: notify = notify_payload_create(PLV1_NOTIFY);
! 1187: }
! 1188: notify->set_notify_type(notify, type);
! 1189: notify->set_notification_data(notify, data);
! 1190: add_payload(this, (payload_t*)notify);
! 1191: }
! 1192:
! 1193: METHOD(message_t, set_source, void,
! 1194: private_message_t *this, host_t *host)
! 1195: {
! 1196: this->packet->set_source(this->packet, host);
! 1197: }
! 1198:
! 1199: METHOD(message_t, set_destination, void,
! 1200: private_message_t *this, host_t *host)
! 1201: {
! 1202: this->packet->set_destination(this->packet, host);
! 1203: }
! 1204:
! 1205: METHOD(message_t, get_source, host_t*,
! 1206: private_message_t *this)
! 1207: {
! 1208: return this->packet->get_source(this->packet);
! 1209: }
! 1210:
! 1211: METHOD(message_t, get_destination, host_t*,
! 1212: private_message_t *this)
! 1213: {
! 1214: return this->packet->get_destination(this->packet);
! 1215: }
! 1216:
! 1217: METHOD(message_t, create_payload_enumerator, enumerator_t*,
! 1218: private_message_t *this)
! 1219: {
! 1220: return this->payloads->create_enumerator(this->payloads);
! 1221: }
! 1222:
! 1223: METHOD(message_t, remove_payload_at, void,
! 1224: private_message_t *this, enumerator_t *enumerator)
! 1225: {
! 1226: this->payloads->remove_at(this->payloads, enumerator);
! 1227: }
! 1228:
! 1229: METHOD(message_t, get_payload, payload_t*,
! 1230: private_message_t *this, payload_type_t type)
! 1231: {
! 1232: payload_t *current, *found = NULL;
! 1233: enumerator_t *enumerator;
! 1234:
! 1235: enumerator = create_payload_enumerator(this);
! 1236: while (enumerator->enumerate(enumerator, ¤t))
! 1237: {
! 1238: if (current->get_type(current) == type)
! 1239: {
! 1240: found = current;
! 1241: break;
! 1242: }
! 1243: }
! 1244: enumerator->destroy(enumerator);
! 1245: return found;
! 1246: }
! 1247:
! 1248: METHOD(message_t, get_notify, notify_payload_t*,
! 1249: private_message_t *this, notify_type_t type)
! 1250: {
! 1251: enumerator_t *enumerator;
! 1252: notify_payload_t *notify = NULL;
! 1253: payload_t *payload;
! 1254:
! 1255: enumerator = create_payload_enumerator(this);
! 1256: while (enumerator->enumerate(enumerator, &payload))
! 1257: {
! 1258: if (payload->get_type(payload) == PLV2_NOTIFY ||
! 1259: payload->get_type(payload) == PLV1_NOTIFY)
! 1260: {
! 1261: notify = (notify_payload_t*)payload;
! 1262: if (notify->get_notify_type(notify) == type)
! 1263: {
! 1264: break;
! 1265: }
! 1266: notify = NULL;
! 1267: }
! 1268: }
! 1269: enumerator->destroy(enumerator);
! 1270: return notify;
! 1271: }
! 1272:
! 1273: /**
! 1274: * get a string representation of the message
! 1275: */
! 1276: static char* get_string(private_message_t *this, char *buf, int len)
! 1277: {
! 1278: enumerator_t *enumerator;
! 1279: payload_t *payload;
! 1280: int written;
! 1281: char *pos = buf;
! 1282:
! 1283: memset(buf, 0, len);
! 1284: len--;
! 1285:
! 1286: written = snprintf(pos, len, "%N %s %u [",
! 1287: exchange_type_names, this->exchange_type,
! 1288: this->is_request ? "request" : "response",
! 1289: this->message_id);
! 1290: if (written >= len || written < 0)
! 1291: {
! 1292: return "";
! 1293: }
! 1294: pos += written;
! 1295: len -= written;
! 1296:
! 1297: enumerator = create_payload_enumerator(this);
! 1298: while (enumerator->enumerate(enumerator, &payload))
! 1299: {
! 1300: written = snprintf(pos, len, " %N", payload_type_short_names,
! 1301: payload->get_type(payload));
! 1302: if (written >= len || written < 0)
! 1303: {
! 1304: return buf;
! 1305: }
! 1306: pos += written;
! 1307: len -= written;
! 1308: if (payload->get_type(payload) == PLV2_NOTIFY ||
! 1309: payload->get_type(payload) == PLV1_NOTIFY)
! 1310: {
! 1311: notify_payload_t *notify;
! 1312: notify_type_t type;
! 1313: chunk_t data;
! 1314:
! 1315: notify = (notify_payload_t*)payload;
! 1316: type = notify->get_notify_type(notify);
! 1317: data = notify->get_notification_data(notify);
! 1318: if (type == MS_NOTIFY_STATUS && data.len == 4)
! 1319: {
! 1320: written = snprintf(pos, len, "(%N(%d))", notify_type_short_names,
! 1321: type, untoh32(data.ptr));
! 1322: }
! 1323: else
! 1324: {
! 1325: written = snprintf(pos, len, "(%N)", notify_type_short_names,
! 1326: type);
! 1327: }
! 1328: if (written >= len || written < 0)
! 1329: {
! 1330: return buf;
! 1331: }
! 1332: pos += written;
! 1333: len -= written;
! 1334: }
! 1335: if (payload->get_type(payload) == PLV2_EAP)
! 1336: {
! 1337: eap_payload_t *eap = (eap_payload_t*)payload;
! 1338: uint32_t vendor;
! 1339: eap_type_t type;
! 1340: char method[64] = "";
! 1341:
! 1342: type = eap->get_type(eap, &vendor);
! 1343: if (type)
! 1344: {
! 1345: if (vendor)
! 1346: {
! 1347: snprintf(method, sizeof(method), "/%d-%d", type, vendor);
! 1348: }
! 1349: else
! 1350: {
! 1351: snprintf(method, sizeof(method), "/%N",
! 1352: eap_type_short_names, type);
! 1353: }
! 1354: }
! 1355: written = snprintf(pos, len, "/%N%s", eap_code_short_names,
! 1356: eap->get_code(eap), method);
! 1357: if (written >= len || written < 0)
! 1358: {
! 1359: return buf;
! 1360: }
! 1361: pos += written;
! 1362: len -= written;
! 1363: }
! 1364: if (payload->get_type(payload) == PLV2_CONFIGURATION ||
! 1365: payload->get_type(payload) == PLV1_CONFIGURATION)
! 1366: {
! 1367: cp_payload_t *cp = (cp_payload_t*)payload;
! 1368: enumerator_t *attributes;
! 1369: configuration_attribute_t *attribute;
! 1370: bool first = TRUE;
! 1371: char *pfx;
! 1372:
! 1373: switch (cp->get_type(cp))
! 1374: {
! 1375: case CFG_REQUEST:
! 1376: pfx = "RQ(";
! 1377: break;
! 1378: case CFG_REPLY:
! 1379: pfx = "RP(";
! 1380: break;
! 1381: case CFG_SET:
! 1382: pfx = "S(";
! 1383: break;
! 1384: case CFG_ACK:
! 1385: pfx = "A(";
! 1386: break;
! 1387: default:
! 1388: pfx = "(";
! 1389: break;
! 1390: }
! 1391:
! 1392: attributes = cp->create_attribute_enumerator(cp);
! 1393: while (attributes->enumerate(attributes, &attribute))
! 1394: {
! 1395: written = snprintf(pos, len, "%s%N", first ? pfx : " ",
! 1396: configuration_attribute_type_short_names,
! 1397: attribute->get_type(attribute));
! 1398: if (written >= len || written < 0)
! 1399: {
! 1400: return buf;
! 1401: }
! 1402: pos += written;
! 1403: len -= written;
! 1404: first = FALSE;
! 1405: }
! 1406: attributes->destroy(attributes);
! 1407: if (!first)
! 1408: {
! 1409: written = snprintf(pos, len, ")");
! 1410: if (written >= len || written < 0)
! 1411: {
! 1412: return buf;
! 1413: }
! 1414: pos += written;
! 1415: len -= written;
! 1416: }
! 1417: }
! 1418: if (payload->get_type(payload) == PLV1_FRAGMENT)
! 1419: {
! 1420: fragment_payload_t *frag;
! 1421:
! 1422: frag = (fragment_payload_t*)payload;
! 1423: if (frag->is_last(frag))
! 1424: {
! 1425: written = snprintf(pos, len, "(%u/%u)",
! 1426: frag->get_number(frag), frag->get_number(frag));
! 1427: }
! 1428: else
! 1429: {
! 1430: written = snprintf(pos, len, "(%u)", frag->get_number(frag));
! 1431: }
! 1432: if (written >= len || written < 0)
! 1433: {
! 1434: return buf;
! 1435: }
! 1436: pos += written;
! 1437: len -= written;
! 1438: }
! 1439: if (payload->get_type(payload) == PLV2_FRAGMENT)
! 1440: {
! 1441: encrypted_fragment_payload_t *frag;
! 1442:
! 1443: frag = (encrypted_fragment_payload_t*)payload;
! 1444: written = snprintf(pos, len, "(%u/%u)",
! 1445: frag->get_fragment_number(frag),
! 1446: frag->get_total_fragments(frag));
! 1447: if (written >= len || written < 0)
! 1448: {
! 1449: return buf;
! 1450: }
! 1451: pos += written;
! 1452: len -= written;
! 1453: }
! 1454: if (payload->get_type(payload) == PL_UNKNOWN)
! 1455: {
! 1456: unknown_payload_t *unknown;
! 1457:
! 1458: unknown = (unknown_payload_t*)payload;
! 1459: written = snprintf(pos, len, "(%d)", unknown->get_type(unknown));
! 1460: if (written >= len || written < 0)
! 1461: {
! 1462: return buf;
! 1463: }
! 1464: pos += written;
! 1465: len -= written;
! 1466: }
! 1467: }
! 1468: enumerator->destroy(enumerator);
! 1469:
! 1470: /* remove last space */
! 1471: snprintf(pos, len, " ]");
! 1472: return buf;
! 1473: }
! 1474:
! 1475: METHOD(message_t, disable_sort, void,
! 1476: private_message_t *this)
! 1477: {
! 1478: this->sort_disabled = TRUE;
! 1479: }
! 1480:
! 1481: /**
! 1482: * reorder payloads depending on reordering rules
! 1483: */
! 1484: static void order_payloads(private_message_t *this)
! 1485: {
! 1486: linked_list_t *list;
! 1487: payload_t *payload;
! 1488: int i;
! 1489:
! 1490: DBG2(DBG_ENC, "order payloads in message");
! 1491:
! 1492: /* move to temp list */
! 1493: list = linked_list_create();
! 1494: while (this->payloads->remove_last(this->payloads,
! 1495: (void**)&payload) == SUCCESS)
! 1496: {
! 1497: list->insert_first(list, payload);
! 1498: }
! 1499: /* for each rule, ... */
! 1500: for (i = 0; i < this->rule->order_count; i++)
! 1501: {
! 1502: enumerator_t *enumerator;
! 1503: notify_payload_t *notify;
! 1504: payload_order_t order;
! 1505:
! 1506: order = this->rule->order[i];
! 1507:
! 1508: /* ... find all payload ... */
! 1509: enumerator = list->create_enumerator(list);
! 1510: while (enumerator->enumerate(enumerator, &payload))
! 1511: {
! 1512: /* ... with that type ... */
! 1513: if (payload->get_type(payload) == order.type)
! 1514: {
! 1515: notify = (notify_payload_t*)payload;
! 1516:
! 1517: /**... and check notify for type. */
! 1518: if (order.type != PLV2_NOTIFY || order.notify == 0 ||
! 1519: order.notify == notify->get_notify_type(notify))
! 1520: {
! 1521: list->remove_at(list, enumerator);
! 1522: add_payload(this, payload);
! 1523: }
! 1524: }
! 1525: }
! 1526: enumerator->destroy(enumerator);
! 1527: }
! 1528: /* append all payloads without a rule to the end */
! 1529: while (list->remove_last(list, (void**)&payload) == SUCCESS)
! 1530: {
! 1531: /* do not complain about payloads in private use space */
! 1532: if (payload->get_type(payload) < 128)
! 1533: {
! 1534: DBG1(DBG_ENC, "payload %N has no ordering rule in %N %s",
! 1535: payload_type_names, payload->get_type(payload),
! 1536: exchange_type_names, this->rule->exchange_type,
! 1537: this->rule->is_request ? "request" : "response");
! 1538: }
! 1539: add_payload(this, payload);
! 1540: }
! 1541: list->destroy(list);
! 1542: }
! 1543:
! 1544: /**
! 1545: * Wrap payloads in an encrypted payload
! 1546: */
! 1547: static encrypted_payload_t* wrap_payloads(private_message_t *this)
! 1548: {
! 1549: encrypted_payload_t *encrypted = NULL;
! 1550: linked_list_t *payloads;
! 1551: payload_t *current;
! 1552:
! 1553: /* move all payloads to a temporary list */
! 1554: payloads = linked_list_create();
! 1555: while (this->payloads->remove_first(this->payloads,
! 1556: (void**)¤t) == SUCCESS)
! 1557: {
! 1558: if (current->get_type(current) == PLV2_FRAGMENT)
! 1559: { /* treat encrypted fragment payload as encrypted payload */
! 1560: encrypted = (encrypted_payload_t*)current;
! 1561: }
! 1562: else
! 1563: {
! 1564: payloads->insert_last(payloads, current);
! 1565: }
! 1566: }
! 1567: if (encrypted)
! 1568: { /* simply adopt all the unencrypted payloads */
! 1569: this->payloads->destroy(this->payloads);
! 1570: this->payloads = payloads;
! 1571: return encrypted;
! 1572: }
! 1573:
! 1574: if (this->is_encrypted)
! 1575: {
! 1576: encrypted = encrypted_payload_create(PLV1_ENCRYPTED);
! 1577: }
! 1578: else
! 1579: {
! 1580: encrypted = encrypted_payload_create(PLV2_ENCRYPTED);
! 1581: }
! 1582: while (payloads->remove_first(payloads, (void**)¤t) == SUCCESS)
! 1583: {
! 1584: payload_rule_t *rule;
! 1585: payload_type_t type;
! 1586: bool encrypt = TRUE;
! 1587:
! 1588: type = current->get_type(current);
! 1589: rule = get_payload_rule(this, type);
! 1590: if (rule)
! 1591: {
! 1592: encrypt = rule->encrypted;
! 1593: }
! 1594: if (encrypt || this->is_encrypted)
! 1595: { /* encryption is forced for IKEv1 */
! 1596: DBG2(DBG_ENC, "insert payload %N into encrypted payload",
! 1597: payload_type_names, type);
! 1598: encrypted->add_payload(encrypted, current);
! 1599: }
! 1600: else
! 1601: {
! 1602: DBG2(DBG_ENC, "insert payload %N unencrypted",
! 1603: payload_type_names, type);
! 1604: add_payload(this, current);
! 1605: }
! 1606: }
! 1607: payloads->destroy(payloads);
! 1608:
! 1609: return encrypted;
! 1610: }
! 1611:
! 1612: /**
! 1613: * Creates the IKE header for this message
! 1614: */
! 1615: static ike_header_t *create_header(private_message_t *this)
! 1616: {
! 1617: ike_header_t *ike_header;
! 1618: bool *reserved;
! 1619: int i;
! 1620:
! 1621: ike_header = ike_header_create_version(this->major_version,
! 1622: this->minor_version);
! 1623: ike_header->set_exchange_type(ike_header, this->exchange_type);
! 1624: ike_header->set_message_id(ike_header, this->message_id);
! 1625: if (this->major_version == IKEV2_MAJOR_VERSION)
! 1626: {
! 1627: ike_header->set_response_flag(ike_header, !this->is_request);
! 1628: ike_header->set_version_flag(ike_header, this->version_flag);
! 1629: ike_header->set_initiator_flag(ike_header,
! 1630: this->ike_sa_id->is_initiator(this->ike_sa_id));
! 1631: }
! 1632: else
! 1633: {
! 1634: ike_header->set_encryption_flag(ike_header, this->is_encrypted);
! 1635: }
! 1636: ike_header->set_initiator_spi(ike_header,
! 1637: this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
! 1638: ike_header->set_responder_spi(ike_header,
! 1639: this->ike_sa_id->get_responder_spi(this->ike_sa_id));
! 1640:
! 1641: for (i = 0; i < countof(this->reserved); i++)
! 1642: {
! 1643: reserved = payload_get_field(&ike_header->payload_interface,
! 1644: RESERVED_BIT, i);
! 1645: if (reserved)
! 1646: {
! 1647: *reserved = this->reserved[i];
! 1648: }
! 1649: }
! 1650: return ike_header;
! 1651: }
! 1652:
! 1653: /**
! 1654: * Generates the message, if needed, wraps the payloads in an encrypted payload.
! 1655: *
! 1656: * The generator and the possible encrypted payload are returned. The latter
! 1657: * is not yet encrypted (but the transform is set). It is also not added to
! 1658: * the payload list (so unless there are unencrypted payloads that list will
! 1659: * be empty afterwards).
! 1660: */
! 1661: static status_t generate_message(private_message_t *this, keymat_t *keymat,
! 1662: generator_t **out_generator, encrypted_payload_t **encrypted)
! 1663: {
! 1664: keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
! 1665: generator_t *generator;
! 1666: payload_type_t next_type;
! 1667: enumerator_t *enumerator;
! 1668: aead_t *aead = NULL;
! 1669: chunk_t hash = chunk_empty;
! 1670: char str[BUF_LEN];
! 1671: ike_header_t *ike_header;
! 1672: payload_t *payload, *next;
! 1673: bool encrypting = FALSE;
! 1674:
! 1675: if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
! 1676: {
! 1677: DBG1(DBG_ENC, "exchange type is not defined");
! 1678: return INVALID_STATE;
! 1679: }
! 1680:
! 1681: if (this->packet->get_source(this->packet) == NULL ||
! 1682: this->packet->get_destination(this->packet) == NULL)
! 1683: {
! 1684: DBG1(DBG_ENC, "source/destination not defined");
! 1685: return INVALID_STATE;
! 1686: }
! 1687:
! 1688: this->rule = get_message_rule(this);
! 1689: if (!this->rule)
! 1690: {
! 1691: DBG1(DBG_ENC, "no message rules specified for this message type");
! 1692: return NOT_SUPPORTED;
! 1693: }
! 1694:
! 1695: if (!this->sort_disabled)
! 1696: {
! 1697: order_payloads(this);
! 1698: }
! 1699:
! 1700: if (keymat && keymat->get_version(keymat) == IKEV1)
! 1701: {
! 1702: /* get a hash for this message, if any is required */
! 1703: if (keymat_v1->get_hash_phase2(keymat_v1, &this->public, &hash))
! 1704: { /* insert a HASH payload as first payload */
! 1705: hash_payload_t *hash_payload;
! 1706:
! 1707: hash_payload = hash_payload_create(PLV1_HASH);
! 1708: hash_payload->set_hash(hash_payload, hash);
! 1709: this->payloads->insert_first(this->payloads, hash_payload);
! 1710: if (this->exchange_type == INFORMATIONAL_V1)
! 1711: {
! 1712: this->is_encrypted = encrypting = TRUE;
! 1713: }
! 1714: chunk_free(&hash);
! 1715: }
! 1716: }
! 1717:
! 1718: if (this->major_version == IKEV2_MAJOR_VERSION)
! 1719: {
! 1720: encrypting = this->rule->encrypted;
! 1721: }
! 1722: else if (!encrypting)
! 1723: {
! 1724: /* If at least one payload requires encryption, encrypt the message.
! 1725: * If no key material is available, the flag will be reset below. */
! 1726: enumerator = this->payloads->create_enumerator(this->payloads);
! 1727: while (enumerator->enumerate(enumerator, (void**)&payload))
! 1728: {
! 1729: payload_rule_t *rule;
! 1730:
! 1731: rule = get_payload_rule(this, payload->get_type(payload));
! 1732: if (rule && rule->encrypted)
! 1733: {
! 1734: this->is_encrypted = encrypting = TRUE;
! 1735: break;
! 1736: }
! 1737: }
! 1738: enumerator->destroy(enumerator);
! 1739: }
! 1740:
! 1741: DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
! 1742:
! 1743: if (keymat)
! 1744: {
! 1745: aead = keymat->get_aead(keymat, FALSE);
! 1746: }
! 1747: if (encrypting)
! 1748: {
! 1749: if (aead)
! 1750: {
! 1751: *encrypted = wrap_payloads(this);
! 1752: (*encrypted)->set_transform(*encrypted, aead);
! 1753: }
! 1754: else if (this->exchange_type == INFORMATIONAL ||
! 1755: this->exchange_type == INFORMATIONAL_V1)
! 1756: { /* allow sending unencrypted INFORMATIONALs */
! 1757: encrypting = FALSE;
! 1758: }
! 1759: else
! 1760: {
! 1761: DBG1(DBG_ENC, "unable to encrypt payloads without AEAD transform");
! 1762: return FAILED;
! 1763: }
! 1764: }
! 1765: if (!encrypting)
! 1766: {
! 1767: DBG2(DBG_ENC, "not encrypting payloads");
! 1768: this->is_encrypted = FALSE;
! 1769: }
! 1770:
! 1771: /* generate all payloads with proper next type */
! 1772: *out_generator = generator = generator_create();
! 1773: ike_header = create_header(this);
! 1774: payload = (payload_t*)ike_header;
! 1775: enumerator = create_payload_enumerator(this);
! 1776: while (enumerator->enumerate(enumerator, &next))
! 1777: {
! 1778: payload->set_next_type(payload, next->get_type(next));
! 1779: generator->generate_payload(generator, payload);
! 1780: payload = next;
! 1781: }
! 1782: enumerator->destroy(enumerator);
! 1783:
! 1784: next_type = PL_NONE;
! 1785: if (this->is_encrypted)
! 1786: { /* for encrypted IKEv1 messages */
! 1787: next_type = (*encrypted)->payload_interface.get_next_type(
! 1788: (payload_t*)*encrypted);
! 1789: }
! 1790: else if (*encrypted)
! 1791: { /* use proper IKEv2 encrypted (fragment) payload type */
! 1792: next_type = (*encrypted)->payload_interface.get_type(
! 1793: (payload_t*)*encrypted);
! 1794: }
! 1795: payload->set_next_type(payload, next_type);
! 1796: generator->generate_payload(generator, payload);
! 1797: ike_header->destroy(ike_header);
! 1798: return SUCCESS;
! 1799: }
! 1800:
! 1801: /**
! 1802: * Encrypts and adds the encrypted payload (if any) to the payload list and
! 1803: * finalizes the message generation. Destroys the given generator.
! 1804: */
! 1805: static status_t finalize_message(private_message_t *this, keymat_t *keymat,
! 1806: generator_t *generator, encrypted_payload_t *encrypted)
! 1807: {
! 1808: keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
! 1809: chunk_t chunk;
! 1810: uint32_t *lenpos;
! 1811:
! 1812: if (encrypted)
! 1813: {
! 1814: if (this->is_encrypted)
! 1815: { /* for IKEv1 instead of associated data we provide the IV */
! 1816: if (!keymat_v1->get_iv(keymat_v1, this->message_id, &chunk))
! 1817: {
! 1818: generator->destroy(generator);
! 1819: encrypted->destroy(encrypted);
! 1820: return FAILED;
! 1821: }
! 1822: }
! 1823: else
! 1824: { /* build associated data (without header of encrypted payload) */
! 1825: chunk = generator->get_chunk(generator, &lenpos);
! 1826: /* fill in length, including encrypted payload */
! 1827: htoun32(lenpos, chunk.len + encrypted->get_length(encrypted));
! 1828: }
! 1829: this->payloads->insert_last(this->payloads, encrypted);
! 1830: if (encrypted->encrypt(encrypted, this->message_id, chunk) != SUCCESS)
! 1831: {
! 1832: generator->destroy(generator);
! 1833: return INVALID_STATE;
! 1834: }
! 1835: generator->generate_payload(generator, &encrypted->payload_interface);
! 1836: }
! 1837: chunk = generator->get_chunk(generator, &lenpos);
! 1838: htoun32(lenpos, chunk.len);
! 1839: this->packet->set_data(this->packet, chunk_clone(chunk));
! 1840: if (this->is_encrypted && this->exchange_type != INFORMATIONAL_V1)
! 1841: {
! 1842: /* update the IV for the next IKEv1 message */
! 1843: chunk_t last_block;
! 1844: aead_t *aead;
! 1845: size_t bs;
! 1846:
! 1847: aead = keymat->get_aead(keymat, FALSE);
! 1848: bs = aead->get_block_size(aead);
! 1849: last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
! 1850: if (!keymat_v1->update_iv(keymat_v1, this->message_id, last_block) ||
! 1851: !keymat_v1->confirm_iv(keymat_v1, this->message_id))
! 1852: {
! 1853: generator->destroy(generator);
! 1854: return FAILED;
! 1855: }
! 1856: }
! 1857: generator->destroy(generator);
! 1858: return SUCCESS;
! 1859: }
! 1860:
! 1861: METHOD(message_t, generate, status_t,
! 1862: private_message_t *this, keymat_t *keymat, packet_t **packet)
! 1863: {
! 1864: generator_t *generator = NULL;
! 1865: encrypted_payload_t *encrypted = NULL;
! 1866: status_t status;
! 1867:
! 1868: status = generate_message(this, keymat, &generator, &encrypted);
! 1869: if (status != SUCCESS)
! 1870: {
! 1871: DESTROY_IF(generator);
! 1872: return status;
! 1873: }
! 1874: status = finalize_message(this, keymat, generator, encrypted);
! 1875: if (status != SUCCESS)
! 1876: {
! 1877: return status;
! 1878: }
! 1879: if (packet)
! 1880: {
! 1881: *packet = this->packet->clone(this->packet);
! 1882: }
! 1883: return SUCCESS;
! 1884: }
! 1885:
! 1886: /**
! 1887: * Creates a (basic) clone of the given message
! 1888: */
! 1889: static message_t *clone_message(private_message_t *this)
! 1890: {
! 1891: message_t *message;
! 1892: host_t *src, *dst;
! 1893:
! 1894: src = this->packet->get_source(this->packet);
! 1895: dst = this->packet->get_destination(this->packet);
! 1896:
! 1897: message = message_create(this->major_version, this->minor_version);
! 1898: message->set_ike_sa_id(message, this->ike_sa_id);
! 1899: message->set_message_id(message, this->message_id);
! 1900: message->set_request(message, this->is_request);
! 1901: message->set_source(message, src->clone(src));
! 1902: message->set_destination(message, dst->clone(dst));
! 1903: message->set_exchange_type(message, this->exchange_type);
! 1904: memcpy(((private_message_t*)message)->reserved, this->reserved,
! 1905: sizeof(this->reserved));
! 1906: return message;
! 1907: }
! 1908:
! 1909: /**
! 1910: * Create a single fragment with the given data
! 1911: */
! 1912: static message_t *create_fragment(private_message_t *this, payload_type_t next,
! 1913: uint16_t num, uint16_t count, chunk_t data)
! 1914: {
! 1915: enumerator_t *enumerator;
! 1916: payload_t *fragment, *payload;
! 1917: message_t *message;
! 1918: peer_cfg_t *peer_cfg;
! 1919: ike_sa_t *ike_sa;
! 1920:
! 1921: message = clone_message(this);
! 1922: if (this->major_version == IKEV1_MAJOR_VERSION)
! 1923: {
! 1924: /* other implementations seem to just use 0 as message ID, so here we go */
! 1925: message->set_message_id(message, 0);
! 1926: /* always use the initial message type for fragments, even for quick mode
! 1927: * or transaction messages. */
! 1928: ike_sa = charon->bus->get_sa(charon->bus);
! 1929: if (ike_sa && (peer_cfg = ike_sa->get_peer_cfg(ike_sa)) &&
! 1930: peer_cfg->use_aggressive(peer_cfg))
! 1931: {
! 1932: message->set_exchange_type(message, AGGRESSIVE);
! 1933: }
! 1934: else
! 1935: {
! 1936: message->set_exchange_type(message, ID_PROT);
! 1937: }
! 1938: fragment = (payload_t*)fragment_payload_create_from_data(
! 1939: num, num == count, data);
! 1940: }
! 1941: else
! 1942: {
! 1943: fragment = (payload_t*)encrypted_fragment_payload_create_from_data(
! 1944: num, count, data);
! 1945: if (num == 1)
! 1946: {
! 1947: /* only in the first fragment is this set to the type of the first
! 1948: * payload in the encrypted payload */
! 1949: fragment->set_next_type(fragment, next);
! 1950: /* move unencrypted payloads to the first fragment */
! 1951: enumerator = this->payloads->create_enumerator(this->payloads);
! 1952: while (enumerator->enumerate(enumerator, &payload))
! 1953: {
! 1954: if (payload->get_type(payload) != PLV2_ENCRYPTED)
! 1955: {
! 1956: this->payloads->remove_at(this->payloads, enumerator);
! 1957: message->add_payload(message, payload);
! 1958: }
! 1959: }
! 1960: enumerator->destroy(enumerator);
! 1961: }
! 1962: }
! 1963: message->add_payload(message, (payload_t*)fragment);
! 1964: return message;
! 1965: }
! 1966:
! 1967: /**
! 1968: * Destroy all fragments
! 1969: */
! 1970: static void clear_fragments(private_message_t *this)
! 1971: {
! 1972: array_destroy_offset(this->fragments, offsetof(packet_t, destroy));
! 1973: this->fragments = NULL;
! 1974: }
! 1975:
! 1976: /**
! 1977: * Reduce the fragment length but ensure it stays > 0
! 1978: */
! 1979: #define REDUCE_FRAG_LEN(fl, amount) ({ \
! 1980: fl = max(1, (ssize_t)fl - (amount)); \
! 1981: })
! 1982:
! 1983: METHOD(message_t, fragment, status_t,
! 1984: private_message_t *this, keymat_t *keymat, size_t frag_len,
! 1985: enumerator_t **fragments)
! 1986: {
! 1987: encrypted_payload_t *encrypted = NULL;
! 1988: generator_t *generator = NULL;
! 1989: message_t *fragment;
! 1990: packet_t *packet;
! 1991: payload_type_t next = PL_NONE;
! 1992: uint16_t num, count;
! 1993: host_t *src, *dst;
! 1994: chunk_t data;
! 1995: status_t status;
! 1996: uint32_t *lenpos;
! 1997: size_t len;
! 1998:
! 1999: src = this->packet->get_source(this->packet);
! 2000: dst = this->packet->get_destination(this->packet);
! 2001: if (!frag_len)
! 2002: {
! 2003: frag_len = (src->get_family(src) == AF_INET) ? 576 : 1280;
! 2004: }
! 2005: /* frag_len is the complete IP datagram length, account for overhead (we
! 2006: * assume no IP options/extension headers are used) */
! 2007: REDUCE_FRAG_LEN(frag_len, (src->get_family(src) == AF_INET) ? 20 : 40);
! 2008: /* 8 (UDP header) */
! 2009: REDUCE_FRAG_LEN(frag_len, 8);
! 2010: if (dst->get_port(dst) != IKEV2_UDP_PORT &&
! 2011: src->get_port(src) != IKEV2_UDP_PORT)
! 2012: { /* reduce length due to non-ESP marker */
! 2013: REDUCE_FRAG_LEN(frag_len, 4);
! 2014: }
! 2015:
! 2016: if (is_encoded(this))
! 2017: {
! 2018: if (this->major_version == IKEV2_MAJOR_VERSION)
! 2019: {
! 2020: encrypted = (encrypted_payload_t*)get_payload(this, PLV2_ENCRYPTED);
! 2021: }
! 2022: data = this->packet->get_data(this->packet);
! 2023: len = data.len;
! 2024: }
! 2025: else
! 2026: {
! 2027: status = generate_message(this, keymat, &generator, &encrypted);
! 2028: if (status != SUCCESS)
! 2029: {
! 2030: DESTROY_IF(generator);
! 2031: return status;
! 2032: }
! 2033: data = generator->get_chunk(generator, &lenpos);
! 2034: len = data.len + (encrypted ? encrypted->get_length(encrypted) : 0);
! 2035: }
! 2036:
! 2037: /* check if we actually need to fragment the message and if we have an
! 2038: * encrypted payload for IKEv2 */
! 2039: if (len <= frag_len ||
! 2040: (this->major_version == IKEV2_MAJOR_VERSION && !encrypted))
! 2041: {
! 2042: if (generator)
! 2043: {
! 2044: status = finalize_message(this, keymat, generator, encrypted);
! 2045: if (status != SUCCESS)
! 2046: {
! 2047: return status;
! 2048: }
! 2049: }
! 2050: *fragments = enumerator_create_single(this->packet, NULL);
! 2051: return SUCCESS;
! 2052: }
! 2053:
! 2054: /* frag_len denoted the maximum IKE message size so far, later on it will
! 2055: * denote the maximum content size of a fragment payload, therefore,
! 2056: * account for IKE header */
! 2057: REDUCE_FRAG_LEN(frag_len, 28);
! 2058:
! 2059: if (this->major_version == IKEV1_MAJOR_VERSION)
! 2060: {
! 2061: if (generator)
! 2062: {
! 2063: status = finalize_message(this, keymat, generator, encrypted);
! 2064: if (status != SUCCESS)
! 2065: {
! 2066: return status;
! 2067: }
! 2068: data = this->packet->get_data(this->packet);
! 2069: generator = NULL;
! 2070: }
! 2071: /* overhead for the fragmentation payload header */
! 2072: REDUCE_FRAG_LEN(frag_len, 8);
! 2073: }
! 2074: else
! 2075: {
! 2076: aead_t *aead;
! 2077:
! 2078: if (generator)
! 2079: {
! 2080: generator->destroy(generator);
! 2081: generator = generator_create();
! 2082: }
! 2083: else
! 2084: { /* do not log again if it was generated previously */
! 2085: generator = generator_create_no_dbg();
! 2086: }
! 2087: next = encrypted->payload_interface.get_next_type((payload_t*)encrypted);
! 2088: encrypted->generate_payloads(encrypted, generator);
! 2089: data = generator->get_chunk(generator, &lenpos);
! 2090: if (!is_encoded(this))
! 2091: {
! 2092: encrypted->destroy(encrypted);
! 2093: }
! 2094: aead = keymat->get_aead(keymat, FALSE);
! 2095: /* overhead for the encrypted fragment payload */
! 2096: REDUCE_FRAG_LEN(frag_len, aead->get_iv_size(aead));
! 2097: REDUCE_FRAG_LEN(frag_len, aead->get_icv_size(aead));
! 2098: /* header */
! 2099: REDUCE_FRAG_LEN(frag_len, 8);
! 2100: /* padding and padding length */
! 2101: frag_len = round_down(frag_len, aead->get_block_size(aead));
! 2102: REDUCE_FRAG_LEN(frag_len, 1);
! 2103: /* TODO-FRAG: if there are unencrypted payloads, should we account for
! 2104: * their length in the first fragment? we still would have to add
! 2105: * an encrypted fragment payload (albeit empty), even so we couldn't
! 2106: * prevent IP fragmentation in every case */
! 2107: }
! 2108:
! 2109: count = data.len / frag_len + (data.len % frag_len ? 1 : 0);
! 2110: this->fragments = array_create(0, count);
! 2111: DBG1(DBG_ENC, "splitting IKE message (%zu bytes) into %hu fragments", len,
! 2112: count);
! 2113: for (num = 1; num <= count; num++)
! 2114: {
! 2115: len = min(data.len, frag_len);
! 2116: fragment = create_fragment(this, next, num, count,
! 2117: chunk_create(data.ptr, len));
! 2118: status = fragment->generate(fragment, keymat, &packet);
! 2119: fragment->destroy(fragment);
! 2120: if (status != SUCCESS)
! 2121: {
! 2122: DBG1(DBG_ENC, "failed to generate IKE fragment");
! 2123: clear_fragments(this);
! 2124: DESTROY_IF(generator);
! 2125: return FAILED;
! 2126: }
! 2127: array_insert(this->fragments, ARRAY_TAIL, packet);
! 2128: data = chunk_skip(data, len);
! 2129: }
! 2130: *fragments = array_create_enumerator(this->fragments);
! 2131: DESTROY_IF(generator);
! 2132: return SUCCESS;
! 2133: }
! 2134:
! 2135: METHOD(message_t, get_packet, packet_t*,
! 2136: private_message_t *this)
! 2137: {
! 2138: return this->packet->clone(this->packet);
! 2139: }
! 2140:
! 2141: METHOD(message_t, get_packet_data, chunk_t,
! 2142: private_message_t *this)
! 2143: {
! 2144: return this->packet->get_data(this->packet);
! 2145: }
! 2146:
! 2147: METHOD(message_t, get_fragments, enumerator_t*,
! 2148: private_message_t *this)
! 2149: {
! 2150: return array_create_enumerator(this->fragments);
! 2151: }
! 2152:
! 2153: METHOD(message_t, parse_header, status_t,
! 2154: private_message_t *this)
! 2155: {
! 2156: ike_header_t *ike_header;
! 2157: status_t status;
! 2158: bool *reserved;
! 2159: int i;
! 2160:
! 2161: DBG2(DBG_ENC, "parsing header of message");
! 2162:
! 2163: if (!this->parser)
! 2164: { /* reassembled IKEv2 message, header is inherited from fragments */
! 2165: return SUCCESS;
! 2166: }
! 2167: this->parser->reset_context(this->parser);
! 2168: status = this->parser->parse_payload(this->parser, PL_HEADER,
! 2169: (payload_t**)&ike_header);
! 2170: if (status != SUCCESS)
! 2171: {
! 2172: DBG1(DBG_ENC, "header could not be parsed");
! 2173: return status;
! 2174:
! 2175: }
! 2176:
! 2177: status = ike_header->payload_interface.verify(
! 2178: &ike_header->payload_interface);
! 2179: if (status != SUCCESS)
! 2180: {
! 2181: DBG1(DBG_ENC, "header verification failed");
! 2182: ike_header->destroy(ike_header);
! 2183: return status;
! 2184: }
! 2185:
! 2186: DESTROY_IF(this->ike_sa_id);
! 2187: this->ike_sa_id = ike_sa_id_create(
! 2188: ike_header->get_maj_version(ike_header),
! 2189: ike_header->get_initiator_spi(ike_header),
! 2190: ike_header->get_responder_spi(ike_header),
! 2191: ike_header->get_initiator_flag(ike_header));
! 2192:
! 2193: this->exchange_type = ike_header->get_exchange_type(ike_header);
! 2194: this->message_id = ike_header->get_message_id(ike_header);
! 2195: this->major_version = ike_header->get_maj_version(ike_header);
! 2196: this->minor_version = ike_header->get_min_version(ike_header);
! 2197: if (this->major_version == IKEV2_MAJOR_VERSION)
! 2198: {
! 2199: this->is_request = !ike_header->get_response_flag(ike_header);
! 2200: }
! 2201: else
! 2202: {
! 2203: this->is_encrypted = ike_header->get_encryption_flag(ike_header);
! 2204: }
! 2205: this->first_payload = ike_header->payload_interface.get_next_type(
! 2206: &ike_header->payload_interface);
! 2207: if (this->first_payload == PLV1_FRAGMENT && this->is_encrypted)
! 2208: { /* racoon sets the encrypted bit when sending a fragment, but these
! 2209: * messages are really not encrypted */
! 2210: this->is_encrypted = FALSE;
! 2211: }
! 2212:
! 2213: for (i = 0; i < countof(this->reserved); i++)
! 2214: {
! 2215: reserved = payload_get_field(&ike_header->payload_interface,
! 2216: RESERVED_BIT, i);
! 2217: if (reserved)
! 2218: {
! 2219: this->reserved[i] = *reserved;
! 2220: }
! 2221: }
! 2222: ike_header->destroy(ike_header);
! 2223:
! 2224: this->parser->set_major_version(this->parser, this->major_version);
! 2225:
! 2226: DBG2(DBG_ENC, "parsed a %N %s header", exchange_type_names,
! 2227: this->exchange_type, this->major_version == IKEV1_MAJOR_VERSION ?
! 2228: "message" : (this->is_request ? "request" : "response"));
! 2229: return SUCCESS;
! 2230: }
! 2231:
! 2232: /**
! 2233: * Check if a payload is for a mediation extension connectivity check
! 2234: */
! 2235: static bool is_connectivity_check(private_message_t *this, payload_t *payload)
! 2236: {
! 2237: #ifdef ME
! 2238: if (this->exchange_type == INFORMATIONAL &&
! 2239: payload->get_type(payload) == PLV2_NOTIFY)
! 2240: {
! 2241: notify_payload_t *notify = (notify_payload_t*)payload;
! 2242:
! 2243: switch (notify->get_notify_type(notify))
! 2244: {
! 2245: case ME_CONNECTID:
! 2246: case ME_ENDPOINT:
! 2247: case ME_CONNECTAUTH:
! 2248: return TRUE;
! 2249: default:
! 2250: break;
! 2251: }
! 2252: }
! 2253: #endif /* !ME */
! 2254: return FALSE;
! 2255: }
! 2256:
! 2257: /**
! 2258: * Parses and verifies the unencrypted payloads contained in the message
! 2259: */
! 2260: static status_t parse_payloads(private_message_t *this)
! 2261: {
! 2262: payload_type_t type = this->first_payload;
! 2263: payload_t *payload;
! 2264: status_t status;
! 2265:
! 2266: if (this->is_encrypted)
! 2267: { /* wrap the whole encrypted IKEv1 message in a special encrypted
! 2268: * payload which is then handled just like a regular payload */
! 2269: encrypted_payload_t *encryption;
! 2270:
! 2271: status = this->parser->parse_payload(this->parser, PLV1_ENCRYPTED,
! 2272: (payload_t**)&encryption);
! 2273: if (status != SUCCESS)
! 2274: {
! 2275: DBG1(DBG_ENC, "failed to wrap encrypted IKEv1 message");
! 2276: return PARSE_ERROR;
! 2277: }
! 2278: encryption->payload_interface.set_next_type((payload_t*)encryption,
! 2279: this->first_payload);
! 2280: this->payloads->insert_last(this->payloads, encryption);
! 2281: return SUCCESS;
! 2282: }
! 2283:
! 2284: while (type != PL_NONE)
! 2285: {
! 2286: DBG2(DBG_ENC, "starting parsing a %N payload",
! 2287: payload_type_names, type);
! 2288:
! 2289: status = this->parser->parse_payload(this->parser, type, &payload);
! 2290: if (status != SUCCESS)
! 2291: {
! 2292: DBG1(DBG_ENC, "payload type %N could not be parsed",
! 2293: payload_type_names, type);
! 2294: return PARSE_ERROR;
! 2295: }
! 2296:
! 2297: DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type);
! 2298: status = payload->verify(payload);
! 2299: if (status != SUCCESS)
! 2300: {
! 2301: DBG1(DBG_ENC, "%N payload verification failed",
! 2302: payload_type_names, type);
! 2303: payload->destroy(payload);
! 2304: return VERIFY_ERROR;
! 2305: }
! 2306: if (payload->get_type(payload) == PL_UNKNOWN)
! 2307: {
! 2308: DBG2(DBG_ENC, "%N payload unknown or not allowed",
! 2309: payload_type_names, type);
! 2310: }
! 2311: else
! 2312: {
! 2313: DBG2(DBG_ENC, "%N payload verified, adding to payload list",
! 2314: payload_type_names, type);
! 2315: }
! 2316: this->payloads->insert_last(this->payloads, payload);
! 2317:
! 2318: /* an encrypted (fragment) payload MUST be the last one, so STOP here.
! 2319: * decryption is done later */
! 2320: if (type == PLV2_ENCRYPTED || type == PLV2_FRAGMENT)
! 2321: {
! 2322: DBG2(DBG_ENC, "%N payload found, stop parsing",
! 2323: payload_type_names, type);
! 2324: break;
! 2325: }
! 2326: type = payload->get_next_type(payload);
! 2327: }
! 2328: return SUCCESS;
! 2329: }
! 2330:
! 2331: /**
! 2332: * Decrypt an encrypted payload and extract all contained payloads.
! 2333: */
! 2334: static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
! 2335: payload_t *previous, encrypted_payload_t *encryption)
! 2336: {
! 2337: payload_t *encrypted;
! 2338: payload_type_t type;
! 2339: chunk_t chunk;
! 2340: aead_t *aead;
! 2341: size_t bs;
! 2342: status_t status = SUCCESS;
! 2343:
! 2344: if (!keymat)
! 2345: {
! 2346: DBG1(DBG_ENC, "found encrypted payload, but no keymat");
! 2347: return INVALID_ARG;
! 2348: }
! 2349: aead = keymat->get_aead(keymat, TRUE);
! 2350: if (!aead)
! 2351: {
! 2352: DBG1(DBG_ENC, "found encrypted payload, but no transform set");
! 2353: return INVALID_ARG;
! 2354: }
! 2355: if (!this->parser)
! 2356: {
! 2357: /* reassembled IKEv2 messages are already decrypted, we still call
! 2358: * decrypt() to parse the contained payloads */
! 2359: status = encryption->decrypt(encryption, chunk_empty);
! 2360: }
! 2361: else
! 2362: {
! 2363: bs = aead->get_block_size(aead);
! 2364: encryption->set_transform(encryption, aead);
! 2365: chunk = this->packet->get_data(this->packet);
! 2366: if (chunk.len < encryption->get_length(encryption) ||
! 2367: chunk.len < bs)
! 2368: {
! 2369: DBG1(DBG_ENC, "invalid payload length");
! 2370: return VERIFY_ERROR;
! 2371: }
! 2372: if (keymat->get_version(keymat) == IKEV1)
! 2373: { /* instead of associated data we provide the IV, we also update
! 2374: * the IV with the last encrypted block */
! 2375: keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
! 2376: chunk_t iv;
! 2377:
! 2378: if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv))
! 2379: {
! 2380: status = encryption->decrypt(encryption, iv);
! 2381: if (status == SUCCESS)
! 2382: {
! 2383: if (!keymat_v1->update_iv(keymat_v1, this->message_id,
! 2384: chunk_create(chunk.ptr + chunk.len - bs, bs)))
! 2385: {
! 2386: status = FAILED;
! 2387: }
! 2388: }
! 2389: }
! 2390: else
! 2391: {
! 2392: status = FAILED;
! 2393: }
! 2394: }
! 2395: else
! 2396: {
! 2397: chunk.len -= encryption->get_length(encryption);
! 2398: status = encryption->decrypt(encryption, chunk);
! 2399: }
! 2400: }
! 2401: if (status != SUCCESS)
! 2402: {
! 2403: return status;
! 2404: }
! 2405:
! 2406: while ((encrypted = encryption->remove_payload(encryption)))
! 2407: {
! 2408: type = encrypted->get_type(encrypted);
! 2409: if (previous)
! 2410: {
! 2411: previous->set_next_type(previous, type);
! 2412: }
! 2413: else
! 2414: {
! 2415: this->first_payload = type;
! 2416: }
! 2417: DBG2(DBG_ENC, "insert decrypted payload of type %N at end of list",
! 2418: payload_type_names, type);
! 2419: this->payloads->insert_last(this->payloads, encrypted);
! 2420: previous = encrypted;
! 2421: }
! 2422: return SUCCESS;
! 2423: }
! 2424:
! 2425: /**
! 2426: * Decrypt an encrypted fragment payload.
! 2427: */
! 2428: static status_t decrypt_fragment(private_message_t *this, keymat_t *keymat,
! 2429: encrypted_fragment_payload_t *fragment)
! 2430: {
! 2431: encrypted_payload_t *encrypted = (encrypted_payload_t*)fragment;
! 2432: chunk_t chunk;
! 2433: aead_t *aead;
! 2434: size_t bs;
! 2435:
! 2436: if (!keymat)
! 2437: {
! 2438: DBG1(DBG_ENC, "found encrypted fragment payload, but no keymat");
! 2439: return INVALID_ARG;
! 2440: }
! 2441: aead = keymat->get_aead(keymat, TRUE);
! 2442: if (!aead)
! 2443: {
! 2444: DBG1(DBG_ENC, "found encrypted fragment payload, but no transform set");
! 2445: return INVALID_ARG;
! 2446: }
! 2447: bs = aead->get_block_size(aead);
! 2448: encrypted->set_transform(encrypted, aead);
! 2449: chunk = this->packet->get_data(this->packet);
! 2450: if (chunk.len < encrypted->get_length(encrypted) ||
! 2451: chunk.len < bs)
! 2452: {
! 2453: DBG1(DBG_ENC, "invalid payload length");
! 2454: return VERIFY_ERROR;
! 2455: }
! 2456: chunk.len -= encrypted->get_length(encrypted);
! 2457: return encrypted->decrypt(encrypted, chunk);
! 2458: }
! 2459:
! 2460: /**
! 2461: * Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
! 2462: * some SonicWall boxes?
! 2463: */
! 2464: static bool accept_unencrypted_mm(private_message_t *this, payload_type_t type)
! 2465: {
! 2466: if (this->exchange_type == ID_PROT)
! 2467: {
! 2468: if (type == PLV1_ID || type == PLV1_HASH)
! 2469: {
! 2470: return lib->settings->get_bool(lib->settings,
! 2471: "%s.accept_unencrypted_mainmode_messages",
! 2472: FALSE, lib->ns);
! 2473: }
! 2474: }
! 2475: return FALSE;
! 2476: }
! 2477:
! 2478: /**
! 2479: * Decrypt payload from the encrypted payload
! 2480: */
! 2481: static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
! 2482: {
! 2483: payload_t *payload, *previous = NULL;
! 2484: enumerator_t *enumerator;
! 2485: payload_rule_t *rule;
! 2486: payload_type_t type;
! 2487: status_t status = SUCCESS;
! 2488: char *was_encrypted = NULL;
! 2489:
! 2490: enumerator = this->payloads->create_enumerator(this->payloads);
! 2491: while (enumerator->enumerate(enumerator, &payload))
! 2492: {
! 2493: type = payload->get_type(payload);
! 2494:
! 2495: DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
! 2496:
! 2497: if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED ||
! 2498: type == PLV2_FRAGMENT)
! 2499: {
! 2500: if (was_encrypted)
! 2501: {
! 2502: DBG1(DBG_ENC, "%s can't contain other payloads of type %N",
! 2503: was_encrypted, payload_type_names, type);
! 2504: status = VERIFY_ERROR;
! 2505: break;
! 2506: }
! 2507: }
! 2508:
! 2509: if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
! 2510: {
! 2511: encrypted_payload_t *encryption;
! 2512:
! 2513: DBG2(DBG_ENC, "found an encrypted payload");
! 2514: encryption = (encrypted_payload_t*)payload;
! 2515: this->payloads->remove_at(this->payloads, enumerator);
! 2516:
! 2517: if (enumerator->enumerate(enumerator, NULL))
! 2518: {
! 2519: DBG1(DBG_ENC, "encrypted payload is not last payload");
! 2520: encryption->destroy(encryption);
! 2521: status = VERIFY_ERROR;
! 2522: break;
! 2523: }
! 2524: status = decrypt_and_extract(this, keymat, previous, encryption);
! 2525: encryption->destroy(encryption);
! 2526: if (status != SUCCESS)
! 2527: {
! 2528: break;
! 2529: }
! 2530: was_encrypted = "encrypted payload";
! 2531: }
! 2532: else if (type == PLV2_FRAGMENT)
! 2533: {
! 2534: encrypted_fragment_payload_t *fragment;
! 2535:
! 2536: DBG2(DBG_ENC, "found an encrypted fragment payload");
! 2537: fragment = (encrypted_fragment_payload_t*)payload;
! 2538:
! 2539: if (enumerator->enumerate(enumerator, NULL))
! 2540: {
! 2541: DBG1(DBG_ENC, "encrypted fragment payload is not last payload");
! 2542: status = VERIFY_ERROR;
! 2543: break;
! 2544: }
! 2545: status = decrypt_fragment(this, keymat, fragment);
! 2546: if (status != SUCCESS)
! 2547: {
! 2548: break;
! 2549: }
! 2550: was_encrypted = "encrypted fragment payload";
! 2551: }
! 2552:
! 2553: if (type != PL_UNKNOWN && !was_encrypted &&
! 2554: !is_connectivity_check(this, payload) &&
! 2555: this->exchange_type != AGGRESSIVE)
! 2556: {
! 2557: rule = get_payload_rule(this, type);
! 2558: if ((!rule || rule->encrypted) &&
! 2559: !accept_unencrypted_mm(this, type))
! 2560: {
! 2561: DBG1(DBG_ENC, "payload type %N was not encrypted",
! 2562: payload_type_names, type);
! 2563: status = FAILED;
! 2564: break;
! 2565: }
! 2566: }
! 2567: previous = payload;
! 2568: }
! 2569: enumerator->destroy(enumerator);
! 2570: return status;
! 2571: }
! 2572:
! 2573: /**
! 2574: * Verify a message and all payload according to message/payload rules
! 2575: */
! 2576: static status_t verify(private_message_t *this)
! 2577: {
! 2578: bool complete = FALSE;
! 2579: int i;
! 2580:
! 2581: DBG2(DBG_ENC, "verifying message structure");
! 2582:
! 2583: /* check for payloads with wrong count */
! 2584: for (i = 0; i < this->rule->rule_count; i++)
! 2585: {
! 2586: enumerator_t *enumerator;
! 2587: payload_t *payload;
! 2588: payload_rule_t *rule;
! 2589: int found = 0;
! 2590:
! 2591: rule = &this->rule->rules[i];
! 2592: enumerator = create_payload_enumerator(this);
! 2593: while (enumerator->enumerate(enumerator, &payload))
! 2594: {
! 2595: payload_type_t type;
! 2596:
! 2597: type = payload->get_type(payload);
! 2598: if (type == rule->type)
! 2599: {
! 2600: found++;
! 2601: DBG2(DBG_ENC, "found payload of type %N",
! 2602: payload_type_names, type);
! 2603: if (found > rule->max_occurrence)
! 2604: {
! 2605: DBG1(DBG_ENC, "payload of type %N more than %d times (%d) "
! 2606: "occurred in current message", payload_type_names,
! 2607: type, rule->max_occurrence, found);
! 2608: enumerator->destroy(enumerator);
! 2609: return VERIFY_ERROR;
! 2610: }
! 2611: }
! 2612: }
! 2613: enumerator->destroy(enumerator);
! 2614:
! 2615: if (!complete && found < rule->min_occurrence)
! 2616: {
! 2617: DBG1(DBG_ENC, "payload of type %N not occurred %d times (%d)",
! 2618: payload_type_names, rule->type, rule->min_occurrence, found);
! 2619: return VERIFY_ERROR;
! 2620: }
! 2621: if (found && rule->sufficient)
! 2622: {
! 2623: complete = TRUE;
! 2624: }
! 2625: }
! 2626: return SUCCESS;
! 2627: }
! 2628:
! 2629: METHOD(message_t, parse_body, status_t,
! 2630: private_message_t *this, keymat_t *keymat)
! 2631: {
! 2632: status_t status = SUCCESS;
! 2633: char str[BUF_LEN];
! 2634:
! 2635: DBG2(DBG_ENC, "parsing body of message, first payload is %N",
! 2636: payload_type_names, this->first_payload);
! 2637:
! 2638: this->rule = get_message_rule(this);
! 2639: if (!this->rule)
! 2640: {
! 2641: DBG1(DBG_ENC, "no message rules specified for a %N %s",
! 2642: exchange_type_names, this->exchange_type,
! 2643: this->is_request ? "request" : "response");
! 2644: return NOT_SUPPORTED;
! 2645: }
! 2646:
! 2647: /* reassembled IKEv2 messages are already parsed (except for the payloads
! 2648: * contained in the encrypted payload, which are handled below) */
! 2649: if (this->parser)
! 2650: {
! 2651: status = parse_payloads(this);
! 2652: if (status != SUCCESS)
! 2653: { /* error is already logged */
! 2654: return status;
! 2655: }
! 2656: }
! 2657:
! 2658: status = decrypt_payloads(this, keymat);
! 2659: if (status != SUCCESS)
! 2660: {
! 2661: DBG1(DBG_ENC, "could not decrypt payloads");
! 2662: return status;
! 2663: }
! 2664:
! 2665: status = verify(this);
! 2666: if (status != SUCCESS)
! 2667: {
! 2668: return status;
! 2669: }
! 2670:
! 2671: DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
! 2672:
! 2673: if (keymat && keymat->get_version(keymat) == IKEV1)
! 2674: {
! 2675: keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
! 2676: chunk_t hash;
! 2677:
! 2678: if (keymat_v1->get_hash_phase2(keymat_v1, &this->public, &hash))
! 2679: {
! 2680: hash_payload_t *hash_payload;
! 2681: chunk_t other_hash;
! 2682:
! 2683: if (this->first_payload != PLV1_HASH)
! 2684: {
! 2685: if (this->exchange_type == INFORMATIONAL_V1)
! 2686: {
! 2687: DBG1(DBG_ENC, "ignoring unprotected INFORMATIONAL from %H",
! 2688: this->packet->get_source(this->packet));
! 2689: }
! 2690: else
! 2691: {
! 2692: DBG1(DBG_ENC, "expected HASH payload as first payload");
! 2693: }
! 2694: chunk_free(&hash);
! 2695: return VERIFY_ERROR;
! 2696: }
! 2697: hash_payload = (hash_payload_t*)get_payload(this, PLV1_HASH);
! 2698: other_hash = hash_payload->get_hash(hash_payload);
! 2699: DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
! 2700: &other_hash, &hash);
! 2701: if (!chunk_equals_const(hash, other_hash))
! 2702: {
! 2703: DBG1(DBG_ENC, "received HASH payload does not match");
! 2704: chunk_free(&hash);
! 2705: return FAILED;
! 2706: }
! 2707: chunk_free(&hash);
! 2708: }
! 2709: if (this->is_encrypted && this->exchange_type != INFORMATIONAL_V1)
! 2710: { /* message verified, confirm IV */
! 2711: if (!keymat_v1->confirm_iv(keymat_v1, this->message_id))
! 2712: {
! 2713: return FAILED;
! 2714: }
! 2715: }
! 2716: }
! 2717: return SUCCESS;
! 2718: }
! 2719:
! 2720: /**
! 2721: * Store the fragment data for the fragment with the given fragment number.
! 2722: */
! 2723: static status_t add_fragment(private_message_t *this, uint16_t num,
! 2724: chunk_t data)
! 2725: {
! 2726: fragment_t *fragment;
! 2727: int i, insert_at = -1;
! 2728:
! 2729: for (i = 0; i < array_count(this->fragments); i++)
! 2730: {
! 2731: array_get(this->fragments, i, &fragment);
! 2732: if (fragment->num == num)
! 2733: {
! 2734: /* ignore a duplicate fragment */
! 2735: DBG1(DBG_ENC, "received duplicate fragment #%hu", num);
! 2736: return NEED_MORE;
! 2737: }
! 2738: if (fragment->num > num)
! 2739: {
! 2740: insert_at = i;
! 2741: break;
! 2742: }
! 2743: }
! 2744: this->frag->len += data.len;
! 2745: if (this->frag->len > this->frag->max_packet)
! 2746: {
! 2747: DBG1(DBG_ENC, "fragmented IKE message is too large");
! 2748: reset_defrag(this);
! 2749: return FAILED;
! 2750: }
! 2751: INIT(fragment,
! 2752: .num = num,
! 2753: .data = chunk_clone(data),
! 2754: );
! 2755: array_insert(this->fragments, insert_at, fragment);
! 2756: return SUCCESS;
! 2757: }
! 2758:
! 2759: /**
! 2760: * Merge the cached fragment data and resets the defragmentation state.
! 2761: * Also updates the IP addresses to those of the last received fragment.
! 2762: */
! 2763: static chunk_t merge_fragments(private_message_t *this, message_t *last)
! 2764: {
! 2765: fragment_t *fragment;
! 2766: bio_writer_t *writer;
! 2767: host_t *src, *dst;
! 2768: chunk_t data;
! 2769: int i;
! 2770:
! 2771: writer = bio_writer_create(this->frag->len);
! 2772: for (i = 0; i < array_count(this->fragments); i++)
! 2773: {
! 2774: array_get(this->fragments, i, &fragment);
! 2775: writer->write_data(writer, fragment->data);
! 2776: }
! 2777: data = writer->extract_buf(writer);
! 2778: writer->destroy(writer);
! 2779:
! 2780: /* set addresses to those of the last fragment we received */
! 2781: src = last->get_source(last);
! 2782: dst = last->get_destination(last);
! 2783: this->packet->set_source(this->packet, src->clone(src));
! 2784: this->packet->set_destination(this->packet, dst->clone(dst));
! 2785:
! 2786: reset_defrag(this);
! 2787: free(this->frag);
! 2788: this->frag = NULL;
! 2789: return data;
! 2790: }
! 2791:
! 2792: METHOD(message_t, add_fragment_v1, status_t,
! 2793: private_message_t *this, message_t *message)
! 2794: {
! 2795: fragment_payload_t *payload;
! 2796: chunk_t data;
! 2797: uint8_t num;
! 2798: status_t status;
! 2799:
! 2800: if (!this->frag)
! 2801: {
! 2802: return INVALID_STATE;
! 2803: }
! 2804: payload = (fragment_payload_t*)message->get_payload(message, PLV1_FRAGMENT);
! 2805: if (!payload)
! 2806: {
! 2807: return INVALID_ARG;
! 2808: }
! 2809: if (!this->fragments || this->message_id != payload->get_id(payload))
! 2810: {
! 2811: reset_defrag(this);
! 2812: this->message_id = payload->get_id(payload);
! 2813: /* we don't know the total number of fragments, assume something */
! 2814: this->fragments = array_create(0, 4);
! 2815: }
! 2816:
! 2817: num = payload->get_number(payload);
! 2818: data = payload->get_data(payload);
! 2819: if (!this->frag->last && payload->is_last(payload))
! 2820: {
! 2821: this->frag->last = num;
! 2822: }
! 2823: status = add_fragment(this, num, data);
! 2824: if (status != SUCCESS)
! 2825: {
! 2826: return status;
! 2827: }
! 2828:
! 2829: if (array_count(this->fragments) != this->frag->last)
! 2830: {
! 2831: /* there are some fragments missing */
! 2832: DBG1(DBG_ENC, "received fragment #%hhu, waiting for complete IKE "
! 2833: "message", num);
! 2834: return NEED_MORE;
! 2835: }
! 2836:
! 2837: data = merge_fragments(this, message);
! 2838: this->packet->set_data(this->packet, data);
! 2839: DBG1(DBG_ENC, "received fragment #%hhu, reassembled fragmented IKE "
! 2840: "message (%zu bytes)", num, data.len);
! 2841:
! 2842: this->parser = parser_create(data);
! 2843:
! 2844: if (parse_header(this) != SUCCESS)
! 2845: {
! 2846: DBG1(DBG_IKE, "failed to parse header of reassembled IKE message");
! 2847: return FAILED;
! 2848: }
! 2849: return SUCCESS;
! 2850: }
! 2851:
! 2852: METHOD(message_t, add_fragment_v2, status_t,
! 2853: private_message_t *this, message_t *message)
! 2854: {
! 2855: encrypted_fragment_payload_t *encrypted_fragment;
! 2856: encrypted_payload_t *encrypted;
! 2857: payload_t *payload;
! 2858: aead_t *aead;
! 2859: enumerator_t *enumerator;
! 2860: chunk_t data;
! 2861: uint16_t total, num;
! 2862: size_t len;
! 2863: status_t status;
! 2864:
! 2865: if (!this->frag)
! 2866: {
! 2867: return INVALID_STATE;
! 2868: }
! 2869: payload = message->get_payload(message, PLV2_FRAGMENT);
! 2870: if (!payload || this->message_id != message->get_message_id(message))
! 2871: {
! 2872: return INVALID_ARG;
! 2873: }
! 2874: encrypted_fragment = (encrypted_fragment_payload_t*)payload;
! 2875: total = encrypted_fragment->get_total_fragments(encrypted_fragment);
! 2876: if (total > MAX_FRAGMENTS)
! 2877: {
! 2878: DBG1(DBG_IKE, "maximum fragment count exceeded");
! 2879: reset_defrag(this);
! 2880: return FAILED;
! 2881: }
! 2882: if (!this->fragments || total > this->frag->last)
! 2883: {
! 2884: reset_defrag(this);
! 2885: this->frag->last = total;
! 2886: this->fragments = array_create(0, total);
! 2887: }
! 2888: num = encrypted_fragment->get_fragment_number(encrypted_fragment);
! 2889: data = encrypted_fragment->get_content(encrypted_fragment);
! 2890: status = add_fragment(this, num, data);
! 2891: if (status != SUCCESS)
! 2892: {
! 2893: return status;
! 2894: }
! 2895:
! 2896: if (num == 1)
! 2897: {
! 2898: /* the first fragment denotes the payload type of the first payload in
! 2899: * the original encrypted payload, cache that */
! 2900: this->first_payload = payload->get_next_type(payload);
! 2901: /* move all unencrypted payloads contained in the first fragment */
! 2902: enumerator = message->create_payload_enumerator(message);
! 2903: while (enumerator->enumerate(enumerator, &payload))
! 2904: {
! 2905: if (payload->get_type(payload) != PLV2_FRAGMENT)
! 2906: {
! 2907: message->remove_payload_at(message, enumerator);
! 2908: this->payloads->insert_last(this->payloads, payload);
! 2909: }
! 2910: }
! 2911: enumerator->destroy(enumerator);
! 2912: }
! 2913:
! 2914: if (array_count(this->fragments) != total)
! 2915: {
! 2916: /* there are some fragments missing */
! 2917: DBG1(DBG_ENC, "received fragment #%hu of %hu, waiting for complete IKE "
! 2918: "message", num, total);
! 2919: return NEED_MORE;
! 2920: }
! 2921:
! 2922: encrypted = (encrypted_payload_t*)encrypted_fragment;
! 2923: aead = encrypted->get_transform(encrypted);
! 2924:
! 2925: data = merge_fragments(this, message);
! 2926:
! 2927: encrypted = encrypted_payload_create_from_plain(this->first_payload, data);
! 2928: encrypted->set_transform(encrypted, aead);
! 2929: this->payloads->insert_last(this->payloads, encrypted);
! 2930: /* update next payload type (could be an unencrypted payload) */
! 2931: this->payloads->get_first(this->payloads, (void**)&payload);
! 2932: this->first_payload = payload->get_type(payload);
! 2933:
! 2934: /* we report the length of the complete IKE message when splitting, do the
! 2935: * same here, so add the IKEv2 header len to the reassembled payload data */
! 2936: len = 28;
! 2937: enumerator = create_payload_enumerator(this);
! 2938: while (enumerator->enumerate(enumerator, &payload))
! 2939: {
! 2940: len += payload->get_length(payload);
! 2941: }
! 2942: enumerator->destroy(enumerator);
! 2943:
! 2944: DBG1(DBG_ENC, "received fragment #%hu of %hu, reassembled fragmented IKE "
! 2945: "message (%zu bytes)", num, total, len);
! 2946: return SUCCESS;
! 2947: }
! 2948:
! 2949: METHOD(message_t, destroy, void,
! 2950: private_message_t *this)
! 2951: {
! 2952: DESTROY_IF(this->ike_sa_id);
! 2953: DESTROY_IF(this->parser);
! 2954: this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
! 2955: this->packet->destroy(this->packet);
! 2956: if (this->frag)
! 2957: {
! 2958: reset_defrag(this);
! 2959: free(this->frag);
! 2960: }
! 2961: else
! 2962: {
! 2963: array_destroy_offset(this->fragments, offsetof(packet_t, destroy));
! 2964: }
! 2965: free(this);
! 2966: }
! 2967:
! 2968: /*
! 2969: * Described in header.
! 2970: */
! 2971: message_t *message_create_from_packet(packet_t *packet)
! 2972: {
! 2973: private_message_t *this;
! 2974:
! 2975: INIT(this,
! 2976: .public = {
! 2977: .set_major_version = _set_major_version,
! 2978: .get_major_version = _get_major_version,
! 2979: .set_minor_version = _set_minor_version,
! 2980: .get_minor_version = _get_minor_version,
! 2981: .set_message_id = _set_message_id,
! 2982: .get_message_id = _get_message_id,
! 2983: .get_initiator_spi = _get_initiator_spi,
! 2984: .get_responder_spi = _get_responder_spi,
! 2985: .set_ike_sa_id = _set_ike_sa_id,
! 2986: .get_ike_sa_id = _get_ike_sa_id,
! 2987: .set_exchange_type = _set_exchange_type,
! 2988: .get_exchange_type = _get_exchange_type,
! 2989: .get_first_payload_type = _get_first_payload_type,
! 2990: .set_request = _set_request,
! 2991: .get_request = _get_request,
! 2992: .set_version_flag = _set_version_flag,
! 2993: .get_reserved_header_bit = _get_reserved_header_bit,
! 2994: .set_reserved_header_bit = _set_reserved_header_bit,
! 2995: .add_payload = _add_payload,
! 2996: .add_notify = _add_notify,
! 2997: .disable_sort = _disable_sort,
! 2998: .generate = _generate,
! 2999: .is_encoded = _is_encoded,
! 3000: .is_fragmented = _is_fragmented,
! 3001: .fragment = _fragment,
! 3002: .add_fragment = _add_fragment_v2,
! 3003: .set_source = _set_source,
! 3004: .get_source = _get_source,
! 3005: .set_destination = _set_destination,
! 3006: .get_destination = _get_destination,
! 3007: .create_payload_enumerator = _create_payload_enumerator,
! 3008: .remove_payload_at = _remove_payload_at,
! 3009: .get_payload = _get_payload,
! 3010: .get_notify = _get_notify,
! 3011: .parse_header = _parse_header,
! 3012: .parse_body = _parse_body,
! 3013: .get_packet = _get_packet,
! 3014: .get_packet_data = _get_packet_data,
! 3015: .get_fragments = _get_fragments,
! 3016: .destroy = _destroy,
! 3017: },
! 3018: .exchange_type = EXCHANGE_TYPE_UNDEFINED,
! 3019: .is_request = TRUE,
! 3020: .first_payload = PL_NONE,
! 3021: .packet = packet,
! 3022: .payloads = linked_list_create(),
! 3023: .parser = parser_create(packet->get_data(packet)),
! 3024: );
! 3025:
! 3026: return &this->public;
! 3027: }
! 3028:
! 3029: /*
! 3030: * Described in header.
! 3031: */
! 3032: message_t *message_create(int major, int minor)
! 3033: {
! 3034: message_t *this = message_create_from_packet(packet_create());
! 3035:
! 3036: this->set_major_version(this, major);
! 3037: this->set_minor_version(this, minor);
! 3038:
! 3039: return this;
! 3040: }
! 3041:
! 3042: /*
! 3043: * Described in header.
! 3044: */
! 3045: message_t *message_create_defrag(message_t *fragment)
! 3046: {
! 3047: private_message_t *this;
! 3048:
! 3049: if (!fragment->get_payload(fragment, PLV1_FRAGMENT) &&
! 3050: !fragment->get_payload(fragment, PLV2_FRAGMENT))
! 3051: {
! 3052: return NULL;
! 3053: }
! 3054: this = (private_message_t*)clone_message((private_message_t*)fragment);
! 3055: /* we don't need a parser for IKEv2, the one for IKEv1 is created after
! 3056: * reassembling the original message */
! 3057: this->parser->destroy(this->parser);
! 3058: this->parser = NULL;
! 3059: if (fragment->get_major_version(fragment) == IKEV1_MAJOR_VERSION)
! 3060: {
! 3061: /* we store the fragment ID in the message ID field, which should be
! 3062: * zero for fragments, but make sure */
! 3063: this->message_id = 0;
! 3064: this->public.add_fragment = _add_fragment_v1;
! 3065: }
! 3066: INIT(this->frag,
! 3067: .max_packet = lib->settings->get_int(lib->settings,
! 3068: "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
! 3069: );
! 3070: return &this->public;
! 3071: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>