Annotation of embedaddon/strongswan/src/libimcv/seg/seg_env.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2014-2015 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "seg_env.h"
! 17:
! 18: #include "imcv.h"
! 19: #include "pa_tnc/pa_tnc_msg.h"
! 20: #include "ietf/ietf_attr_pa_tnc_error.h"
! 21: #include "tcg/seg/tcg_seg_attr_seg_env.h"
! 22:
! 23: #include <utils/debug.h>
! 24: #include <bio/bio_reader.h>
! 25: #include <bio/bio_writer.h>
! 26:
! 27: #define BASE_ATTR_ID_PREFIX 0xFF
! 28:
! 29: typedef struct private_seg_env_t private_seg_env_t;
! 30:
! 31: /**
! 32: * Private data of a seg_env_t object.
! 33: */
! 34: struct private_seg_env_t {
! 35:
! 36: /**
! 37: * Public seg_env_t interface.
! 38: */
! 39: seg_env_t public;
! 40:
! 41: /**
! 42: * Base Attribute ID
! 43: */
! 44: uint32_t base_attr_id;
! 45:
! 46: /**
! 47: * Base Attribute
! 48: */
! 49: pa_tnc_attr_t *base_attr;
! 50:
! 51: /**
! 52: * Base Attribute Info to be used for PA-TNC error messages
! 53: */
! 54: u_char base_attr_info[8];
! 55:
! 56: /**
! 57: * Base Attribute needs more segment data
! 58: */
! 59: bool need_more;
! 60:
! 61: /**
! 62: * Pointer to remaining attribute data to be sent
! 63: */
! 64: chunk_t data;
! 65:
! 66: /**
! 67: * Maximum PA-TNC attribute segment size
! 68: */
! 69: uint32_t max_seg_size;
! 70:
! 71: };
! 72:
! 73: METHOD(seg_env_t, get_base_attr_id, uint32_t,
! 74: private_seg_env_t *this)
! 75: {
! 76: return this->base_attr_id;
! 77: }
! 78:
! 79: METHOD(seg_env_t, get_base_attr, pa_tnc_attr_t*,
! 80: private_seg_env_t *this)
! 81: {
! 82: return this->need_more ? NULL : this->base_attr->get_ref(this->base_attr);
! 83: }
! 84:
! 85: METHOD(seg_env_t, get_base_attr_info, chunk_t,
! 86: private_seg_env_t *this)
! 87: {
! 88: return chunk_create(this->base_attr_info, 8);
! 89: }
! 90:
! 91: METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
! 92: private_seg_env_t *this, size_t max_attr_len)
! 93: {
! 94: pa_tnc_attr_t *seg_env_attr;
! 95: bio_writer_t *writer;
! 96: pen_type_t type;
! 97: chunk_t segment_data, value;
! 98: size_t seg_size;
! 99: uint8_t flags, seg_env_flags;
! 100:
! 101: /* compute size of first segment */
! 102: seg_size = max_attr_len ? min(this->max_seg_size,
! 103: max_attr_len - PA_TNC_ATTR_HEADER_SIZE
! 104: - TCG_SEG_ATTR_SEG_ENV_HEADER)
! 105: : this->max_seg_size;
! 106:
! 107: /* get components of base attribute header and data */
! 108: flags = this->base_attr->get_noskip_flag(this->base_attr) ?
! 109: PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE;
! 110: type = this->base_attr->get_type(this->base_attr);
! 111:
! 112: /* attribute data going into the first segment */
! 113: segment_data = this->data;
! 114: segment_data.len = seg_size - PA_TNC_ATTR_HEADER_SIZE;
! 115:
! 116: /* build encoding of the base attribute header and first segment data */
! 117: writer = bio_writer_create(this->max_seg_size);
! 118: writer->write_uint8 (writer, flags);
! 119: writer->write_uint24(writer, type.vendor_id);
! 120: writer->write_uint32(writer, type.type);
! 121: writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + this->data.len);
! 122: writer->write_data (writer, segment_data);
! 123: value = writer->extract_buf(writer);
! 124: writer->destroy(writer);
! 125: this->data = chunk_skip(this->data, segment_data.len);
! 126:
! 127: DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)",
! 128: this->base_attr_id, seg_size);
! 129:
! 130: seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE;
! 131: seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags,
! 132: this->base_attr_id);
! 133: chunk_free(&value);
! 134:
! 135: return seg_env_attr;
! 136: }
! 137:
! 138: METHOD(seg_env_t, next_segment, pa_tnc_attr_t*,
! 139: private_seg_env_t *this, bool *last)
! 140: {
! 141: pa_tnc_attr_t *seg_env_attr;
! 142: chunk_t segment_data;
! 143: uint8_t seg_env_flags;
! 144: bool is_last_segment;
! 145:
! 146: if (this->data.len == 0)
! 147: {
! 148: /* no more attribute data to segment available */
! 149: return NULL;
! 150: }
! 151:
! 152: /* attribute data going into the next segment */
! 153: segment_data = this->data;
! 154: segment_data.len = min(this->max_seg_size, this->data.len);
! 155: this->data = chunk_skip(this->data, segment_data.len);
! 156:
! 157: is_last_segment = (this->data.len == 0);
! 158: if (last)
! 159: {
! 160: *last = is_last_segment;
! 161: }
! 162: DBG2(DBG_TNC, "creating %s segment for base attribute ID %d (%d bytes)",
! 163: is_last_segment ? "last" : "next", this->base_attr_id,
! 164: segment_data.len);
! 165:
! 166: seg_env_flags = is_last_segment ? SEG_ENV_FLAG_NONE : SEG_ENV_FLAG_MORE;
! 167: seg_env_attr = tcg_seg_attr_seg_env_create(segment_data, seg_env_flags,
! 168: this->base_attr_id);
! 169:
! 170: return seg_env_attr;
! 171: }
! 172:
! 173: METHOD(seg_env_t, add_segment, bool,
! 174: private_seg_env_t *this, chunk_t segment, pa_tnc_attr_t **error)
! 175: {
! 176: pen_type_t type, error_code;
! 177: uint32_t attr_offset;
! 178: chunk_t msg_info;
! 179: status_t status;
! 180:
! 181: this->base_attr->add_segment(this->base_attr, segment);
! 182: status = this->base_attr->process(this->base_attr, &attr_offset);
! 183:
! 184: if (status != SUCCESS && status != NEED_MORE)
! 185: {
! 186: type = this->base_attr->get_type(this->base_attr);
! 187: if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
! 188: {
! 189: /* error while processing a PA-TNC error attribute - abort */
! 190: return FALSE;
! 191: }
! 192: error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
! 193: msg_info = get_base_attr_info(this);
! 194: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 195: msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
! 196: return FALSE;
! 197: }
! 198: this->need_more = (status == NEED_MORE);
! 199:
! 200: return TRUE;
! 201: }
! 202:
! 203: METHOD(seg_env_t, destroy, void,
! 204: private_seg_env_t *this)
! 205: {
! 206: DESTROY_IF(this->base_attr);
! 207: free(this);
! 208: }
! 209:
! 210: /**
! 211: * See header
! 212: */
! 213: seg_env_t *seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
! 214: uint32_t max_seg_size)
! 215: {
! 216: private_seg_env_t *this;
! 217: chunk_t value;
! 218:
! 219: base_attr->build(base_attr);
! 220: value = base_attr->get_value(base_attr);
! 221:
! 222: /**
! 223: * The PA-TNC attribute header must not be segmented and
! 224: * there must be at least a first and one next segment
! 225: */
! 226: if (max_seg_size < PA_TNC_ATTR_HEADER_SIZE ||
! 227: max_seg_size >= PA_TNC_ATTR_HEADER_SIZE + value.len)
! 228: {
! 229: base_attr->destroy(base_attr);
! 230: return NULL;
! 231: }
! 232:
! 233: INIT(this,
! 234: .public = {
! 235: .get_base_attr_id = _get_base_attr_id,
! 236: .get_base_attr = _get_base_attr,
! 237: .get_base_attr_info = _get_base_attr_info,
! 238: .first_segment = _first_segment,
! 239: .next_segment = _next_segment,
! 240: .add_segment = _add_segment,
! 241: .destroy = _destroy,
! 242: },
! 243: .base_attr_id = base_attr_id,
! 244: .base_attr = base_attr,
! 245: .max_seg_size = max_seg_size,
! 246: .data = base_attr->get_value(base_attr),
! 247: );
! 248:
! 249: return &this->public;
! 250: }
! 251:
! 252: /**
! 253: * See header
! 254: */
! 255: seg_env_t *seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
! 256: uint32_t max_seg_size, pa_tnc_attr_t** error)
! 257: {
! 258: private_seg_env_t *this;
! 259: pen_type_t type, error_code;
! 260: bio_reader_t *reader;
! 261: chunk_t msg_info;
! 262: uint32_t offset = 0, attr_offset;
! 263: status_t status;
! 264:
! 265: INIT(this,
! 266: .public = {
! 267: .get_base_attr_id = _get_base_attr_id,
! 268: .get_base_attr = _get_base_attr,
! 269: .get_base_attr_info = _get_base_attr_info,
! 270: .first_segment = _first_segment,
! 271: .next_segment = _next_segment,
! 272: .add_segment = _add_segment,
! 273: .destroy = _destroy,
! 274: },
! 275: .base_attr_id = base_attr_id,
! 276: .max_seg_size = max_seg_size,
! 277: );
! 278:
! 279: /* create info field to be used by PA-TNC error messages */
! 280: memset(this->base_attr_info, 0xff, 4);
! 281: htoun32(this->base_attr_info + 4, base_attr_id);
! 282: msg_info = get_base_attr_info(this);
! 283:
! 284: /* extract from base attribute segment from data */
! 285: reader = bio_reader_create(data);
! 286: this->base_attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
! 287: reader, TRUE, &offset, msg_info, error);
! 288: reader->destroy(reader);
! 289:
! 290: if (!this->base_attr)
! 291: {
! 292: destroy(this);
! 293: return NULL;
! 294: }
! 295: status = this->base_attr->process(this->base_attr, &attr_offset);
! 296:
! 297: if (status != SUCCESS && status != NEED_MORE)
! 298: {
! 299: type = this->base_attr->get_type(this->base_attr);
! 300: if (!(type.vendor_id == PEN_IETF &&
! 301: type.type == IETF_ATTR_PA_TNC_ERROR))
! 302: {
! 303: error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
! 304: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
! 305: msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
! 306: }
! 307: destroy(this);
! 308: return NULL;
! 309: }
! 310: this->need_more = (status == NEED_MORE);
! 311:
! 312: return &this->public;
! 313: }
! 314:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>