Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011 Martin Willi
! 3: * Copyright (C) 2011 revosec AG
! 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 "isakmp_cert_post.h"
! 17:
! 18: #include <daemon.h>
! 19: #include <sa/ike_sa.h>
! 20: #include <encoding/payloads/cert_payload.h>
! 21: #include <encoding/payloads/certreq_payload.h>
! 22: #include <encoding/payloads/auth_payload.h>
! 23: #include <encoding/payloads/sa_payload.h>
! 24: #include <credentials/certificates/x509.h>
! 25:
! 26:
! 27: typedef struct private_isakmp_cert_post_t private_isakmp_cert_post_t;
! 28:
! 29: /**
! 30: * Private members of a isakmp_cert_post_t task.
! 31: */
! 32: struct private_isakmp_cert_post_t {
! 33:
! 34: /**
! 35: * Public methods and task_t interface.
! 36: */
! 37: isakmp_cert_post_t public;
! 38:
! 39: /**
! 40: * Assigned IKE_SA.
! 41: */
! 42: ike_sa_t *ike_sa;
! 43:
! 44: /**
! 45: * Are we the initiator?
! 46: */
! 47: bool initiator;
! 48:
! 49: /**
! 50: * States of ike cert pre
! 51: */
! 52: enum {
! 53: CR_SA,
! 54: CR_KE,
! 55: CR_AUTH,
! 56: } state;
! 57: };
! 58:
! 59: /**
! 60: * Check if we actually use certificates for authentication
! 61: */
! 62: static bool use_certs(private_isakmp_cert_post_t *this, message_t *message)
! 63: {
! 64: enumerator_t *enumerator;
! 65: payload_t *payload;
! 66: bool use = FALSE;
! 67:
! 68: enumerator = message->create_payload_enumerator(message);
! 69: while (enumerator->enumerate(enumerator, &payload))
! 70: {
! 71: if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
! 72: {
! 73: sa_payload_t *sa_payload = (sa_payload_t*)payload;
! 74:
! 75: switch (sa_payload->get_auth_method(sa_payload))
! 76: {
! 77: case AUTH_RSA:
! 78: case AUTH_ECDSA_256:
! 79: case AUTH_ECDSA_384:
! 80: case AUTH_ECDSA_521:
! 81: case AUTH_XAUTH_INIT_RSA:
! 82: case AUTH_XAUTH_RESP_RSA:
! 83: case AUTH_HYBRID_INIT_RSA:
! 84: case AUTH_HYBRID_RESP_RSA:
! 85: use = TRUE;
! 86: break;
! 87: default:
! 88: break;
! 89: }
! 90: break;
! 91: }
! 92: }
! 93: enumerator->destroy(enumerator);
! 94:
! 95: return use;
! 96: }
! 97:
! 98: /**
! 99: * Add certificates to message
! 100: */
! 101: static void build_certs(private_isakmp_cert_post_t *this, message_t *message)
! 102: {
! 103: peer_cfg_t *peer_cfg;
! 104:
! 105: peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
! 106: if (!peer_cfg)
! 107: {
! 108: return;
! 109: }
! 110:
! 111: switch (peer_cfg->get_cert_policy(peer_cfg))
! 112: {
! 113: case CERT_NEVER_SEND:
! 114: break;
! 115: case CERT_SEND_IF_ASKED:
! 116: if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
! 117: {
! 118: break;
! 119: }
! 120: /* FALL */
! 121: case CERT_ALWAYS_SEND:
! 122: {
! 123: cert_payload_t *payload;
! 124: enumerator_t *enumerator;
! 125: certificate_t *cert;
! 126: auth_rule_t type;
! 127: auth_cfg_t *auth;
! 128:
! 129: auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
! 130: cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
! 131: if (!cert)
! 132: {
! 133: break;
! 134: }
! 135: payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
! 136: if (!payload)
! 137: {
! 138: break;
! 139: }
! 140: DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
! 141: cert->get_subject(cert));
! 142: message->add_payload(message, (payload_t*)payload);
! 143:
! 144: enumerator = auth->create_enumerator(auth);
! 145: while (enumerator->enumerate(enumerator, &type, &cert))
! 146: {
! 147: if (type == AUTH_RULE_IM_CERT)
! 148: {
! 149: payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
! 150: if (payload)
! 151: {
! 152: DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
! 153: cert->get_subject(cert));
! 154: message->add_payload(message, (payload_t*)payload);
! 155: }
! 156: }
! 157: }
! 158: enumerator->destroy(enumerator);
! 159: }
! 160: }
! 161: }
! 162:
! 163: METHOD(task_t, build_i, status_t,
! 164: private_isakmp_cert_post_t *this, message_t *message)
! 165: {
! 166: switch (message->get_exchange_type(message))
! 167: {
! 168: case ID_PROT:
! 169: if (this->state == CR_AUTH)
! 170: {
! 171: build_certs(this, message);
! 172: return SUCCESS;
! 173: }
! 174: return NEED_MORE;
! 175: case AGGRESSIVE:
! 176: if (this->state == CR_AUTH)
! 177: {
! 178: build_certs(this, message);
! 179: return SUCCESS;
! 180: }
! 181: return NEED_MORE;
! 182: default:
! 183: return FAILED;
! 184: }
! 185: }
! 186:
! 187: METHOD(task_t, process_r, status_t,
! 188: private_isakmp_cert_post_t *this, message_t *message)
! 189: {
! 190: switch (message->get_exchange_type(message))
! 191: {
! 192: case ID_PROT:
! 193: {
! 194: switch (this->state)
! 195: {
! 196: case CR_SA:
! 197: if (!use_certs(this, message))
! 198: {
! 199: return SUCCESS;
! 200: }
! 201: return NEED_MORE;
! 202: case CR_KE:
! 203: return NEED_MORE;
! 204: case CR_AUTH:
! 205: return NEED_MORE;
! 206: default:
! 207: return FAILED;
! 208: }
! 209: }
! 210: case AGGRESSIVE:
! 211: {
! 212: switch (this->state)
! 213: {
! 214: case CR_SA:
! 215: if (!use_certs(this, message))
! 216: {
! 217: return SUCCESS;
! 218: }
! 219: return NEED_MORE;
! 220: case CR_AUTH:
! 221: return SUCCESS;
! 222: default:
! 223: return FAILED;
! 224: }
! 225: }
! 226: default:
! 227: return FAILED;
! 228: }
! 229: }
! 230:
! 231: METHOD(task_t, build_r, status_t,
! 232: private_isakmp_cert_post_t *this, message_t *message)
! 233: {
! 234: switch (message->get_exchange_type(message))
! 235: {
! 236: case ID_PROT:
! 237: switch (this->state)
! 238: {
! 239: case CR_SA:
! 240: this->state = CR_KE;
! 241: return NEED_MORE;
! 242: case CR_KE:
! 243: this->state = CR_AUTH;
! 244: return NEED_MORE;
! 245: case CR_AUTH:
! 246: build_certs(this, message);
! 247: return SUCCESS;
! 248: }
! 249: case AGGRESSIVE:
! 250: switch (this->state)
! 251: {
! 252: case CR_SA:
! 253: build_certs(this, message);
! 254: this->state = CR_AUTH;
! 255: return NEED_MORE;
! 256: case CR_AUTH:
! 257: return SUCCESS;
! 258: default:
! 259: return FAILED;
! 260: }
! 261: default:
! 262: return FAILED;
! 263: }
! 264: }
! 265:
! 266: METHOD(task_t, process_i, status_t,
! 267: private_isakmp_cert_post_t *this, message_t *message)
! 268: {
! 269: switch (message->get_exchange_type(message))
! 270: {
! 271: case ID_PROT:
! 272: {
! 273: switch (this->state)
! 274: {
! 275: case CR_SA:
! 276: if (!use_certs(this, message))
! 277: {
! 278: return SUCCESS;
! 279: }
! 280: this->state = CR_KE;
! 281: return NEED_MORE;
! 282: case CR_KE:
! 283: this->state = CR_AUTH;
! 284: return NEED_MORE;
! 285: case CR_AUTH:
! 286: return SUCCESS;
! 287: default:
! 288: return FAILED;
! 289: }
! 290: }
! 291: case AGGRESSIVE:
! 292: {
! 293: if (this->state == CR_SA)
! 294: {
! 295: if (!use_certs(this, message))
! 296: {
! 297: return SUCCESS;
! 298: }
! 299: this->state = CR_AUTH;
! 300: return NEED_MORE;
! 301: }
! 302: return SUCCESS;
! 303: }
! 304: default:
! 305: return FAILED;
! 306: }
! 307: }
! 308:
! 309: METHOD(task_t, get_type, task_type_t,
! 310: private_isakmp_cert_post_t *this)
! 311: {
! 312: return TASK_ISAKMP_CERT_POST;
! 313: }
! 314:
! 315: METHOD(task_t, migrate, void,
! 316: private_isakmp_cert_post_t *this, ike_sa_t *ike_sa)
! 317: {
! 318: this->ike_sa = ike_sa;
! 319: this->state = CR_SA;
! 320: }
! 321:
! 322: METHOD(task_t, destroy, void,
! 323: private_isakmp_cert_post_t *this)
! 324: {
! 325: free(this);
! 326: }
! 327:
! 328: /*
! 329: * Described in header.
! 330: */
! 331: isakmp_cert_post_t *isakmp_cert_post_create(ike_sa_t *ike_sa, bool initiator)
! 332: {
! 333: private_isakmp_cert_post_t *this;
! 334:
! 335: INIT(this,
! 336: .public = {
! 337: .task = {
! 338: .get_type = _get_type,
! 339: .migrate = _migrate,
! 340: .destroy = _destroy,
! 341: },
! 342: },
! 343: .ike_sa = ike_sa,
! 344: .initiator = initiator,
! 345: .state = CR_SA,
! 346: );
! 347: if (initiator)
! 348: {
! 349: this->public.task.process = _process_i;
! 350: this->public.task.build = _build_i;
! 351: }
! 352: else
! 353: {
! 354: this->public.task.process = _process_r;
! 355: this->public.task.build = _build_r;
! 356: }
! 357: return &this->public;
! 358: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>