Return to cert_payload.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / encoding / payloads |
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: }