Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/cert_payload.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008 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: #include <ctype.h>
! 21:
! 22: #include <daemon.h>
! 23:
! 24: #include "cert_payload.h"
! 25:
! 26: ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT,
! 27: "ENC_PKCS7_WRAPPED_X509",
! 28: "ENC_PGP",
! 29: "ENC_DNS_SIGNED_KEY",
! 30: "ENC_X509_SIGNATURE",
! 31: "ENC_X509_KEY_EXCHANGE",
! 32: "ENC_KERBEROS_TOKENS",
! 33: "ENC_CRL",
! 34: "ENC_ARL",
! 35: "ENC_SPKI",
! 36: "ENC_X509_ATTRIBUTE",
! 37: "ENC_RAW_RSA_KEY",
! 38: "ENC_X509_HASH_AND_URL",
! 39: "ENC_X509_HASH_AND_URL_BUNDLE",
! 40: "ENC_OCSP_CONTENT",
! 41: );
! 42:
! 43: typedef struct private_cert_payload_t private_cert_payload_t;
! 44:
! 45: /**
! 46: * Private data of an cert_payload_t object.
! 47: */
! 48: struct private_cert_payload_t {
! 49:
! 50: /**
! 51: * Public cert_payload_t interface.
! 52: */
! 53: cert_payload_t public;
! 54:
! 55: /**
! 56: * Next payload type.
! 57: */
! 58: uint8_t next_payload;
! 59:
! 60: /**
! 61: * Critical flag.
! 62: */
! 63: bool critical;
! 64:
! 65: /**
! 66: * reserved bits
! 67: */
! 68: bool reserved[7];
! 69:
! 70: /**
! 71: * Length of this payload.
! 72: */
! 73: uint16_t payload_length;
! 74:
! 75: /**
! 76: * Encoding of the CERT Data.
! 77: */
! 78: uint8_t encoding;
! 79:
! 80: /**
! 81: * The contained cert data value.
! 82: */
! 83: chunk_t data;
! 84:
! 85: /**
! 86: * TRUE if the "Hash and URL" data is invalid
! 87: */
! 88: bool invalid_hash_and_url;
! 89:
! 90: /**
! 91: * The payload type.
! 92: */
! 93: payload_type_t type;
! 94: };
! 95:
! 96: /**
! 97: * Encoding rules to parse or generate a CERT payload
! 98: *
! 99: * The defined offsets are the positions in a object of type
! 100: * private_cert_payload_t.
! 101: *
! 102: */
! 103: static encoding_rule_t encodings[] = {
! 104: /* 1 Byte next payload type, stored in the field next_payload */
! 105: { U_INT_8, offsetof(private_cert_payload_t, next_payload) },
! 106: /* the critical bit */
! 107: { FLAG, offsetof(private_cert_payload_t, critical) },
! 108: /* 7 Bit reserved bits, nowhere stored */
! 109: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[0]) },
! 110: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[1]) },
! 111: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[2]) },
! 112: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[3]) },
! 113: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[4]) },
! 114: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[5]) },
! 115: { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[6]) },
! 116: /* Length of the whole payload*/
! 117: { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)},
! 118: /* 1 Byte CERT type*/
! 119: { U_INT_8, offsetof(private_cert_payload_t, encoding) },
! 120: /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
! 121: { CHUNK_DATA, offsetof(private_cert_payload_t, data) }
! 122: };
! 123:
! 124: /*
! 125: 1 2 3
! 126: 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
! 127: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 128: ! Next Payload !C! RESERVED ! Payload Length !
! 129: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 130: ! Cert Encoding ! !
! 131: +-+-+-+-+-+-+-+-+ !
! 132: ~ Certificate Data ~
! 133: ! !
! 134: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 135: */
! 136:
! 137: METHOD(payload_t, verify, status_t,
! 138: private_cert_payload_t *this)
! 139: {
! 140: if (this->encoding == ENC_X509_HASH_AND_URL ||
! 141: this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
! 142: {
! 143: int i;
! 144:
! 145: /* coarse verification of "Hash and URL" encoded certificates */
! 146: if (this->data.len <= 20)
! 147: {
! 148: DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
! 149: this->data.len);
! 150: this->invalid_hash_and_url = TRUE;
! 151: return SUCCESS;
! 152: }
! 153: for (i = 20; i < this->data.len; ++i)
! 154: {
! 155: if (this->data.ptr[i] == '\0')
! 156: {
! 157: /* null terminated, fine */
! 158: return SUCCESS;
! 159: }
! 160: else if (!isprint(this->data.ptr[i]))
! 161: {
! 162: DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
! 163: " encoded certificate payload, ignore");
! 164: this->invalid_hash_and_url = TRUE;
! 165: return SUCCESS;
! 166: }
! 167: }
! 168: /* URL is not null terminated, correct that */
! 169: this->data = chunk_cat("mc", this->data, chunk_from_chars(0));
! 170: }
! 171: return SUCCESS;
! 172: }
! 173:
! 174: METHOD(payload_t, get_encoding_rules, int,
! 175: private_cert_payload_t *this, encoding_rule_t **rules)
! 176: {
! 177: *rules = encodings;
! 178: return countof(encodings);
! 179: }
! 180:
! 181: METHOD(payload_t, get_header_length, int,
! 182: private_cert_payload_t *this)
! 183: {
! 184: return 5;
! 185: }
! 186:
! 187: METHOD(payload_t, get_type, payload_type_t,
! 188: private_cert_payload_t *this)
! 189: {
! 190: return this->type;
! 191: }
! 192:
! 193: METHOD(payload_t, get_next_type, payload_type_t,
! 194: private_cert_payload_t *this)
! 195: {
! 196: return this->next_payload;
! 197: }
! 198:
! 199: METHOD(payload_t, set_next_type, void,
! 200: private_cert_payload_t *this, payload_type_t type)
! 201: {
! 202: this->next_payload = type;
! 203: }
! 204:
! 205: METHOD(payload_t, get_length, size_t,
! 206: private_cert_payload_t *this)
! 207: {
! 208: return this->payload_length;
! 209: }
! 210:
! 211: METHOD(cert_payload_t, get_cert_encoding, cert_encoding_t,
! 212: private_cert_payload_t *this)
! 213: {
! 214: return this->encoding;
! 215: }
! 216:
! 217: METHOD(cert_payload_t, get_cert, certificate_t*,
! 218: private_cert_payload_t *this)
! 219: {
! 220: int type;
! 221:
! 222: switch (this->encoding)
! 223: {
! 224: case ENC_X509_SIGNATURE:
! 225: type = CERT_X509;
! 226: break;
! 227: case ENC_X509_ATTRIBUTE:
! 228: type = CERT_X509_AC;
! 229: break;
! 230: case ENC_CRL:
! 231: type = CERT_X509_CRL;
! 232: break;
! 233: default:
! 234: return NULL;
! 235: }
! 236: return lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
! 237: BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
! 238: }
! 239:
! 240: METHOD(cert_payload_t, get_container, container_t*,
! 241: private_cert_payload_t *this)
! 242: {
! 243: int type;
! 244:
! 245: switch (this->encoding)
! 246: {
! 247: case ENC_PKCS7_WRAPPED_X509:
! 248: type = CONTAINER_PKCS7;
! 249: break;
! 250: default:
! 251: return NULL;
! 252: }
! 253: return lib->creds->create(lib->creds, CRED_CONTAINER, type,
! 254: BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
! 255: }
! 256:
! 257: METHOD(cert_payload_t, get_hash, chunk_t,
! 258: private_cert_payload_t *this)
! 259: {
! 260: chunk_t hash = chunk_empty;
! 261:
! 262: if ((this->encoding != ENC_X509_HASH_AND_URL &&
! 263: this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
! 264: this->invalid_hash_and_url)
! 265: {
! 266: return hash;
! 267: }
! 268: hash.ptr = this->data.ptr;
! 269: hash.len = 20;
! 270: return hash;
! 271: }
! 272:
! 273: METHOD(cert_payload_t, get_url, char*,
! 274: private_cert_payload_t *this)
! 275: {
! 276: if ((this->encoding != ENC_X509_HASH_AND_URL &&
! 277: this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
! 278: this->invalid_hash_and_url)
! 279: {
! 280: return NULL;
! 281: }
! 282: return (char*)this->data.ptr + 20;
! 283: }
! 284:
! 285: METHOD2(payload_t, cert_payload_t, destroy, void,
! 286: private_cert_payload_t *this)
! 287: {
! 288: free(this->data.ptr);
! 289: free(this);
! 290: }
! 291:
! 292: /*
! 293: * Described in header
! 294: */
! 295: cert_payload_t *cert_payload_create(payload_type_t type)
! 296: {
! 297: private_cert_payload_t *this;
! 298:
! 299: INIT(this,
! 300: .public = {
! 301: .payload_interface = {
! 302: .verify = _verify,
! 303: .get_encoding_rules = _get_encoding_rules,
! 304: .get_header_length = _get_header_length,
! 305: .get_length = _get_length,
! 306: .get_next_type = _get_next_type,
! 307: .set_next_type = _set_next_type,
! 308: .get_type = _get_type,
! 309: .destroy = _destroy,
! 310: },
! 311: .get_cert = _get_cert,
! 312: .get_container = _get_container,
! 313: .get_cert_encoding = _get_cert_encoding,
! 314: .get_hash = _get_hash,
! 315: .get_url = _get_url,
! 316: .destroy = _destroy,
! 317: },
! 318: .next_payload = PL_NONE,
! 319: .payload_length = get_header_length(this),
! 320: .type = type,
! 321: );
! 322: return &this->public;
! 323: }
! 324:
! 325: /*
! 326: * Described in header
! 327: */
! 328: cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
! 329: certificate_t *cert)
! 330: {
! 331: private_cert_payload_t *this;
! 332:
! 333: this = (private_cert_payload_t*)cert_payload_create(type);
! 334: switch (cert->get_type(cert))
! 335: {
! 336: case CERT_X509:
! 337: this->encoding = ENC_X509_SIGNATURE;
! 338: break;
! 339: case CERT_X509_AC:
! 340: this->encoding = ENC_X509_ATTRIBUTE;
! 341: break;
! 342: default:
! 343: DBG1(DBG_ENC, "embedding %N certificate in payload failed",
! 344: certificate_type_names, cert->get_type(cert));
! 345: free(this);
! 346: return NULL;
! 347: }
! 348: if (!cert->get_encoding(cert, CERT_ASN1_DER, &this->data))
! 349: {
! 350: DBG1(DBG_ENC, "encoding certificate for cert payload failed");
! 351: free(this);
! 352: return NULL;
! 353: }
! 354: this->payload_length = get_header_length(this) + this->data.len;
! 355:
! 356: return &this->public;
! 357: }
! 358:
! 359: /*
! 360: * Described in header
! 361: */
! 362: cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
! 363: {
! 364: private_cert_payload_t *this;
! 365:
! 366: this = (private_cert_payload_t*)cert_payload_create(PLV2_CERTIFICATE);
! 367: this->encoding = ENC_X509_HASH_AND_URL;
! 368: this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
! 369: this->payload_length = get_header_length(this) + this->data.len;
! 370:
! 371: return &this->public;
! 372: }
! 373:
! 374: /*
! 375: * Described in header
! 376: */
! 377: cert_payload_t *cert_payload_create_custom(payload_type_t type,
! 378: cert_encoding_t encoding, chunk_t data)
! 379: {
! 380: private_cert_payload_t *this;
! 381:
! 382: this = (private_cert_payload_t*)cert_payload_create(type);
! 383: this->encoding = encoding;
! 384: this->data = data;
! 385: this->payload_length = get_header_length(this) + this->data.len;
! 386:
! 387: return &this->public;
! 388: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>