Statistics
| Branch: | Tag: | Revision:

root / src / charon / sa / tasks / child_create.c @ 0a3ca29021ffe389ae4f7400ee05f42dcf384d6b

History | View | Annotate | Download (29.8 KB)

1
/*
2
 * Copyright (C) 2008 Tobias Brunner
3
 * Copyright (C) 2005-2008 Martin Willi
4
 * Copyright (C) 2005 Jan Hutter
5
 * Hochschule fuer Technik Rapperswil
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#include "child_create.h"
19
20
#include <daemon.h>
21
#include <crypto/diffie_hellman.h>
22
#include <encoding/payloads/sa_payload.h>
23
#include <encoding/payloads/ke_payload.h>
24
#include <encoding/payloads/ts_payload.h>
25
#include <encoding/payloads/nonce_payload.h>
26
#include <encoding/payloads/notify_payload.h>
27
#include <processing/jobs/delete_ike_sa_job.h>
28
29
30
typedef struct private_child_create_t private_child_create_t;
31
32
/**
33
 * Private members of a child_create_t task.
34
 */
35
struct private_child_create_t {
36
    
37
    /**
38
     * Public methods and task_t interface.
39
     */
40
    child_create_t public;
41
    
42
    /**
43
     * Assigned IKE_SA.
44
     */
45
    ike_sa_t *ike_sa;
46
    
47
    /**
48
     * Are we the initiator?
49
     */
50
    bool initiator;
51
    
52
    /**
53
     * nonce chosen by us
54
     */
55
    chunk_t my_nonce;
56
    
57
    /**
58
     * nonce chosen by peer
59
     */
60
    chunk_t other_nonce;
61
    
62
    /**
63
     * config to create the CHILD_SA from
64
     */
65
    child_cfg_t *config;
66
    
67
    /**
68
     * list of proposal candidates
69
     */
70
    linked_list_t *proposals;
71
    
72
    /**
73
     * selected proposal to use for CHILD_SA
74
     */
75
    proposal_t *proposal;
76
    
77
    /**
78
     * traffic selectors for initiators side
79
     */
80
    linked_list_t *tsi;
81
    
82
    /**
83
     * traffic selectors for responders side
84
     */
85
    linked_list_t *tsr;
86
    
87
    /**
88
     * optional diffie hellman exchange
89
     */
90
    diffie_hellman_t *dh;
91
    
92
    /**
93
     * group used for DH exchange
94
     */
95
    diffie_hellman_group_t dh_group;
96
    
97
    /**
98
     * IKE_SAs keymat
99
     */
100
    keymat_t *keymat;
101
    
102
    /**
103
     * mode the new CHILD_SA uses (transport/tunnel/beet)
104
     */
105
    ipsec_mode_t mode;
106
    
107
    /**
108
     * IPComp transform to use
109
     */
110
    ipcomp_transform_t ipcomp;
111
    
112
    /**
113
     * IPComp transform proposed or accepted by the other peer
114
     */
115
    ipcomp_transform_t ipcomp_received;
116
    
117
    /**
118
     * Own allocated SPI
119
     */
120
    u_int32_t my_spi;
121
    
122
    /**
123
     * SPI received in proposal
124
     */
125
    u_int32_t other_spi;
126
    
127
    /**
128
     * Own allocated Compression Parameter Index (CPI)
129
     */
130
    u_int16_t my_cpi;
131
    
132
    /**
133
     * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
134
     */
135
    u_int16_t other_cpi;
136
    
137
    /**
138
     * reqid to use if we are rekeying
139
     */
140
    u_int32_t reqid;
141
    
142
    /**
143
     * CHILD_SA which gets established
144
     */
145
    child_sa_t *child_sa;
146
    
147
    /**
148
     * successfully established the CHILD?
149
     */
150
    bool established;
151
};
152
153
/**
154
 * get the nonce from a message
155
 */
156
static status_t get_nonce(message_t *message, chunk_t *nonce)
157
{
158
    nonce_payload_t *payload;
159
    
160
    payload = (nonce_payload_t*)message->get_payload(message, NONCE);
161
    if (payload == NULL)
162
    {
163
        return FAILED;
164
    }
165
    *nonce = payload->get_nonce(payload);
166
    return NEED_MORE;
167
}
168
169
/**
170
 * generate a new nonce to include in a CREATE_CHILD_SA message
171
 */
172
static status_t generate_nonce(chunk_t *nonce)
173
{
174
    rng_t *rng;
175
    
176
    rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
177
    if (!rng)
178
    {
179
        DBG1(DBG_IKE, "error generating nonce value, no RNG found");
180
        return FAILED;
181
    }
182
    rng->allocate_bytes(rng, NONCE_SIZE, nonce);
183
    rng->destroy(rng);
184
    return SUCCESS;
185
}
186
187
/**
188
 * Check a list of traffic selectors if any selector belongs to host
189
 */
190
static bool ts_list_is_host(linked_list_t *list, host_t *host)
191
{
192
    traffic_selector_t *ts;
193
    bool is_host = TRUE;
194
    iterator_t *iterator = list->create_iterator(list, TRUE);
195
    
196
    while (is_host && iterator->iterate(iterator, (void**)&ts))
197
    {
198
        is_host = is_host && ts->is_host(ts, host);
199
    }
200
    iterator->destroy(iterator);
201
    return is_host;
202
}
203
204
/**
205
 * Allocate SPIs and update proposals
206
 */
207
static bool allocate_spi(private_child_create_t *this)
208
{
209
    enumerator_t *enumerator;
210
    proposal_t *proposal;
211
    
212
    /* TODO: allocate additional SPI for AH if we have such proposals */ 
213
    this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
214
    if (this->my_spi)
215
    {
216
        if (this->initiator)
217
        {
218
            enumerator = this->proposals->create_enumerator(this->proposals);
219
            while (enumerator->enumerate(enumerator, &proposal))
220
            {
221
                proposal->set_spi(proposal, this->my_spi);
222
            }
223
            enumerator->destroy(enumerator);
224
        }
225
        else
226
        {
227
            this->proposal->set_spi(this->proposal, this->my_spi);
228
        }
229
        return TRUE;
230
    }
231
    return FALSE;
232
}
233
234
/**
235
 * Install a CHILD_SA for usage, return value:
236
 * - FAILED: no acceptable proposal
237
 * - INVALID_ARG: diffie hellman group inacceptable
238
 * - NOT_FOUND: TS inacceptable
239
 */
240
static status_t select_and_install(private_child_create_t *this, bool no_dh)
241
{
242
    status_t status;
243
    chunk_t nonce_i, nonce_r;
244
    chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
245
    chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
246
    linked_list_t *my_ts, *other_ts;
247
    host_t *me, *other, *other_vip, *my_vip;
248
    
249
    if (this->proposals == NULL)
250
    {
251
        DBG1(DBG_IKE, "SA payload missing in message");
252
        return FAILED;
253
    }
254
    if (this->tsi == NULL || this->tsr == NULL)
255
    {
256
        DBG1(DBG_IKE, "TS payloads missing in message");
257
        return NOT_FOUND;
258
    }
259
    
260
    me = this->ike_sa->get_my_host(this->ike_sa);
261
    other = this->ike_sa->get_other_host(this->ike_sa);
262
    my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
263
    other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
264
    
265
    this->proposal = this->config->select_proposal(this->config, this->proposals,
266
                                                   no_dh);
267
    if (this->proposal == NULL)
268
    {
269
        DBG1(DBG_IKE, "no acceptable proposal found");
270
        return FAILED;
271
    }
272
    this->other_spi = this->proposal->get_spi(this->proposal);
273
    
274
    if (!this->initiator && !allocate_spi(this))
275
    {    /* responder has no SPI allocated yet */
276
        DBG1(DBG_IKE, "allocating SPI failed");
277
        return FAILED;
278
    }
279
    this->child_sa->set_proposal(this->child_sa, this->proposal);
280
    
281
    if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
282
    {
283
        u_int16_t group;
284
        
285
        if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
286
                                          &group, NULL))
287
        {
288
            DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
289
                 diffie_hellman_group_names, this->dh_group,
290
                 diffie_hellman_group_names, group);
291
            this->dh_group = group;
292
            return INVALID_ARG;
293
        }
294
        else
295
        {
296
            DBG1(DBG_IKE, "no acceptable proposal found");
297
            return FAILED;
298
        }
299
    }
300
    
301
    if (my_vip == NULL)
302
    {
303
        my_vip = me;
304
    }
305
    if (other_vip == NULL)
306
    {
307
        other_vip = other;
308
    }
309
    
310
    if (this->initiator)
311
    {
312
        nonce_i = this->my_nonce;
313
        nonce_r = this->other_nonce;
314
        my_ts = this->tsi;
315
        other_ts = this->tsr;
316
    }
317
    else
318
    {
319
        nonce_r = this->my_nonce;
320
        nonce_i = this->other_nonce;
321
        my_ts = this->tsr;
322
        other_ts = this->tsi;
323
    }
324
    my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
325
                                                my_vip);
326
    other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts, 
327
                                                   other_vip);
328
    
329
    if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
330
    {
331
        my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
332
        other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
333
        DBG1(DBG_IKE, "no acceptable traffic selectors found");
334
        return NOT_FOUND;
335
    }
336
    
337
    this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
338
    this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
339
    if (this->initiator)
340
    {
341
        this->tsi = my_ts;
342
        this->tsr = other_ts;
343
    }
344
    else
345
    {
346
        this->tsr = my_ts;
347
        this->tsi = other_ts;
348
    }
349
    
350
    if (!this->initiator)
351
    {
352
        /* check if requested mode is acceptable, downgrade if required */
353
        switch (this->mode)
354
        {
355
            case MODE_TRANSPORT:
356
                if (!this->config->use_proxy_mode(this->config) &&
357
                       (!ts_list_is_host(this->tsi, other) ||
358
                        !ts_list_is_host(this->tsr, me))
359
                   )
360
                {
361
                    this->mode = MODE_TUNNEL;
362
                    DBG1(DBG_IKE, "not using transport mode, not host-to-host");
363
                }
364
                else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
365
                {
366
                    this->mode = MODE_TUNNEL;
367
                    DBG1(DBG_IKE, "not using transport mode, connection NATed");
368
                }
369
                break;
370
            case MODE_BEET:
371
                if (!ts_list_is_host(this->tsi, NULL) ||
372
                    !ts_list_is_host(this->tsr, NULL))
373
                {
374
                    this->mode = MODE_TUNNEL;
375
                    DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
376
                }
377
                break;
378
            default:
379
                break;
380
        }
381
    }
382
    
383
    this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
384
    this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
385
    this->child_sa->set_mode(this->child_sa, this->mode);
386
    this->child_sa->set_protocol(this->child_sa,
387
                                 this->proposal->get_protocol(this->proposal));
388
    
389
    if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
390
    {
391
        this->my_cpi = this->other_cpi = 0;
392
        this->ipcomp = IPCOMP_NONE;
393
    }
394
    status = FAILED;
395
    if (this->keymat->derive_child_keys(this->keymat, this->proposal,
396
            this->dh, nonce_i, nonce_r,    &encr_i, &integ_i, &encr_r, &integ_r))
397
    {
398
        if (this->initiator)
399
        {
400
            status = this->child_sa->install(this->child_sa, encr_r, integ_r,
401
                                        this->my_spi, this->my_cpi, TRUE);
402
            status = this->child_sa->install(this->child_sa, encr_i, integ_i,
403
                                        this->other_spi, this->other_cpi, FALSE);
404
        }
405
        else
406
        {
407
            status = this->child_sa->install(this->child_sa, encr_i, integ_i,
408
                                        this->my_spi, this->my_cpi, TRUE);
409
            status = this->child_sa->install(this->child_sa, encr_r, integ_r,
410
                                        this->other_spi, this->other_cpi, FALSE);
411
        }
412
    }
413
    chunk_clear(&integ_i);
414
    chunk_clear(&integ_r);
415
    chunk_clear(&encr_i);
416
    chunk_clear(&encr_r);
417
    
418
    if (status != SUCCESS)
419
    {
420
        DBG1(DBG_IKE, "unable to install IPsec SA (SAD) in kernel");
421
        return FAILED;
422
    }
423
    
424
    status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
425
    if (status != SUCCESS)
426
    {    
427
        DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
428
        return NOT_FOUND;
429
    }
430
    
431
    charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
432
                            nonce_i, nonce_r);
433
    
434
    /* add to IKE_SA, and remove from task */
435
    this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
436
    this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
437
    this->established = TRUE;
438
    return SUCCESS;
439
}
440
441
/**
442
 * build the payloads for the message
443
 */
444
static void build_payloads(private_child_create_t *this, message_t *message)
445
{
446
    sa_payload_t *sa_payload;
447
    nonce_payload_t *nonce_payload;
448
    ke_payload_t *ke_payload;
449
    ts_payload_t *ts_payload;
450
451
    /* add SA payload */
452
    if (this->initiator)
453
    {
454
        sa_payload = sa_payload_create_from_proposal_list(this->proposals);
455
    }
456
    else
457
    {
458
        sa_payload = sa_payload_create_from_proposal(this->proposal);
459
    }
460
    message->add_payload(message, (payload_t*)sa_payload);
461
    
462
    /* add nonce payload if not in IKE_AUTH */
463
    if (message->get_exchange_type(message) == CREATE_CHILD_SA)
464
    {
465
        nonce_payload = nonce_payload_create();
466
        nonce_payload->set_nonce(nonce_payload, this->my_nonce);
467
        message->add_payload(message, (payload_t*)nonce_payload);
468
    }
469
    
470
    /* diffie hellman exchange, if PFS enabled */
471
    if (this->dh)
472
    {
473
        ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
474
        message->add_payload(message, (payload_t*)ke_payload);
475
    }
476
    
477
    /* add TSi/TSr payloads */
478
    ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
479
    message->add_payload(message, (payload_t*)ts_payload);
480
    ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
481
    message->add_payload(message, (payload_t*)ts_payload);
482
483
    /* add a notify if we are not in tunnel mode */
484
    switch (this->mode)
485
    {
486
        case MODE_TRANSPORT:
487
            message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
488
            break;
489
        case MODE_BEET:
490
            message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
491
            break;
492
        default:
493
            break;
494
    }
495
}
496
497
/**
498
 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
499
 */
500
static void add_ipcomp_notify(private_child_create_t *this,
501
                                  message_t *message, u_int8_t ipcomp)
502
{
503
    if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
504
    {
505
        DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
506
             "IPComp disabled");
507
        return;
508
    }
509
    
510
    this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
511
    if (this->my_cpi)
512
    {
513
        this->ipcomp = ipcomp;
514
        message->add_notify(message, FALSE, IPCOMP_SUPPORTED, 
515
                            chunk_cata("cc", chunk_from_thing(this->my_cpi),
516
                                       chunk_from_thing(ipcomp)));
517
    }
518
    else
519
    {
520
        DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
521
    }
522
}
523
524
/**
525
 * handle a received notify payload
526
 */
527
static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
528
{
529
    switch (notify->get_notify_type(notify))
530
    {
531
        case USE_TRANSPORT_MODE:
532
            this->mode = MODE_TRANSPORT;
533
            break;
534
        case USE_BEET_MODE:
535
            this->mode = MODE_BEET;
536
            break;
537
        case IPCOMP_SUPPORTED:
538
        {
539
            ipcomp_transform_t ipcomp;
540
            u_int16_t cpi;
541
            chunk_t data;
542
            
543
            data = notify->get_notification_data(notify);
544
            cpi = *(u_int16_t*)data.ptr;
545
            ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
546
            switch (ipcomp)
547
            {
548
                case IPCOMP_DEFLATE:
549
                    this->other_cpi = cpi;
550
                    this->ipcomp_received = ipcomp;
551
                    break;
552
                case IPCOMP_LZS:
553
                case IPCOMP_LZJH:
554
                default:
555
                    DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
556
                         "transform ID we don't support %N",
557
                         ipcomp_transform_names, ipcomp);
558
                    break;
559
            }
560
        }
561
        default:
562
            break;
563
    }
564
}
565
566
/**
567
 * Read payloads from message
568
 */
569
static void process_payloads(private_child_create_t *this, message_t *message)
570
{
571
    enumerator_t *enumerator;
572
    payload_t *payload;
573
    sa_payload_t *sa_payload;
574
    ke_payload_t *ke_payload;
575
    ts_payload_t *ts_payload;
576
    
577
    /* defaults to TUNNEL mode */
578
    this->mode = MODE_TUNNEL;
579
580
    enumerator = message->create_payload_enumerator(message);
581
    while (enumerator->enumerate(enumerator, &payload))
582
    {
583
        switch (payload->get_type(payload))
584
        {
585
            case SECURITY_ASSOCIATION:
586
                sa_payload = (sa_payload_t*)payload;
587
                this->proposals = sa_payload->get_proposals(sa_payload);
588
                break;
589
            case KEY_EXCHANGE:
590
                ke_payload = (ke_payload_t*)payload;
591
                if (!this->initiator)
592
                {
593
                    this->dh_group = ke_payload->get_dh_group_number(ke_payload);
594
                    this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
595
                }
596
                if (this->dh)
597
                {
598
                    this->dh->set_other_public_value(this->dh,
599
                                ke_payload->get_key_exchange_data(ke_payload));
600
                }
601
                break;
602
            case TRAFFIC_SELECTOR_INITIATOR:
603
                ts_payload = (ts_payload_t*)payload;
604
                this->tsi = ts_payload->get_traffic_selectors(ts_payload);
605
                break;    
606
            case TRAFFIC_SELECTOR_RESPONDER:
607
                ts_payload = (ts_payload_t*)payload;
608
                this->tsr = ts_payload->get_traffic_selectors(ts_payload);
609
                break;
610
            case NOTIFY:
611
                handle_notify(this, (notify_payload_t*)payload);
612
                break;
613
            default:
614
                break;
615
        }
616
    }
617
    enumerator->destroy(enumerator);
618
}
619
620
/**
621
 * Implementation of task_t.build for initiator
622
 */
623
static status_t build_i(private_child_create_t *this, message_t *message)
624
{
625
    host_t *me, *other, *vip;
626
    peer_cfg_t *peer_cfg;
627
    
628
    switch (message->get_exchange_type(message))
629
    {
630
        case IKE_SA_INIT:
631
            return get_nonce(message, &this->my_nonce);
632
        case CREATE_CHILD_SA:
633
            if (generate_nonce(&this->my_nonce) != SUCCESS)
634
            {
635
                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
636
                return SUCCESS;
637
            }
638
            if (this->dh_group == MODP_NONE)
639
            {
640
                this->dh_group = this->config->get_dh_group(this->config);
641
            }
642
            break;
643
        case IKE_AUTH:
644
            if (message->get_message_id(message) != 1)
645
            {
646
                /* send only in the first request, not in subsequent rounds */
647
                return NEED_MORE;
648
            }
649
            break;
650
        default:
651
            break;
652
    }
653
    
654
    if (this->reqid)
655
    {
656
        DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
657
             this->config->get_name(this->config), this->reqid);
658
    }
659
    else
660
    {
661
        DBG0(DBG_IKE, "establishing CHILD_SA %s",
662
             this->config->get_name(this->config));
663
    }
664
    
665
    /* reuse virtual IP if we already have one */
666
    me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
667
    if (me == NULL)
668
    {
669
        me = this->ike_sa->get_my_host(this->ike_sa);
670
    }
671
    other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
672
    if (other == NULL)
673
    {
674
        other = this->ike_sa->get_other_host(this->ike_sa);
675
    }
676
    
677
    /* check if we want a virtual IP, but don't have one */
678
    peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
679
    vip = peer_cfg->get_virtual_ip(peer_cfg);
680
    if (!this->reqid && vip)
681
    {
682
        /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
683
        vip = host_create_any(vip->get_family(vip));
684
        this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
685
                                                        NULL, vip);
686
        vip->destroy(vip);
687
    }
688
    else
689
    {    /* but narrow it for host2host / if we already have a vip */
690
        this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
691
                                                        NULL, me);
692
    }
693
    this->tsr = this->config->get_traffic_selectors(this->config, FALSE, 
694
                                                    NULL, other);
695
696
    this->proposals = this->config->get_proposals(this->config,
697
                                                  this->dh_group == MODP_NONE);
698
    this->mode = this->config->get_mode(this->config);
699
    
700
    this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
701
            this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
702
            this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
703
    
704
    if (!allocate_spi(this))
705
    {
706
        DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
707
        return FAILED;
708
    }
709
    
710
    if (this->dh_group != MODP_NONE)
711
    {
712
        this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
713
    }
714
    
715
    if (this->config->use_ipcomp(this->config))
716
    {
717
        /* IPCOMP_DEFLATE is the only transform we support at the moment */
718
        add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
719
    }
720
    
721
    build_payloads(this, message);
722
    
723
    this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
724
    this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
725
    this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
726
    this->tsi = NULL;
727
    this->tsr = NULL;
728
    this->proposals = NULL;
729
    
730
    return NEED_MORE;
731
}
732
733
/**
734
 * Implementation of task_t.process for responder
735
 */
736
static status_t process_r(private_child_create_t *this, message_t *message)
737
{
738
    switch (message->get_exchange_type(message))
739
    {
740
        case IKE_SA_INIT:
741
            return get_nonce(message, &this->other_nonce);
742
        case CREATE_CHILD_SA:
743
            get_nonce(message, &this->other_nonce);
744
            break;
745
        case IKE_AUTH:
746
            if (message->get_message_id(message) != 1)
747
            {
748
                /* only handle first AUTH payload, not additional rounds */
749
                return NEED_MORE;
750
            }
751
        default:
752
            break;
753
    }
754
    
755
    process_payloads(this, message);
756
    
757
    return NEED_MORE;
758
}
759
760
/**
761
 * handle CHILD_SA setup failure
762
 */
763
static void handle_child_sa_failure(private_child_create_t *this,
764
                                    message_t *message)
765
{
766
    if (message->get_exchange_type(message) == IKE_AUTH &&
767
        lib->settings->get_bool(lib->settings,
768
                                "charon.close_ike_on_child_failure", FALSE))
769
    {
770
        /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
771
         * first */
772
        DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
773
        charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
774
            delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
775
            100);
776
    }
777
}
778
779
/**
780
 * Implementation of task_t.build for responder
781
 */
782
static status_t build_r(private_child_create_t *this, message_t *message)
783
{
784
    peer_cfg_t *peer_cfg;
785
    payload_t *payload;
786
    enumerator_t *enumerator;
787
    bool no_dh = TRUE;
788
    
789
    switch (message->get_exchange_type(message))
790
    {
791
        case IKE_SA_INIT:
792
            return get_nonce(message, &this->my_nonce);
793
        case CREATE_CHILD_SA:
794
            if (generate_nonce(&this->my_nonce) != SUCCESS)
795
            {
796
                message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
797
                                    chunk_empty);
798
                return SUCCESS;
799
            }
800
            no_dh = FALSE;
801
            break;
802
        case IKE_AUTH:
803
            if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
804
            {    /* wait until all authentication round completed */
805
                return NEED_MORE;
806
            }
807
        default:
808
            break;
809
    }
810
    
811
    if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
812
    {
813
        DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
814
        message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
815
        return SUCCESS;
816
    }
817
    
818
    peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
819
    if (peer_cfg && this->tsi && this->tsr)
820
    {
821
        host_t *me, *other;
822
        
823
        me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
824
        if (me == NULL)
825
        {
826
            me = this->ike_sa->get_my_host(this->ike_sa);
827
        }
828
        other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
829
        if (other == NULL)
830
        {
831
            other = this->ike_sa->get_other_host(this->ike_sa);
832
        }
833
        this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
834
                                                  this->tsi, me, other);
835
    }
836
    
837
    if (this->config == NULL)
838
    {
839
        DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
840
             this->tsr, this->tsi);
841
        message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
842
        handle_child_sa_failure(this, message);
843
        return SUCCESS;
844
    }
845
    
846
    /* check if ike_config_t included non-critical error notifies */
847
    enumerator = message->create_payload_enumerator(message);
848
    while (enumerator->enumerate(enumerator, &payload))
849
    {
850
        if (payload->get_type(payload) == NOTIFY)
851
        {
852
            notify_payload_t *notify = (notify_payload_t*)payload;
853
            
854
            switch (notify->get_notify_type(notify))
855
            {
856
                case INTERNAL_ADDRESS_FAILURE:
857
                case FAILED_CP_REQUIRED:
858
                {
859
                    DBG1(DBG_IKE,"configuration payload negotation "
860
                         "failed, no CHILD_SA built");
861
                    enumerator->destroy(enumerator);
862
                    handle_child_sa_failure(this, message);
863
                    return SUCCESS;
864
                }
865
                default:
866
                    break;
867
            }
868
        }
869
    }
870
    enumerator->destroy(enumerator);
871
    
872
    this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
873
            this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
874
            this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
875
    
876
    if (this->ipcomp_received != IPCOMP_NONE)
877
    {
878
        if (this->config->use_ipcomp(this->config))
879
        {
880
            add_ipcomp_notify(this, message, this->ipcomp_received);
881
        }
882
        else
883
        {
884
            DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
885
                 notify_type_names, IPCOMP_SUPPORTED);
886
        }
887
    }
888
    
889
    switch (select_and_install(this, no_dh))
890
    {
891
        case SUCCESS:
892
            break;
893
        case NOT_FOUND:
894
            message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
895
            handle_child_sa_failure(this, message);
896
            return SUCCESS;
897
        case INVALID_ARG:
898
        {
899
            u_int16_t group = htons(this->dh_group);
900
            message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
901
                                chunk_from_thing(group));
902
            handle_child_sa_failure(this, message);
903
            return SUCCESS;
904
        }
905
        case FAILED:
906
        default:
907
            message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
908
            handle_child_sa_failure(this, message);
909
            return SUCCESS;
910
    }
911
    
912
    build_payloads(this, message);
913
    
914
    DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
915
         "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
916
         this->child_sa->get_name(this->child_sa),
917
         this->child_sa->get_reqid(this->child_sa),
918
         ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
919
         ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
920
         this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
921
         this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
922
923
    return SUCCESS;
924
}
925
926
/**
927
 * Implementation of task_t.process for initiator
928
 */
929
static status_t process_i(private_child_create_t *this, message_t *message)
930
{
931
    enumerator_t *enumerator;
932
    payload_t *payload;
933
    bool no_dh = TRUE;
934
935
    switch (message->get_exchange_type(message))
936
    {
937
        case IKE_SA_INIT:
938
            return get_nonce(message, &this->other_nonce);
939
        case CREATE_CHILD_SA:
940
            get_nonce(message, &this->other_nonce);
941
            no_dh = FALSE;
942
            break;
943
        case IKE_AUTH:
944
            if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
945
            {    /* wait until all authentication round completed */
946
                return NEED_MORE;
947
            }
948
        default:
949
            break;
950
    }
951
952
    /* check for erronous notifies */
953
    enumerator = message->create_payload_enumerator(message);
954
    while (enumerator->enumerate(enumerator, &payload))
955
    {
956
        if (payload->get_type(payload) == NOTIFY)
957
        {
958
            notify_payload_t *notify = (notify_payload_t*)payload;
959
            notify_type_t type = notify->get_notify_type(notify);
960
            
961
            switch (type)
962
            {
963
                /* handle notify errors related to CHILD_SA only */
964
                case NO_PROPOSAL_CHOSEN:
965
                case SINGLE_PAIR_REQUIRED:
966
                case NO_ADDITIONAL_SAS:
967
                case INTERNAL_ADDRESS_FAILURE:
968
                case FAILED_CP_REQUIRED:
969
                case TS_UNACCEPTABLE:
970
                case INVALID_SELECTORS:
971
                {
972
                    DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
973
                         notify_type_names, type);
974
                    enumerator->destroy(enumerator);
975
                    handle_child_sa_failure(this, message);
976
                    /* an error in CHILD_SA creation is not critical */
977
                    return SUCCESS;
978
                }
979
                case INVALID_KE_PAYLOAD:
980
                {
981
                    chunk_t data;
982
                    diffie_hellman_group_t bad_group;
983
                    
984
                    bad_group = this->dh_group;
985
                    data = notify->get_notification_data(notify);
986
                    this->dh_group = ntohs(*((u_int16_t*)data.ptr));
987
                    DBG1(DBG_IKE, "peer didn't accept DH group %N, "
988
                         "it requested %N", diffie_hellman_group_names,
989
                         bad_group, diffie_hellman_group_names, this->dh_group);
990
                    
991
                    this->public.task.migrate(&this->public.task, this->ike_sa);
992
                    enumerator->destroy(enumerator);
993
                    return NEED_MORE;
994
                }
995
                default:
996
                    break;
997
            }
998
        }
999
    }
1000
    enumerator->destroy(enumerator);
1001
    
1002
    process_payloads(this, message);
1003
    
1004
    if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
1005
    {
1006
        DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
1007
             " one, no CHILD_SA built");
1008
        handle_child_sa_failure(this, message);
1009
        return SUCCESS;
1010
    }
1011
    else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
1012
    {
1013
        DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
1014
             "IPComp is disabled");
1015
        this->ipcomp = IPCOMP_NONE;
1016
    }
1017
    else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
1018
    {
1019
        DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1020
             "no CHILD_SA built");
1021
        handle_child_sa_failure(this, message);
1022
        return SUCCESS;
1023
    }
1024
    
1025
    if (select_and_install(this, no_dh) == SUCCESS)
1026
    {
1027
        DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
1028
             "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1029
             this->child_sa->get_name(this->child_sa),
1030
             this->child_sa->get_reqid(this->child_sa),
1031
             ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
1032
             ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
1033
             this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
1034
             this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
1035
    }
1036
    else
1037
    {
1038
        handle_child_sa_failure(this, message);
1039
    }
1040
    return SUCCESS;
1041
}
1042
1043
/**
1044
 * Implementation of task_t.get_type
1045
 */
1046
static task_type_t get_type(private_child_create_t *this)
1047
{
1048
    return CHILD_CREATE;
1049
}
1050
1051
/**
1052
 * Implementation of child_create_t.use_reqid
1053
 */
1054
static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1055
{
1056
    this->reqid = reqid;
1057
}
1058
1059
/**
1060
 * Implementation of child_create_t.get_child
1061
 */
1062
static child_sa_t* get_child(private_child_create_t *this)
1063
{
1064
    return this->child_sa;
1065
}
1066
1067
/**
1068
 * Implementation of child_create_t.get_lower_nonce
1069
 */
1070
static chunk_t get_lower_nonce(private_child_create_t *this)
1071
{    
1072
    if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1073
               min(this->my_nonce.len, this->other_nonce.len)) < 0)
1074
    {
1075
        return this->my_nonce;
1076
    }
1077
    else
1078
    {
1079
        return this->other_nonce;
1080
    }
1081
}
1082
1083
/**
1084
 * Implementation of task_t.migrate
1085
 */
1086
static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1087
{
1088
    chunk_free(&this->my_nonce);
1089
    chunk_free(&this->other_nonce);
1090
    if (this->tsi)
1091
    {
1092
        this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1093
    }
1094
    if (this->tsr)
1095
    {
1096
        this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1097
    }
1098
    DESTROY_IF(this->child_sa);
1099
    DESTROY_IF(this->proposal);
1100
    DESTROY_IF(this->dh);
1101
    if (this->proposals)
1102
    {
1103
        this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1104
    }
1105
    
1106
    this->ike_sa = ike_sa;
1107
    this->keymat = ike_sa->get_keymat(ike_sa);
1108
    this->proposal = NULL;
1109
    this->proposals = NULL;
1110
    this->tsi = NULL;
1111
    this->tsr = NULL;
1112
    this->dh = NULL;
1113
    this->child_sa = NULL;
1114
    this->mode = MODE_TUNNEL;
1115
    this->ipcomp = IPCOMP_NONE;
1116
    this->ipcomp_received = IPCOMP_NONE;
1117
    this->other_cpi = 0;
1118
    this->reqid = 0;
1119
    this->established = FALSE;
1120
}
1121
1122
/**
1123
 * Implementation of task_t.destroy
1124
 */
1125
static void destroy(private_child_create_t *this)
1126
{
1127
    chunk_free(&this->my_nonce);
1128
    chunk_free(&this->other_nonce);
1129
    if (this->tsr)
1130
    {
1131
        this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1132
    }
1133
    if (this->tsi)
1134
    {
1135
        this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1136
    }
1137
    if (!this->established)
1138
    {
1139
        DESTROY_IF(this->child_sa);
1140
    }
1141
    DESTROY_IF(this->proposal);
1142
    DESTROY_IF(this->dh);
1143
    if (this->proposals)
1144
    {
1145
        this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1146
    }
1147
    
1148
    DESTROY_IF(this->config);
1149
    free(this);
1150
}
1151
1152
/*
1153
 * Described in header.
1154
 */
1155
child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1156
{
1157
    private_child_create_t *this = malloc_thing(private_child_create_t);
1158
1159
    this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1160
    this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1161
    this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1162
    this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1163
    this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1164
    this->public.task.destroy = (void(*)(task_t*))destroy;
1165
    if (config)
1166
    {
1167
        this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1168
        this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1169
        this->initiator = TRUE;
1170
        config->get_ref(config);
1171
    }
1172
    else
1173
    {
1174
        this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1175
        this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1176
        this->initiator = FALSE;
1177
    }
1178
    
1179
    this->ike_sa = ike_sa;
1180
    this->config = config;
1181
    this->my_nonce = chunk_empty;
1182
    this->other_nonce = chunk_empty;
1183
    this->proposals = NULL;
1184
    this->proposal = NULL;
1185
    this->tsi = NULL;
1186
    this->tsr = NULL;
1187
    this->dh = NULL;
1188
    this->dh_group = MODP_NONE;
1189
    this->keymat = ike_sa->get_keymat(ike_sa);
1190
    this->child_sa = NULL;
1191
    this->mode = MODE_TUNNEL;
1192
    this->ipcomp = IPCOMP_NONE;
1193
    this->ipcomp_received = IPCOMP_NONE;
1194
    this->my_spi = 0;
1195
    this->other_spi = 0;
1196
    this->my_cpi = 0;
1197
    this->other_cpi = 0;
1198
    this->reqid = 0;
1199
    this->established = FALSE;
1200
    
1201
    return &this->public;
1202
}