Annotation of embedaddon/strongswan/src/libcharon/sa/redirect_manager.c, revision 1.1.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>