Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/xauth.c, revision 1.1.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 "xauth.h"
                     17: 
                     18: #include <daemon.h>
                     19: #include <encoding/payloads/cp_payload.h>
                     20: #include <processing/jobs/adopt_children_job.h>
                     21: #include <sa/ikev1/tasks/mode_config.h>
                     22: 
                     23: typedef struct private_xauth_t private_xauth_t;
                     24: 
                     25: /**
                     26:  * Status types exchanged
                     27:  */
                     28: typedef enum {
                     29:        XAUTH_FAILED = 0,
                     30:        XAUTH_OK = 1,
                     31: } xauth_status_t;
                     32: 
                     33: /**
                     34:  * Private members of a xauth_t task.
                     35:  */
                     36: struct private_xauth_t {
                     37: 
                     38:        /**
                     39:         * Public methods and task_t interface.
                     40:         */
                     41:        xauth_t public;
                     42: 
                     43:        /**
                     44:         * Assigned IKE_SA.
                     45:         */
                     46:        ike_sa_t *ike_sa;
                     47: 
                     48:        /**
                     49:         * Are we the XAUTH initiator?
                     50:         */
                     51:        bool initiator;
                     52: 
                     53:        /**
                     54:         * XAuth backend to use
                     55:         */
                     56:        xauth_method_t *xauth;
                     57: 
                     58:        /**
                     59:         * XAuth username
                     60:         */
                     61:        identification_t *user;
                     62: 
                     63:        /**
                     64:         * Generated configuration payload
                     65:         */
                     66:        cp_payload_t *cp;
                     67: 
                     68:        /**
                     69:         * received identifier
                     70:         */
                     71:        uint16_t identifier;
                     72: 
                     73:        /**
                     74:         * status of Xauth exchange
                     75:         */
                     76:        xauth_status_t status;
                     77: 
                     78:        /**
                     79:         * Queue a Mode Config Push mode after completing XAuth?
                     80:         */
                     81:        bool mode_config_push;
                     82: };
                     83: 
                     84: /**
                     85:  * Load XAuth backend
                     86:  */
                     87: static xauth_method_t *load_method(private_xauth_t* this)
                     88: {
                     89:        identification_t *server, *peer;
                     90:        enumerator_t *enumerator;
                     91:        xauth_method_t *xauth;
                     92:        xauth_role_t role;
                     93:        peer_cfg_t *peer_cfg;
                     94:        auth_cfg_t *auth;
                     95:        char *name;
                     96: 
                     97:        if (this->initiator)
                     98:        {
                     99:                server = this->ike_sa->get_my_id(this->ike_sa);
                    100:                peer = this->ike_sa->get_other_id(this->ike_sa);
                    101:                role = XAUTH_SERVER;
                    102:        }
                    103:        else
                    104:        {
                    105:                peer = this->ike_sa->get_my_id(this->ike_sa);
                    106:                server = this->ike_sa->get_other_id(this->ike_sa);
                    107:                role = XAUTH_PEER;
                    108:        }
                    109:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
                    110:        enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, !this->initiator);
                    111:        if (!enumerator->enumerate(enumerator, &auth) ||
                    112:                (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
                    113:        {
                    114:                if (!enumerator->enumerate(enumerator, &auth) ||
                    115:                        (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH)
                    116:                {
                    117:                        DBG1(DBG_CFG, "no XAuth authentication round found");
                    118:                        enumerator->destroy(enumerator);
                    119:                        return NULL;
                    120:                }
                    121:        }
                    122:        name = auth->get(auth, AUTH_RULE_XAUTH_BACKEND);
                    123:        this->user = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
                    124:        enumerator->destroy(enumerator);
                    125:        if (!this->initiator && this->user)
                    126:        {       /* use XAUTH username, if configured */
                    127:                peer = this->user;
                    128:        }
                    129:        xauth = charon->xauth->create_instance(charon->xauth, name, role,
                    130:                                                                                   server, peer);
                    131:        if (!xauth)
                    132:        {
                    133:                if (name)
                    134:                {
                    135:                        DBG1(DBG_CFG, "no XAuth method found for '%s'", name);
                    136:                }
                    137:                else
                    138:                {
                    139:                        DBG1(DBG_CFG, "no XAuth method found");
                    140:                }
                    141:        }
                    142:        return xauth;
                    143: }
                    144: 
                    145: /**
                    146:  * Check if XAuth connection is allowed to succeed
                    147:  */
                    148: static bool allowed(private_xauth_t *this)
                    149: {
                    150:        if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
                    151:                                                                                                 this->ike_sa, FALSE))
                    152:        {
                    153:                DBG1(DBG_IKE, "cancelling XAuth due to uniqueness policy");
                    154:                return FALSE;
                    155:        }
                    156:        if (!charon->bus->authorize(charon->bus, FALSE))
                    157:        {
                    158:                DBG1(DBG_IKE, "XAuth authorization hook forbids IKE_SA, cancelling");
                    159:                return FALSE;
                    160:        }
                    161:        if (!charon->bus->authorize(charon->bus, TRUE))
                    162:        {
                    163:                DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
                    164:                return FALSE;
                    165:        }
                    166:        return TRUE;
                    167: }
                    168: 
                    169: /**
                    170:  * Set IKE_SA to established state
                    171:  */
                    172: static bool establish(private_xauth_t *this)
                    173: {
                    174:        DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
                    175:                 this->ike_sa->get_name(this->ike_sa),
                    176:                 this->ike_sa->get_unique_id(this->ike_sa),
                    177:                 this->ike_sa->get_my_host(this->ike_sa),
                    178:                 this->ike_sa->get_my_id(this->ike_sa),
                    179:                 this->ike_sa->get_other_host(this->ike_sa),
                    180:                 this->ike_sa->get_other_id(this->ike_sa));
                    181: 
                    182:        this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
                    183:        charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
                    184: 
                    185:        return TRUE;
                    186: }
                    187: 
                    188: /**
                    189:  * Check if we are compliant to a given peer config
                    190:  */
                    191: static bool is_compliant(private_xauth_t *this, peer_cfg_t *peer_cfg, bool log)
                    192: {
                    193:        bool complies = TRUE;
                    194:        enumerator_t *e1, *e2;
                    195:        auth_cfg_t *c1, *c2;
                    196: 
                    197:        e1 = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
                    198:        e2 = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
                    199:        while (e1->enumerate(e1, &c1))
                    200:        {
                    201:                if (!e2->enumerate(e2, &c2) || !c2->complies(c2, c1, log))
                    202:                {
                    203:                        complies = FALSE;
                    204:                        break;
                    205:                }
                    206:        }
                    207:        e1->destroy(e1);
                    208:        e2->destroy(e2);
                    209: 
                    210:        return complies;
                    211: }
                    212: 
                    213: /**
                    214:  * Check if we are compliant to current config, switch to another if not
                    215:  */
                    216: static bool select_compliant_config(private_xauth_t *this)
                    217: {
                    218:        peer_cfg_t *peer_cfg = NULL, *old, *current;
                    219:        identification_t *my_id, *other_id;
                    220:        host_t *my_host, *other_host;
                    221:        enumerator_t *enumerator;
                    222:        bool aggressive;
                    223: 
                    224:        old = this->ike_sa->get_peer_cfg(this->ike_sa);
                    225:        if (is_compliant(this, old, TRUE))
                    226:        {       /* current config is fine */
                    227:                return TRUE;
                    228:        }
                    229:        DBG1(DBG_CFG, "selected peer config '%s' unacceptable",
                    230:                 old->get_name(old));
                    231:        aggressive = old->use_aggressive(old);
                    232: 
                    233:        my_host = this->ike_sa->get_my_host(this->ike_sa);
                    234:        other_host = this->ike_sa->get_other_host(this->ike_sa);
                    235:        my_id = this->ike_sa->get_my_id(this->ike_sa);
                    236:        other_id = this->ike_sa->get_other_id(this->ike_sa);
                    237:        enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
                    238:                                                                my_host, other_host, my_id, other_id, IKEV1);
                    239:        while (enumerator->enumerate(enumerator, &current))
                    240:        {
                    241:                if (!current->equals(current, old) &&
                    242:                        current->use_aggressive(current) == aggressive &&
                    243:                        is_compliant(this, current, FALSE))
                    244:                {
                    245:                        peer_cfg = current;
                    246:                        break;
                    247:                }
                    248:        }
                    249:        if (peer_cfg)
                    250:        {
                    251:                DBG1(DBG_CFG, "switching to peer config '%s'",
                    252:                         peer_cfg->get_name(peer_cfg));
                    253:                this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
                    254:        }
                    255:        else
                    256:        {
                    257:                DBG1(DBG_CFG, "no alternative config found");
                    258:        }
                    259:        enumerator->destroy(enumerator);
                    260: 
                    261:        return peer_cfg != NULL;
                    262: }
                    263: 
                    264: /**
                    265:  * Create auth config after successful authentication
                    266:  */
                    267: static bool add_auth_cfg(private_xauth_t *this, identification_t *id, bool local)
                    268: {
                    269:        auth_cfg_t *auth;
                    270: 
                    271:        auth = auth_cfg_create();
                    272:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
                    273:        if (id)
                    274:        {
                    275:                auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id));
                    276:        }
                    277:        auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), FALSE);
                    278:        this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
                    279: 
                    280:        return select_compliant_config(this);
                    281: }
                    282: 
                    283: METHOD(task_t, build_i_status, status_t,
                    284:        private_xauth_t *this, message_t *message)
                    285: {
                    286:        cp_payload_t *cp;
                    287: 
                    288:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);
                    289:        cp->add_attribute(cp,
                    290:                        configuration_attribute_create_value(XAUTH_STATUS, this->status));
                    291: 
                    292:        message->add_payload(message, (payload_t *)cp);
                    293: 
                    294:        return NEED_MORE;
                    295: }
                    296: 
                    297: METHOD(task_t, process_i_status, status_t,
                    298:        private_xauth_t *this, message_t *message)
                    299: {
                    300:        cp_payload_t *cp;
                    301:        adopt_children_job_t *job;
                    302: 
                    303:        cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
                    304:        if (!cp || cp->get_type(cp) != CFG_ACK)
                    305:        {
                    306:                DBG1(DBG_IKE, "received invalid XAUTH status response");
                    307:                return FAILED;
                    308:        }
                    309:        if (this->status != XAUTH_OK)
                    310:        {
                    311:                DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication");
                    312:                return FAILED;
                    313:        }
                    314:        if (!establish(this))
                    315:        {
                    316:                return FAILED;
                    317:        }
                    318:        this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE);
                    319:        job = adopt_children_job_create(this->ike_sa->get_id(this->ike_sa));
                    320:        if (this->mode_config_push)
                    321:        {
                    322:                job->queue_task(job,
                    323:                                (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
                    324:        }
                    325:        lib->processor->queue_job(lib->processor, (job_t*)job);
                    326:        return SUCCESS;
                    327: }
                    328: 
                    329: METHOD(task_t, build_i, status_t,
                    330:        private_xauth_t *this, message_t *message)
                    331: {
                    332:        if (!this->xauth)
                    333:        {
                    334:                cp_payload_t *cp = NULL;
                    335: 
                    336:                this->xauth = load_method(this);
                    337:                if (!this->xauth)
                    338:                {
                    339:                        return FAILED;
                    340:                }
                    341:                switch (this->xauth->initiate(this->xauth, &cp))
                    342:                {
                    343:                        case NEED_MORE:
                    344:                                break;
                    345:                        case SUCCESS:
                    346:                                DESTROY_IF(cp);
                    347:                                if (add_auth_cfg(this, NULL, FALSE) && allowed(this))
                    348:                                {
                    349:                                        this->status = XAUTH_OK;
                    350:                                }
                    351:                                this->public.task.process = _process_i_status;
                    352:                                return build_i_status(this, message);
                    353:                        default:
                    354:                                return FAILED;
                    355:                }
                    356:                message->add_payload(message, (payload_t *)cp);
                    357:                return NEED_MORE;
                    358:        }
                    359: 
                    360:        if (this->cp)
                    361:        {       /* send previously generated payload */
                    362:                message->add_payload(message, (payload_t *)this->cp);
                    363:                this->cp = NULL;
                    364:                return NEED_MORE;
                    365:        }
                    366:        return FAILED;
                    367: }
                    368: 
                    369: METHOD(task_t, build_r_ack, status_t,
                    370:        private_xauth_t *this, message_t *message)
                    371: {
                    372:        cp_payload_t *cp;
                    373: 
                    374:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);
                    375:        cp->set_identifier(cp, this->identifier);
                    376:        cp->add_attribute(cp,
                    377:                        configuration_attribute_create_chunk(
                    378:                                        PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_STATUS, chunk_empty));
                    379: 
                    380:        message->add_payload(message, (payload_t *)cp);
                    381: 
                    382:        if (this->status == XAUTH_OK && allowed(this) && establish(this))
                    383:        {
                    384:                return SUCCESS;
                    385:        }
                    386:        return FAILED;
                    387: }
                    388: 
                    389: METHOD(task_t, process_r, status_t,
                    390:        private_xauth_t *this, message_t *message)
                    391: {
                    392:        cp_payload_t *cp;
                    393: 
                    394:        if (!this->xauth)
                    395:        {
                    396:                this->xauth = load_method(this);
                    397:                if (!this->xauth)
                    398:                {       /* send empty reply */
                    399:                        return NEED_MORE;
                    400:                }
                    401:        }
                    402:        cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
                    403:        if (!cp)
                    404:        {
                    405:                DBG1(DBG_IKE, "configuration payload missing in XAuth request");
                    406:                return FAILED;
                    407:        }
                    408:        if (cp->get_type(cp) == CFG_REQUEST)
                    409:        {
                    410:                switch (this->xauth->process(this->xauth, cp, &this->cp))
                    411:                {
                    412:                        case NEED_MORE:
                    413:                                return NEED_MORE;
                    414:                        case SUCCESS:
                    415:                        case FAILED:
                    416:                        default:
                    417:                                break;
                    418:                }
                    419:                this->cp = NULL;
                    420:                return NEED_MORE;
                    421:        }
                    422:        if (cp->get_type(cp) == CFG_SET)
                    423:        {
                    424:                configuration_attribute_t *attribute;
                    425:                enumerator_t *enumerator;
                    426: 
                    427:                enumerator = cp->create_attribute_enumerator(cp);
                    428:                while (enumerator->enumerate(enumerator, &attribute))
                    429:                {
                    430:                        if (attribute->get_type(attribute) == XAUTH_STATUS)
                    431:                        {
                    432:                                this->status = attribute->get_value(attribute);
                    433:                        }
                    434:                }
                    435:                enumerator->destroy(enumerator);
                    436:                if (this->status == XAUTH_OK &&
                    437:                        add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE))
                    438:                {
                    439:                        DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful",
                    440:                                 this->xauth->get_identity(this->xauth));
                    441:                }
                    442:                else
                    443:                {
                    444:                        DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed",
                    445:                                 this->xauth->get_identity(this->xauth));
                    446:                }
                    447:        }
                    448:        this->identifier = cp->get_identifier(cp);
                    449:        this->public.task.build = _build_r_ack;
                    450:        return NEED_MORE;
                    451: }
                    452: 
                    453: METHOD(task_t, build_r, status_t,
                    454:        private_xauth_t *this, message_t *message)
                    455: {
                    456:        if (!this->cp)
                    457:        {       /* send empty reply if building data failed */
                    458:                this->cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
                    459:        }
                    460:        message->add_payload(message, (payload_t *)this->cp);
                    461:        this->cp = NULL;
                    462:        return NEED_MORE;
                    463: }
                    464: 
                    465: METHOD(task_t, process_i, status_t,
                    466:        private_xauth_t *this, message_t *message)
                    467: {
                    468:        identification_t *id;
                    469:        cp_payload_t *cp;
                    470: 
                    471:        cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
                    472:        if (!cp)
                    473:        {
                    474:                DBG1(DBG_IKE, "configuration payload missing in XAuth response");
                    475:                return FAILED;
                    476:        }
                    477:        switch (this->xauth->process(this->xauth, cp, &this->cp))
                    478:        {
                    479:                case NEED_MORE:
                    480:                        return NEED_MORE;
                    481:                case SUCCESS:
                    482:                        id = this->xauth->get_identity(this->xauth);
                    483:                        DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id);
                    484:                        if (add_auth_cfg(this, id, FALSE) && allowed(this))
                    485:                        {
                    486:                                this->status = XAUTH_OK;
                    487:                        }
                    488:                        break;
                    489:                case FAILED:
                    490:                        DBG1(DBG_IKE, "XAuth authentication of '%Y' failed",
                    491:                                 this->xauth->get_identity(this->xauth));
                    492:                        break;
                    493:                default:
                    494:                        return FAILED;
                    495:        }
                    496:        this->public.task.build = _build_i_status;
                    497:        this->public.task.process = _process_i_status;
                    498:        return NEED_MORE;
                    499: }
                    500: 
                    501: METHOD(task_t, get_type, task_type_t,
                    502:        private_xauth_t *this)
                    503: {
                    504:        return TASK_XAUTH;
                    505: }
                    506: 
                    507: METHOD(task_t, migrate, void,
                    508:        private_xauth_t *this, ike_sa_t *ike_sa)
                    509: {
                    510:        DESTROY_IF(this->xauth);
                    511:        DESTROY_IF(this->cp);
                    512: 
                    513:        this->ike_sa = ike_sa;
                    514:        this->xauth = NULL;
                    515:        this->cp = NULL;
                    516:        this->user = NULL;
                    517:        this->status = XAUTH_FAILED;
                    518: 
                    519:        if (this->initiator)
                    520:        {
                    521:                this->public.task.build = _build_i;
                    522:                this->public.task.process = _process_i;
                    523:        }
                    524:        else
                    525:        {
                    526:                this->public.task.build = _build_r;
                    527:                this->public.task.process = _process_r;
                    528:        }
                    529: }
                    530: 
                    531: METHOD(xauth_t, queue_mode_config_push, void,
                    532:        private_xauth_t *this)
                    533: {
                    534:        this->mode_config_push = TRUE;
                    535: }
                    536: 
                    537: METHOD(task_t, destroy, void,
                    538:        private_xauth_t *this)
                    539: {
                    540:        DESTROY_IF(this->xauth);
                    541:        DESTROY_IF(this->cp);
                    542:        free(this);
                    543: }
                    544: 
                    545: /*
                    546:  * Described in header.
                    547:  */
                    548: xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
                    549: {
                    550:        private_xauth_t *this;
                    551: 
                    552:        INIT(this,
                    553:                .public = {
                    554:                        .task = {
                    555:                                .get_type = _get_type,
                    556:                                .migrate = _migrate,
                    557:                                .destroy = _destroy,
                    558:                        },
                    559:                        .queue_mode_config_push = _queue_mode_config_push,
                    560:                },
                    561:                .initiator = initiator,
                    562:                .ike_sa = ike_sa,
                    563:                .status = XAUTH_FAILED,
                    564:        );
                    565: 
                    566:        if (initiator)
                    567:        {
                    568:                this->public.task.build = _build_i;
                    569:                this->public.task.process = _process_i;
                    570:        }
                    571:        else
                    572:        {
                    573:                this->public.task.build = _build_r;
                    574:                this->public.task.process = _process_r;
                    575:        }
                    576:        return &this->public;
                    577: }

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