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>