Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008 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_pre.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 <credentials/certificates/x509.h>
                     24: 
                     25: 
                     26: typedef struct private_ike_cert_pre_t private_ike_cert_pre_t;
                     27: 
                     28: /**
                     29:  * Private members of a ike_cert_pre_t task.
                     30:  */
                     31: struct private_ike_cert_pre_t {
                     32: 
                     33:        /**
                     34:         * Public methods and task_t interface.
                     35:         */
                     36:        ike_cert_pre_t public;
                     37: 
                     38:        /**
                     39:         * Assigned IKE_SA.
                     40:         */
                     41:        ike_sa_t *ike_sa;
                     42: 
                     43:        /**
                     44:         * Are we the initiator?
                     45:         */
                     46:        bool initiator;
                     47: 
                     48:        /**
                     49:         * Do we accept HTTP certificate lookup requests
                     50:         */
                     51:        bool do_http_lookup;
                     52: 
                     53:        /**
                     54:         * whether this is the final authentication round
                     55:         */
                     56:        bool final;
                     57: };
                     58: 
                     59: /**
                     60:  * Process a single certificate request payload
                     61:  */
                     62: static void process_certreq(private_ike_cert_pre_t *this,
                     63:                                                        certreq_payload_t *certreq, auth_cfg_t *auth)
                     64: {
                     65:        enumerator_t *enumerator;
                     66:        u_int unknown = 0;
                     67:        chunk_t keyid;
                     68: 
                     69:        this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
                     70: 
                     71:        if (certreq->get_cert_type(certreq) != CERT_X509)
                     72:        {
                     73:                DBG1(DBG_IKE, "cert payload %N not supported - ignored",
                     74:                         certificate_type_names, certreq->get_cert_type(certreq));
                     75:                return;
                     76:        }
                     77: 
                     78:        enumerator = certreq->create_keyid_enumerator(certreq);
                     79:        while (enumerator->enumerate(enumerator, &keyid))
                     80:        {
                     81:                identification_t *id;
                     82:                certificate_t *cert;
                     83: 
                     84:                id = identification_create_from_encoding(ID_KEY_ID, keyid);
                     85:                cert = lib->credmgr->get_cert(lib->credmgr,
                     86:                                                                          CERT_X509, KEY_ANY, id, TRUE);
                     87:                if (cert)
                     88:                {
                     89:                        DBG1(DBG_IKE, "received cert request for \"%Y\"",
                     90:                                 cert->get_subject(cert));
                     91:                        auth->add(auth, AUTH_RULE_CA_CERT, cert);
                     92:                }
                     93:                else
                     94:                {
                     95:                        DBG2(DBG_IKE, "received cert request for unknown ca with keyid %Y",
                     96:                                 id);
                     97:                        unknown++;
                     98:                }
                     99:                id->destroy(id);
                    100:        }
                    101:        enumerator->destroy(enumerator);
                    102:        if (unknown)
                    103:        {
                    104:                DBG1(DBG_IKE, "received %u cert requests for an unknown ca",
                    105:                         unknown);
                    106:        }
                    107: }
                    108: 
                    109: /**
                    110:  * Process a single notify payload
                    111:  */
                    112: static void process_notify(private_ike_cert_pre_t *this,
                    113:                                                   notify_payload_t *notify)
                    114: {
                    115:        switch (notify->get_notify_type(notify))
                    116:        {
                    117:                case HTTP_CERT_LOOKUP_SUPPORTED:
                    118:                        this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL);
                    119:                        break;
                    120:                default:
                    121:                        break;
                    122:        }
                    123: }
                    124: 
                    125: /**
                    126:  * read certificate requests
                    127:  */
                    128: static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
                    129: {
                    130:        enumerator_t *enumerator;
                    131:        payload_t *payload;
                    132:        auth_cfg_t *auth;
                    133: 
                    134:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
                    135: 
                    136:        enumerator = message->create_payload_enumerator(message);
                    137:        while (enumerator->enumerate(enumerator, &payload))
                    138:        {
                    139:                switch (payload->get_type(payload))
                    140:                {
                    141:                        case PLV2_CERTREQ:
                    142:                                process_certreq(this, (certreq_payload_t*)payload, auth);
                    143:                                break;
                    144:                        case PLV2_NOTIFY:
                    145:                                process_notify(this, (notify_payload_t*)payload);
                    146:                                break;
                    147:                        default:
                    148:                                /* ignore other payloads here, these are handled elsewhere */
                    149:                                break;
                    150:                }
                    151:        }
                    152:        enumerator->destroy(enumerator);
                    153: }
                    154: 
                    155: /**
                    156:  * tries to extract a certificate from the cert payload or the credential
                    157:  * manager (based on the hash of a "Hash and URL" encoded cert).
                    158:  * Note: the returned certificate (if any) has to be destroyed
                    159:  */
                    160: static certificate_t *try_get_cert(cert_payload_t *cert_payload)
                    161: {
                    162:        certificate_t *cert = NULL;
                    163: 
                    164:        switch (cert_payload->get_cert_encoding(cert_payload))
                    165:        {
                    166:                case ENC_X509_SIGNATURE:
                    167:                {
                    168:                        cert = cert_payload->get_cert(cert_payload);
                    169:                        break;
                    170:                }
                    171:                case ENC_X509_HASH_AND_URL:
                    172:                {
                    173:                        identification_t *id;
                    174:                        chunk_t hash = cert_payload->get_hash(cert_payload);
                    175:                        if (!hash.ptr)
                    176:                        {
                    177:                                /* invalid "Hash and URL" data (logged elsewhere) */
                    178:                                break;
                    179:                        }
                    180:                        id = identification_create_from_encoding(ID_KEY_ID, hash);
                    181:                        cert = lib->credmgr->get_cert(lib->credmgr,
                    182:                                                                                  CERT_X509, KEY_ANY, id, FALSE);
                    183:                        id->destroy(id);
                    184:                        break;
                    185:                }
                    186:                default:
                    187:                {
                    188:                        break;
                    189:                }
                    190:        }
                    191:        return cert;
                    192: }
                    193: 
                    194: /**
                    195:  * Process a X509 certificate payload
                    196:  */
                    197: static void process_x509(cert_payload_t *payload, auth_cfg_t *auth,
                    198:                                                 cert_encoding_t encoding, bool *first)
                    199: {
                    200:        certificate_t *cert;
                    201:        char *url;
                    202: 
                    203:        cert = try_get_cert(payload);
                    204:        if (cert)
                    205:        {
                    206:                if (*first)
                    207:                {       /* the first is an end entity certificate */
                    208:                        DBG1(DBG_IKE, "received end entity cert \"%Y\"",
                    209:                                 cert->get_subject(cert));
                    210:                        auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert);
                    211:                        *first = FALSE;
                    212:                }
                    213:                else
                    214:                {
                    215:                        DBG1(DBG_IKE, "received issuer cert \"%Y\"",
                    216:                                 cert->get_subject(cert));
                    217:                        auth->add(auth, AUTH_HELPER_IM_CERT, cert);
                    218:                }
                    219:        }
                    220:        else if (encoding == ENC_X509_HASH_AND_URL)
                    221:        {
                    222:                /* we fetch the certificate not yet, but only if
                    223:                 * it is really needed during authentication */
                    224:                url = payload->get_url(payload);
                    225:                if (!url)
                    226:                {
                    227:                        DBG1(DBG_IKE, "received invalid hash-and-url "
                    228:                                 "encoded cert, ignore");
                    229:                        return;
                    230:                }
                    231:                url = strdup(url);
                    232:                if (*first)
                    233:                {       /* first URL is for an end entity certificate */
                    234:                        DBG1(DBG_IKE, "received hash-and-url for end entity cert \"%s\"",
                    235:                                 url);
                    236:                        auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url);
                    237:                        *first = FALSE;
                    238:                }
                    239:                else
                    240:                {
                    241:                        DBG1(DBG_IKE, "received hash-and-url for issuer cert \"%s\"", url);
                    242:                        auth->add(auth, AUTH_HELPER_IM_HASH_URL, url);
                    243:                }
                    244:        }
                    245: }
                    246: 
                    247: /**
                    248:  * Process a CRL certificate payload
                    249:  */
                    250: static void process_crl(cert_payload_t *payload, auth_cfg_t *auth)
                    251: {
                    252:        certificate_t *cert;
                    253: 
                    254:        cert = payload->get_cert(payload);
                    255:        if (cert)
                    256:        {
                    257:                DBG1(DBG_IKE, "received CRL \"%Y\"", cert->get_subject(cert));
                    258:                auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert);
                    259:        }
                    260: }
                    261: 
                    262: /**
                    263:  * Process an attribute certificate payload
                    264:  */
                    265: static void process_ac(cert_payload_t *payload, auth_cfg_t *auth)
                    266: {
                    267:        certificate_t *cert;
                    268: 
                    269:        cert = payload->get_cert(payload);
                    270:        if (cert)
                    271:        {
                    272:                if (cert->get_issuer(cert))
                    273:                {
                    274:                        DBG1(DBG_IKE, "received attribute certificate issued by \"%Y\"",
                    275:                                 cert->get_issuer(cert));
                    276:                }
                    277:                else if (cert->get_subject(cert))
                    278:                {
                    279:                        DBG1(DBG_IKE, "received attribute certificate for \"%Y\"",
                    280:                                 cert->get_subject(cert));
                    281:                }
                    282:                auth->add(auth, AUTH_HELPER_AC_CERT, cert);
                    283:        }
                    284: }
                    285: 
                    286: /**
                    287:  * Process certificate payloads
                    288:  */
                    289: static void process_certs(private_ike_cert_pre_t *this, message_t *message)
                    290: {
                    291:        enumerator_t *enumerator;
                    292:        payload_t *payload;
                    293:        auth_cfg_t *auth;
                    294:        bool first = TRUE;
                    295: 
                    296:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
                    297: 
                    298:        enumerator = message->create_payload_enumerator(message);
                    299:        while (enumerator->enumerate(enumerator, &payload))
                    300:        {
                    301:                if (payload->get_type(payload) == PLV2_CERTIFICATE)
                    302:                {
                    303:                        cert_payload_t *cert_payload;
                    304:                        cert_encoding_t encoding;
                    305: 
                    306:                        cert_payload = (cert_payload_t*)payload;
                    307:                        encoding = cert_payload->get_cert_encoding(cert_payload);
                    308: 
                    309:                        switch (encoding)
                    310:                        {
                    311:                                case ENC_X509_HASH_AND_URL:
                    312:                                        if (!this->do_http_lookup)
                    313:                                        {
                    314:                                                DBG1(DBG_IKE, "received hash-and-url encoded cert, but "
                    315:                                                         "we don't accept them, ignore");
                    316:                                                break;
                    317:                                        }
                    318:                                        /* FALL */
                    319:                                case ENC_X509_SIGNATURE:
                    320:                                        process_x509(cert_payload, auth, encoding, &first);
                    321:                                        break;
                    322:                                case ENC_CRL:
                    323:                                        process_crl(cert_payload, auth);
                    324:                                        break;
                    325:                                case ENC_X509_ATTRIBUTE:
                    326:                                        process_ac(cert_payload, auth);
                    327:                                        break;
                    328:                                case ENC_PKCS7_WRAPPED_X509:
                    329:                                case ENC_PGP:
                    330:                                case ENC_DNS_SIGNED_KEY:
                    331:                                case ENC_KERBEROS_TOKEN:
                    332:                                case ENC_ARL:
                    333:                                case ENC_SPKI:
                    334:                                case ENC_RAW_RSA_KEY:
                    335:                                case ENC_X509_HASH_AND_URL_BUNDLE:
                    336:                                case ENC_OCSP_CONTENT:
                    337:                                default:
                    338:                                        DBG1(DBG_ENC, "certificate encoding %N not supported",
                    339:                                                 cert_encoding_names, encoding);
                    340:                        }
                    341:                }
                    342:        }
                    343:        enumerator->destroy(enumerator);
                    344: }
                    345: 
                    346: /**
                    347:  * add the keyid of a certificate to the certificate request payload
                    348:  */
                    349: static void add_certreq(certreq_payload_t **req, certificate_t *cert)
                    350: {
                    351:        switch (cert->get_type(cert))
                    352:        {
                    353:                case CERT_X509:
                    354:                {
                    355:                        public_key_t *public;
                    356:                        chunk_t keyid;
                    357:                        x509_t *x509 = (x509_t*)cert;
                    358: 
                    359:                        if (!(x509->get_flags(x509) & X509_CA))
                    360:                        {       /* no CA cert, skip */
                    361:                                break;
                    362:                        }
                    363:                        public = cert->get_public_key(cert);
                    364:                        if (!public)
                    365:                        {
                    366:                                break;
                    367:                        }
                    368:                        if (*req == NULL)
                    369:                        {
                    370:                                *req = certreq_payload_create_type(CERT_X509);
                    371:                        }
                    372:                        if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
                    373:                        {
                    374:                                (*req)->add_keyid(*req, keyid);
                    375:                                DBG1(DBG_IKE, "sending cert request for \"%Y\"",
                    376:                                         cert->get_subject(cert));
                    377:                        }
                    378:                        public->destroy(public);
                    379:                        break;
                    380:                }
                    381:                default:
                    382:                        break;
                    383:        }
                    384: }
                    385: 
                    386: /**
                    387:  * add a auth_cfg's CA certificates to the certificate request
                    388:  */
                    389: static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth)
                    390: {
                    391:        enumerator_t *enumerator;
                    392:        auth_rule_t type;
                    393:        void *value;
                    394: 
                    395:        enumerator = auth->create_enumerator(auth);
                    396:        while (enumerator->enumerate(enumerator, &type, &value))
                    397:        {
                    398:                switch (type)
                    399:                {
                    400:                        case AUTH_RULE_CA_CERT:
                    401:                                add_certreq(req, (certificate_t*)value);
                    402:                                break;
                    403:                        default:
                    404:                                break;
                    405:                }
                    406:        }
                    407:        enumerator->destroy(enumerator);
                    408: }
                    409: 
                    410: /**
                    411:  * build certificate requests
                    412:  */
                    413: static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
                    414: {
                    415:        enumerator_t *enumerator;
                    416:        ike_cfg_t *ike_cfg;
                    417:        peer_cfg_t *peer_cfg;
                    418:        certificate_t *cert;
                    419:        auth_cfg_t *auth;
                    420:        certreq_payload_t *req = NULL;
                    421: 
                    422:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
                    423:        if (!ike_cfg->send_certreq(ike_cfg))
                    424:        {
                    425:                return;
                    426:        }
                    427: 
                    428:        /* check if we require a specific CA for that peer */
                    429:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
                    430:        if (peer_cfg)
                    431:        {
                    432:                enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
                    433:                while (enumerator->enumerate(enumerator, &auth))
                    434:                {
                    435:                        add_certreqs(&req, auth);
                    436:                }
                    437:                enumerator->destroy(enumerator);
                    438:        }
                    439: 
                    440:        if (!req)
                    441:        {
                    442:                /* otherwise add all trusted CA certificates */
                    443:                enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
                    444:                                                                                                CERT_ANY, KEY_ANY, NULL, TRUE);
                    445:                while (enumerator->enumerate(enumerator, &cert))
                    446:                {
                    447:                        add_certreq(&req, cert);
                    448:                }
                    449:                enumerator->destroy(enumerator);
                    450:        }
                    451: 
                    452:        if (req)
                    453:        {
                    454:                message->add_payload(message, (payload_t*)req);
                    455: 
                    456:                if (lib->settings->get_bool(lib->settings,
                    457:                                                                        "%s.hash_and_url", FALSE, lib->ns))
                    458:                {
                    459:                        message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
                    460:                                                                chunk_empty);
                    461:                        this->do_http_lookup = TRUE;
                    462:                }
                    463:        }
                    464: }
                    465: 
                    466: /**
                    467:  * Check if this is the final authentication round
                    468:  */
                    469: static bool final_auth(message_t *message)
                    470: {
                    471:        /* we check for an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify */
                    472:        if (message->get_payload(message, PLV2_AUTH) == NULL)
                    473:        {
                    474:                return FALSE;
                    475:        }
                    476:        if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS))
                    477:        {
                    478:                return FALSE;
                    479:        }
                    480:        return TRUE;
                    481: }
                    482: 
                    483: METHOD(task_t, build_i, status_t,
                    484:        private_ike_cert_pre_t *this, message_t *message)
                    485: {
                    486:        if (message->get_message_id(message) == 1)
                    487:        {       /* initiator sends CERTREQs in first IKE_AUTH */
                    488:                build_certreqs(this, message);
                    489:        }
                    490:        return NEED_MORE;
                    491: }
                    492: 
                    493: METHOD(task_t, process_r, status_t,
                    494:        private_ike_cert_pre_t *this, message_t *message)
                    495: {
                    496:        if (message->get_exchange_type(message) != IKE_SA_INIT)
                    497:        {       /* handle certreqs/certs in any IKE_AUTH, just in case */
                    498:                process_certreqs(this, message);
                    499:                process_certs(this, message);
                    500:        }
                    501:        this->final = final_auth(message);
                    502:        return NEED_MORE;
                    503: }
                    504: 
                    505: METHOD(task_t, build_r, status_t,
                    506:        private_ike_cert_pre_t *this, message_t *message)
                    507: {
                    508:        if (message->get_exchange_type(message) == IKE_SA_INIT)
                    509:        {
                    510:                build_certreqs(this, message);
                    511:        }
                    512:        if (this->final)
                    513:        {
                    514:                return SUCCESS;
                    515:        }
                    516:        return NEED_MORE;
                    517: }
                    518: 
                    519: METHOD(task_t, process_i, status_t,
                    520:        private_ike_cert_pre_t *this, message_t *message)
                    521: {
                    522:        if (message->get_exchange_type(message) == IKE_SA_INIT)
                    523:        {
                    524:                process_certreqs(this, message);
                    525:        }
                    526:        process_certs(this, message);
                    527: 
                    528:        if (final_auth(message))
                    529:        {
                    530:                return SUCCESS;
                    531:        }
                    532:        return NEED_MORE;
                    533: }
                    534: 
                    535: METHOD(task_t, get_type, task_type_t,
                    536:        private_ike_cert_pre_t *this)
                    537: {
                    538:        return TASK_IKE_CERT_PRE;
                    539: }
                    540: 
                    541: METHOD(task_t, migrate, void,
                    542:        private_ike_cert_pre_t *this, ike_sa_t *ike_sa)
                    543: {
                    544:        this->ike_sa = ike_sa;
                    545: }
                    546: 
                    547: METHOD(task_t, destroy, void,
                    548:        private_ike_cert_pre_t *this)
                    549: {
                    550:        free(this);
                    551: }
                    552: 
                    553: /*
                    554:  * Described in header.
                    555:  */
                    556: ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
                    557: {
                    558:        private_ike_cert_pre_t *this;
                    559: 
                    560:        INIT(this,
                    561:                .public = {
                    562:                        .task = {
                    563:                                .get_type = _get_type,
                    564:                                .migrate = _migrate,
                    565:                                .destroy = _destroy,
                    566:                        },
                    567:                },
                    568:                .ike_sa = ike_sa,
                    569:                .initiator = initiator,
                    570:        );
                    571: 
                    572:        if (initiator)
                    573:        {
                    574:                this->public.task.build = _build_i;
                    575:                this->public.task.process = _process_i;
                    576:        }
                    577:        else
                    578:        {
                    579:                this->public.task.build = _build_r;
                    580:                this->public.task.process = _process_r;
                    581:        }
                    582: 
                    583:        return &this->public;
                    584: }

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