Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_cert_post.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008-2019 Tobias Brunner
        !             3:  * Copyright (C) 2006-2009 Martin Willi
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #include "ike_cert_post.h"
        !            18: 
        !            19: #include <daemon.h>
        !            20: #include <sa/ike_sa.h>
        !            21: #include <encoding/payloads/cert_payload.h>
        !            22: #include <encoding/payloads/certreq_payload.h>
        !            23: #include <encoding/payloads/auth_payload.h>
        !            24: #include <credentials/certificates/x509.h>
        !            25: #include <credentials/certificates/ac.h>
        !            26: 
        !            27: 
        !            28: typedef struct private_ike_cert_post_t private_ike_cert_post_t;
        !            29: 
        !            30: /**
        !            31:  * Private members of a ike_cert_post_t task.
        !            32:  */
        !            33: struct private_ike_cert_post_t {
        !            34: 
        !            35:        /**
        !            36:         * Public methods and task_t interface.
        !            37:         */
        !            38:        ike_cert_post_t public;
        !            39: 
        !            40:        /**
        !            41:         * Assigned IKE_SA.
        !            42:         */
        !            43:        ike_sa_t *ike_sa;
        !            44: 
        !            45:        /**
        !            46:         * Are we the initiator?
        !            47:         */
        !            48:        bool initiator;
        !            49: };
        !            50: 
        !            51: /**
        !            52:  * Generate the payload for a hash-and-URL encoded certificate
        !            53:  */
        !            54: static bool build_hash_url_payload(char *base, certificate_t *cert,
        !            55:                                                                   cert_payload_t **payload)
        !            56: {
        !            57:        hasher_t *hasher;
        !            58:        chunk_t hash, encoded;
        !            59:        char *url, *hex_hash;
        !            60: 
        !            61:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        !            62:        if (!hasher)
        !            63:        {
        !            64:                DBG1(DBG_IKE, "unable to use hash-and-url: SHA-1 not supported");
        !            65:                return FALSE;
        !            66:        }
        !            67: 
        !            68:        if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
        !            69:        {
        !            70:                hasher->destroy(hasher);
        !            71:                return FALSE;
        !            72:        }
        !            73:        if (!hasher->allocate_hash(hasher, encoded, &hash))
        !            74:        {
        !            75:                hasher->destroy(hasher);
        !            76:                chunk_free(&encoded);
        !            77:                return FALSE;
        !            78:        }
        !            79:        chunk_free(&encoded);
        !            80:        hasher->destroy(hasher);
        !            81: 
        !            82:        url = malloc(strlen(base) + 40 + 1);
        !            83:        strcpy(url, base);
        !            84:        hex_hash = chunk_to_hex(hash, NULL, FALSE).ptr;
        !            85:        strncat(url, hex_hash, 40);
        !            86:        free(hex_hash);
        !            87: 
        !            88:        DBG1(DBG_IKE, "sending hash-and-url \"%s\"", url);
        !            89:        *payload = cert_payload_create_from_hash_and_url(hash, url);
        !            90:        chunk_free(&hash);
        !            91:        free(url);
        !            92:        return TRUE;
        !            93: }
        !            94: 
        !            95: /**
        !            96:  * Generates the cert payload, if possible with "Hash and URL"
        !            97:  */
        !            98: static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
        !            99:                                                                                 certificate_t *cert)
        !           100: {
        !           101:        enumerator_t *enumerator;
        !           102:        char *base;
        !           103:        cert_payload_t *payload = NULL;
        !           104: 
        !           105:        if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
        !           106:        {
        !           107:                return cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
        !           108:        }
        !           109: 
        !           110:        enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509,
        !           111:                                                                                                         cert->get_issuer(cert));
        !           112:        if (!enumerator->enumerate(enumerator, &base) ||
        !           113:                !build_hash_url_payload(base, cert, &payload))
        !           114:        {
        !           115:                payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
        !           116:        }
        !           117:        enumerator->destroy(enumerator);
        !           118:        return payload;
        !           119: }
        !           120: 
        !           121: /**
        !           122:  * Add subject certificate to message
        !           123:  */
        !           124: static bool add_subject_cert(private_ike_cert_post_t *this, auth_cfg_t *auth,
        !           125:                                                         message_t *message)
        !           126: {
        !           127:        cert_payload_t *payload;
        !           128:        certificate_t *cert;
        !           129: 
        !           130:        cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
        !           131:        if (!cert)
        !           132:        {
        !           133:                return FALSE;
        !           134:        }
        !           135:        payload = build_cert_payload(this, cert);
        !           136:        if (!payload)
        !           137:        {
        !           138:                return FALSE;
        !           139:        }
        !           140:        DBG1(DBG_IKE, "sending end entity cert \"%Y\"", cert->get_subject(cert));
        !           141:        message->add_payload(message, (payload_t*)payload);
        !           142:        return TRUE;
        !           143: }
        !           144: 
        !           145: /**
        !           146:  * Add intermediate CA certificates to message
        !           147:  */
        !           148: static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth,
        !           149:                                                 message_t *message)
        !           150: {
        !           151:        cert_payload_t *payload;
        !           152:        enumerator_t *enumerator;
        !           153:        certificate_t *cert;
        !           154:        auth_rule_t type;
        !           155: 
        !           156:        enumerator = auth->create_enumerator(auth);
        !           157:        while (enumerator->enumerate(enumerator, &type, &cert))
        !           158:        {
        !           159:                if (type == AUTH_RULE_IM_CERT)
        !           160:                {
        !           161:                        payload = build_cert_payload(this, cert);
        !           162:                        if (payload)
        !           163:                        {
        !           164:                                DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
        !           165:                                         cert->get_subject(cert));
        !           166:                                message->add_payload(message, (payload_t*)payload);
        !           167:                        }
        !           168:                }
        !           169:        }
        !           170:        enumerator->destroy(enumerator);
        !           171: }
        !           172: 
        !           173: /**
        !           174:  * Add any valid attribute certificates of subject to message
        !           175:  */
        !           176: static void add_attribute_certs(private_ike_cert_post_t *this,
        !           177:                                                                auth_cfg_t *auth, message_t *message)
        !           178: {
        !           179:        certificate_t *subject, *cert;
        !           180: 
        !           181:        subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
        !           182:        if (subject && subject->get_type(subject) == CERT_X509)
        !           183:        {
        !           184:                x509_t *x509 = (x509_t*)subject;
        !           185:                identification_t *id, *serial;
        !           186:                enumerator_t *enumerator;
        !           187:                cert_payload_t *payload;
        !           188:                ac_t *ac;
        !           189: 
        !           190:                /* we look for attribute certs having our serial and holder issuer,
        !           191:                 * which is recommended by RFC 5755 */
        !           192:                serial = identification_create_from_encoding(ID_KEY_ID,
        !           193:                                                                                                         x509->get_serial(x509));
        !           194:                enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
        !           195:                                                                                CERT_X509_AC, KEY_ANY, serial, FALSE);
        !           196:                while (enumerator->enumerate(enumerator, &ac))
        !           197:                {
        !           198:                        cert = &ac->certificate;
        !           199:                        id = ac->get_holderIssuer(ac);
        !           200:                        if (id && id->equals(id, subject->get_issuer(subject)) &&
        !           201:                                cert->get_validity(cert, NULL, NULL, NULL))
        !           202:                        {
        !           203:                                payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
        !           204:                                if (payload)
        !           205:                                {
        !           206:                                        DBG1(DBG_IKE, "sending attribute certificate "
        !           207:                                                 "issued by \"%Y\"", cert->get_issuer(cert));
        !           208:                                        message->add_payload(message, (payload_t*)payload);
        !           209:                                }
        !           210:                        }
        !           211:                }
        !           212:                enumerator->destroy(enumerator);
        !           213:                serial->destroy(serial);
        !           214:        }
        !           215: }
        !           216: 
        !           217: /**
        !           218:  * add certificates to message
        !           219:  */
        !           220: static void build_certs(private_ike_cert_post_t *this, message_t *message)
        !           221: {
        !           222:        peer_cfg_t *peer_cfg;
        !           223:        auth_payload_t *payload;
        !           224:        auth_cfg_t *auth;
        !           225: 
        !           226:        payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
        !           227:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !           228:        if (!peer_cfg || !payload || payload->get_auth_method(payload) == AUTH_PSK)
        !           229:        {       /* no CERT payload for EAP/PSK */
        !           230:                return;
        !           231:        }
        !           232: 
        !           233:        switch (peer_cfg->get_cert_policy(peer_cfg))
        !           234:        {
        !           235:                case CERT_NEVER_SEND:
        !           236:                        break;
        !           237:                case CERT_SEND_IF_ASKED:
        !           238:                        if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
        !           239:                        {
        !           240:                                break;
        !           241:                        }
        !           242:                        /* FALL */
        !           243:                case CERT_ALWAYS_SEND:
        !           244:                        auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !           245:                        if (add_subject_cert(this, auth, message))
        !           246:                        {
        !           247:                                add_im_certs(this, auth, message);
        !           248:                                add_attribute_certs(this, auth, message);
        !           249:                        }
        !           250:                        break;
        !           251:        }
        !           252: }
        !           253: 
        !           254: METHOD(task_t, build_i, status_t,
        !           255:        private_ike_cert_post_t *this, message_t *message)
        !           256: {
        !           257:        build_certs(this, message);
        !           258: 
        !           259:        return NEED_MORE;
        !           260: }
        !           261: 
        !           262: METHOD(task_t, process_r, status_t,
        !           263:        private_ike_cert_post_t *this, message_t *message)
        !           264: {
        !           265:        return NEED_MORE;
        !           266: }
        !           267: 
        !           268: METHOD(task_t, build_r, status_t,
        !           269:        private_ike_cert_post_t *this, message_t *message)
        !           270: {
        !           271:        build_certs(this, message);
        !           272: 
        !           273:        if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
        !           274:        {       /* stay alive, we might have additional rounds with certs */
        !           275:                return NEED_MORE;
        !           276:        }
        !           277:        return SUCCESS;
        !           278: }
        !           279: 
        !           280: METHOD(task_t, process_i, status_t,
        !           281:        private_ike_cert_post_t *this, message_t *message)
        !           282: {
        !           283:        if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
        !           284:        {       /* stay alive, we might have additional rounds with CERTS */
        !           285:                return NEED_MORE;
        !           286:        }
        !           287:        return SUCCESS;
        !           288: }
        !           289: 
        !           290: METHOD(task_t, get_type, task_type_t,
        !           291:        private_ike_cert_post_t *this)
        !           292: {
        !           293:        return TASK_IKE_CERT_POST;
        !           294: }
        !           295: 
        !           296: METHOD(task_t, migrate, void,
        !           297:        private_ike_cert_post_t *this, ike_sa_t *ike_sa)
        !           298: {
        !           299:        this->ike_sa = ike_sa;
        !           300: }
        !           301: 
        !           302: METHOD(task_t, destroy, void,
        !           303:        private_ike_cert_post_t *this)
        !           304: {
        !           305:        free(this);
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * Described in header.
        !           310:  */
        !           311: ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
        !           312: {
        !           313:        private_ike_cert_post_t *this;
        !           314: 
        !           315:        INIT(this,
        !           316:                .public = {
        !           317:                        .task = {
        !           318:                                .get_type = _get_type,
        !           319:                                .migrate = _migrate,
        !           320:                                .destroy = _destroy,
        !           321:                        },
        !           322:                },
        !           323:                .ike_sa = ike_sa,
        !           324:                .initiator = initiator,
        !           325:        );
        !           326: 
        !           327:        if (initiator)
        !           328:        {
        !           329:                this->public.task.build = _build_i;
        !           330:                this->public.task.process = _process_i;
        !           331:        }
        !           332:        else
        !           333:        {
        !           334:                this->public.task.build = _build_r;
        !           335:                this->public.task.process = _process_r;
        !           336:        }
        !           337: 
        !           338:        return &this->public;
        !           339: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>