Annotation of embedaddon/strongswan/src/libcharon/sa/redirect_manager.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2015 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             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 "redirect_manager.h"
        !            17: 
        !            18: #include <collections/linked_list.h>
        !            19: #include <threading/rwlock.h>
        !            20: #include <bio/bio_reader.h>
        !            21: #include <bio/bio_writer.h>
        !            22: 
        !            23: typedef struct private_redirect_manager_t private_redirect_manager_t;
        !            24: 
        !            25: /**
        !            26:  * Private data
        !            27:  */
        !            28: struct private_redirect_manager_t {
        !            29: 
        !            30:        /**
        !            31:         * Public interface
        !            32:         */
        !            33:        redirect_manager_t public;
        !            34: 
        !            35:        /**
        !            36:         * Registered providers
        !            37:         */
        !            38:        linked_list_t *providers;
        !            39: 
        !            40:        /**
        !            41:         * Lock to access list of providers
        !            42:         */
        !            43:        rwlock_t *lock;
        !            44: };
        !            45: 
        !            46: 
        !            47: /**
        !            48:  * Gateway identify types
        !            49:  *
        !            50:  * The encoding is the same as that for corresponding ID payloads.
        !            51:  */
        !            52: typedef enum {
        !            53:        /** IPv4 address of the VPN gateway */
        !            54:        GATEWAY_ID_TYPE_IPV4 = 1,
        !            55:        /** IPv6 address of the VPN gateway */
        !            56:        GATEWAY_ID_TYPE_IPV6 = 2,
        !            57:        /** FQDN of the VPN gateway */
        !            58:        GATEWAY_ID_TYPE_FQDN = 3,
        !            59: } gateway_id_type_t;
        !            60: 
        !            61: /**
        !            62:  * Mapping of gateway identity types to identity types
        !            63:  */
        !            64: static id_type_t gateway_to_id_type(gateway_id_type_t type)
        !            65: {
        !            66:        switch (type)
        !            67:        {
        !            68:                case GATEWAY_ID_TYPE_IPV4:
        !            69:                        return ID_IPV4_ADDR;
        !            70:                case GATEWAY_ID_TYPE_IPV6:
        !            71:                        return ID_IPV6_ADDR;
        !            72:                case GATEWAY_ID_TYPE_FQDN:
        !            73:                        return ID_FQDN;
        !            74:                default:
        !            75:                        return 0;
        !            76:        }
        !            77: }
        !            78: 
        !            79: /**
        !            80:  * Mapping of identity types to gateway identity types
        !            81:  */
        !            82: static gateway_id_type_t id_type_to_gateway(id_type_t type)
        !            83: {
        !            84:        switch (type)
        !            85:        {
        !            86:                case ID_IPV4_ADDR:
        !            87:                        return GATEWAY_ID_TYPE_IPV4;
        !            88:                case ID_IPV6_ADDR:
        !            89:                        return GATEWAY_ID_TYPE_IPV6;
        !            90:                case ID_FQDN:
        !            91:                        return GATEWAY_ID_TYPE_FQDN;
        !            92:                default:
        !            93:                        return 0;
        !            94:        }
        !            95: }
        !            96: 
        !            97: METHOD(redirect_manager_t, add_provider, void,
        !            98:        private_redirect_manager_t *this, redirect_provider_t *provider)
        !            99: {
        !           100:        this->lock->write_lock(this->lock);
        !           101:        this->providers->insert_last(this->providers, provider);
        !           102:        this->lock->unlock(this->lock);
        !           103: }
        !           104: 
        !           105: METHOD(redirect_manager_t, remove_provider, void,
        !           106:        private_redirect_manager_t *this, redirect_provider_t *provider)
        !           107: {
        !           108:        this->lock->write_lock(this->lock);
        !           109:        this->providers->remove(this->providers, provider, NULL);
        !           110:        this->lock->unlock(this->lock);
        !           111: }
        !           112: 
        !           113: /**
        !           114:  * Determine whether a client should be redirected using the callback with the
        !           115:  * given offset into the redirect_provider_t interface.
        !           116:  */
        !           117: static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa,
        !           118:                                                        identification_t **gateway, size_t offset)
        !           119: {
        !           120:        enumerator_t *enumerator;
        !           121:        void *provider;
        !           122:        bool redirect = FALSE;
        !           123: 
        !           124:        this->lock->read_lock(this->lock);
        !           125:        enumerator = this->providers->create_enumerator(this->providers);
        !           126:        while (enumerator->enumerate(enumerator, &provider))
        !           127:        {
        !           128:                bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset;
        !           129:                if (*method && (*method)(provider, ike_sa, gateway))
        !           130:                {
        !           131:                        if (*gateway && id_type_to_gateway((*gateway)->get_type(*gateway)))
        !           132:                        {
        !           133:                                redirect = TRUE;
        !           134:                                break;
        !           135:                        }
        !           136:                        else
        !           137:                        {
        !           138:                                DBG1(DBG_CFG, "redirect provider returned invalid gateway ID");
        !           139:                                DESTROY_IF(*gateway);
        !           140:                        }
        !           141:                }
        !           142:        }
        !           143:        enumerator->destroy(enumerator);
        !           144:        this->lock->unlock(this->lock);
        !           145:        return redirect;
        !           146: }
        !           147: 
        !           148: METHOD(redirect_manager_t, redirect_on_init, bool,
        !           149:        private_redirect_manager_t *this, ike_sa_t *ike_sa,
        !           150:        identification_t **gateway)
        !           151: {
        !           152:        return should_redirect(this, ike_sa, gateway,
        !           153:                                                   offsetof(redirect_provider_t, redirect_on_init));
        !           154: }
        !           155: 
        !           156: METHOD(redirect_manager_t, redirect_on_auth, bool,
        !           157:        private_redirect_manager_t *this, ike_sa_t *ike_sa,
        !           158:        identification_t **gateway)
        !           159: {
        !           160:        return should_redirect(this, ike_sa, gateway,
        !           161:                                                   offsetof(redirect_provider_t, redirect_on_auth));
        !           162: }
        !           163: 
        !           164: METHOD(redirect_manager_t, destroy, void,
        !           165:        private_redirect_manager_t *this)
        !           166: {
        !           167:        this->providers->destroy(this->providers);
        !           168:        this->lock->destroy(this->lock);
        !           169:        free(this);
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Described in header
        !           174:  */
        !           175: redirect_manager_t *redirect_manager_create()
        !           176: {
        !           177:        private_redirect_manager_t *this;
        !           178: 
        !           179:        INIT(this,
        !           180:                .public = {
        !           181:                        .add_provider = _add_provider,
        !           182:                        .remove_provider = _remove_provider,
        !           183:                        .redirect_on_init = _redirect_on_init,
        !           184:                        .redirect_on_auth = _redirect_on_auth,
        !           185:                        .destroy = _destroy,
        !           186:                },
        !           187:                .providers = linked_list_create(),
        !           188:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        !           189:        );
        !           190: 
        !           191:        return &this->public;
        !           192: }
        !           193: 
        !           194: /*
        !           195:  * Encoding of a REDIRECT or REDIRECTED_FROM notify
        !           196:  *
        !           197:                          1                   2                   3
        !           198:      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           199:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           200:     | Next Payload  |C|  RESERVED   |         Payload Length        |
        !           201:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           202:     |Protocol ID(=0)| SPI Size (=0) |      Notify Message Type      |
        !           203:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           204:     | GW Ident Type |  GW Ident Len |                               |
        !           205:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               ~
        !           206:     ~                   New Responder GW Identity                   ~
        !           207:     |                                                               |
        !           208:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           209:     |                                                               |
        !           210:     ~                        Nonce Data                             ~
        !           211:     |                                                               |
        !           212:     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           213: */
        !           214: 
        !           215: /*
        !           216:  * Described in header
        !           217:  */
        !           218: chunk_t redirect_data_create(identification_t *gw, chunk_t nonce)
        !           219: {
        !           220:        gateway_id_type_t type;
        !           221:        bio_writer_t *writer;
        !           222:        chunk_t data;
        !           223: 
        !           224:        type = id_type_to_gateway(gw->get_type(gw));
        !           225:        if (!type)
        !           226:        {
        !           227:                return chunk_empty;
        !           228:        }
        !           229: 
        !           230:        writer = bio_writer_create(0);
        !           231:        writer->write_uint8(writer, type);
        !           232:        writer->write_data8(writer, gw->get_encoding(gw));
        !           233:        if (nonce.ptr)
        !           234:        {
        !           235:                writer->write_data(writer, nonce);
        !           236:        }
        !           237: 
        !           238:        data = writer->extract_buf(writer);
        !           239:        writer->destroy(writer);
        !           240:        return data;
        !           241: }
        !           242: 
        !           243: /*
        !           244:  * Described in header
        !           245:  */
        !           246: identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce)
        !           247: {
        !           248:        bio_reader_t *reader;
        !           249:        id_type_t id_type;
        !           250:        chunk_t gateway;
        !           251:        uint8_t type;
        !           252: 
        !           253:        reader = bio_reader_create(data);
        !           254:        if (!reader->read_uint8(reader, &type) ||
        !           255:                !reader->read_data8(reader, &gateway))
        !           256:        {
        !           257:                DBG1(DBG_ENC, "invalid REDIRECT notify data");
        !           258:                reader->destroy(reader);
        !           259:                return NULL;
        !           260:        }
        !           261:        id_type = gateway_to_id_type(type);
        !           262:        if (!id_type)
        !           263:        {
        !           264:                DBG1(DBG_ENC, "invalid gateway ID type (%d) in REDIRECT notify", type);
        !           265:                reader->destroy(reader);
        !           266:                return NULL;
        !           267:        }
        !           268:        if (nonce)
        !           269:        {
        !           270:                *nonce = chunk_clone(reader->peek(reader));
        !           271:        }
        !           272:        reader->destroy(reader);
        !           273:        return identification_create_from_encoding(id_type, gateway);
        !           274: }

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