Return to id_payload.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / encoding / payloads |
1.1 misho 1: /* 2: * Copyright (C) 2005-2011 Martin Willi 3: * Copyright (C) 2010 revosec AG 4: * Copyright (C) 2007-2011 Tobias Brunner 5: * Copyright (C) 2005 Jan Hutter 6: * HSR Hochschule fuer Technik Rapperswil 7: * 8: * This program is free software; you can redistribute it and/or modify it 9: * under the terms of the GNU General Public License as published by the 10: * Free Software Foundation; either version 2 of the License, or (at your 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 12: * 13: * This program is distributed in the hope that it will be useful, but 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16: * for more details. 17: */ 18: 19: #include <stddef.h> 20: 21: #include "id_payload.h" 22: 23: #include <daemon.h> 24: #include <encoding/payloads/encodings.h> 25: 26: typedef struct private_id_payload_t private_id_payload_t; 27: 28: /** 29: * Private data of an id_payload_t object. 30: */ 31: struct private_id_payload_t { 32: 33: /** 34: * Public id_payload_t interface. 35: */ 36: id_payload_t public; 37: 38: /** 39: * Next payload type. 40: */ 41: uint8_t next_payload; 42: 43: /** 44: * Critical flag. 45: */ 46: bool critical; 47: 48: /** 49: * Reserved bits 50: */ 51: bool reserved_bit[7]; 52: 53: /** 54: * Reserved bytes 55: */ 56: uint8_t reserved_byte[3]; 57: 58: /** 59: * Length of this payload. 60: */ 61: uint16_t payload_length; 62: 63: /** 64: * Type of the ID Data. 65: */ 66: uint8_t id_type; 67: 68: /** 69: * The contained id data value. 70: */ 71: chunk_t id_data; 72: 73: /** 74: * Tunneled protocol ID for IKEv1 quick modes. 75: */ 76: uint8_t protocol_id; 77: 78: /** 79: * Tunneled port for IKEv1 quick modes. 80: */ 81: uint16_t port; 82: 83: /** 84: * one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, IDv1 and PLV1_NAT_OA 85: */ 86: payload_type_t type; 87: }; 88: 89: /** 90: * Encoding rules for an IKEv2 ID payload 91: */ 92: static encoding_rule_t encodings_v2[] = { 93: /* 1 Byte next payload type, stored in the field next_payload */ 94: { U_INT_8, offsetof(private_id_payload_t, next_payload) }, 95: /* the critical bit */ 96: { FLAG, offsetof(private_id_payload_t, critical) }, 97: /* 7 Bit reserved bits */ 98: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) }, 99: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) }, 100: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[2]) }, 101: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[3]) }, 102: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[4]) }, 103: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) }, 104: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) }, 105: /* Length of the whole payload*/ 106: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) }, 107: /* 1 Byte ID type*/ 108: { U_INT_8, offsetof(private_id_payload_t, id_type) }, 109: /* 3 reserved bytes */ 110: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])}, 111: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])}, 112: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])}, 113: /* some id data bytes, length is defined in PAYLOAD_LENGTH */ 114: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) }, 115: }; 116: 117: /* 118: 1 2 3 119: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 120: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 121: ! Next Payload !C! RESERVED ! Payload Length ! 122: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 123: ! ID Type ! RESERVED | 124: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 125: ! ! 126: ~ Identification Data ~ 127: ! ! 128: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 129: */ 130: 131: /** 132: * Encoding rules for an IKEv1 ID payload 133: */ 134: static encoding_rule_t encodings_v1[] = { 135: /* 1 Byte next payload type, stored in the field next_payload */ 136: { U_INT_8, offsetof(private_id_payload_t, next_payload) }, 137: /* Reserved Byte is skipped */ 138: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])}, 139: /* Length of the whole payload*/ 140: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) }, 141: /* 1 Byte ID type*/ 142: { U_INT_8, offsetof(private_id_payload_t, id_type) }, 143: { U_INT_8, offsetof(private_id_payload_t, protocol_id) }, 144: { U_INT_16, offsetof(private_id_payload_t, port) }, 145: /* some id data bytes, length is defined in PAYLOAD_LENGTH */ 146: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) }, 147: }; 148: 149: /* 150: 1 2 3 151: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 152: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 153: ! Next Payload ! RESERVED ! Payload Length ! 154: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 155: ! ID Type ! Protocol ID ! Port | 156: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 157: ! ! 158: ~ Identification Data ~ 159: ! ! 160: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 161: */ 162: 163: METHOD(payload_t, verify, status_t, 164: private_id_payload_t *this) 165: { 166: bool bad_length = FALSE; 167: 168: if ((this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) && 169: this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR) 170: { 171: DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names, 172: this->id_type, payload_type_short_names, this->type); 173: return FAILED; 174: } 175: switch (this->id_type) 176: { 177: case ID_IPV4_ADDR_RANGE: 178: case ID_IPV4_ADDR_SUBNET: 179: bad_length = this->id_data.len != 8; 180: break; 181: case ID_IPV6_ADDR_RANGE: 182: case ID_IPV6_ADDR_SUBNET: 183: bad_length = this->id_data.len != 32; 184: break; 185: } 186: if (bad_length) 187: { 188: DBG1(DBG_ENC, "invalid %N length (%d bytes)", 189: id_type_names, this->id_type, this->id_data.len); 190: return FAILED; 191: } 192: return SUCCESS; 193: } 194: 195: METHOD(payload_t, get_encoding_rules, int, 196: private_id_payload_t *this, encoding_rule_t **rules) 197: { 198: if (this->type == PLV1_ID || 199: this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) 200: { 201: *rules = encodings_v1; 202: return countof(encodings_v1); 203: } 204: *rules = encodings_v2; 205: return countof(encodings_v2); 206: } 207: 208: METHOD(payload_t, get_header_length, int, 209: private_id_payload_t *this) 210: { 211: return 8; 212: } 213: 214: METHOD(payload_t, get_type, payload_type_t, 215: private_id_payload_t *this) 216: { 217: return this->type; 218: } 219: 220: METHOD(payload_t, get_next_type, payload_type_t, 221: private_id_payload_t *this) 222: { 223: return this->next_payload; 224: } 225: 226: METHOD(payload_t, set_next_type, void, 227: private_id_payload_t *this, payload_type_t type) 228: { 229: this->next_payload = type; 230: } 231: 232: METHOD(payload_t, get_length, size_t, 233: private_id_payload_t *this) 234: { 235: return this->payload_length; 236: } 237: 238: METHOD(id_payload_t, get_identification, identification_t*, 239: private_id_payload_t *this) 240: { 241: return identification_create_from_encoding(this->id_type, this->id_data); 242: } 243: 244: /** 245: * Create a traffic selector from an range ID 246: */ 247: static traffic_selector_t *get_ts_from_range(private_id_payload_t *this, 248: ts_type_t type) 249: { 250: return traffic_selector_create_from_bytes(this->protocol_id, type, 251: chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port, 252: chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535); 253: } 254: 255: /** 256: * Create a traffic selector from an subnet ID 257: */ 258: static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this, 259: ts_type_t type) 260: { 261: traffic_selector_t *ts; 262: chunk_t net, netmask; 263: int i; 264: 265: net = chunk_create(this->id_data.ptr, this->id_data.len / 2); 266: netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2)); 267: for (i = 0; i < net.len; i++) 268: { 269: netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i]; 270: } 271: ts = traffic_selector_create_from_bytes(this->protocol_id, type, 272: net, this->port, netmask, this->port ?: 65535); 273: chunk_free(&netmask); 274: return ts; 275: } 276: 277: /** 278: * Create a traffic selector from an IP ID 279: */ 280: static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this, 281: ts_type_t type) 282: { 283: return traffic_selector_create_from_bytes(this->protocol_id, type, 284: this->id_data, this->port, this->id_data, this->port ?: 65535); 285: } 286: 287: METHOD(id_payload_t, get_ts, traffic_selector_t*, 288: private_id_payload_t *this) 289: { 290: switch (this->id_type) 291: { 292: case ID_IPV4_ADDR_SUBNET: 293: if (this->id_data.len == 8) 294: { 295: return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE); 296: } 297: break; 298: case ID_IPV6_ADDR_SUBNET: 299: if (this->id_data.len == 32) 300: { 301: return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE); 302: } 303: break; 304: case ID_IPV4_ADDR_RANGE: 305: if (this->id_data.len == 8) 306: { 307: return get_ts_from_range(this, TS_IPV4_ADDR_RANGE); 308: } 309: break; 310: case ID_IPV6_ADDR_RANGE: 311: if (this->id_data.len == 32) 312: { 313: return get_ts_from_range(this, TS_IPV6_ADDR_RANGE); 314: } 315: break; 316: case ID_IPV4_ADDR: 317: if (this->id_data.len == 4) 318: { 319: return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE); 320: } 321: break; 322: case ID_IPV6_ADDR: 323: if (this->id_data.len == 16) 324: { 325: return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE); 326: } 327: break; 328: default: 329: break; 330: } 331: return NULL; 332: } 333: 334: METHOD(id_payload_t, get_encoded, chunk_t, 335: private_id_payload_t *this) 336: { 337: uint16_t port = htons(this->port); 338: return chunk_cat("cccc", chunk_from_thing(this->id_type), 339: chunk_from_thing(this->protocol_id), 340: chunk_from_thing(port), this->id_data); 341: } 342: 343: METHOD2(payload_t, id_payload_t, destroy, void, 344: private_id_payload_t *this) 345: { 346: free(this->id_data.ptr); 347: free(this); 348: } 349: 350: /* 351: * Described in header. 352: */ 353: id_payload_t *id_payload_create(payload_type_t type) 354: { 355: private_id_payload_t *this; 356: 357: INIT(this, 358: .public = { 359: .payload_interface = { 360: .verify = _verify, 361: .get_encoding_rules = _get_encoding_rules, 362: .get_header_length = _get_header_length, 363: .get_length = _get_length, 364: .get_next_type = _get_next_type, 365: .set_next_type = _set_next_type, 366: .get_type = _get_type, 367: .destroy = _destroy, 368: }, 369: .get_identification = _get_identification, 370: .get_encoded = _get_encoded, 371: .get_ts = _get_ts, 372: .destroy = _destroy, 373: }, 374: .next_payload = PL_NONE, 375: .payload_length = get_header_length(this), 376: .type = type, 377: ); 378: return &this->public; 379: } 380: 381: /* 382: * Described in header. 383: */ 384: id_payload_t *id_payload_create_from_identification(payload_type_t type, 385: identification_t *id) 386: { 387: private_id_payload_t *this; 388: 389: this = (private_id_payload_t*)id_payload_create(type); 390: this->id_data = chunk_clone(id->get_encoding(id)); 391: this->id_type = id->get_type(id); 392: this->payload_length += this->id_data.len; 393: 394: return &this->public; 395: } 396: 397: /* 398: * Described in header. 399: */ 400: id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts) 401: { 402: private_id_payload_t *this; 403: uint8_t mask; 404: host_t *net; 405: 406: this = (private_id_payload_t*)id_payload_create(PLV1_ID); 407: 408: if (ts->is_host(ts, NULL)) 409: { 410: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) 411: { 412: this->id_type = ID_IPV4_ADDR; 413: } 414: else 415: { 416: this->id_type = ID_IPV6_ADDR; 417: } 418: this->id_data = chunk_clone(ts->get_from_address(ts)); 419: } 420: else if (ts->to_subnet(ts, &net, &mask)) 421: { 422: uint8_t netmask[16], len, byte; 423: 424: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) 425: { 426: this->id_type = ID_IPV4_ADDR_SUBNET; 427: len = 4; 428: } 429: else 430: { 431: this->id_type = ID_IPV6_ADDR_SUBNET; 432: len = 16; 433: } 434: memset(netmask, 0, sizeof(netmask)); 435: for (byte = 0; byte < sizeof(netmask); byte++) 436: { 437: if (mask < 8) 438: { 439: netmask[byte] = 0xFF << (8 - mask); 440: break; 441: } 442: netmask[byte] = 0xFF; 443: mask -= 8; 444: } 445: this->id_data = chunk_cat("cc", net->get_address(net), 446: chunk_create(netmask, len)); 447: net->destroy(net); 448: } 449: else 450: { 451: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) 452: { 453: this->id_type = ID_IPV4_ADDR_RANGE; 454: } 455: else 456: { 457: this->id_type = ID_IPV6_ADDR_RANGE; 458: } 459: this->id_data = chunk_cat("cc", 460: ts->get_from_address(ts), ts->get_to_address(ts)); 461: net->destroy(net); 462: } 463: this->port = ts->get_from_port(ts); 464: this->protocol_id = ts->get_protocol(ts); 465: this->payload_length += this->id_data.len; 466: 467: return &this->public; 468: } 469: