Statistics
| Branch: | Tag: | Revision:

root / src / charon / sa / tasks / ike_config.c @ b5a2055fb1b88ea4abb97334d89e311c9ceaa7d4

History | View | Annotate | Download (9.9 KB)

1
/*
2
 * Copyright (C) 2007 Martin Willi
3
 * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
4
 * 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_config.h"
18
19
#include <daemon.h>
20
#include <encoding/payloads/cp_payload.h>
21
22
typedef struct private_ike_config_t private_ike_config_t;
23
24
/**
25
 * Private members of a ike_config_t task.
26
 */
27
struct private_ike_config_t {
28
29
    /**
30
     * Public methods and task_t interface.
31
     */
32
    ike_config_t public;
33
34
    /**
35
     * Assigned IKE_SA.
36
     */
37
    ike_sa_t *ike_sa;
38
39
    /**
40
     * Are we the initiator?
41
     */
42
    bool initiator;
43
44
    /**
45
     * virtual ip
46
     */
47
    host_t *virtual_ip;
48
49
    /**
50
     * list of attributes requested and its handler, entry_t
51
     */
52
    linked_list_t *requested;
53
};
54
55
/**
56
 * Entry for a requested attribute and the requesting handler
57
 */
58
typedef struct {
59
    /** attribute requested */
60
    configuration_attribute_type_t type;
61
    /** handler requesting this attribute */
62
    attribute_handler_t *handler;
63
} entry_t;
64
65
/**
66
 * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
67
 */
68
static configuration_attribute_t *build_vip(host_t *vip)
69
{
70
    configuration_attribute_type_t type;
71
    chunk_t chunk, prefix;
72
73
    if (vip->get_family(vip) == AF_INET)
74
    {
75
        type = INTERNAL_IP4_ADDRESS;
76
        if (vip->is_anyaddr(vip))
77
        {
78
            chunk = chunk_empty;
79
        }
80
        else
81
        {
82
            chunk = vip->get_address(vip);
83
        }
84
    }
85
    else
86
    {
87
        type = INTERNAL_IP6_ADDRESS;
88
        if (vip->is_anyaddr(vip))
89
        {
90
            chunk = chunk_empty;
91
        }
92
        else
93
        {
94
            prefix = chunk_alloca(1);
95
            *prefix.ptr = 64;
96
            chunk = vip->get_address(vip);
97
            chunk = chunk_cata("cc", chunk, prefix);
98
        }
99
    }
100
    return configuration_attribute_create_value(type, chunk);
101
}
102
103
/**
104
 * Handle a received attribute as initiator
105
 */
106
static void handle_attribute(private_ike_config_t *this,
107
                             configuration_attribute_t *ca)
108
{
109
    attribute_handler_t *handler = NULL;
110
    enumerator_t *enumerator;
111
    entry_t *entry;
112
113
    /* find the handler which requested this attribute */
114
    enumerator = this->requested->create_enumerator(this->requested);
115
    while (enumerator->enumerate(enumerator, &entry))
116
    {
117
        if (entry->type == ca->get_type(ca))
118
        {
119
            handler = entry->handler;
120
            this->requested->remove_at(this->requested, enumerator);
121
            free(entry);
122
            break;
123
        }
124
    }
125
126
    /* and pass it to the handle function */
127
    handler = lib->attributes->handle(lib->attributes,
128
                            this->ike_sa->get_other_id(this->ike_sa), handler,
129
                            ca->get_type(ca), ca->get_value(ca));
130
    if (handler)
131
    {
132
        this->ike_sa->add_configuration_attribute(this->ike_sa,
133
                handler, ca->get_type(ca), ca->get_value(ca));
134
    }
135
}
136
137
/**
138
 * process a single configuration attribute
139
 */
140
static void process_attribute(private_ike_config_t *this,
141
                              configuration_attribute_t *ca)
142
{
143
    host_t *ip;
144
    chunk_t addr;
145
    int family = AF_INET6;
146
147
    switch (ca->get_type(ca))
148
    {
149
        case INTERNAL_IP4_ADDRESS:
150
            family = AF_INET;
151
            /* fall */
152
        case INTERNAL_IP6_ADDRESS:
153
        {
154
            addr = ca->get_value(ca);
155
            if (addr.len == 0)
156
            {
157
                ip = host_create_any(family);
158
            }
159
            else
160
            {
161
                /* skip prefix byte in IPv6 payload*/
162
                if (family == AF_INET6)
163
                {
164
                    addr.len--;
165
                }
166
                ip = host_create_from_chunk(family, addr, 0);
167
            }
168
            if (ip)
169
            {
170
                DESTROY_IF(this->virtual_ip);
171
                this->virtual_ip = ip;
172
            }
173
            break;
174
        }
175
        default:
176
        {
177
            if (this->initiator)
178
            {
179
                handle_attribute(this, ca);
180
            }
181
        }
182
    }
183
}
184
185
/**
186
 * Scan for configuration payloads and attributes
187
 */
188
static void process_payloads(private_ike_config_t *this, message_t *message)
189
{
190
    enumerator_t *enumerator, *attributes;
191
    payload_t *payload;
192
193
    enumerator = message->create_payload_enumerator(message);
194
    while (enumerator->enumerate(enumerator, &payload))
195
    {
196
        if (payload->get_type(payload) == CONFIGURATION)
197
        {
198
            cp_payload_t *cp = (cp_payload_t*)payload;
199
            configuration_attribute_t *ca;
200
201
            switch (cp->get_type(cp))
202
            {
203
                case CFG_REQUEST:
204
                case CFG_REPLY:
205
                {
206
                    attributes = cp->create_attribute_enumerator(cp);
207
                    while (attributes->enumerate(attributes, &ca))
208
                    {
209
                        process_attribute(this, ca);
210
                    }
211
                    attributes->destroy(attributes);
212
                    break;
213
                }
214
                default:
215
                    DBG1(DBG_IKE, "ignoring %N config payload",
216
                         config_type_names, cp->get_type(cp));
217
                    break;
218
            }
219
        }
220
    }
221
    enumerator->destroy(enumerator);
222
}
223
224
/**
225
 * Implementation of task_t.process for initiator
226
 */
227
static status_t build_i(private_ike_config_t *this, message_t *message)
228
{
229
    if (message->get_message_id(message) == 1)
230
    {    /* in first IKE_AUTH only */
231
        cp_payload_t *cp = NULL;
232
        enumerator_t *enumerator;
233
        attribute_handler_t *handler;
234
        peer_cfg_t *config;
235
        configuration_attribute_type_t type;
236
        chunk_t data;
237
        host_t *vip;
238
239
        /* reuse virtual IP if we already have one */
240
        vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
241
        if (!vip)
242
        {
243
            config = this->ike_sa->get_peer_cfg(this->ike_sa);
244
            vip = config->get_virtual_ip(config);
245
        }
246
        if (vip)
247
        {
248
            cp = cp_payload_create_type(CFG_REQUEST);
249
            cp->add_attribute(cp, build_vip(vip));
250
        }
251
252
        enumerator = lib->attributes->create_initiator_enumerator(lib->attributes,
253
                                this->ike_sa->get_other_id(this->ike_sa), vip);
254
        while (enumerator->enumerate(enumerator, &handler, &type, &data))
255
        {
256
            configuration_attribute_t *ca;
257
            entry_t *entry;
258
259
            /* create configuration attribute */
260
            ca = configuration_attribute_create_value(type, data);
261
            if (!cp)
262
            {
263
                cp = cp_payload_create_type(CFG_REQUEST);
264
            }
265
            cp->add_attribute(cp, ca);
266
267
            /* save handler along with requested type */
268
            entry = malloc_thing(entry_t);
269
            entry->type = type;
270
            entry->handler = handler;
271
272
            this->requested->insert_last(this->requested, entry);
273
        }
274
        enumerator->destroy(enumerator);
275
276
        if (cp)
277
        {
278
            message->add_payload(message, (payload_t*)cp);
279
        }
280
    }
281
    return NEED_MORE;
282
}
283
284
/**
285
 * Implementation of task_t.process for responder
286
 */
287
static status_t process_r(private_ike_config_t *this, message_t *message)
288
{
289
    if (message->get_message_id(message) == 1)
290
    {    /* in first IKE_AUTH only */
291
        process_payloads(this, message);
292
    }
293
    return NEED_MORE;
294
}
295
296
/**
297
 * Implementation of task_t.build for responder
298
 */
299
static status_t build_r(private_ike_config_t *this, message_t *message)
300
{
301
    if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
302
    {    /* in last IKE_AUTH exchange */
303
        enumerator_t *enumerator;
304
        configuration_attribute_type_t type;
305
        chunk_t value;
306
        host_t *vip = NULL;
307
        cp_payload_t *cp = NULL;
308
        peer_cfg_t *config;
309
310
        config = this->ike_sa->get_peer_cfg(this->ike_sa);
311
        if (config && this->virtual_ip)
312
        {
313
            DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
314
            if (config->get_pool(config))
315
            {
316
                vip = lib->attributes->acquire_address(lib->attributes,
317
                                    config->get_pool(config),
318
                                    this->ike_sa->get_other_id(this->ike_sa),
319
                                    this->virtual_ip);
320
            }
321
            if (vip == NULL)
322
            {
323
                DBG1(DBG_IKE, "no virtual IP found, sending %N",
324
                     notify_type_names, INTERNAL_ADDRESS_FAILURE);
325
                message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
326
                                    chunk_empty);
327
                return SUCCESS;
328
            }
329
            DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
330
            this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
331
332
            cp = cp_payload_create_type(CFG_REPLY);
333
            cp->add_attribute(cp, build_vip(vip));
334
        }
335
336
        /* query registered providers for additional attributes to include */
337
        enumerator = lib->attributes->create_responder_enumerator(
338
                lib->attributes, this->ike_sa->get_other_id(this->ike_sa), vip);
339
        while (enumerator->enumerate(enumerator, &type, &value))
340
        {
341
            if (!cp)
342
            {
343
                cp = cp_payload_create_type(CFG_REPLY);
344
            }
345
            cp->add_attribute(cp,
346
                        configuration_attribute_create_value(type, value));
347
        }
348
        enumerator->destroy(enumerator);
349
350
        if (cp)
351
        {
352
            message->add_payload(message, (payload_t*)cp);
353
        }
354
        DESTROY_IF(vip);
355
        return SUCCESS;
356
    }
357
    return NEED_MORE;
358
}
359
360
/**
361
 * Implementation of task_t.process for initiator
362
 */
363
static status_t process_i(private_ike_config_t *this, message_t *message)
364
{
365
    if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
366
    {    /* in last IKE_AUTH exchange */
367
368
        process_payloads(this, message);
369
370
        if (this->virtual_ip)
371
        {
372
            this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
373
        }
374
        return SUCCESS;
375
    }
376
    return NEED_MORE;
377
}
378
379
/**
380
 * Implementation of task_t.get_type
381
 */
382
static task_type_t get_type(private_ike_config_t *this)
383
{
384
    return IKE_CONFIG;
385
}
386
387
/**
388
 * Implementation of task_t.migrate
389
 */
390
static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
391
{
392
    DESTROY_IF(this->virtual_ip);
393
394
    this->ike_sa = ike_sa;
395
    this->virtual_ip = NULL;
396
    this->requested->destroy_function(this->requested, free);
397
    this->requested = linked_list_create();
398
}
399
400
/**
401
 * Implementation of task_t.destroy
402
 */
403
static void destroy(private_ike_config_t *this)
404
{
405
    DESTROY_IF(this->virtual_ip);
406
    this->requested->destroy_function(this->requested, free);
407
    free(this);
408
}
409
410
/*
411
 * Described in header.
412
 */
413
ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
414
{
415
    private_ike_config_t *this = malloc_thing(private_ike_config_t);
416
417
    this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
418
    this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
419
    this->public.task.destroy = (void(*)(task_t*))destroy;
420
421
    this->initiator = initiator;
422
    this->ike_sa = ike_sa;
423
    this->virtual_ip = NULL;
424
    this->requested = linked_list_create();
425
426
    if (initiator)
427
    {
428
        this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
429
        this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
430
    }
431
    else
432
    {
433
        this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
434
        this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
435
    }
436
437
    return &this->public;
438
}
439