Return to delete_payload.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / encoding / payloads |
1.1 misho 1: /* 2: * Copyright (C) 2015 Tobias Brunner 3: * Copyright (C) 2005-2010 Martin Willi 4: * Copyright (C) 2010 revosec AG 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 "delete_payload.h" 22: 23: 24: typedef struct private_delete_payload_t private_delete_payload_t; 25: 26: /** 27: * Private data of an delete_payload_t object. 28: */ 29: struct private_delete_payload_t { 30: 31: /** 32: * Public delete_payload_t interface. 33: */ 34: delete_payload_t public; 35: 36: /** 37: * Next payload type. 38: */ 39: uint8_t next_payload; 40: 41: /** 42: * Critical flag. 43: */ 44: bool critical; 45: 46: /** 47: * reserved bits 48: */ 49: bool reserved[8]; 50: 51: /** 52: * Length of this payload. 53: */ 54: uint16_t payload_length; 55: 56: /** 57: * IKEv1 Domain of Interpretation 58: */ 59: uint32_t doi; 60: 61: /** 62: * Protocol ID. 63: */ 64: uint8_t protocol_id; 65: 66: /** 67: * SPI Size. 68: */ 69: uint8_t spi_size; 70: 71: /** 72: * Number of SPI's. 73: */ 74: uint16_t spi_count; 75: 76: /** 77: * The contained SPI's. 78: */ 79: chunk_t spis; 80: 81: /** 82: * Payload type, PLV2_DELETE or PLV1_DELETE 83: */ 84: payload_type_t type; 85: }; 86: 87: /** 88: * Encoding rules for an IKEv2 delete payload. 89: */ 90: static encoding_rule_t encodings_v2[] = { 91: /* 1 Byte next payload type, stored in the field next_payload */ 92: { U_INT_8, offsetof(private_delete_payload_t, next_payload) }, 93: /* the critical bit */ 94: { FLAG, offsetof(private_delete_payload_t, critical) }, 95: /* 7 Bit reserved bits */ 96: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) }, 97: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) }, 98: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) }, 99: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) }, 100: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) }, 101: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) }, 102: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) }, 103: /* Length of the whole payload*/ 104: { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) }, 105: { U_INT_8, offsetof(private_delete_payload_t, protocol_id) }, 106: { U_INT_8, offsetof(private_delete_payload_t, spi_size) }, 107: { U_INT_16, offsetof(private_delete_payload_t, spi_count) }, 108: /* some delete data bytes, length is defined in PAYLOAD_LENGTH */ 109: { CHUNK_DATA, offsetof(private_delete_payload_t, spis) }, 110: }; 111: 112: /* 113: 1 2 3 114: 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 115: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 116: ! Next Payload !C! RESERVED ! Payload Length ! 117: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 118: ! Protocol ID ! SPI Size ! # of SPIs ! 119: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 120: ! ! 121: ~ Security Parameter Index(es) (SPI) ~ 122: ! ! 123: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 124: */ 125: 126: /** 127: * Encoding rules for an IKEv1 delete payload. 128: */ 129: static encoding_rule_t encodings_v1[] = { 130: /* 1 Byte next payload type, stored in the field next_payload */ 131: { U_INT_8, offsetof(private_delete_payload_t, next_payload) }, 132: /* 8 Bit reserved bits */ 133: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) }, 134: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) }, 135: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) }, 136: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) }, 137: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) }, 138: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) }, 139: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) }, 140: { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[7]) }, 141: /* Length of the whole payload*/ 142: { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) }, 143: /* Domain of interpretation */ 144: { U_INT_32, offsetof(private_delete_payload_t, doi) }, 145: { U_INT_8, offsetof(private_delete_payload_t, protocol_id) }, 146: { U_INT_8, offsetof(private_delete_payload_t, spi_size) }, 147: { U_INT_16, offsetof(private_delete_payload_t, spi_count) }, 148: /* some delete data bytes, length is defined in PAYLOAD_LENGTH */ 149: { CHUNK_DATA, offsetof(private_delete_payload_t, spis) }, 150: }; 151: 152: /* 153: 1 2 3 154: 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 155: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 156: ! Next Payload !C! RESERVED ! Payload Length ! 157: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 158: ! DOI ! 159: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 160: ! Protocol ID ! SPI Size ! # of SPIs ! 161: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 162: ! ! 163: ~ Security Parameter Index(es) (SPI) ~ 164: ! ! 165: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 166: */ 167: 168: METHOD(payload_t, verify, status_t, 169: private_delete_payload_t *this) 170: { 171: switch (this->protocol_id) 172: { 173: case PROTO_AH: 174: case PROTO_ESP: 175: if (this->spi_size != 4) 176: { 177: return FAILED; 178: } 179: break; 180: case PROTO_IKE: 181: case 0: 182: if (this->type == PLV2_DELETE) 183: { /* IKEv2 deletion has no spi assigned! */ 184: if (this->spi_size != 0) 185: { 186: return FAILED; 187: } 188: } 189: else 190: { /* IKEv1 uses the two concatenated ISAKMP cookies as SPI */ 191: if (this->spi_size != 16) 192: { 193: return FAILED; 194: } 195: } 196: break; 197: default: 198: return FAILED; 199: } 200: if (this->spis.len != (this->spi_count * this->spi_size)) 201: { 202: return FAILED; 203: } 204: return SUCCESS; 205: } 206: 207: METHOD(payload_t, get_encoding_rules, int, 208: private_delete_payload_t *this, encoding_rule_t **rules) 209: { 210: if (this->type == PLV2_DELETE) 211: { 212: *rules = encodings_v2; 213: return countof(encodings_v2); 214: } 215: *rules = encodings_v1; 216: return countof(encodings_v1); 217: } 218: 219: METHOD(payload_t, get_header_length, int, 220: private_delete_payload_t *this) 221: { 222: if (this->type == PLV2_DELETE) 223: { 224: return 8; 225: } 226: return 12; 227: } 228: 229: METHOD(payload_t, get_payload_type, payload_type_t, 230: private_delete_payload_t *this) 231: { 232: return this->type; 233: } 234: 235: METHOD(payload_t, get_next_type, payload_type_t, 236: private_delete_payload_t *this) 237: { 238: return this->next_payload; 239: } 240: 241: METHOD(payload_t, set_next_type, void, 242: private_delete_payload_t *this,payload_type_t type) 243: { 244: this->next_payload = type; 245: } 246: 247: METHOD(payload_t, get_length, size_t, 248: private_delete_payload_t *this) 249: { 250: return this->payload_length; 251: } 252: 253: METHOD(delete_payload_t, get_protocol_id, protocol_id_t, 254: private_delete_payload_t *this) 255: { 256: return this->protocol_id; 257: } 258: 259: METHOD(delete_payload_t, add_spi, void, 260: private_delete_payload_t *this, uint32_t spi) 261: { 262: switch (this->protocol_id) 263: { 264: case PROTO_AH: 265: case PROTO_ESP: 266: this->spi_count++; 267: this->payload_length += sizeof(spi); 268: this->spis = chunk_cat("mc", this->spis, chunk_from_thing(spi)); 269: break; 270: default: 271: break; 272: } 273: } 274: 275: METHOD(delete_payload_t, set_ike_spi, void, 276: private_delete_payload_t *this, uint64_t spi_i, uint64_t spi_r) 277: { 278: free(this->spis.ptr); 279: this->spis = chunk_cat("cc", chunk_from_thing(spi_i), 280: chunk_from_thing(spi_r)); 281: this->spi_count = 1; 282: this->payload_length = get_header_length(this) + this->spi_size; 283: } 284: 285: METHOD(delete_payload_t, get_ike_spi, bool, 286: private_delete_payload_t *this, uint64_t *spi_i, uint64_t *spi_r) 287: { 288: if (this->protocol_id != PROTO_IKE || 289: this->spis.len < 2 * sizeof(uint64_t)) 290: { 291: return FALSE; 292: } 293: memcpy(spi_i, this->spis.ptr, sizeof(uint64_t)); 294: memcpy(spi_r, this->spis.ptr + sizeof(uint64_t), sizeof(uint64_t)); 295: return TRUE; 296: } 297: 298: /** 299: * SPI enumerator implementation 300: */ 301: typedef struct { 302: /** implements enumerator_t */ 303: enumerator_t public; 304: /** remaining SPIs */ 305: chunk_t spis; 306: } spi_enumerator_t; 307: 308: METHOD(enumerator_t, spis_enumerate, bool, 309: spi_enumerator_t *this, va_list args) 310: { 311: uint32_t *spi; 312: 313: VA_ARGS_VGET(args, spi); 314: 315: if (this->spis.len >= sizeof(*spi)) 316: { 317: memcpy(spi, this->spis.ptr, sizeof(*spi)); 318: this->spis = chunk_skip(this->spis, sizeof(*spi)); 319: return TRUE; 320: } 321: return FALSE; 322: } 323: 324: METHOD(delete_payload_t, create_spi_enumerator, enumerator_t*, 325: private_delete_payload_t *this) 326: { 327: spi_enumerator_t *e; 328: 329: if (this->spi_size != sizeof(uint32_t)) 330: { 331: return enumerator_create_empty(); 332: } 333: INIT(e, 334: .public = { 335: .enumerate = enumerator_enumerate_default, 336: .venumerate = _spis_enumerate, 337: .destroy = (void*)free, 338: }, 339: .spis = this->spis, 340: ); 341: return &e->public; 342: } 343: 344: METHOD2(payload_t, delete_payload_t, destroy, void, 345: private_delete_payload_t *this) 346: { 347: free(this->spis.ptr); 348: free(this); 349: } 350: 351: /* 352: * Described in header 353: */ 354: delete_payload_t *delete_payload_create(payload_type_t type, 355: protocol_id_t protocol_id) 356: { 357: private_delete_payload_t *this; 358: 359: INIT(this, 360: .public = { 361: .payload_interface = { 362: .verify = _verify, 363: .get_encoding_rules = _get_encoding_rules, 364: .get_header_length = _get_header_length, 365: .get_length = _get_length, 366: .get_next_type = _get_next_type, 367: .set_next_type = _set_next_type, 368: .get_type = _get_payload_type, 369: .destroy = _destroy, 370: }, 371: .get_protocol_id = _get_protocol_id, 372: .add_spi = _add_spi, 373: .set_ike_spi = _set_ike_spi, 374: .get_ike_spi = _get_ike_spi, 375: .create_spi_enumerator = _create_spi_enumerator, 376: .destroy = _destroy, 377: }, 378: .next_payload = PL_NONE, 379: .protocol_id = protocol_id, 380: .doi = IKEV1_DOI_IPSEC, 381: .type = type, 382: ); 383: this->payload_length = get_header_length(this); 384: 385: if (protocol_id == PROTO_IKE) 386: { 387: if (type == PLV1_DELETE) 388: { 389: this->spi_size = 16; 390: } 391: } 392: else 393: { 394: this->spi_size = 4; 395: } 396: return &this->public; 397: }