Annotation of embedaddon/strongswan/src/conftest/hooks/pretend_auth.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 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 "hook.h"
                     17: 
                     18: #include <sa/ikev2/keymat_v2.h>
                     19: #include <encoding/payloads/nonce_payload.h>
                     20: #include <encoding/payloads/cert_payload.h>
                     21: #include <encoding/payloads/auth_payload.h>
                     22: #include <encoding/payloads/id_payload.h>
                     23: #include <encoding/payloads/sa_payload.h>
                     24: #include <encoding/payloads/ts_payload.h>
                     25: 
                     26: typedef struct private_pretend_auth_t private_pretend_auth_t;
                     27: 
                     28: /**
                     29:  * Private data of an pretend_auth_t object.
                     30:  */
                     31: struct private_pretend_auth_t {
                     32: 
                     33:        /**
                     34:         * Implements the hook_t interface.
                     35:         */
                     36:        hook_t hook;
                     37: 
                     38:        /**
                     39:         * remote peer identity
                     40:         */
                     41:        identification_t *id;
                     42: 
                     43:        /**
                     44:         * reserved bytes of ID payload
                     45:         */
                     46:        char reserved[3];
                     47: 
                     48:        /**
                     49:         * IKE_SA_INIT data for signature
                     50:         */
                     51:        chunk_t ike_init;
                     52: 
                     53:        /**
                     54:         * Nonce for signature
                     55:         */
                     56:        chunk_t nonce;
                     57: 
                     58:        /**
                     59:         * Selected CHILD_SA proposal
                     60:         */
                     61:        proposal_t *proposal;
                     62: 
                     63:        /**
                     64:         * List of initiators Traffic Selectors
                     65:         */
                     66:        linked_list_t *tsi;
                     67: 
                     68:        /**
                     69:         * List of responders Traffic Selectors
                     70:         */
                     71:        linked_list_t *tsr;
                     72: };
                     73: 
                     74: /**
                     75:  * Process IKE_SA_INIT request message, outgoing
                     76:  */
                     77: static void process_init_request(private_pretend_auth_t *this,
                     78:                                                                 ike_sa_t *ike_sa, message_t *message)
                     79: {
                     80:        nonce_payload_t *nonce;
                     81: 
                     82:        nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
                     83:        if (nonce)
                     84:        {
                     85:                free(this->nonce.ptr);
                     86:                this->nonce = nonce->get_nonce(nonce);
                     87:        }
                     88: }
                     89: 
                     90: /**
                     91:  * Process IKE_AUTH request message, outgoing
                     92:  */
                     93: static void process_auth_request(private_pretend_auth_t *this,
                     94:                                                                 ike_sa_t *ike_sa, message_t *message)
                     95: {
                     96:        id_payload_t *id;
                     97:        sa_payload_t *sa;
                     98:        ts_payload_t *tsi, *tsr;
                     99:        linked_list_t *proposals;
                    100: 
                    101:        id = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER);
                    102:        if (id)
                    103:        {
                    104:                this->id->destroy(this->id);
                    105:                this->id = id->get_identification(id);
                    106:        }
                    107:        sa = (sa_payload_t*)message->get_payload(message, PLV2_SECURITY_ASSOCIATION);
                    108:        if (sa)
                    109:        {
                    110:                proposals = sa->get_proposals(sa);
                    111:                proposals->remove_first(proposals, (void**)&this->proposal);
                    112:                if (this->proposal)
                    113:                {
                    114:                        this->proposal->set_spi(this->proposal, htonl(0x12345678));
                    115:                }
                    116:                proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
                    117:        }
                    118:        tsi = (ts_payload_t*)message->get_payload(message,
                    119:                                                                                          PLV2_TS_INITIATOR);
                    120:        if (tsi)
                    121:        {
                    122:                this->tsi = tsi->get_traffic_selectors(tsi);
                    123:        }
                    124:        tsr = (ts_payload_t*)message->get_payload(message,
                    125:                                                                                          PLV2_TS_RESPONDER);
                    126:        if (tsr)
                    127:        {
                    128:                this->tsr = tsr->get_traffic_selectors(tsr);
                    129:        }
                    130: 
                    131: }
                    132: 
                    133: /**
                    134:  * Process IKE_SA_INIT response message, incoming
                    135:  */
                    136: static void process_init_response(private_pretend_auth_t *this,
                    137:                                                                  ike_sa_t *ike_sa, message_t *message)
                    138: {
                    139:        this->ike_init = chunk_clone(message->get_packet_data(message));
                    140: }
                    141: 
                    142: /**
                    143:  * Build CERT payloads
                    144:  */
                    145: static void build_certs(private_pretend_auth_t *this,
                    146:                                                ike_sa_t *ike_sa, message_t *message, auth_cfg_t *auth)
                    147: {
                    148:        enumerator_t *enumerator;
                    149:        cert_payload_t *payload;
                    150:        certificate_t *cert;
                    151:        auth_rule_t type;
                    152: 
                    153:        /* get subject cert first, then issuing certificates */
                    154:        cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
                    155:        if (cert)
                    156:        {
                    157:                payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
                    158:                if (payload)
                    159:                {
                    160:                        DBG1(DBG_IKE, "pretending end entity cert \"%Y\"",
                    161:                                 cert->get_subject(cert));
                    162:                        message->add_payload(message, (payload_t*)payload);
                    163:                }
                    164:        }
                    165:        enumerator = auth->create_enumerator(auth);
                    166:        while (enumerator->enumerate(enumerator, &type, &cert))
                    167:        {
                    168:                if (type == AUTH_RULE_IM_CERT)
                    169:                {
                    170:                        payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
                    171:                        if (payload)
                    172:                        {
                    173:                                DBG1(DBG_IKE, "pretending issuer cert \"%Y\"",
                    174:                                         cert->get_subject(cert));
                    175:                                message->add_payload(message, (payload_t*)payload);
                    176:                        }
                    177:                }
                    178:        }
                    179:        enumerator->destroy(enumerator);
                    180: }
                    181: 
                    182: /**
                    183:  * Build faked AUTH payload
                    184:  */
                    185: static bool build_auth(private_pretend_auth_t *this,
                    186:                                           ike_sa_t *ike_sa, message_t *message)
                    187: {
                    188:        chunk_t octets, auth_data;
                    189:        private_key_t *private;
                    190:        auth_cfg_t *auth;
                    191:        auth_payload_t *auth_payload;
                    192:        auth_method_t auth_method;
                    193:        signature_scheme_t scheme;
                    194:        keymat_v2_t *keymat;
                    195: 
                    196:        auth = auth_cfg_create();
                    197:        private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, this->id, auth);
                    198:        build_certs(this, ike_sa, message, auth);
                    199:        auth->destroy(auth);
                    200:        if (private == NULL)
                    201:        {
                    202:                DBG1(DBG_CFG, "no private key found for '%Y' to pretend AUTH", this->id);
                    203:                return FALSE;
                    204:        }
                    205: 
                    206:        switch (private->get_type(private))
                    207:        {
                    208:                case KEY_RSA:
                    209:                        scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
                    210:                        auth_method = AUTH_RSA;
                    211:                        break;
                    212:                case KEY_ECDSA:
                    213:                        /* we try to deduct the signature scheme from the keysize */
                    214:                        switch (private->get_keysize(private))
                    215:                        {
                    216:                                case 256:
                    217:                                        scheme = SIGN_ECDSA_256;
                    218:                                        auth_method = AUTH_ECDSA_256;
                    219:                                        break;
                    220:                                case 384:
                    221:                                        scheme = SIGN_ECDSA_384;
                    222:                                        auth_method = AUTH_ECDSA_384;
                    223:                                        break;
                    224:                                case 521:
                    225:                                        scheme = SIGN_ECDSA_521;
                    226:                                        auth_method = AUTH_ECDSA_521;
                    227:                                        break;
                    228:                                default:
                    229:                                        DBG1(DBG_CFG, "%d bit ECDSA private key size not supported",
                    230:                                                        private->get_keysize(private));
                    231:                                        return FALSE;
                    232:                        }
                    233:                        break;
                    234:                default:
                    235:                        DBG1(DBG_CFG, "private key of type %N not supported",
                    236:                                        key_type_names, private->get_type(private));
                    237:                        return FALSE;
                    238:        }
                    239:        keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
                    240:        if (!keymat->get_auth_octets(keymat, TRUE, this->ike_init, this->nonce,
                    241:                                                                 chunk_empty, this->id, this->reserved,
                    242:                                                                 &octets, NULL))
                    243:        {
                    244:                private->destroy(private);
                    245:                return FALSE;
                    246:        }
                    247:        if (!private->sign(private, scheme, NULL, octets, &auth_data))
                    248:        {
                    249:                chunk_free(&octets);
                    250:                private->destroy(private);
                    251:                return FALSE;
                    252:        }
                    253:        auth_payload = auth_payload_create();
                    254:        auth_payload->set_auth_method(auth_payload, auth_method);
                    255:        auth_payload->set_data(auth_payload, auth_data);
                    256:        chunk_free(&auth_data);
                    257:        chunk_free(&octets);
                    258:        private->destroy(private);
                    259:        message->add_payload(message, (payload_t*)auth_payload);
                    260:        DBG1(DBG_CFG, "pretending AUTH payload for '%Y' with %N",
                    261:                 this->id, auth_method_names, auth_method);
                    262:        return TRUE;
                    263: }
                    264: 
                    265: /**
                    266:  * Process IKE_AUTH response message, incoming
                    267:  */
                    268: static void process_auth_response(private_pretend_auth_t *this,
                    269:                                                                  ike_sa_t *ike_sa, message_t *message)
                    270: {
                    271:        enumerator_t *enumerator;
                    272:        payload_t *payload;
                    273: 
                    274:        /* check for, and remove AUTHENTICATION_FAILED notify */
                    275:        enumerator = message->create_payload_enumerator(message);
                    276:        while (enumerator->enumerate(enumerator, &payload))
                    277:        {
                    278:                notify_payload_t *notify = (notify_payload_t*)payload;
                    279: 
                    280:                if (payload->get_type(payload) != PLV2_NOTIFY ||
                    281:                        notify->get_notify_type(notify) != AUTHENTICATION_FAILED)
                    282:                {
                    283:                        DBG1(DBG_CFG, "no %N notify found, disabling AUTH pretending",
                    284:                                 notify_type_names, AUTHENTICATION_FAILED);
                    285:                        enumerator->destroy(enumerator);
                    286:                        return;
                    287:                }
                    288:                message->remove_payload_at(message, enumerator);
                    289:                payload->destroy(payload);
                    290:        }
                    291:        enumerator->destroy(enumerator);
                    292: 
                    293:        if (!build_auth(this, ike_sa, message))
                    294:        {
                    295:                message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
                    296:                return;
                    297:        }
                    298:        message->add_payload(message, (payload_t*)
                    299:                                id_payload_create_from_identification(PLV2_ID_RESPONDER, this->id));
                    300:        if (this->proposal)
                    301:        {
                    302:                message->add_payload(message, (payload_t*)
                    303:                                        sa_payload_create_from_proposal_v2(this->proposal));
                    304:        }
                    305:        if (this->tsi)
                    306:        {
                    307:                message->add_payload(message, (payload_t*)
                    308:                                        ts_payload_create_from_traffic_selectors(TRUE, this->tsi));
                    309:        }
                    310:        if (this->tsr)
                    311:        {
                    312:                message->add_payload(message, (payload_t*)
                    313:                                        ts_payload_create_from_traffic_selectors(FALSE, this->tsr));
                    314:        }
                    315: }
                    316: 
                    317: METHOD(listener_t, message, bool,
                    318:        private_pretend_auth_t *this, ike_sa_t *ike_sa, message_t *message,
                    319:        bool incoming, bool plain)
                    320: {
                    321:        if (plain)
                    322:        {
                    323:                if (incoming)
                    324:                {
                    325:                        if (!message->get_request(message))
                    326:                        {
                    327:                                if (message->get_exchange_type(message) == IKE_SA_INIT)
                    328:                                {
                    329:                                        process_init_response(this, ike_sa, message);
                    330:                                }
                    331:                                if (message->get_exchange_type(message) == IKE_AUTH &&
                    332:                                        message->get_message_id(message) == 1)
                    333:                                {
                    334:                                        process_auth_response(this, ike_sa, message);
                    335:                                }
                    336:                        }
                    337:                }
                    338:                else
                    339:                {
                    340:                        if (message->get_request(message))
                    341:                        {
                    342:                                if (message->get_exchange_type(message) == IKE_SA_INIT)
                    343:                                {
                    344:                                        process_init_request(this, ike_sa, message);
                    345:                                }
                    346:                                if (message->get_exchange_type(message) == IKE_AUTH &&
                    347:                                        message->get_message_id(message) == 1)
                    348:                                {
                    349:                                        process_auth_request(this, ike_sa, message);
                    350:                                }
                    351:                        }
                    352:                }
                    353:        }
                    354:        return TRUE;
                    355: }
                    356: 
                    357: METHOD(hook_t, destroy, void,
                    358:        private_pretend_auth_t *this)
                    359: {
                    360:        if (this->tsi)
                    361:        {
                    362:                this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
                    363:        }
                    364:        if (this->tsr)
                    365:        {
                    366:                this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
                    367:        }
                    368:        DESTROY_IF(this->proposal);
                    369:        this->id->destroy(this->id);
                    370:        free(this->ike_init.ptr);
                    371:        free(this->nonce.ptr);
                    372:        free(this);
                    373: }
                    374: 
                    375: /**
                    376:  * Create the IKE_AUTH fill hook
                    377:  */
                    378: hook_t *pretend_auth_hook_create(char *name)
                    379: {
                    380:        private_pretend_auth_t *this;
                    381: 
                    382:        INIT(this,
                    383:                .hook = {
                    384:                        .listener = {
                    385:                                .message = _message,
                    386:                        },
                    387:                        .destroy = _destroy,
                    388:                },
                    389:                .id = identification_create_from_string(
                    390:                                conftest->test->get_str(conftest->test,
                    391:                                                                                "hooks.%s.peer", "%any", name)),
                    392:        );
                    393: 
                    394:        return &this->hook;
                    395: }

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