| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: ikev2_pld.c,v 1.62 2017/04/13 07:04:09 patrick Exp $ */  | 
    ||
2  | 
    |||
3  | 
    /*  | 
    ||
4  | 
    * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>  | 
    ||
5  | 
    * Copyright (c) 2014 Hans-Joerg Hoexer  | 
    ||
6  | 
    *  | 
    ||
7  | 
    * Permission to use, copy, modify, and distribute this software for any  | 
    ||
8  | 
    * purpose with or without fee is hereby granted, provided that the above  | 
    ||
9  | 
    * copyright notice and this permission notice appear in all copies.  | 
    ||
10  | 
    *  | 
    ||
11  | 
    * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  | 
    ||
12  | 
    * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
    ||
13  | 
    * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR  | 
    ||
14  | 
    * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
    ||
15  | 
    * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  | 
    ||
16  | 
    * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  | 
    ||
17  | 
    * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  | 
    ||
18  | 
    */  | 
    ||
19  | 
    |||
20  | 
    #include <sys/queue.h>  | 
    ||
21  | 
    #include <sys/socket.h>  | 
    ||
22  | 
    #include <sys/wait.h>  | 
    ||
23  | 
    #include <sys/uio.h>  | 
    ||
24  | 
    |||
25  | 
    #include <netinet/in.h>  | 
    ||
26  | 
    #include <arpa/inet.h>  | 
    ||
27  | 
    |||
28  | 
    #include <stdlib.h>  | 
    ||
29  | 
    #include <stdio.h>  | 
    ||
30  | 
    #include <unistd.h>  | 
    ||
31  | 
    #include <string.h>  | 
    ||
32  | 
    #include <signal.h>  | 
    ||
33  | 
    #include <errno.h>  | 
    ||
34  | 
    #include <err.h>  | 
    ||
35  | 
    #include <pwd.h>  | 
    ||
36  | 
    #include <event.h>  | 
    ||
37  | 
    |||
38  | 
    #include <openssl/sha.h>  | 
    ||
39  | 
    #include <openssl/evp.h>  | 
    ||
40  | 
    |||
41  | 
    #include "iked.h"  | 
    ||
42  | 
    #include "ikev2.h"  | 
    ||
43  | 
    #include "eap.h"  | 
    ||
44  | 
    #include "dh.h"  | 
    ||
45  | 
    |||
46  | 
    int ikev2_validate_pld(struct iked_message *, size_t, size_t,  | 
    ||
47  | 
    struct ikev2_payload *);  | 
    ||
48  | 
    int ikev2_pld_payloads(struct iked *, struct iked_message *,  | 
    ||
49  | 
    size_t, size_t, unsigned int);  | 
    ||
50  | 
    int ikev2_validate_sa(struct iked_message *, size_t, size_t,  | 
    ||
51  | 
    struct ikev2_payload *, struct ikev2_sa_proposal *);  | 
    ||
52  | 
    int ikev2_pld_sa(struct iked *, struct ikev2_payload *,  | 
    ||
53  | 
    struct iked_message *, size_t, size_t);  | 
    ||
54  | 
    int ikev2_validate_xform(struct iked_message *, size_t, size_t,  | 
    ||
55  | 
    struct ikev2_transform *);  | 
    ||
56  | 
    int ikev2_pld_xform(struct iked *, struct ikev2_sa_proposal *,  | 
    ||
57  | 
    struct iked_message *, size_t, size_t);  | 
    ||
58  | 
    int ikev2_validate_attr(struct iked_message *, size_t, size_t,  | 
    ||
59  | 
    struct ikev2_attribute *);  | 
    ||
60  | 
    int ikev2_pld_attr(struct iked *, struct ikev2_transform *,  | 
    ||
61  | 
    struct iked_message *, size_t, size_t);  | 
    ||
62  | 
    int ikev2_validate_ke(struct iked_message *, size_t, size_t,  | 
    ||
63  | 
    struct ikev2_payload *, struct ikev2_keyexchange *);  | 
    ||
64  | 
    int ikev2_pld_ke(struct iked *, struct ikev2_payload *,  | 
    ||
65  | 
    struct iked_message *, size_t, size_t);  | 
    ||
66  | 
    int ikev2_validate_id(struct iked_message *, size_t, size_t,  | 
    ||
67  | 
    struct ikev2_payload *, struct ikev2_id *);  | 
    ||
68  | 
    int ikev2_pld_id(struct iked *, struct ikev2_payload *,  | 
    ||
69  | 
    struct iked_message *, size_t, size_t, unsigned int);  | 
    ||
70  | 
    int ikev2_validate_cert(struct iked_message *, size_t, size_t,  | 
    ||
71  | 
    struct ikev2_payload *, struct ikev2_cert *);  | 
    ||
72  | 
    int ikev2_pld_cert(struct iked *, struct ikev2_payload *,  | 
    ||
73  | 
    struct iked_message *, size_t, size_t);  | 
    ||
74  | 
    int ikev2_validate_certreq(struct iked_message *, size_t, size_t,  | 
    ||
75  | 
    struct ikev2_payload *, struct ikev2_cert *);  | 
    ||
76  | 
    int ikev2_pld_certreq(struct iked *, struct ikev2_payload *,  | 
    ||
77  | 
    struct iked_message *, size_t, size_t);  | 
    ||
78  | 
    int ikev2_validate_nonce(struct iked_message *, size_t, size_t,  | 
    ||
79  | 
    struct ikev2_payload *);  | 
    ||
80  | 
    int ikev2_pld_nonce(struct iked *, struct ikev2_payload *,  | 
    ||
81  | 
    struct iked_message *, size_t, size_t);  | 
    ||
82  | 
    int ikev2_validate_notify(struct iked_message *, size_t, size_t,  | 
    ||
83  | 
    struct ikev2_payload *, struct ikev2_notify *);  | 
    ||
84  | 
    int ikev2_pld_notify(struct iked *, struct ikev2_payload *,  | 
    ||
85  | 
    struct iked_message *, size_t, size_t);  | 
    ||
86  | 
    int ikev2_validate_delete(struct iked_message *, size_t, size_t,  | 
    ||
87  | 
    struct ikev2_payload *, struct ikev2_delete *);  | 
    ||
88  | 
    int ikev2_pld_delete(struct iked *, struct ikev2_payload *,  | 
    ||
89  | 
    struct iked_message *, size_t, size_t);  | 
    ||
90  | 
    int ikev2_validate_ts(struct iked_message *, size_t, size_t,  | 
    ||
91  | 
    struct ikev2_payload *, struct ikev2_tsp *);  | 
    ||
92  | 
    int ikev2_pld_ts(struct iked *, struct ikev2_payload *,  | 
    ||
93  | 
    struct iked_message *, size_t, size_t, unsigned int);  | 
    ||
94  | 
    int ikev2_validate_auth(struct iked_message *, size_t, size_t,  | 
    ||
95  | 
    struct ikev2_payload *, struct ikev2_auth *);  | 
    ||
96  | 
    int ikev2_pld_auth(struct iked *, struct ikev2_payload *,  | 
    ||
97  | 
    struct iked_message *, size_t, size_t);  | 
    ||
98  | 
    int ikev2_pld_e(struct iked *, struct ikev2_payload *,  | 
    ||
99  | 
    struct iked_message *, size_t);  | 
    ||
100  | 
    int ikev2_validate_cp(struct iked_message *, size_t, size_t,  | 
    ||
101  | 
    struct ikev2_payload *, struct ikev2_cp *);  | 
    ||
102  | 
    int ikev2_pld_cp(struct iked *, struct ikev2_payload *,  | 
    ||
103  | 
    struct iked_message *, size_t, size_t);  | 
    ||
104  | 
    int ikev2_validate_eap(struct iked_message *, size_t, size_t,  | 
    ||
105  | 
    struct ikev2_payload *, struct eap_header *);  | 
    ||
106  | 
    int ikev2_pld_eap(struct iked *, struct ikev2_payload *,  | 
    ||
107  | 
    struct iked_message *, size_t, size_t);  | 
    ||
108  | 
    |||
109  | 
    int  | 
    ||
110  | 
    ikev2_pld_parse(struct iked *env, struct ike_header *hdr,  | 
    ||
111  | 
    struct iked_message *msg, size_t offset)  | 
    ||
112  | 
    { | 
    ||
113  | 
    333357680  | 
    	log_debug("%s: header ispi %s rspi %s" | 
    |
114  | 
    " nextpayload %s version 0x%02x exchange %s flags 0x%02x"  | 
    ||
115  | 
    " msgid %d length %u response %d", __func__,  | 
    ||
116  | 
    666715360  | 
    print_spi(betoh64(hdr->ike_ispi), 8),  | 
    |
117  | 
    333357680  | 
    print_spi(betoh64(hdr->ike_rspi), 8),  | 
    |
118  | 
    333357680  | 
    print_map(hdr->ike_nextpayload, ikev2_payload_map),  | 
    |
119  | 
    333357680  | 
    hdr->ike_version,  | 
    |
120  | 
    333357680  | 
    print_map(hdr->ike_exchange, ikev2_exchange_map),  | 
    |
121  | 
    333357680  | 
    hdr->ike_flags,  | 
    |
122  | 
    333357680  | 
    betoh32(hdr->ike_msgid),  | 
    |
123  | 
    333357680  | 
    betoh32(hdr->ike_length),  | 
    |
124  | 
    333357680  | 
    msg->msg_response);  | 
    |
125  | 
    |||
126  | 
    ✓✓ | 333357680  | 
    	if (ibuf_size(msg->msg_data) < betoh32(hdr->ike_length)) { | 
    
127  | 
    9618560  | 
    		log_debug("%s: short message", __func__); | 
    |
128  | 
    9618560  | 
    return (-1);  | 
    |
129  | 
    }  | 
    ||
130  | 
    |||
131  | 
    323739120  | 
    offset += sizeof(*hdr);  | 
    |
132  | 
    |||
133  | 
    323739120  | 
    return (ikev2_pld_payloads(env, msg, offset,  | 
    |
134  | 
    323739120  | 
    betoh32(hdr->ike_length), hdr->ike_nextpayload));  | 
    |
135  | 
    333357680  | 
    }  | 
    |
136  | 
    |||
137  | 
    int  | 
    ||
138  | 
    ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
139  | 
    struct ikev2_payload *pld)  | 
    ||
140  | 
    { | 
    ||
141  | 
    1690421140  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
142  | 
    size_t pld_length;  | 
    ||
143  | 
    |||
144  | 
    /* We need at least the generic header. */  | 
    ||
145  | 
    ✓✓ | 845210570  | 
    	if (left < sizeof(*pld)) { | 
    
146  | 
    690  | 
    		log_debug("%s: malformed payload: too short for generic " | 
    |
147  | 
    "header (%zu < %zu)", __func__, left, sizeof(*pld));  | 
    ||
148  | 
    690  | 
    return (-1);  | 
    |
149  | 
    }  | 
    ||
150  | 
    845209880  | 
    memcpy(pld, msgbuf + offset, sizeof(*pld));  | 
    |
151  | 
    |||
152  | 
    /*  | 
    ||
153  | 
    * We need at least the specified number of bytes.  | 
    ||
154  | 
    * pld_length is the full size of the payload including  | 
    ||
155  | 
    * the generic payload header.  | 
    ||
156  | 
    */  | 
    ||
157  | 
    845209880  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
158  | 
    ✓✓ | 845209880  | 
    	if (left < pld_length) { | 
    
159  | 
    10508620  | 
    		log_debug("%s: malformed payload: shorter than specified " | 
    |
160  | 
    "(%zu < %zu)", __func__, left, pld_length);  | 
    ||
161  | 
    10508620  | 
    return (-1);  | 
    |
162  | 
    }  | 
    ||
163  | 
    /*  | 
    ||
164  | 
    * Sanity check the specified payload size, it must  | 
    ||
165  | 
    * be at last the size of the generic payload header.  | 
    ||
166  | 
    */  | 
    ||
167  | 
    ✓✓ | 834701260  | 
    	if (pld_length < sizeof(*pld)) { | 
    
168  | 
    437070  | 
    		log_debug("%s: malformed payload: shorter than minimum " | 
    |
169  | 
    "header size (%zu < %zu)", __func__, pld_length,  | 
    ||
170  | 
    sizeof(*pld));  | 
    ||
171  | 
    437070  | 
    return (-1);  | 
    |
172  | 
    }  | 
    ||
173  | 
    |||
174  | 
    834264190  | 
    return (0);  | 
    |
175  | 
    845210570  | 
    }  | 
    |
176  | 
    |||
177  | 
    int  | 
    ||
178  | 
    ikev2_pld_payloads(struct iked *env, struct iked_message *msg,  | 
    ||
179  | 
    size_t offset, size_t length, unsigned int payload)  | 
    ||
180  | 
    { | 
    ||
181  | 
    647478240  | 
    struct ikev2_payload pld;  | 
    |
182  | 
    unsigned int e;  | 
    ||
183  | 
    int ret;  | 
    ||
184  | 
    323739120  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
185  | 
    size_t left;  | 
    ||
186  | 
    |||
187  | 
    /* Check if message was decrypted in an E payload */  | 
    ||
188  | 
    323739120  | 
    e = msg->msg_e ? IKED_E : 0;  | 
    |
189  | 
    |||
190  | 
    ✓✓✓✓ | 
    3163255900  | 
    	while (payload != 0 && offset < length) { | 
    
191  | 
    /* Bytes left in datagram. */  | 
    ||
192  | 
    845210570  | 
    left = length - offset;  | 
    |
193  | 
    |||
194  | 
    ✓✓ | 845210570  | 
    if (ikev2_validate_pld(msg, offset, left, &pld))  | 
    
195  | 
    10946380  | 
    return (-1);  | 
    |
196  | 
    |||
197  | 
    834264190  | 
    		log_debug("%s: %spayload %s" | 
    |
198  | 
    " nextpayload %s critical 0x%02x length %d",  | 
    ||
199  | 
    834264190  | 
    __func__, e ? "decrypted " : "",  | 
    |
200  | 
    834264190  | 
    print_map(payload, ikev2_payload_map),  | 
    |
201  | 
    834264190  | 
    print_map(pld.pld_nextpayload, ikev2_payload_map),  | 
    |
202  | 
    834264190  | 
    pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,  | 
    |
203  | 
    834264190  | 
    betoh16(pld.pld_length));  | 
    |
204  | 
    |||
205  | 
    /* Skip over generic payload header. */  | 
    ||
206  | 
    834264190  | 
    offset += sizeof(pld);  | 
    |
207  | 
    834264190  | 
    left -= sizeof(pld);  | 
    |
208  | 
    ret = 0;  | 
    ||
209  | 
    |||
210  | 
    ✗✓✗✓ ✗✗✗✗ ✓✗✗✓ ✗✓✗✗ ✗✓✗✗ ✓  | 
    834264190  | 
    		switch (payload | e) { | 
    
211  | 
    case IKEV2_PAYLOAD_SA:  | 
    ||
212  | 
    case IKEV2_PAYLOAD_SA | IKED_E:  | 
    ||
213  | 
    133239710  | 
    ret = ikev2_pld_sa(env, &pld, msg, offset, left);  | 
    |
214  | 
    133239710  | 
    break;  | 
    |
215  | 
    case IKEV2_PAYLOAD_KE:  | 
    ||
216  | 
    case IKEV2_PAYLOAD_KE | IKED_E:  | 
    ||
217  | 
    179417390  | 
    ret = ikev2_pld_ke(env, &pld, msg, offset, left);  | 
    |
218  | 
    179417390  | 
    break;  | 
    |
219  | 
    case IKEV2_PAYLOAD_IDi | IKED_E:  | 
    ||
220  | 
    case IKEV2_PAYLOAD_IDr | IKED_E:  | 
    ||
221  | 
    ret = ikev2_pld_id(env, &pld, msg, offset, left,  | 
    ||
222  | 
    payload);  | 
    ||
223  | 
    break;  | 
    ||
224  | 
    case IKEV2_PAYLOAD_CERT | IKED_E:  | 
    ||
225  | 
    ret = ikev2_pld_cert(env, &pld, msg, offset, left);  | 
    ||
226  | 
    break;  | 
    ||
227  | 
    case IKEV2_PAYLOAD_CERTREQ:  | 
    ||
228  | 
    case IKEV2_PAYLOAD_CERTREQ | IKED_E:  | 
    ||
229  | 
    625130  | 
    ret = ikev2_pld_certreq(env, &pld, msg, offset, left);  | 
    |
230  | 
    625130  | 
    break;  | 
    |
231  | 
    case IKEV2_PAYLOAD_AUTH | IKED_E:  | 
    ||
232  | 
    ret = ikev2_pld_auth(env, &pld, msg, offset, left);  | 
    ||
233  | 
    break;  | 
    ||
234  | 
    case IKEV2_PAYLOAD_NONCE:  | 
    ||
235  | 
    case IKEV2_PAYLOAD_NONCE | IKED_E:  | 
    ||
236  | 
    127288420  | 
    ret = ikev2_pld_nonce(env, &pld, msg, offset, left);  | 
    |
237  | 
    127288420  | 
    break;  | 
    |
238  | 
    case IKEV2_PAYLOAD_NOTIFY:  | 
    ||
239  | 
    case IKEV2_PAYLOAD_NOTIFY | IKED_E:  | 
    ||
240  | 
    250235690  | 
    ret = ikev2_pld_notify(env, &pld, msg, offset, left);  | 
    |
241  | 
    250235690  | 
    break;  | 
    |
242  | 
    case IKEV2_PAYLOAD_DELETE | IKED_E:  | 
    ||
243  | 
    ret = ikev2_pld_delete(env, &pld, msg, offset, left);  | 
    ||
244  | 
    break;  | 
    ||
245  | 
    case IKEV2_PAYLOAD_TSi | IKED_E:  | 
    ||
246  | 
    case IKEV2_PAYLOAD_TSr | IKED_E:  | 
    ||
247  | 
    ret = ikev2_pld_ts(env, &pld, msg, offset, left,  | 
    ||
248  | 
    payload);  | 
    ||
249  | 
    break;  | 
    ||
250  | 
    case IKEV2_PAYLOAD_SK:  | 
    ||
251  | 
    68340  | 
    ret = ikev2_pld_e(env, &pld, msg, offset);  | 
    |
252  | 
    68340  | 
    break;  | 
    |
253  | 
    case IKEV2_PAYLOAD_CP | IKED_E:  | 
    ||
254  | 
    ret = ikev2_pld_cp(env, &pld, msg, offset, left);  | 
    ||
255  | 
    break;  | 
    ||
256  | 
    case IKEV2_PAYLOAD_EAP | IKED_E:  | 
    ||
257  | 
    ret = ikev2_pld_eap(env, &pld, msg, offset, left);  | 
    ||
258  | 
    break;  | 
    ||
259  | 
    default:  | 
    ||
260  | 
    143389510  | 
    print_hex(msgbuf, offset,  | 
    |
261  | 
    143389510  | 
    betoh16(pld.pld_length) - sizeof(pld));  | 
    |
262  | 
    143389510  | 
    break;  | 
    |
263  | 
    }  | 
    ||
264  | 
    |||
265  | 
    ✓✓✗✓ | 
    849204790  | 
    		if (ret != 0 && ikev2_msg_frompeer(msg)) { | 
    
266  | 
    (void)ikev2_send_informational(env, msg);  | 
    ||
267  | 
    return (-1);  | 
    ||
268  | 
    }  | 
    ||
269  | 
    |||
270  | 
    /* Encrypted payload must appear last */  | 
    ||
271  | 
    ✓✓ | 834264190  | 
    if (payload == IKEV2_PAYLOAD_SK)  | 
    
272  | 
    68340  | 
    return (0);  | 
    |
273  | 
    |||
274  | 
    834195850  | 
    payload = pld.pld_nextpayload;  | 
    |
275  | 
    834195850  | 
    offset += betoh16(pld.pld_length) - sizeof(pld);  | 
    |
276  | 
    }  | 
    ||
277  | 
    |||
278  | 
    312724400  | 
    return (0);  | 
    |
279  | 
    323739120  | 
    }  | 
    |
280  | 
    |||
281  | 
    int  | 
    ||
282  | 
    ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
283  | 
    struct ikev2_payload *pld, struct ikev2_sa_proposal *sap)  | 
    ||
284  | 
    { | 
    ||
285  | 
    266479420  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
286  | 
    size_t pld_length, sap_length;  | 
    ||
287  | 
    |||
288  | 
    133239710  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
289  | 
    ✓✓ | 133239710  | 
    	if (pld_length < sizeof(*pld) + sizeof(*sap)) { | 
    
290  | 
    10880  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    |
291  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
292  | 
    sizeof(*pld) + sizeof(*sap));  | 
    ||
293  | 
    10880  | 
    return (-1);  | 
    |
294  | 
    }  | 
    ||
295  | 
    |||
296  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
297  | 
    ✗✓ | 133228830  | 
    	if (left < sizeof(*sap)) { | 
    
298  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
299  | 
    "(%zu < %zu)", __func__, left, sizeof(*sap));  | 
    ||
300  | 
    return (-1);  | 
    ||
301  | 
    }  | 
    ||
302  | 
    133228830  | 
    memcpy(sap, msgbuf + offset, sizeof(*sap));  | 
    |
303  | 
    |||
304  | 
    133228830  | 
    sap_length = betoh16(sap->sap_length);  | 
    |
305  | 
    ✓✓ | 133228830  | 
    	if (sap_length < sizeof(*sap)) { | 
    
306  | 
    58270  | 
    		log_debug("%s: malformed payload: shorter than minimum header " | 
    |
307  | 
    "size (%zu < %zu)", __func__, sap_length, sizeof(*sap));  | 
    ||
308  | 
    58270  | 
    return (-1);  | 
    |
309  | 
    }  | 
    ||
310  | 
    ✓✓ | 133170560  | 
    	if (left < sap_length) { | 
    
311  | 
    902020  | 
    		log_debug("%s: malformed payload: too long for actual payload " | 
    |
312  | 
    "size (%zu < %zu)", __func__, left, sap_length);  | 
    ||
313  | 
    902020  | 
    return (-1);  | 
    |
314  | 
    }  | 
    ||
315  | 
    /*  | 
    ||
316  | 
    * NB: There might be more proposals, we parse only the first one.  | 
    ||
317  | 
    * This condition must never be true.  | 
    ||
318  | 
    */  | 
    ||
319  | 
    ✓✓ | 132268540  | 
    	if (pld_length - sizeof(*pld) < sap_length) { | 
    
320  | 
    361980  | 
    		log_debug("%s: payload malformed: SA payload length mismatches " | 
    |
321  | 
    "proposal substructure length (%lu < %zu)", __func__,  | 
    ||
322  | 
    pld_length - sizeof(*pld), sap_length);  | 
    ||
323  | 
    361980  | 
    return (-1);  | 
    |
324  | 
    }  | 
    ||
325  | 
    /*  | 
    ||
326  | 
    * If there is only one proposal, sap_length must be the  | 
    ||
327  | 
    * total payload size.  | 
    ||
328  | 
    */  | 
    ||
329  | 
    ✓✓✓✓ | 
    263091030  | 
    	if (!sap->sap_more && ((pld_length - sizeof(*pld)) != sap_length)) { | 
    
330  | 
    905910  | 
    		log_debug("%s: payload malformed: SA payload length mismatches " | 
    |
331  | 
    "single proposal substructure length (%lu != %zu)",  | 
    ||
332  | 
    __func__, pld_length - sizeof(*pld), sap_length);  | 
    ||
333  | 
    905910  | 
    return (-1);  | 
    |
334  | 
    }  | 
    ||
335  | 
    /*  | 
    ||
336  | 
    * If there are more than one proposal, there must be bytes  | 
    ||
337  | 
    * left in the payload.  | 
    ||
338  | 
    */  | 
    ||
339  | 
    ✓✓✓✓ | 
    131722740  | 
    	if (sap->sap_more && ((pld_length - sizeof(*pld)) <= sap_length)) { | 
    
340  | 
    719390  | 
    		log_debug("%s: payload malformed: SA payload too small for " | 
    |
341  | 
    "further proposals (%zu <= %zu)", __func__,  | 
    ||
342  | 
    pld_length - sizeof(*pld), sap_length);  | 
    ||
343  | 
    719390  | 
    return (-1);  | 
    |
344  | 
    }  | 
    ||
345  | 
    130281260  | 
    return (0);  | 
    |
346  | 
    133239710  | 
    }  | 
    |
347  | 
    |||
348  | 
    /*  | 
    ||
349  | 
    * NB: This function parses both the SA header and the first proposal.  | 
    ||
350  | 
    * Additional proposals are ignored.  | 
    ||
351  | 
    */  | 
    ||
352  | 
    int  | 
    ||
353  | 
    ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,  | 
    ||
354  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
355  | 
    { | 
    ||
356  | 
    266479420  | 
    struct ikev2_sa_proposal sap;  | 
    |
357  | 
    struct iked_proposal *prop = NULL;  | 
    ||
358  | 
    uint32_t spi32;  | 
    ||
359  | 
    uint64_t spi = 0, spi64;  | 
    ||
360  | 
    133239710  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
361  | 
    struct iked_proposals *props;  | 
    ||
362  | 
    size_t total;  | 
    ||
363  | 
    |||
364  | 
    ✓✓ | 133239710  | 
    if (ikev2_validate_sa(msg, offset, left, pld, &sap))  | 
    
365  | 
    2958450  | 
    return (-1);  | 
    |
366  | 
    |||
367  | 
    ✓✓ | 130281260  | 
    if (sap.sap_more)  | 
    
368  | 
    2700  | 
    		log_debug("%s: more than one proposal specified", __func__); | 
    |
369  | 
    |||
370  | 
    /* Assumed size of the first proposals, including SPI if present. */  | 
    ||
371  | 
    130281260  | 
    total = (betoh16(sap.sap_length) - sizeof(sap));  | 
    |
372  | 
    |||
373  | 
    130281260  | 
    props = &msg->msg_parent->msg_proposals;  | 
    |
374  | 
    |||
375  | 
    130281260  | 
    offset += sizeof(sap);  | 
    |
376  | 
    130281260  | 
    left -= sizeof(sap);  | 
    |
377  | 
    |||
378  | 
    ✓✓ | 130281260  | 
    	if (sap.sap_spisize) { | 
    
379  | 
    ✓✓ | 715590  | 
    		if (left < sap.sap_spisize) { | 
    
380  | 
    67390  | 
    			log_debug("%s: malformed payload: SPI larger than " | 
    |
381  | 
    "actual payload (%zu < %d)", __func__, left,  | 
    ||
382  | 
    67390  | 
    sap.sap_spisize);  | 
    |
383  | 
    67390  | 
    return (-1);  | 
    |
384  | 
    }  | 
    ||
385  | 
    ✓✓ | 648200  | 
    		if (total < sap.sap_spisize) { | 
    
386  | 
    149600  | 
    			log_debug("%s: malformed payload: SPI larger than " | 
    |
387  | 
    "proposal (%zu < %d)", __func__, total,  | 
    ||
388  | 
    149600  | 
    sap.sap_spisize);  | 
    |
389  | 
    149600  | 
    return (-1);  | 
    |
390  | 
    }  | 
    ||
391  | 
    ✗✓ | 498600  | 
    		if (total < sap.sap_spisize) { | 
    
392  | 
    			log_debug("%s: malformed payload: SPI too large " | 
    ||
393  | 
    "(%zu < %d)", __func__, total, sap.sap_spisize);  | 
    ||
394  | 
    return (-1);  | 
    ||
395  | 
    }  | 
    ||
396  | 
    ✓✓✓ | 498600  | 
    		switch (sap.sap_spisize) { | 
    
397  | 
    case 4:  | 
    ||
398  | 
    82960  | 
    memcpy(&spi32, msgbuf + offset, 4);  | 
    |
399  | 
    82960  | 
    spi = betoh32(spi32);  | 
    |
400  | 
    82960  | 
    break;  | 
    |
401  | 
    case 8:  | 
    ||
402  | 
    82960  | 
    memcpy(&spi64, msgbuf + offset, 8);  | 
    |
403  | 
    82960  | 
    spi = betoh64(spi64);  | 
    |
404  | 
    82960  | 
    break;  | 
    |
405  | 
    default:  | 
    ||
406  | 
    332680  | 
    			log_debug("%s: unsupported SPI size %d", | 
    |
407  | 
    __func__, sap.sap_spisize);  | 
    ||
408  | 
    332680  | 
    return (-1);  | 
    |
409  | 
    }  | 
    ||
410  | 
    |||
411  | 
    165920  | 
    offset += sap.sap_spisize;  | 
    |
412  | 
    165920  | 
    left -= sap.sap_spisize;  | 
    |
413  | 
    |||
414  | 
    /* Assumed size of the proposal, now without SPI. */  | 
    ||
415  | 
    165920  | 
    total -= sap.sap_spisize;  | 
    |
416  | 
    165920  | 
    }  | 
    |
417  | 
    |||
418  | 
    /*  | 
    ||
419  | 
    * As we verified sanity of packet headers, this check will  | 
    ||
420  | 
    * be always false, but just to be sure we keep it.  | 
    ||
421  | 
    */  | 
    ||
422  | 
    ✗✓ | 129731590  | 
    	if (left < total) { | 
    
423  | 
    		log_debug("%s: payload malformed: too long for payload " | 
    ||
424  | 
    "(%zu < %zu)", __func__, left, total);  | 
    ||
425  | 
    return (-1);  | 
    ||
426  | 
    }  | 
    ||
427  | 
    |||
428  | 
    129731590  | 
    	log_debug("%s: more %d reserved %d length %d" | 
    |
429  | 
    " proposal #%d protoid %s spisize %d xforms %d spi %s",  | 
    ||
430  | 
    129731590  | 
    __func__, sap.sap_more, sap.sap_reserved,  | 
    |
431  | 
    129731590  | 
    betoh16(sap.sap_length), sap.sap_proposalnr,  | 
    |
432  | 
    129731590  | 
    print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,  | 
    |
433  | 
    129731590  | 
    sap.sap_transforms, print_spi(spi, sap.sap_spisize));  | 
    |
434  | 
    |||
435  | 
    ✗✓ | 129731590  | 
    	if (ikev2_msg_frompeer(msg)) { | 
    
436  | 
    if ((msg->msg_parent->msg_prop = config_add_proposal(props,  | 
    ||
437  | 
    		    sap.sap_proposalnr, sap.sap_protoid)) == NULL) { | 
    ||
438  | 
    			log_debug("%s: invalid proposal", __func__); | 
    ||
439  | 
    return (-1);  | 
    ||
440  | 
    }  | 
    ||
441  | 
    prop = msg->msg_parent->msg_prop;  | 
    ||
442  | 
    prop->prop_peerspi.spi = spi;  | 
    ||
443  | 
    prop->prop_peerspi.spi_protoid = sap.sap_protoid;  | 
    ||
444  | 
    prop->prop_peerspi.spi_size = sap.sap_spisize;  | 
    ||
445  | 
    |||
446  | 
    prop->prop_localspi.spi_protoid = sap.sap_protoid;  | 
    ||
447  | 
    prop->prop_localspi.spi_size = sap.sap_spisize;  | 
    ||
448  | 
    }  | 
    ||
449  | 
    |||
450  | 
    /*  | 
    ||
451  | 
    * Parse the attached transforms  | 
    ||
452  | 
    */  | 
    ||
453  | 
    ✓✓✓✓ | 
    258932010  | 
    if (sap.sap_transforms &&  | 
    
454  | 
    129200420  | 
    	    ikev2_pld_xform(env, &sap, msg, offset, total) != 0) { | 
    |
455  | 
    11160320  | 
    		log_debug("%s: invalid proposal transforms", __func__); | 
    |
456  | 
    11160320  | 
    return (-1);  | 
    |
457  | 
    }  | 
    ||
458  | 
    |||
459  | 
    118571270  | 
    return (0);  | 
    |
460  | 
    133239710  | 
    }  | 
    |
461  | 
    |||
462  | 
    int  | 
    ||
463  | 
    ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,  | 
    ||
464  | 
    struct ikev2_transform *xfrm)  | 
    ||
465  | 
    { | 
    ||
466  | 
    1489756120  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
467  | 
    size_t xfrm_length;  | 
    ||
468  | 
    |||
469  | 
    ✓✓ | 744878060  | 
    	if (total < sizeof(*xfrm)) { | 
    
470  | 
    195300  | 
    		log_debug("%s: payload malformed: too short for header " | 
    |
471  | 
    "(%zu < %zu)", __func__, total, sizeof(*xfrm));  | 
    ||
472  | 
    195300  | 
    return (-1);  | 
    |
473  | 
    }  | 
    ||
474  | 
    744682760  | 
    memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));  | 
    |
475  | 
    |||
476  | 
    744682760  | 
    xfrm_length = betoh16(xfrm->xfrm_length);  | 
    |
477  | 
    ✓✓ | 744682760  | 
    	if (xfrm_length < sizeof(*xfrm)) { | 
    
478  | 
    480600  | 
    		log_debug("%s: payload malformed: shorter than minimal header " | 
    |
479  | 
    "(%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));  | 
    ||
480  | 
    480600  | 
    return (-1);  | 
    |
481  | 
    }  | 
    ||
482  | 
    ✓✓ | 744202160  | 
    	if (total < xfrm_length) { | 
    
483  | 
    5745240  | 
    		log_debug("%s: malformed payload: too long for payload size " | 
    |
484  | 
    "(%zu < %zu)", __func__, total, xfrm_length);  | 
    ||
485  | 
    5745240  | 
    return (-1);  | 
    |
486  | 
    }  | 
    ||
487  | 
    |||
488  | 
    738456920  | 
    return (0);  | 
    |
489  | 
    744878060  | 
    }  | 
    |
490  | 
    |||
491  | 
    int  | 
    ||
492  | 
    ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap,  | 
    ||
493  | 
    struct iked_message *msg, size_t offset, size_t total)  | 
    ||
494  | 
    { | 
    ||
495  | 
    1489756120  | 
    struct ikev2_transform xfrm;  | 
    |
496  | 
    744878060  | 
    char id[BUFSIZ];  | 
    |
497  | 
    int ret = 0;  | 
    ||
498  | 
    size_t xfrm_length;  | 
    ||
499  | 
    |||
500  | 
    ✓✓ | 744878060  | 
    if (ikev2_validate_xform(msg, offset, total, &xfrm))  | 
    
501  | 
    6421140  | 
    return (-1);  | 
    |
502  | 
    |||
503  | 
    738456920  | 
    xfrm_length = betoh16(xfrm.xfrm_length);  | 
    |
504  | 
    |||
505  | 
    ✓✓✓✓ ✓✓  | 
    738456920  | 
    	switch (xfrm.xfrm_type) { | 
    
506  | 
    case IKEV2_XFORMTYPE_ENCR:  | 
    ||
507  | 
    125562720  | 
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),  | 
    |
508  | 
    ikev2_xformencr_map), sizeof(id));  | 
    ||
509  | 
    125562720  | 
    break;  | 
    |
510  | 
    case IKEV2_XFORMTYPE_PRF:  | 
    ||
511  | 
    358344180  | 
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),  | 
    |
512  | 
    ikev2_xformprf_map), sizeof(id));  | 
    ||
513  | 
    358344180  | 
    break;  | 
    |
514  | 
    case IKEV2_XFORMTYPE_INTEGR:  | 
    ||
515  | 
    127792040  | 
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),  | 
    |
516  | 
    ikev2_xformauth_map), sizeof(id));  | 
    ||
517  | 
    127792040  | 
    break;  | 
    |
518  | 
    case IKEV2_XFORMTYPE_DH:  | 
    ||
519  | 
    123335660  | 
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),  | 
    |
520  | 
    ikev2_xformdh_map), sizeof(id));  | 
    ||
521  | 
    123335660  | 
    break;  | 
    |
522  | 
    case IKEV2_XFORMTYPE_ESN:  | 
    ||
523  | 
    161560  | 
    strlcpy(id, print_map(betoh16(xfrm.xfrm_id),  | 
    |
524  | 
    ikev2_xformesn_map), sizeof(id));  | 
    ||
525  | 
    161560  | 
    break;  | 
    |
526  | 
    default:  | 
    ||
527  | 
    3260760  | 
    snprintf(id, sizeof(id), "<%d>", betoh16(xfrm.xfrm_id));  | 
    |
528  | 
    3260760  | 
    break;  | 
    |
529  | 
    }  | 
    ||
530  | 
    |||
531  | 
    738456920  | 
    	log_debug("%s: more %d reserved %d length %zu" | 
    |
532  | 
    " type %s id %s",  | 
    ||
533  | 
    738456920  | 
    __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length,  | 
    |
534  | 
    738456920  | 
    print_map(xfrm.xfrm_type, ikev2_xformtype_map), id);  | 
    |
535  | 
    |||
536  | 
    /*  | 
    ||
537  | 
    * Parse transform attributes, if available  | 
    ||
538  | 
    */  | 
    ||
539  | 
    738456920  | 
    msg->msg_attrlength = 0;  | 
    |
540  | 
    ✓✓ | 738456920  | 
    	if (xfrm_length > sizeof(xfrm)) { | 
    
541  | 
    ✓✓ | 382296540  | 
    if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm),  | 
    
542  | 
    254864360  | 
    		    xfrm_length - sizeof(xfrm)) != 0) { | 
    |
543  | 
    1472580  | 
    return (-1);  | 
    |
544  | 
    }  | 
    ||
545  | 
    }  | 
    ||
546  | 
    |||
547  | 
    ✗✓ | 736984340  | 
    	if (ikev2_msg_frompeer(msg)) { | 
    
548  | 
    if (config_add_transform(msg->msg_parent->msg_prop,  | 
    ||
549  | 
    xfrm.xfrm_type, betoh16(xfrm.xfrm_id),  | 
    ||
550  | 
    		    msg->msg_attrlength, msg->msg_attrlength) == NULL) { | 
    ||
551  | 
    			log_debug("%s: failed to add transform", __func__); | 
    ||
552  | 
    return (-1);  | 
    ||
553  | 
    }  | 
    ||
554  | 
    }  | 
    ||
555  | 
    |||
556  | 
    /* Next transform */  | 
    ||
557  | 
    736984340  | 
    offset += xfrm_length;  | 
    |
558  | 
    736984340  | 
    total -= xfrm_length;  | 
    |
559  | 
    ✓✓ | 736984340  | 
    if (xfrm.xfrm_more == IKEV2_XFORM_MORE)  | 
    
560  | 
    615677640  | 
    ret = ikev2_pld_xform(env, sap, msg, offset, total);  | 
    |
561  | 
    ✓✓ | 121306700  | 
    	else if (total != 0) { | 
    
562  | 
    /* No more transforms but still some data left. */  | 
    ||
563  | 
    3266600  | 
    		log_debug("%s: less data than specified, %zu bytes left", | 
    |
564  | 
    __func__, total);  | 
    ||
565  | 
    ret = -1;  | 
    ||
566  | 
    3266600  | 
    }  | 
    |
567  | 
    |||
568  | 
    736984340  | 
    return (ret);  | 
    |
569  | 
    744878060  | 
    }  | 
    |
570  | 
    |||
571  | 
    int  | 
    ||
572  | 
    ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,  | 
    ||
573  | 
    struct ikev2_attribute *attr)  | 
    ||
574  | 
    { | 
    ||
575  | 
    257132400  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
576  | 
    |||
577  | 
    ✓✓ | 128566200  | 
    	if (total < sizeof(*attr)) { | 
    
578  | 
    805020  | 
    		log_debug("%s: payload malformed: too short for header " | 
    |
579  | 
    "(%zu < %zu)", __func__, total, sizeof(*attr));  | 
    ||
580  | 
    805020  | 
    return (-1);  | 
    |
581  | 
    }  | 
    ||
582  | 
    127761180  | 
    memcpy(attr, msgbuf + offset, sizeof(*attr));  | 
    |
583  | 
    |||
584  | 
    127761180  | 
    return (0);  | 
    |
585  | 
    128566200  | 
    }  | 
    |
586  | 
    |||
587  | 
    int  | 
    ||
588  | 
    ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,  | 
    ||
589  | 
    struct iked_message *msg, size_t offset, size_t total)  | 
    ||
590  | 
    { | 
    ||
591  | 
    257132400  | 
    struct ikev2_attribute attr;  | 
    |
592  | 
    unsigned int type;  | 
    ||
593  | 
    128566200  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
594  | 
    int ret = 0;  | 
    ||
595  | 
    size_t attr_length;  | 
    ||
596  | 
    |||
597  | 
    ✓✓ | 128566200  | 
    if (ikev2_validate_attr(msg, offset, total, &attr))  | 
    
598  | 
    805020  | 
    return (-1);  | 
    |
599  | 
    |||
600  | 
    127761180  | 
    type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;  | 
    |
601  | 
    |||
602  | 
    127761180  | 
    	log_debug("%s: attribute type %s length %d total %zu", | 
    |
603  | 
    127761180  | 
    __func__, print_map(type, ikev2_attrtype_map),  | 
    |
604  | 
    127761180  | 
    betoh16(attr.attr_length), total);  | 
    |
605  | 
    |||
606  | 
    ✓✓ | 127761180  | 
    	if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) { | 
    
607  | 
    /* Type-Value attribute */  | 
    ||
608  | 
    125969600  | 
    offset += sizeof(attr);  | 
    |
609  | 
    125969600  | 
    total -= sizeof(attr);  | 
    |
610  | 
    |||
611  | 
    ✓✓ | 125969600  | 
    if (type == IKEV2_ATTRTYPE_KEY_LENGTH)  | 
    
612  | 
    124739360  | 
    msg->msg_attrlength = betoh16(attr.attr_length);  | 
    |
613  | 
    	} else { | 
    ||
614  | 
    /* Type-Length-Value attribute */  | 
    ||
615  | 
    1791580  | 
    attr_length = betoh16(attr.attr_length);  | 
    |
616  | 
    ✓✓ | 1791580  | 
    		if (attr_length < sizeof(attr)) { | 
    
617  | 
    1040  | 
    			log_debug("%s: payload malformed: shorter than " | 
    |
618  | 
    "minimal header (%zu < %zu)", __func__,  | 
    ||
619  | 
    attr_length, sizeof(attr));  | 
    ||
620  | 
    1040  | 
    return (-1);  | 
    |
621  | 
    }  | 
    ||
622  | 
    ✓✓ | 1790540  | 
    		if (total < attr_length) { | 
    
623  | 
    666520  | 
    			log_debug("%s: payload malformed: attribute larger " | 
    |
624  | 
    "than actual payload (%zu < %zu)", __func__,  | 
    ||
625  | 
    total, attr_length);  | 
    ||
626  | 
    666520  | 
    return (-1);  | 
    |
627  | 
    }  | 
    ||
628  | 
    2248040  | 
    print_hex(msgbuf, offset + sizeof(attr),  | 
    |
629  | 
    1124020  | 
    attr_length - sizeof(attr));  | 
    |
630  | 
    1124020  | 
    offset += attr_length;  | 
    |
631  | 
    1124020  | 
    total -= attr_length;  | 
    |
632  | 
    }  | 
    ||
633  | 
    |||
634  | 
    ✓✓ | 127093620  | 
    	if (total > 0) { | 
    
635  | 
    /* Next attribute */  | 
    ||
636  | 
    1134020  | 
    ret = ikev2_pld_attr(env, xfrm, msg, offset, total);  | 
    |
637  | 
    1134020  | 
    }  | 
    |
638  | 
    |||
639  | 
    127093620  | 
    return (ret);  | 
    |
640  | 
    128566200  | 
    }  | 
    |
641  | 
    |||
642  | 
    int  | 
    ||
643  | 
    ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
644  | 
    struct ikev2_payload *pld, struct ikev2_keyexchange *kex)  | 
    ||
645  | 
    { | 
    ||
646  | 
    358834780  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
647  | 
    size_t pld_length;  | 
    ||
648  | 
    |||
649  | 
    179417390  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
650  | 
    ✓✓ | 179417390  | 
    	if (pld_length < sizeof(*pld) + sizeof(*kex)) { | 
    
651  | 
    4270  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    |
652  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
653  | 
    sizeof(*pld) + sizeof(*kex));  | 
    ||
654  | 
    4270  | 
    return (-1);  | 
    |
655  | 
    }  | 
    ||
656  | 
    |||
657  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
658  | 
    ✗✓ | 179413120  | 
    	if (left < sizeof(*kex)) { | 
    
659  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
660  | 
    "(%zu < %zu)", __func__, left, sizeof(*kex));  | 
    ||
661  | 
    return (-1);  | 
    ||
662  | 
    }  | 
    ||
663  | 
    179413120  | 
    memcpy(kex, msgbuf + offset, sizeof(*kex));  | 
    |
664  | 
    |||
665  | 
    179413120  | 
    return (0);  | 
    |
666  | 
    179417390  | 
    }  | 
    |
667  | 
    |||
668  | 
    int  | 
    ||
669  | 
    ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,  | 
    ||
670  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
671  | 
    { | 
    ||
672  | 
    358834780  | 
    struct ikev2_keyexchange kex;  | 
    |
673  | 
    uint8_t *buf;  | 
    ||
674  | 
    size_t len;  | 
    ||
675  | 
    179417390  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
676  | 
    |||
677  | 
    ✓✓ | 179417390  | 
    if (ikev2_validate_ke(msg, offset, left, pld, &kex))  | 
    
678  | 
    4270  | 
    return (-1);  | 
    |
679  | 
    |||
680  | 
    179413120  | 
    	log_debug("%s: dh group %s reserved %d", __func__, | 
    |
681  | 
    179413120  | 
    print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),  | 
    |
682  | 
    179413120  | 
    betoh16(kex.kex_reserved));  | 
    |
683  | 
    |||
684  | 
    179413120  | 
    buf = msgbuf + offset + sizeof(kex);  | 
    |
685  | 
    179413120  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex);  | 
    |
686  | 
    |||
687  | 
    ✓✓ | 179413120  | 
    	if (len == 0) { | 
    
688  | 
    116120  | 
    		log_debug("%s: malformed payload: no KE data given", __func__); | 
    |
689  | 
    116120  | 
    return (-1);  | 
    |
690  | 
    }  | 
    ||
691  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
692  | 
    ✗✓ | 179297000  | 
    	if (left < len) { | 
    
693  | 
    		log_debug("%s: malformed payload: smaller than specified " | 
    ||
694  | 
    "(%zu < %zu)", __func__, left, len);  | 
    ||
695  | 
    return (-1);  | 
    ||
696  | 
    }  | 
    ||
697  | 
    |||
698  | 
    179297000  | 
    print_hex(buf, 0, len);  | 
    |
699  | 
    |||
700  | 
    ✗✓ | 179297000  | 
    	if (ikev2_msg_frompeer(msg)) { | 
    
701  | 
    ibuf_release(msg->msg_parent->msg_ke);  | 
    ||
702  | 
    		if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) { | 
    ||
703  | 
    			log_debug("%s: failed to get exchange", __func__); | 
    ||
704  | 
    return (-1);  | 
    ||
705  | 
    }  | 
    ||
706  | 
    }  | 
    ||
707  | 
    |||
708  | 
    179297000  | 
    return (0);  | 
    |
709  | 
    179417390  | 
    }  | 
    |
710  | 
    |||
711  | 
    int  | 
    ||
712  | 
    ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
713  | 
    struct ikev2_payload *pld, struct ikev2_id *id)  | 
    ||
714  | 
    { | 
    ||
715  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
716  | 
    size_t pld_length;  | 
    ||
717  | 
    |||
718  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
719  | 
    	if (pld_length < sizeof(*pld) + sizeof(*id)) { | 
    ||
720  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
721  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
722  | 
    sizeof(*pld) + sizeof(*id));  | 
    ||
723  | 
    return (-1);  | 
    ||
724  | 
    }  | 
    ||
725  | 
    |||
726  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
727  | 
    	if (left < sizeof(*id)) { | 
    ||
728  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
729  | 
    "(%zu < %zu)", __func__, left, sizeof(*id));  | 
    ||
730  | 
    return (-1);  | 
    ||
731  | 
    }  | 
    ||
732  | 
    memcpy(id, msgbuf + offset, sizeof(*id));  | 
    ||
733  | 
    |||
734  | 
    return (0);  | 
    ||
735  | 
    }  | 
    ||
736  | 
    |||
737  | 
    int  | 
    ||
738  | 
    ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,  | 
    ||
739  | 
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)  | 
    ||
740  | 
    { | 
    ||
741  | 
    uint8_t *ptr;  | 
    ||
742  | 
    struct ikev2_id id;  | 
    ||
743  | 
    size_t len;  | 
    ||
744  | 
    struct iked_id *idp, idb;  | 
    ||
745  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    ||
746  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
747  | 
    char idstr[IKED_ID_SIZE];  | 
    ||
748  | 
    |||
749  | 
    if (ikev2_validate_id(msg, offset, left, pld, &id))  | 
    ||
750  | 
    return (-1);  | 
    ||
751  | 
    |||
752  | 
    bzero(&idb, sizeof(idb));  | 
    ||
753  | 
    |||
754  | 
    /* Don't strip the Id payload header */  | 
    ||
755  | 
    ptr = msgbuf + offset;  | 
    ||
756  | 
    len = betoh16(pld->pld_length) - sizeof(*pld);  | 
    ||
757  | 
    |||
758  | 
    idb.id_type = id.id_type;  | 
    ||
759  | 
    idb.id_offset = sizeof(id);  | 
    ||
760  | 
    if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)  | 
    ||
761  | 
    return (-1);  | 
    ||
762  | 
    |||
763  | 
    	if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) { | 
    ||
764  | 
    		log_debug("%s: malformed id", __func__); | 
    ||
765  | 
    return (-1);  | 
    ||
766  | 
    }  | 
    ||
767  | 
    |||
768  | 
    	log_debug("%s: id %s length %zu", __func__, idstr, len); | 
    ||
769  | 
    |||
770  | 
    	if (!ikev2_msg_frompeer(msg)) { | 
    ||
771  | 
    ibuf_release(idb.id_buf);  | 
    ||
772  | 
    return (0);  | 
    ||
773  | 
    }  | 
    ||
774  | 
    |||
775  | 
    if (!((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||  | 
    ||
776  | 
    	    (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi))) { | 
    ||
777  | 
    		log_debug("%s: unexpected id payload", __func__); | 
    ||
778  | 
    return (0);  | 
    ||
779  | 
    }  | 
    ||
780  | 
    |||
781  | 
    idp = &msg->msg_parent->msg_id;  | 
    ||
782  | 
    	if (idp->id_type) { | 
    ||
783  | 
    		log_debug("%s: duplicate id payload", __func__); | 
    ||
784  | 
    return (-1);  | 
    ||
785  | 
    }  | 
    ||
786  | 
    |||
787  | 
    idp->id_buf = idb.id_buf;  | 
    ||
788  | 
    idp->id_offset = idb.id_offset;  | 
    ||
789  | 
    idp->id_type = idb.id_type;  | 
    ||
790  | 
    |||
791  | 
    return (0);  | 
    ||
792  | 
    }  | 
    ||
793  | 
    |||
794  | 
    int  | 
    ||
795  | 
    ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
796  | 
    struct ikev2_payload *pld, struct ikev2_cert *cert)  | 
    ||
797  | 
    { | 
    ||
798  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
799  | 
    size_t pld_length;  | 
    ||
800  | 
    |||
801  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
802  | 
    	if (pld_length < sizeof(*pld) + sizeof(*cert)) { | 
    ||
803  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
804  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
805  | 
    sizeof(*pld) + sizeof(*cert));  | 
    ||
806  | 
    return (-1);  | 
    ||
807  | 
    }  | 
    ||
808  | 
    |||
809  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
810  | 
    	if (left < sizeof(*cert)) { | 
    ||
811  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
812  | 
    "(%zu < %zu)", __func__, left, sizeof(*cert));  | 
    ||
813  | 
    return (-1);  | 
    ||
814  | 
    }  | 
    ||
815  | 
    memcpy(cert, msgbuf + offset, sizeof(*cert));  | 
    ||
816  | 
    |||
817  | 
    return (0);  | 
    ||
818  | 
    }  | 
    ||
819  | 
    |||
820  | 
    int  | 
    ||
821  | 
    ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,  | 
    ||
822  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
823  | 
    { | 
    ||
824  | 
    struct ikev2_cert cert;  | 
    ||
825  | 
    uint8_t *buf;  | 
    ||
826  | 
    size_t len;  | 
    ||
827  | 
    struct iked_id *certid;  | 
    ||
828  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
829  | 
    |||
830  | 
    if (ikev2_validate_cert(msg, offset, left, pld, &cert))  | 
    ||
831  | 
    return (-1);  | 
    ||
832  | 
    offset += sizeof(cert);  | 
    ||
833  | 
    |||
834  | 
    buf = msgbuf + offset;  | 
    ||
835  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);  | 
    ||
836  | 
    |||
837  | 
    	log_debug("%s: type %s length %zu", | 
    ||
838  | 
    __func__, print_map(cert.cert_type, ikev2_cert_map), len);  | 
    ||
839  | 
    |||
840  | 
    print_hex(buf, 0, len);  | 
    ||
841  | 
    |||
842  | 
    if (!ikev2_msg_frompeer(msg))  | 
    ||
843  | 
    return (0);  | 
    ||
844  | 
    |||
845  | 
    certid = &msg->msg_parent->msg_cert;  | 
    ||
846  | 
    	if (certid->id_type) { | 
    ||
847  | 
    		log_debug("%s: duplicate cert payload", __func__); | 
    ||
848  | 
    return (-1);  | 
    ||
849  | 
    }  | 
    ||
850  | 
    |||
851  | 
    	if ((certid->id_buf = ibuf_new(buf, len)) == NULL) { | 
    ||
852  | 
    		log_debug("%s: failed to save cert", __func__); | 
    ||
853  | 
    return (-1);  | 
    ||
854  | 
    }  | 
    ||
855  | 
    certid->id_type = cert.cert_type;  | 
    ||
856  | 
    certid->id_offset = 0;  | 
    ||
857  | 
    |||
858  | 
    return (0);  | 
    ||
859  | 
    }  | 
    ||
860  | 
    |||
861  | 
    int  | 
    ||
862  | 
    ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
863  | 
    struct ikev2_payload *pld, struct ikev2_cert *cert)  | 
    ||
864  | 
    { | 
    ||
865  | 
    1250260  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
866  | 
    size_t pld_length;  | 
    ||
867  | 
    |||
868  | 
    625130  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
869  | 
    ✓✓ | 625130  | 
    	if (pld_length < sizeof(*pld) + sizeof(*cert)) { | 
    
870  | 
    4190  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    |
871  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
872  | 
    sizeof(*pld) + sizeof(*cert));  | 
    ||
873  | 
    4190  | 
    return (-1);  | 
    |
874  | 
    }  | 
    ||
875  | 
    |||
876  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
877  | 
    ✗✓ | 620940  | 
    	if (left < sizeof(*cert)) { | 
    
878  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
879  | 
    "(%zu < %zu)", __func__, left, sizeof(*cert));  | 
    ||
880  | 
    return (-1);  | 
    ||
881  | 
    }  | 
    ||
882  | 
    620940  | 
    memcpy(cert, msgbuf + offset, sizeof(*cert));  | 
    |
883  | 
    |||
884  | 
    620940  | 
    return (0);  | 
    |
885  | 
    625130  | 
    }  | 
    |
886  | 
    |||
887  | 
    int  | 
    ||
888  | 
    ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,  | 
    ||
889  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
890  | 
    { | 
    ||
891  | 
    1250260  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    |
892  | 
    625130  | 
    struct ikev2_cert cert;  | 
    |
893  | 
    uint8_t *buf;  | 
    ||
894  | 
    ssize_t len;  | 
    ||
895  | 
    625130  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
896  | 
    |||
897  | 
    ✓✓ | 625130  | 
    if (ikev2_validate_certreq(msg, offset, left, pld, &cert))  | 
    
898  | 
    4190  | 
    return (-1);  | 
    |
899  | 
    620940  | 
    offset += sizeof(cert);  | 
    |
900  | 
    |||
901  | 
    620940  | 
    buf = msgbuf + offset;  | 
    |
902  | 
    620940  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);  | 
    |
903  | 
    |||
904  | 
    620940  | 
    	log_debug("%s: type %s length %zd", | 
    |
905  | 
    620940  | 
    __func__, print_map(cert.cert_type, ikev2_cert_map), len);  | 
    |
906  | 
    |||
907  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
908  | 
    ✗✓ | 620940  | 
    	if (len < 0) { | 
    
909  | 
    		log_debug("%s: invalid certificate request length", __func__); | 
    ||
910  | 
    return (-1);  | 
    ||
911  | 
    }  | 
    ||
912  | 
    |||
913  | 
    620940  | 
    print_hex(buf, 0, len);  | 
    |
914  | 
    |||
915  | 
    ✓✗ | 620940  | 
    if (!ikev2_msg_frompeer(msg))  | 
    
916  | 
    620940  | 
    return (0);  | 
    |
917  | 
    |||
918  | 
    	if (cert.cert_type == IKEV2_CERT_X509_CERT) { | 
    ||
919  | 
    if (!len)  | 
    ||
920  | 
    return (0);  | 
    ||
921  | 
    		if ((len % SHA_DIGEST_LENGTH) != 0) { | 
    ||
922  | 
    			log_debug("%s: invalid certificate request", __func__); | 
    ||
923  | 
    return (-1);  | 
    ||
924  | 
    }  | 
    ||
925  | 
    }  | 
    ||
926  | 
    |||
927  | 
    if (msg->msg_sa == NULL)  | 
    ||
928  | 
    return (-1);  | 
    ||
929  | 
    |||
930  | 
    /* Optional certreq for PSK */  | 
    ||
931  | 
    if (sa->sa_hdr.sh_initiator)  | 
    ||
932  | 
    sa->sa_stateinit |= IKED_REQ_CERT;  | 
    ||
933  | 
    else  | 
    ||
934  | 
    sa->sa_statevalid |= IKED_REQ_CERT;  | 
    ||
935  | 
    |||
936  | 
    ca_setreq(env, sa, &sa->sa_policy->pol_localid,  | 
    ||
937  | 
    cert.cert_type, buf, len, PROC_CERT);  | 
    ||
938  | 
    |||
939  | 
    return (0);  | 
    ||
940  | 
    625130  | 
    }  | 
    |
941  | 
    |||
942  | 
    int  | 
    ||
943  | 
    ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
944  | 
    struct ikev2_payload *pld, struct ikev2_auth *auth)  | 
    ||
945  | 
    { | 
    ||
946  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
947  | 
    size_t pld_length;  | 
    ||
948  | 
    |||
949  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
950  | 
    	if (pld_length < sizeof(*pld) + sizeof(*auth)) { | 
    ||
951  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
952  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
953  | 
    sizeof(*pld) + sizeof(*auth));  | 
    ||
954  | 
    return (-1);  | 
    ||
955  | 
    }  | 
    ||
956  | 
    |||
957  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
958  | 
    	if (left < sizeof(*auth)) { | 
    ||
959  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
960  | 
    "(%zu < %zu)", __func__, left, sizeof(*auth));  | 
    ||
961  | 
    return (-1);  | 
    ||
962  | 
    }  | 
    ||
963  | 
    memcpy(auth, msgbuf + offset, sizeof(*auth));  | 
    ||
964  | 
    |||
965  | 
    return (0);  | 
    ||
966  | 
    }  | 
    ||
967  | 
    |||
968  | 
    int  | 
    ||
969  | 
    ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,  | 
    ||
970  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
971  | 
    { | 
    ||
972  | 
    struct ikev2_auth auth;  | 
    ||
973  | 
    struct iked_id *idp;  | 
    ||
974  | 
    uint8_t *buf;  | 
    ||
975  | 
    size_t len;  | 
    ||
976  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    ||
977  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
978  | 
    |||
979  | 
    if (ikev2_validate_auth(msg, offset, left, pld, &auth))  | 
    ||
980  | 
    return (-1);  | 
    ||
981  | 
    offset += sizeof(auth);  | 
    ||
982  | 
    |||
983  | 
    buf = msgbuf + offset;  | 
    ||
984  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(auth);  | 
    ||
985  | 
    |||
986  | 
    	log_debug("%s: method %s length %zu", | 
    ||
987  | 
    __func__, print_map(auth.auth_method, ikev2_auth_map), len);  | 
    ||
988  | 
    |||
989  | 
    print_hex(buf, 0, len);  | 
    ||
990  | 
    |||
991  | 
    if (!ikev2_msg_frompeer(msg))  | 
    ||
992  | 
    return (0);  | 
    ||
993  | 
    |||
994  | 
    /* The AUTH payload indicates if the responder wants EAP or not */  | 
    ||
995  | 
    if (!sa_stateok(sa, IKEV2_STATE_EAP))  | 
    ||
996  | 
    sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST);  | 
    ||
997  | 
    |||
998  | 
    idp = &msg->msg_parent->msg_auth;  | 
    ||
999  | 
    	if (idp->id_type) { | 
    ||
1000  | 
    		log_debug("%s: duplicate auth payload", __func__); | 
    ||
1001  | 
    return (-1);  | 
    ||
1002  | 
    }  | 
    ||
1003  | 
    |||
1004  | 
    ibuf_release(idp->id_buf);  | 
    ||
1005  | 
    idp->id_type = auth.auth_method;  | 
    ||
1006  | 
    idp->id_offset = 0;  | 
    ||
1007  | 
    if ((idp->id_buf = ibuf_new(buf, len)) == NULL)  | 
    ||
1008  | 
    return (-1);  | 
    ||
1009  | 
    |||
1010  | 
    return (0);  | 
    ||
1011  | 
    }  | 
    ||
1012  | 
    |||
1013  | 
    int  | 
    ||
1014  | 
    ikev2_validate_nonce(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1015  | 
    struct ikev2_payload *pld)  | 
    ||
1016  | 
    { | 
    ||
1017  | 
    size_t pld_length;  | 
    ||
1018  | 
    |||
1019  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1020  | 
    254576840  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
1021  | 
    ✗✓ | 127288420  | 
    	if (pld_length < sizeof(*pld)) { | 
    
1022  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
1023  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1024  | 
    sizeof(*pld));  | 
    ||
1025  | 
    return (-1);  | 
    ||
1026  | 
    }  | 
    ||
1027  | 
    |||
1028  | 
    127288420  | 
    return (0);  | 
    |
1029  | 
    127288420  | 
    }  | 
    |
1030  | 
    |||
1031  | 
    int  | 
    ||
1032  | 
    ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1033  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
1034  | 
    { | 
    ||
1035  | 
    size_t len;  | 
    ||
1036  | 
    uint8_t *buf;  | 
    ||
1037  | 
    254576840  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
1038  | 
    |||
1039  | 
    ✗✓ | 127288420  | 
    if (ikev2_validate_nonce(msg, offset, left, pld))  | 
    
1040  | 
    return (-1);  | 
    ||
1041  | 
    |||
1042  | 
    127288420  | 
    buf = msgbuf + offset;  | 
    |
1043  | 
    127288420  | 
    len = betoh16(pld->pld_length) - sizeof(*pld);  | 
    |
1044  | 
    |||
1045  | 
    ✓✓ | 127288420  | 
    	if (len == 0) { | 
    
1046  | 
    79080  | 
    		log_debug("%s: malformed payload: no NONCE given", __func__); | 
    |
1047  | 
    79080  | 
    return (-1);  | 
    |
1048  | 
    }  | 
    ||
1049  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1050  | 
    ✗✓ | 127209340  | 
    	if (left < len) { | 
    
1051  | 
    		log_debug("%s: malformed payload: smaller than specified " | 
    ||
1052  | 
    "(%zu < %zu)", __func__, left, len);  | 
    ||
1053  | 
    return (-1);  | 
    ||
1054  | 
    }  | 
    ||
1055  | 
    |||
1056  | 
    127209340  | 
    print_hex(buf, 0, len);  | 
    |
1057  | 
    |||
1058  | 
    ✗✓ | 127209340  | 
    	if (ikev2_msg_frompeer(msg)) { | 
    
1059  | 
    ibuf_release(msg->msg_nonce);  | 
    ||
1060  | 
    		if ((msg->msg_nonce = ibuf_new(buf, len)) == NULL) { | 
    ||
1061  | 
    			log_debug("%s: failed to get peer nonce", __func__); | 
    ||
1062  | 
    return (-1);  | 
    ||
1063  | 
    }  | 
    ||
1064  | 
    msg->msg_parent->msg_nonce = msg->msg_nonce;  | 
    ||
1065  | 
    }  | 
    ||
1066  | 
    |||
1067  | 
    127209340  | 
    return (0);  | 
    |
1068  | 
    127288420  | 
    }  | 
    |
1069  | 
    |||
1070  | 
    int  | 
    ||
1071  | 
    ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1072  | 
    struct ikev2_payload *pld, struct ikev2_notify *n)  | 
    ||
1073  | 
    { | 
    ||
1074  | 
    500471380  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
1075  | 
    size_t pld_length;  | 
    ||
1076  | 
    |||
1077  | 
    250235690  | 
    pld_length = betoh16(pld->pld_length);  | 
    |
1078  | 
    ✓✓ | 250235690  | 
    	if (pld_length < sizeof(*pld) + sizeof(*n)) { | 
    
1079  | 
    160  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    |
1080  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1081  | 
    sizeof(*pld) + sizeof(*n));  | 
    ||
1082  | 
    160  | 
    return (-1);  | 
    |
1083  | 
    }  | 
    ||
1084  | 
    |||
1085  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1086  | 
    ✗✓ | 250235530  | 
    	if (left < sizeof(*n)) { | 
    
1087  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
1088  | 
    "(%zu < %zu)", __func__, left, sizeof(*n));  | 
    ||
1089  | 
    return (-1);  | 
    ||
1090  | 
    }  | 
    ||
1091  | 
    250235530  | 
    memcpy(n, msgbuf + offset, sizeof(*n));  | 
    |
1092  | 
    |||
1093  | 
    250235530  | 
    return (0);  | 
    |
1094  | 
    250235690  | 
    }  | 
    |
1095  | 
    |||
1096  | 
    int  | 
    ||
1097  | 
    ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1098  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
1099  | 
    { | 
    ||
1100  | 
    500471380  | 
    struct ikev2_notify n;  | 
    |
1101  | 
    250235690  | 
    uint8_t *buf, md[SHA_DIGEST_LENGTH];  | 
    |
1102  | 
    size_t len;  | 
    ||
1103  | 
    250235690  | 
    uint32_t spi32;  | 
    |
1104  | 
    250235690  | 
    uint64_t spi64;  | 
    |
1105  | 
    struct iked_spi *rekey;  | 
    ||
1106  | 
    uint16_t type;  | 
    ||
1107  | 
    250235690  | 
    uint16_t group;  | 
    |
1108  | 
    uint16_t cpi;  | 
    ||
1109  | 
    uint16_t signature_hash;  | 
    ||
1110  | 
    uint8_t transform;  | 
    ||
1111  | 
    |||
1112  | 
    ✓✓ | 250235690  | 
    if (ikev2_validate_notify(msg, offset, left, pld, &n))  | 
    
1113  | 
    160  | 
    return (-1);  | 
    |
1114  | 
    250235530  | 
    type = betoh16(n.n_type);  | 
    |
1115  | 
    |||
1116  | 
    250235530  | 
    	log_debug("%s: protoid %s spisize %d type %s", | 
    |
1117  | 
    __func__,  | 
    ||
1118  | 
    250235530  | 
    print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,  | 
    |
1119  | 
    250235530  | 
    print_map(type, ikev2_n_map));  | 
    |
1120  | 
    |||
1121  | 
    250235530  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(n);  | 
    |
1122  | 
    ✗✓ | 250235530  | 
    if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), len)) == NULL)  | 
    
1123  | 
    return (-1);  | 
    ||
1124  | 
    |||
1125  | 
    250235530  | 
    print_hex(buf, 0, len);  | 
    |
1126  | 
    |||
1127  | 
    ✓✗ | 250235530  | 
    if (!ikev2_msg_frompeer(msg))  | 
    
1128  | 
    250235530  | 
    return (0);  | 
    |
1129  | 
    |||
1130  | 
    	switch (type) { | 
    ||
1131  | 
    case IKEV2_N_NAT_DETECTION_SOURCE_IP:  | 
    ||
1132  | 
    case IKEV2_N_NAT_DETECTION_DESTINATION_IP:  | 
    ||
1133  | 
    		if (len != sizeof(md)) { | 
    ||
1134  | 
    			log_debug("%s: malformed payload: hash size mismatch" | 
    ||
1135  | 
    " (%zu != %zu)", __func__, len, sizeof(md));  | 
    ||
1136  | 
    return (-1);  | 
    ||
1137  | 
    }  | 
    ||
1138  | 
    if (ikev2_nat_detection(env, msg, md, sizeof(md), type) == -1)  | 
    ||
1139  | 
    return (-1);  | 
    ||
1140  | 
    		if (memcmp(buf, md, len) != 0) { | 
    ||
1141  | 
    			log_debug("%s: %s detected NAT, enabling " | 
    ||
1142  | 
    "UDP encapsulation", __func__,  | 
    ||
1143  | 
    print_map(type, ikev2_n_map));  | 
    ||
1144  | 
    |||
1145  | 
    /*  | 
    ||
1146  | 
    * Enable UDP encapsulation of ESP packages if  | 
    ||
1147  | 
    * the check detected NAT.  | 
    ||
1148  | 
    */  | 
    ||
1149  | 
    if (msg->msg_sa != NULL)  | 
    ||
1150  | 
    msg->msg_sa->sa_udpencap = 1;  | 
    ||
1151  | 
    /* Send keepalive, since we are behind a NAT-gw */  | 
    ||
1152  | 
    if (type == IKEV2_N_NAT_DETECTION_DESTINATION_IP)  | 
    ||
1153  | 
    msg->msg_sa->sa_usekeepalive = 1;  | 
    ||
1154  | 
    }  | 
    ||
1155  | 
    print_hex(md, 0, sizeof(md));  | 
    ||
1156  | 
    break;  | 
    ||
1157  | 
    case IKEV2_N_AUTHENTICATION_FAILED:  | 
    ||
1158  | 
    		if (!msg->msg_e) { | 
    ||
1159  | 
    			log_debug("%s: AUTHENTICATION_FAILED not encrypted", | 
    ||
1160  | 
    __func__);  | 
    ||
1161  | 
    return (-1);  | 
    ||
1162  | 
    }  | 
    ||
1163  | 
    /*  | 
    ||
1164  | 
    * If we are the responder, then we only accept  | 
    ||
1165  | 
    * AUTHENTICATION_FAILED from authenticated peers.  | 
    ||
1166  | 
    * If we are the initiator, the peer cannot be authenticated.  | 
    ||
1167  | 
    */  | 
    ||
1168  | 
    		if (!msg->msg_sa->sa_hdr.sh_initiator) { | 
    ||
1169  | 
    			if (!sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { | 
    ||
1170  | 
    				log_debug("%s: ignoring AUTHENTICATION_FAILED" | 
    ||
1171  | 
    " from unauthenticated initiator",  | 
    ||
1172  | 
    __func__);  | 
    ||
1173  | 
    return (-1);  | 
    ||
1174  | 
    }  | 
    ||
1175  | 
    		} else { | 
    ||
1176  | 
    			if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID)) { | 
    ||
1177  | 
    				log_debug("%s: ignoring AUTHENTICATION_FAILED" | 
    ||
1178  | 
    " from authenticated responder",  | 
    ||
1179  | 
    __func__);  | 
    ||
1180  | 
    return (-1);  | 
    ||
1181  | 
    }  | 
    ||
1182  | 
    }  | 
    ||
1183  | 
    		log_debug("%s: AUTHENTICATION_FAILED, closing SA", __func__); | 
    ||
1184  | 
    sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED);  | 
    ||
1185  | 
    msg->msg_sa = NULL;  | 
    ||
1186  | 
    break;  | 
    ||
1187  | 
    case IKEV2_N_INVALID_KE_PAYLOAD:  | 
    ||
1188  | 
    if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID) &&  | 
    ||
1189  | 
    		    !msg->msg_e) { | 
    ||
1190  | 
    			log_debug("%s: INVALID_KE_PAYLOAD not encrypted", | 
    ||
1191  | 
    __func__);  | 
    ||
1192  | 
    return (-1);  | 
    ||
1193  | 
    }  | 
    ||
1194  | 
    		if (len != sizeof(group)) { | 
    ||
1195  | 
    			log_debug("%s: malformed payload: group size mismatch" | 
    ||
1196  | 
    " (%zu != %zu)", __func__, len, sizeof(group));  | 
    ||
1197  | 
    return (-1);  | 
    ||
1198  | 
    }  | 
    ||
1199  | 
    /* XXX chould also happen for PFS */  | 
    ||
1200  | 
    		if (!msg->msg_sa->sa_hdr.sh_initiator) { | 
    ||
1201  | 
    			log_debug("%s: not an initiator", __func__); | 
    ||
1202  | 
    sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED);  | 
    ||
1203  | 
    msg->msg_sa = NULL;  | 
    ||
1204  | 
    return (-1);  | 
    ||
1205  | 
    }  | 
    ||
1206  | 
    memcpy(&group, buf, len);  | 
    ||
1207  | 
    group = betoh16(group);  | 
    ||
1208  | 
    		if (group_getid(group) == NULL) { | 
    ||
1209  | 
    			log_debug("%s: unable to select DH group %u", __func__, | 
    ||
1210  | 
    group);  | 
    ||
1211  | 
    return (-1);  | 
    ||
1212  | 
    }  | 
    ||
1213  | 
    msg->msg_policy->pol_peerdh = group;  | 
    ||
1214  | 
    		log_debug("%s: responder selected DH group %u", __func__, | 
    ||
1215  | 
    group);  | 
    ||
1216  | 
    sa_state(env, msg->msg_sa, IKEV2_STATE_CLOSED);  | 
    ||
1217  | 
    msg->msg_sa = NULL;  | 
    ||
1218  | 
    |||
1219  | 
    /*  | 
    ||
1220  | 
    * XXX should also happen for PFS so we have to check state.  | 
    ||
1221  | 
    */  | 
    ||
1222  | 
    timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL);  | 
    ||
1223  | 
    timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL);  | 
    ||
1224  | 
    break;  | 
    ||
1225  | 
    case IKEV2_N_NO_ADDITIONAL_SAS:  | 
    ||
1226  | 
    		if (!msg->msg_e) { | 
    ||
1227  | 
    			log_debug("%s: NO_ADDITIONAL_SAS not encrypted", | 
    ||
1228  | 
    __func__);  | 
    ||
1229  | 
    return (-1);  | 
    ||
1230  | 
    }  | 
    ||
1231  | 
    /* This makes sense for Child SAs only atm */  | 
    ||
1232  | 
    		if (msg->msg_sa->sa_stateflags & IKED_REQ_CHILDSA) { | 
    ||
1233  | 
    ikev2_disable_rekeying(env, msg->msg_sa);  | 
    ||
1234  | 
    msg->msg_sa->sa_stateflags &= ~IKED_REQ_CHILDSA;  | 
    ||
1235  | 
    }  | 
    ||
1236  | 
    break;  | 
    ||
1237  | 
    case IKEV2_N_REKEY_SA:  | 
    ||
1238  | 
    		if (!msg->msg_e) { | 
    ||
1239  | 
    			log_debug("%s: N_REKEY_SA not encrypted", __func__); | 
    ||
1240  | 
    return (-1);  | 
    ||
1241  | 
    }  | 
    ||
1242  | 
    		if (len != n.n_spisize) { | 
    ||
1243  | 
    			log_debug("%s: malformed notification", __func__); | 
    ||
1244  | 
    return (-1);  | 
    ||
1245  | 
    }  | 
    ||
1246  | 
    rekey = &msg->msg_parent->msg_rekey;  | 
    ||
1247  | 
    		if (rekey->spi != 0) { | 
    ||
1248  | 
    			log_debug("%s: rekeying of multiple SAs not supported", | 
    ||
1249  | 
    __func__);  | 
    ||
1250  | 
    return (-1);  | 
    ||
1251  | 
    }  | 
    ||
1252  | 
    		switch (n.n_spisize) { | 
    ||
1253  | 
    case 4:  | 
    ||
1254  | 
    memcpy(&spi32, buf, len);  | 
    ||
1255  | 
    rekey->spi = betoh32(spi32);  | 
    ||
1256  | 
    break;  | 
    ||
1257  | 
    case 8:  | 
    ||
1258  | 
    memcpy(&spi64, buf, len);  | 
    ||
1259  | 
    rekey->spi = betoh64(spi64);  | 
    ||
1260  | 
    break;  | 
    ||
1261  | 
    default:  | 
    ||
1262  | 
    			log_debug("%s: invalid spi size %d", __func__, | 
    ||
1263  | 
    n.n_spisize);  | 
    ||
1264  | 
    return (-1);  | 
    ||
1265  | 
    }  | 
    ||
1266  | 
    rekey->spi_size = n.n_spisize;  | 
    ||
1267  | 
    rekey->spi_protoid = n.n_protoid;  | 
    ||
1268  | 
    |||
1269  | 
    		log_debug("%s: rekey %s spi %s", __func__, | 
    ||
1270  | 
    print_map(n.n_protoid, ikev2_saproto_map),  | 
    ||
1271  | 
    print_spi(rekey->spi, n.n_spisize));  | 
    ||
1272  | 
    break;  | 
    ||
1273  | 
    case IKEV2_N_IPCOMP_SUPPORTED:  | 
    ||
1274  | 
    		if (!msg->msg_e) { | 
    ||
1275  | 
    			log_debug("%s: N_IPCOMP_SUPPORTED not encrypted", | 
    ||
1276  | 
    __func__);  | 
    ||
1277  | 
    return (-1);  | 
    ||
1278  | 
    }  | 
    ||
1279  | 
    		if (len < sizeof(cpi) + sizeof(transform)) { | 
    ||
1280  | 
    			log_debug("%s: ignoring malformed ipcomp notification", | 
    ||
1281  | 
    __func__);  | 
    ||
1282  | 
    return (0);  | 
    ||
1283  | 
    }  | 
    ||
1284  | 
    memcpy(&cpi, buf, sizeof(cpi));  | 
    ||
1285  | 
    memcpy(&transform, buf + sizeof(cpi), sizeof(transform));  | 
    ||
1286  | 
    		log_debug("%s: cpi 0x%x, transform %s, len %zu", __func__, | 
    ||
1287  | 
    betoh16(cpi), print_map(transform, ikev2_ipcomp_map), len);  | 
    ||
1288  | 
    /* we only support deflate */  | 
    ||
1289  | 
    if ((msg->msg_policy->pol_flags & IKED_POLICY_IPCOMP) &&  | 
    ||
1290  | 
    		    (transform == IKEV2_IPCOMP_DEFLATE)) { | 
    ||
1291  | 
    msg->msg_sa->sa_ipcomp = transform;  | 
    ||
1292  | 
    msg->msg_sa->sa_cpi_out = betoh16(cpi);  | 
    ||
1293  | 
    }  | 
    ||
1294  | 
    break;  | 
    ||
1295  | 
    case IKEV2_N_COOKIE:  | 
    ||
1296  | 
    		if (msg->msg_e) { | 
    ||
1297  | 
    			log_debug("%s: N_COOKIE encrypted", | 
    ||
1298  | 
    __func__);  | 
    ||
1299  | 
    return (-1);  | 
    ||
1300  | 
    }  | 
    ||
1301  | 
    		if (len < IKED_COOKIE_MIN || len > IKED_COOKIE_MAX) { | 
    ||
1302  | 
    			log_debug("%s: ignoring malformed cookie" | 
    ||
1303  | 
    " notification: %zu", __func__, len);  | 
    ||
1304  | 
    return (0);  | 
    ||
1305  | 
    }  | 
    ||
1306  | 
    		log_debug("%s: received cookie, len %zu", __func__, len); | 
    ||
1307  | 
    print_hex(buf, 0, len);  | 
    ||
1308  | 
    |||
1309  | 
    ibuf_release(msg->msg_cookie);  | 
    ||
1310  | 
    		if ((msg->msg_cookie = ibuf_new(buf, len)) == NULL) { | 
    ||
1311  | 
    			log_debug("%s: failed to get peer cookie", __func__); | 
    ||
1312  | 
    return (-1);  | 
    ||
1313  | 
    }  | 
    ||
1314  | 
    msg->msg_parent->msg_cookie = msg->msg_cookie;  | 
    ||
1315  | 
    break;  | 
    ||
1316  | 
    case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:  | 
    ||
1317  | 
    		if (msg->msg_e) { | 
    ||
1318  | 
    			log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted", | 
    ||
1319  | 
    __func__);  | 
    ||
1320  | 
    return (-1);  | 
    ||
1321  | 
    }  | 
    ||
1322  | 
    if (msg->msg_sa == NULL ||  | 
    ||
1323  | 
    		    msg->msg_sa->sa_sigsha2) { | 
    ||
1324  | 
    			log_debug("%s: SIGNATURE_HASH_ALGORITHMS: no SA or " | 
    ||
1325  | 
    "duplicate notify", __func__);  | 
    ||
1326  | 
    return (-1);  | 
    ||
1327  | 
    }  | 
    ||
1328  | 
    if (len < sizeof(signature_hash) ||  | 
    ||
1329  | 
    		    len % sizeof(signature_hash)) { | 
    ||
1330  | 
    			log_debug("%s: malformed signature hash notification" | 
    ||
1331  | 
    "(%zu bytes)", __func__, len);  | 
    ||
1332  | 
    return (0);  | 
    ||
1333  | 
    }  | 
    ||
1334  | 
    		while (len >= sizeof(signature_hash)) { | 
    ||
1335  | 
    memcpy(&signature_hash, buf, sizeof(signature_hash));  | 
    ||
1336  | 
    signature_hash = betoh16(signature_hash);  | 
    ||
1337  | 
    			log_debug("%s: signature hash %s (%x)", __func__, | 
    ||
1338  | 
    print_map(signature_hash, ikev2_sighash_map),  | 
    ||
1339  | 
    signature_hash);  | 
    ||
1340  | 
    len -= sizeof(signature_hash);  | 
    ||
1341  | 
    buf += sizeof(signature_hash);  | 
    ||
1342  | 
    if (signature_hash == IKEV2_SIGHASH_SHA2_256)  | 
    ||
1343  | 
    msg->msg_sa->sa_sigsha2 = 1;  | 
    ||
1344  | 
    }  | 
    ||
1345  | 
    break;  | 
    ||
1346  | 
    }  | 
    ||
1347  | 
    |||
1348  | 
    return (0);  | 
    ||
1349  | 
    250235690  | 
    }  | 
    |
1350  | 
    |||
1351  | 
    int  | 
    ||
1352  | 
    ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1353  | 
    struct ikev2_payload *pld, struct ikev2_delete *del)  | 
    ||
1354  | 
    { | 
    ||
1355  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1356  | 
    size_t pld_length;  | 
    ||
1357  | 
    |||
1358  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
1359  | 
    	if (pld_length < sizeof(*pld) + sizeof(*del)) { | 
    ||
1360  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
1361  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1362  | 
    sizeof(*pld) + sizeof(*del));  | 
    ||
1363  | 
    return (-1);  | 
    ||
1364  | 
    }  | 
    ||
1365  | 
    |||
1366  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1367  | 
    	if (left < sizeof(*del)) { | 
    ||
1368  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
1369  | 
    "(%zu < %zu)", __func__, left, sizeof(*del));  | 
    ||
1370  | 
    return (-1);  | 
    ||
1371  | 
    }  | 
    ||
1372  | 
    memcpy(del, msgbuf + offset, sizeof(*del));  | 
    ||
1373  | 
    |||
1374  | 
    return (0);  | 
    ||
1375  | 
    }  | 
    ||
1376  | 
    |||
1377  | 
    int  | 
    ||
1378  | 
    ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1379  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
1380  | 
    { | 
    ||
1381  | 
    struct iked_childsa **peersas = NULL;  | 
    ||
1382  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    ||
1383  | 
    struct ikev2_delete del, *localdel;  | 
    ||
1384  | 
    struct ibuf *resp = NULL;  | 
    ||
1385  | 
    uint64_t *localspi = NULL;  | 
    ||
1386  | 
    uint64_t spi64, spi = 0;  | 
    ||
1387  | 
    uint32_t spi32;  | 
    ||
1388  | 
    uint8_t *buf, *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1389  | 
    size_t found = 0, failed = 0;  | 
    ||
1390  | 
    int cnt, i, len, sz, ret = -1;  | 
    ||
1391  | 
    |||
1392  | 
    /* Skip if it's a response, then we don't have to deal with it */  | 
    ||
1393  | 
    if (ikev2_msg_frompeer(msg) &&  | 
    ||
1394  | 
    msg->msg_parent->msg_response)  | 
    ||
1395  | 
    return (0);  | 
    ||
1396  | 
    |||
1397  | 
    if (ikev2_validate_delete(msg, offset, left, pld, &del))  | 
    ||
1398  | 
    return (-1);  | 
    ||
1399  | 
    cnt = betoh16(del.del_nspi);  | 
    ||
1400  | 
    sz = del.del_spisize;  | 
    ||
1401  | 
    |||
1402  | 
    	log_debug("%s: proto %s spisize %d nspi %d", | 
    ||
1403  | 
    __func__, print_map(del.del_protoid, ikev2_saproto_map),  | 
    ||
1404  | 
    sz, cnt);  | 
    ||
1405  | 
    |||
1406  | 
    buf = msgbuf + offset + sizeof(del);  | 
    ||
1407  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(del);  | 
    ||
1408  | 
    |||
1409  | 
    print_hex(buf, 0, len);  | 
    ||
1410  | 
    |||
1411  | 
    	switch (sz) { | 
    ||
1412  | 
    case 4:  | 
    ||
1413  | 
    case 8:  | 
    ||
1414  | 
    break;  | 
    ||
1415  | 
    default:  | 
    ||
1416  | 
    		if (del.del_protoid != IKEV2_SAPROTO_IKE) { | 
    ||
1417  | 
    			log_debug("%s: invalid SPI size", __func__); | 
    ||
1418  | 
    return (-1);  | 
    ||
1419  | 
    }  | 
    ||
1420  | 
    		if (ikev2_msg_frompeer(msg)) { | 
    ||
1421  | 
    /* Send an empty informational response */  | 
    ||
1422  | 
    if ((resp = ibuf_static()) == NULL)  | 
    ||
1423  | 
    goto done;  | 
    ||
1424  | 
    ret = ikev2_send_ike_e(env, sa, resp,  | 
    ||
1425  | 
    IKEV2_PAYLOAD_NONE,  | 
    ||
1426  | 
    IKEV2_EXCHANGE_INFORMATIONAL, 1);  | 
    ||
1427  | 
    msg->msg_parent->msg_responded = 1;  | 
    ||
1428  | 
    ibuf_release(resp);  | 
    ||
1429  | 
    ikev2_ikesa_recv_delete(env, sa);  | 
    ||
1430  | 
    		} else { | 
    ||
1431  | 
    /*  | 
    ||
1432  | 
    * We're sending a delete message. Upper layer  | 
    ||
1433  | 
    * must deal with deletion of the IKE SA.  | 
    ||
1434  | 
    */  | 
    ||
1435  | 
    ret = 0;  | 
    ||
1436  | 
    }  | 
    ||
1437  | 
    return (ret);  | 
    ||
1438  | 
    }  | 
    ||
1439  | 
    |||
1440  | 
    	if ((len / sz) != cnt) { | 
    ||
1441  | 
    		log_debug("%s: invalid payload length %d/%d != %d", | 
    ||
1442  | 
    __func__, len, sz, cnt);  | 
    ||
1443  | 
    return (-1);  | 
    ||
1444  | 
    }  | 
    ||
1445  | 
    |||
1446  | 
    if (ikev2_msg_frompeer(msg) &&  | 
    ||
1447  | 
    ((peersas = calloc(cnt, sizeof(struct iked_childsa *))) == NULL ||  | 
    ||
1448  | 
    	     (localspi = calloc(cnt, sizeof(uint64_t))) == NULL)) { | 
    ||
1449  | 
    		log_warn("%s", __func__); | 
    ||
1450  | 
    goto done;  | 
    ||
1451  | 
    }  | 
    ||
1452  | 
    |||
1453  | 
    	for (i = 0; i < cnt; i++) { | 
    ||
1454  | 
    		switch (sz) { | 
    ||
1455  | 
    case 4:  | 
    ||
1456  | 
    memcpy(&spi32, buf + (i * sz), sizeof(spi32));  | 
    ||
1457  | 
    spi = betoh32(spi32);  | 
    ||
1458  | 
    break;  | 
    ||
1459  | 
    case 8:  | 
    ||
1460  | 
    memcpy(&spi64, buf + (i * sz), sizeof(spi64));  | 
    ||
1461  | 
    spi = betoh64(spi64);  | 
    ||
1462  | 
    break;  | 
    ||
1463  | 
    }  | 
    ||
1464  | 
    |||
1465  | 
    		log_debug("%s: spi %s", __func__, print_spi(spi, sz)); | 
    ||
1466  | 
    |||
1467  | 
    if (peersas == NULL || sa == NULL)  | 
    ||
1468  | 
    continue;  | 
    ||
1469  | 
    |||
1470  | 
    if ((peersas[i] = childsa_lookup(sa, spi,  | 
    ||
1471  | 
    		    del.del_protoid)) == NULL) { | 
    ||
1472  | 
    			log_warnx("%s: CHILD SA doesn't exist for spi %s", | 
    ||
1473  | 
    __func__, print_spi(spi, del.del_spisize));  | 
    ||
1474  | 
    continue;  | 
    ||
1475  | 
    }  | 
    ||
1476  | 
    |||
1477  | 
    if (ikev2_childsa_delete(env, sa, del.del_protoid, spi,  | 
    ||
1478  | 
    &localspi[i], 0) == -1)  | 
    ||
1479  | 
    failed++;  | 
    ||
1480  | 
    else  | 
    ||
1481  | 
    found++;  | 
    ||
1482  | 
    |||
1483  | 
    /*  | 
    ||
1484  | 
    * Flows are left in the require mode so that it would be  | 
    ||
1485  | 
    * possible to quickly negotiate a new Child SA  | 
    ||
1486  | 
    */  | 
    ||
1487  | 
    }  | 
    ||
1488  | 
    |||
1489  | 
    /* Parsed outgoing message? */  | 
    ||
1490  | 
    if (!ikev2_msg_frompeer(msg))  | 
    ||
1491  | 
    goto done;  | 
    ||
1492  | 
    |||
1493  | 
    	if (msg->msg_parent->msg_response) { | 
    ||
1494  | 
    ret = 0;  | 
    ||
1495  | 
    goto done;  | 
    ||
1496  | 
    }  | 
    ||
1497  | 
    |||
1498  | 
    /* Response to the INFORMATIONAL with Delete payload */  | 
    ||
1499  | 
    |||
1500  | 
    if ((resp = ibuf_static()) == NULL)  | 
    ||
1501  | 
    goto done;  | 
    ||
1502  | 
    |||
1503  | 
    	if (found) { | 
    ||
1504  | 
    if ((localdel = ibuf_advance(resp, sizeof(*localdel))) == NULL)  | 
    ||
1505  | 
    goto done;  | 
    ||
1506  | 
    |||
1507  | 
    localdel->del_protoid = del.del_protoid;  | 
    ||
1508  | 
    localdel->del_spisize = del.del_spisize;  | 
    ||
1509  | 
    localdel->del_nspi = htobe16(found);  | 
    ||
1510  | 
    |||
1511  | 
    		for (i = 0; i < cnt; i++) { | 
    ||
1512  | 
    if (localspi[i] == 0) /* happens if found < cnt */  | 
    ||
1513  | 
    continue;  | 
    ||
1514  | 
    			switch (sz) { | 
    ||
1515  | 
    case 4:  | 
    ||
1516  | 
    spi32 = htobe32(localspi[i]);  | 
    ||
1517  | 
    if (ibuf_add(resp, &spi32, sizeof(spi32)) != 0)  | 
    ||
1518  | 
    goto done;  | 
    ||
1519  | 
    break;  | 
    ||
1520  | 
    case 8:  | 
    ||
1521  | 
    spi64 = htobe64(localspi[i]);  | 
    ||
1522  | 
    if (ibuf_add(resp, &spi64, sizeof(spi64)) != 0)  | 
    ||
1523  | 
    goto done;  | 
    ||
1524  | 
    break;  | 
    ||
1525  | 
    }  | 
    ||
1526  | 
    }  | 
    ||
1527  | 
    |||
1528  | 
    		log_warnx("%s: deleted %zu spis", __func__, found); | 
    ||
1529  | 
    }  | 
    ||
1530  | 
    |||
1531  | 
    	if (found) { | 
    ||
1532  | 
    ret = ikev2_send_ike_e(env, sa, resp, IKEV2_PAYLOAD_DELETE,  | 
    ||
1533  | 
    IKEV2_EXCHANGE_INFORMATIONAL, 1);  | 
    ||
1534  | 
    msg->msg_parent->msg_responded = 1;  | 
    ||
1535  | 
    	} else { | 
    ||
1536  | 
    /* XXX should we send an INVALID_SPI notification? */  | 
    ||
1537  | 
    ret = 0;  | 
    ||
1538  | 
    }  | 
    ||
1539  | 
    |||
1540  | 
    done:  | 
    ||
1541  | 
    free(localspi);  | 
    ||
1542  | 
    free(peersas);  | 
    ||
1543  | 
    ibuf_release(resp);  | 
    ||
1544  | 
    return (ret);  | 
    ||
1545  | 
    }  | 
    ||
1546  | 
    |||
1547  | 
    int  | 
    ||
1548  | 
    ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1549  | 
    struct ikev2_payload *pld, struct ikev2_tsp *tsp)  | 
    ||
1550  | 
    { | 
    ||
1551  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1552  | 
    size_t pld_length;  | 
    ||
1553  | 
    |||
1554  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
1555  | 
    	if (pld_length < sizeof(*pld) + sizeof(*tsp)) { | 
    ||
1556  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
1557  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1558  | 
    sizeof(*pld) + sizeof(*tsp));  | 
    ||
1559  | 
    return (-1);  | 
    ||
1560  | 
    }  | 
    ||
1561  | 
    |||
1562  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1563  | 
    	if (left < sizeof(*tsp)) { | 
    ||
1564  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
1565  | 
    "(%zu < %zu)", __func__, left, sizeof(*tsp));  | 
    ||
1566  | 
    return (-1);  | 
    ||
1567  | 
    }  | 
    ||
1568  | 
    memcpy(tsp, msgbuf + offset, sizeof(*tsp));  | 
    ||
1569  | 
    |||
1570  | 
    return (0);  | 
    ||
1571  | 
    }  | 
    ||
1572  | 
    |||
1573  | 
    int  | 
    ||
1574  | 
    ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1575  | 
    struct iked_message *msg, size_t offset, size_t left, unsigned int payload)  | 
    ||
1576  | 
    { | 
    ||
1577  | 
    struct ikev2_tsp tsp;  | 
    ||
1578  | 
    struct ikev2_ts ts;  | 
    ||
1579  | 
    size_t len, i;  | 
    ||
1580  | 
    struct sockaddr_in s4;  | 
    ||
1581  | 
    struct sockaddr_in6 s6;  | 
    ||
1582  | 
    uint8_t buf[2][128];  | 
    ||
1583  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1584  | 
    |||
1585  | 
    if (ikev2_validate_ts(msg, offset, left, pld, &tsp))  | 
    ||
1586  | 
    return (-1);  | 
    ||
1587  | 
    offset += sizeof(tsp);  | 
    ||
1588  | 
    |||
1589  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(tsp);  | 
    ||
1590  | 
    |||
1591  | 
    	log_debug("%s: count %d length %zu", __func__, | 
    ||
1592  | 
    tsp.tsp_count, len);  | 
    ||
1593  | 
    |||
1594  | 
    	for (i = 0; i < tsp.tsp_count; i++) { | 
    ||
1595  | 
    memcpy(&ts, msgbuf + offset, sizeof(ts));  | 
    ||
1596  | 
    |||
1597  | 
    		log_debug("%s: type %s protoid %u length %d " | 
    ||
1598  | 
    "startport %u endport %u", __func__,  | 
    ||
1599  | 
    print_map(ts.ts_type, ikev2_ts_map),  | 
    ||
1600  | 
    ts.ts_protoid, betoh16(ts.ts_length),  | 
    ||
1601  | 
    betoh16(ts.ts_startport),  | 
    ||
1602  | 
    betoh16(ts.ts_endport));  | 
    ||
1603  | 
    |||
1604  | 
    		switch (ts.ts_type) { | 
    ||
1605  | 
    case IKEV2_TS_IPV4_ADDR_RANGE:  | 
    ||
1606  | 
    bzero(&s4, sizeof(s4));  | 
    ||
1607  | 
    s4.sin_family = AF_INET;  | 
    ||
1608  | 
    s4.sin_len = sizeof(s4);  | 
    ||
1609  | 
    memcpy(&s4.sin_addr.s_addr,  | 
    ||
1610  | 
    msgbuf + offset + sizeof(ts), 4);  | 
    ||
1611  | 
    print_host((struct sockaddr *)&s4,  | 
    ||
1612  | 
    (char *)buf[0], sizeof(buf[0]));  | 
    ||
1613  | 
    memcpy(&s4.sin_addr.s_addr,  | 
    ||
1614  | 
    msgbuf + offset + sizeof(ts) + 4, 4);  | 
    ||
1615  | 
    print_host((struct sockaddr *)&s4,  | 
    ||
1616  | 
    (char *)buf[1], sizeof(buf[1]));  | 
    ||
1617  | 
    			log_debug("%s: start %s end %s", __func__, | 
    ||
1618  | 
    buf[0], buf[1]);  | 
    ||
1619  | 
    break;  | 
    ||
1620  | 
    case IKEV2_TS_IPV6_ADDR_RANGE:  | 
    ||
1621  | 
    bzero(&s6, sizeof(s6));  | 
    ||
1622  | 
    s6.sin6_family = AF_INET6;  | 
    ||
1623  | 
    s6.sin6_len = sizeof(s6);  | 
    ||
1624  | 
    memcpy(&s6.sin6_addr,  | 
    ||
1625  | 
    msgbuf + offset + sizeof(ts), 16);  | 
    ||
1626  | 
    print_host((struct sockaddr *)&s6,  | 
    ||
1627  | 
    (char *)buf[0], sizeof(buf[0]));  | 
    ||
1628  | 
    memcpy(&s6.sin6_addr,  | 
    ||
1629  | 
    msgbuf + offset + sizeof(ts) + 16, 16);  | 
    ||
1630  | 
    print_host((struct sockaddr *)&s6,  | 
    ||
1631  | 
    (char *)buf[1], sizeof(buf[1]));  | 
    ||
1632  | 
    			log_debug("%s: start %s end %s", __func__, | 
    ||
1633  | 
    buf[0], buf[1]);  | 
    ||
1634  | 
    break;  | 
    ||
1635  | 
    default:  | 
    ||
1636  | 
    break;  | 
    ||
1637  | 
    }  | 
    ||
1638  | 
    |||
1639  | 
    offset += betoh16(ts.ts_length);  | 
    ||
1640  | 
    }  | 
    ||
1641  | 
    |||
1642  | 
    return (0);  | 
    ||
1643  | 
    }  | 
    ||
1644  | 
    |||
1645  | 
    int  | 
    ||
1646  | 
    ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1647  | 
    struct iked_message *msg, size_t offset)  | 
    ||
1648  | 
    { | 
    ||
1649  | 
    136680  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    |
1650  | 
    struct ibuf *e = NULL;  | 
    ||
1651  | 
    68340  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    |
1652  | 
    68340  | 
    struct iked_message emsg;  | 
    |
1653  | 
    uint8_t *buf;  | 
    ||
1654  | 
    size_t len;  | 
    ||
1655  | 
    int ret = -1;  | 
    ||
1656  | 
    |||
1657  | 
    68340  | 
    buf = msgbuf + offset;  | 
    |
1658  | 
    68340  | 
    len = betoh16(pld->pld_length) - sizeof(*pld);  | 
    |
1659  | 
    |||
1660  | 
    ✓✗ | 68340  | 
    if ((e = ibuf_new(buf, len)) == NULL)  | 
    
1661  | 
    goto done;  | 
    ||
1662  | 
    |||
1663  | 
    ✗✓ | 68340  | 
    	if (ikev2_msg_frompeer(msg)) { | 
    
1664  | 
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);  | 
    ||
1665  | 
    	} else { | 
    ||
1666  | 
    68340  | 
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;  | 
    |
1667  | 
    68340  | 
    e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);  | 
    |
1668  | 
    68340  | 
    sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;  | 
    |
1669  | 
    }  | 
    ||
1670  | 
    |||
1671  | 
    ✗✓ | 68340  | 
    if (e == NULL)  | 
    
1672  | 
    goto done;  | 
    ||
1673  | 
    |||
1674  | 
    /*  | 
    ||
1675  | 
    * Parse decrypted payload  | 
    ||
1676  | 
    */  | 
    ||
1677  | 
    bzero(&emsg, sizeof(emsg));  | 
    ||
1678  | 
    memcpy(&emsg, msg, sizeof(*msg));  | 
    ||
1679  | 
    emsg.msg_data = e;  | 
    ||
1680  | 
    emsg.msg_e = 1;  | 
    ||
1681  | 
    emsg.msg_parent = msg;  | 
    ||
1682  | 
    TAILQ_INIT(&emsg.msg_proposals);  | 
    ||
1683  | 
    |||
1684  | 
    ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),  | 
    ||
1685  | 
    pld->pld_nextpayload);  | 
    ||
1686  | 
    |||
1687  | 
    done:  | 
    ||
1688  | 
    68340  | 
    ibuf_release(e);  | 
    |
1689  | 
    |||
1690  | 
    68340  | 
    return (ret);  | 
    |
1691  | 
    68340  | 
    }  | 
    |
1692  | 
    |||
1693  | 
    int  | 
    ||
1694  | 
    ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1695  | 
    struct ikev2_payload *pld, struct ikev2_cp *cp)  | 
    ||
1696  | 
    { | 
    ||
1697  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1698  | 
    size_t pld_length;  | 
    ||
1699  | 
    |||
1700  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
1701  | 
    	if (pld_length < sizeof(*pld) + sizeof(*cp)) { | 
    ||
1702  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
1703  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1704  | 
    sizeof(*pld) + sizeof(*cp));  | 
    ||
1705  | 
    return (-1);  | 
    ||
1706  | 
    }  | 
    ||
1707  | 
    |||
1708  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1709  | 
    	if (left < sizeof(*cp)) { | 
    ||
1710  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
1711  | 
    "(%zu < %zu)", __func__, left, sizeof(*cp));  | 
    ||
1712  | 
    return (-1);  | 
    ||
1713  | 
    }  | 
    ||
1714  | 
    memcpy(cp, msgbuf + offset, sizeof(*cp));  | 
    ||
1715  | 
    |||
1716  | 
    return (0);  | 
    ||
1717  | 
    }  | 
    ||
1718  | 
    |||
1719  | 
    int  | 
    ||
1720  | 
    ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1721  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
1722  | 
    { | 
    ||
1723  | 
    struct ikev2_cp cp;  | 
    ||
1724  | 
    struct ikev2_cfg *cfg;  | 
    ||
1725  | 
    uint8_t *buf;  | 
    ||
1726  | 
    size_t len, i;  | 
    ||
1727  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1728  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    ||
1729  | 
    |||
1730  | 
    if (ikev2_validate_cp(msg, offset, left, pld, &cp))  | 
    ||
1731  | 
    return (-1);  | 
    ||
1732  | 
    offset += sizeof(cp);  | 
    ||
1733  | 
    |||
1734  | 
    buf = msgbuf + offset;  | 
    ||
1735  | 
    len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cp);  | 
    ||
1736  | 
    |||
1737  | 
    	log_debug("%s: type %s length %zu", | 
    ||
1738  | 
    __func__, print_map(cp.cp_type, ikev2_cp_map), len);  | 
    ||
1739  | 
    print_hex(buf, 0, len);  | 
    ||
1740  | 
    |||
1741  | 
    	for (i = 0; i < len;) { | 
    ||
1742  | 
    cfg = (struct ikev2_cfg *)(buf + i);  | 
    ||
1743  | 
    |||
1744  | 
    		log_debug("%s: %s 0x%04x length %d", __func__, | 
    ||
1745  | 
    print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),  | 
    ||
1746  | 
    betoh16(cfg->cfg_type),  | 
    ||
1747  | 
    betoh16(cfg->cfg_length));  | 
    ||
1748  | 
    |||
1749  | 
    i += betoh16(cfg->cfg_length) + sizeof(*cfg);  | 
    ||
1750  | 
    }  | 
    ||
1751  | 
    |||
1752  | 
    if (!ikev2_msg_frompeer(msg))  | 
    ||
1753  | 
    return (0);  | 
    ||
1754  | 
    |||
1755  | 
    if (sa)  | 
    ||
1756  | 
    sa->sa_cp = cp.cp_type;  | 
    ||
1757  | 
    |||
1758  | 
    return (0);  | 
    ||
1759  | 
    }  | 
    ||
1760  | 
    |||
1761  | 
    int  | 
    ||
1762  | 
    ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,  | 
    ||
1763  | 
    struct ikev2_payload *pld, struct eap_header *hdr)  | 
    ||
1764  | 
    { | 
    ||
1765  | 
    uint8_t *msgbuf = ibuf_data(msg->msg_data);  | 
    ||
1766  | 
    size_t pld_length;  | 
    ||
1767  | 
    |||
1768  | 
    pld_length = betoh16(pld->pld_length);  | 
    ||
1769  | 
    	if (pld_length < sizeof(*pld) + sizeof(*hdr)) { | 
    ||
1770  | 
    		log_debug("%s: malformed payload: specified length smaller " | 
    ||
1771  | 
    "than minimum size (%zu < %zu)", __func__, pld_length,  | 
    ||
1772  | 
    sizeof(*pld) + sizeof(*hdr));  | 
    ||
1773  | 
    return (-1);  | 
    ||
1774  | 
    }  | 
    ||
1775  | 
    |||
1776  | 
    /* This will actually be caught by earlier checks. */  | 
    ||
1777  | 
    	if (left < sizeof(*hdr)) { | 
    ||
1778  | 
    		log_debug("%s: malformed payload: too short for header " | 
    ||
1779  | 
    "(%zu < %zu)", __func__, left, sizeof(*hdr));  | 
    ||
1780  | 
    return (-1);  | 
    ||
1781  | 
    }  | 
    ||
1782  | 
    memcpy(hdr, msgbuf + offset, sizeof(*hdr));  | 
    ||
1783  | 
    |||
1784  | 
    return (0);  | 
    ||
1785  | 
    }  | 
    ||
1786  | 
    |||
1787  | 
    int  | 
    ||
1788  | 
    ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld,  | 
    ||
1789  | 
    struct iked_message *msg, size_t offset, size_t left)  | 
    ||
1790  | 
    { | 
    ||
1791  | 
    struct eap_header hdr;  | 
    ||
1792  | 
    struct eap_message *eap = NULL;  | 
    ||
1793  | 
    struct iked_sa *sa = msg->msg_sa;  | 
    ||
1794  | 
    size_t len;  | 
    ||
1795  | 
    |||
1796  | 
    if (ikev2_validate_eap(msg, offset, left, pld, &hdr))  | 
    ||
1797  | 
    return (-1);  | 
    ||
1798  | 
    len = betoh16(hdr.eap_length);  | 
    ||
1799  | 
    |||
1800  | 
    	if (len < sizeof(*eap)) { | 
    ||
1801  | 
    		log_info("%s: %s id %d length %d", __func__, | 
    ||
1802  | 
    print_map(hdr.eap_code, eap_code_map),  | 
    ||
1803  | 
    hdr.eap_id, betoh16(hdr.eap_length));  | 
    ||
1804  | 
    	} else { | 
    ||
1805  | 
    /* Now try to get the indicated length */  | 
    ||
1806  | 
    		if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) { | 
    ||
1807  | 
    			log_debug("%s: invalid EAP length", __func__); | 
    ||
1808  | 
    return (-1);  | 
    ||
1809  | 
    }  | 
    ||
1810  | 
    |||
1811  | 
    		log_info("%s: %s id %d length %d EAP-%s", __func__, | 
    ||
1812  | 
    print_map(eap->eap_code, eap_code_map),  | 
    ||
1813  | 
    eap->eap_id, betoh16(eap->eap_length),  | 
    ||
1814  | 
    print_map(eap->eap_type, eap_type_map));  | 
    ||
1815  | 
    |||
1816  | 
    if (eap_parse(env, sa, eap, msg->msg_response) == -1)  | 
    ||
1817  | 
    return (-1);  | 
    ||
1818  | 
    }  | 
    ||
1819  | 
    |||
1820  | 
    return (0);  | 
    ||
1821  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |