GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: ike.c,v 1.81 2015/12/09 21:41:50 naddy Exp $ */ |
||
2 |
/* |
||
3 |
* Copyright (c) 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> |
||
4 |
* |
||
5 |
* Permission to use, copy, modify, and distribute this software for any |
||
6 |
* purpose with or without fee is hereby granted, provided that the above |
||
7 |
* copyright notice and this permission notice appear in all copies. |
||
8 |
* |
||
9 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||
10 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||
11 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||
12 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
13 |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||
14 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||
15 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||
16 |
*/ |
||
17 |
|||
18 |
#include <sys/types.h> |
||
19 |
#include <sys/socket.h> |
||
20 |
#include <sys/stat.h> |
||
21 |
#include <sys/queue.h> |
||
22 |
#include <netinet/in.h> |
||
23 |
#include <netdb.h> |
||
24 |
#include <arpa/inet.h> |
||
25 |
|||
26 |
#include <err.h> |
||
27 |
#include <fcntl.h> |
||
28 |
#include <stdio.h> |
||
29 |
#include <stdlib.h> |
||
30 |
#include <string.h> |
||
31 |
#include <unistd.h> |
||
32 |
#include <limits.h> |
||
33 |
|||
34 |
#include "ipsecctl.h" |
||
35 |
|||
36 |
static void ike_section_general(struct ipsec_rule *, FILE *); |
||
37 |
static void ike_section_peer(struct ipsec_rule *, FILE *); |
||
38 |
static void ike_section_ids(struct ipsec_rule *, FILE *); |
||
39 |
static void ike_section_ipsec(struct ipsec_rule *, FILE *); |
||
40 |
static int ike_section_p1(struct ipsec_rule *, FILE *); |
||
41 |
static int ike_section_p2(struct ipsec_rule *, FILE *); |
||
42 |
static void ike_section_p2ids(struct ipsec_rule *, FILE *); |
||
43 |
static int ike_connect(struct ipsec_rule *, FILE *); |
||
44 |
static int ike_gen_config(struct ipsec_rule *, FILE *); |
||
45 |
static int ike_delete_config(struct ipsec_rule *, FILE *); |
||
46 |
static void ike_setup_ids(struct ipsec_rule *); |
||
47 |
|||
48 |
int ike_print_config(struct ipsec_rule *, int); |
||
49 |
int ike_ipsec_establish(int, struct ipsec_rule *, const char *); |
||
50 |
|||
51 |
#define SET "C set " |
||
52 |
#define ADD "C add " |
||
53 |
#define DELETE "C rms " |
||
54 |
#define RMV "C rmv " |
||
55 |
|||
56 |
#define CONF_DFLT_DYNAMIC_DPD_CHECK_INTERVAL 5 |
||
57 |
#define CONF_DFLT_DYNAMIC_CHECK_INTERVAL 30 |
||
58 |
|||
59 |
char *ike_id_types[] = { |
||
60 |
"", "", "IPV4_ADDR", "IPV6_ADDR", "FQDN", "USER_FQDN" |
||
61 |
}; |
||
62 |
|||
63 |
static void |
||
64 |
ike_section_general(struct ipsec_rule *r, FILE *fd) |
||
65 |
{ |
||
66 |
✓✓ | 218 |
if (r->ikemode == IKE_DYNAMIC) { |
67 |
2 |
fprintf(fd, SET "[General]:Check-interval=%d force\n", |
|
68 |
CONF_DFLT_DYNAMIC_CHECK_INTERVAL); |
||
69 |
2 |
fprintf(fd, SET "[General]:DPD-check-interval=%d force\n", |
|
70 |
CONF_DFLT_DYNAMIC_DPD_CHECK_INTERVAL); |
||
71 |
2 |
} |
|
72 |
109 |
} |
|
73 |
|||
74 |
static void |
||
75 |
ike_section_peer(struct ipsec_rule *r, FILE *fd) |
||
76 |
{ |
||
77 |
✓✓ | 218 |
if (r->peer) |
78 |
178 |
fprintf(fd, SET "[Phase 1]:%s=%s force\n", r->peer->name, |
|
79 |
89 |
r->p1name); |
|
80 |
else |
||
81 |
20 |
fprintf(fd, SET "[Phase 1]:Default=%s force\n", r->p1name); |
|
82 |
109 |
fprintf(fd, SET "[%s]:Phase=1 force\n", r->p1name); |
|
83 |
✓✓ | 109 |
if (r->peer) |
84 |
178 |
fprintf(fd, SET "[%s]:Address=%s force\n", r->p1name, |
|
85 |
89 |
r->peer->name); |
|
86 |
✓✓ | 109 |
if (r->local) |
87 |
18 |
fprintf(fd, SET "[%s]:Local-address=%s force\n", r->p1name, |
|
88 |
9 |
r->local->name); |
|
89 |
✓✓ | 109 |
if (r->ikeauth->type == IKE_AUTH_PSK) |
90 |
14 |
fprintf(fd, SET "[%s]:Authentication=%s force\n", r->p1name, |
|
91 |
7 |
r->ikeauth->string); |
|
92 |
109 |
} |
|
93 |
|||
94 |
static void |
||
95 |
ike_section_ids(struct ipsec_rule *r, FILE *fd) |
||
96 |
{ |
||
97 |
218 |
char myname[HOST_NAME_MAX+1]; |
|
98 |
|||
99 |
✗✓ | 109 |
if (r->auth == NULL) |
100 |
return; |
||
101 |
|||
102 |
✓✓✗✓ |
111 |
if (r->ikemode == IKE_DYNAMIC && r->auth->srcid == NULL) { |
103 |
if (gethostname(myname, sizeof(myname)) == -1) |
||
104 |
err(1, "ike_section_ids: gethostname"); |
||
105 |
if ((r->auth->srcid = strdup(myname)) == NULL) |
||
106 |
err(1, "ike_section_ids: strdup"); |
||
107 |
r->auth->srcid_type = ID_FQDN; |
||
108 |
} |
||
109 |
✓✓ | 109 |
if (r->auth->srcid) { |
110 |
23 |
fprintf(fd, SET "[%s]:ID=id-%s force\n", r->p1name, |
|
111 |
r->auth->srcid); |
||
112 |
46 |
fprintf(fd, SET "[id-%s]:ID-type=%s force\n", r->auth->srcid, |
|
113 |
23 |
ike_id_types[r->auth->srcid_type]); |
|
114 |
✓✓✓✓ |
44 |
if (r->auth->srcid_type == ID_IPV4 || |
115 |
21 |
r->auth->srcid_type == ID_IPV6) |
|
116 |
4 |
fprintf(fd, SET "[id-%s]:Address=%s force\n", |
|
117 |
4 |
r->auth->srcid, r->auth->srcid); |
|
118 |
else |
||
119 |
19 |
fprintf(fd, SET "[id-%s]:Name=%s force\n", |
|
120 |
19 |
r->auth->srcid, r->auth->srcid); |
|
121 |
} |
||
122 |
✓✓ | 109 |
if (r->auth->dstid) { |
123 |
21 |
fprintf(fd, SET "[%s]:Remote-ID=id-%s force\n", r->p1name, |
|
124 |
r->auth->dstid); |
||
125 |
42 |
fprintf(fd, SET "[id-%s]:ID-type=%s force\n", r->auth->dstid, |
|
126 |
21 |
ike_id_types[r->auth->dstid_type]); |
|
127 |
✓✓✓✓ |
40 |
if (r->auth->dstid_type == ID_IPV4 || |
128 |
19 |
r->auth->dstid_type == ID_IPV6) |
|
129 |
4 |
fprintf(fd, SET "[id-%s]:Address=%s force\n", |
|
130 |
4 |
r->auth->dstid, r->auth->dstid); |
|
131 |
else |
||
132 |
17 |
fprintf(fd, SET "[id-%s]:Name=%s force\n", |
|
133 |
17 |
r->auth->dstid, r->auth->dstid); |
|
134 |
} |
||
135 |
218 |
} |
|
136 |
|||
137 |
static void |
||
138 |
ike_section_ipsec(struct ipsec_rule *r, FILE *fd) |
||
139 |
{ |
||
140 |
218 |
fprintf(fd, SET "[%s]:Phase=2 force\n", r->p2name); |
|
141 |
109 |
fprintf(fd, SET "[%s]:ISAKMP-peer=%s force\n", r->p2name, r->p1name); |
|
142 |
109 |
fprintf(fd, SET "[%s]:Configuration=phase2-%s force\n", r->p2name, |
|
143 |
r->p2name); |
||
144 |
109 |
fprintf(fd, SET "[%s]:Local-ID=%s force\n", r->p2name, r->p2lid); |
|
145 |
✓✓ | 109 |
if (r->p2nid) |
146 |
7 |
fprintf(fd, SET "[%s]:NAT-ID=%s force\n", r->p2name, r->p2nid); |
|
147 |
109 |
fprintf(fd, SET "[%s]:Remote-ID=%s force\n", r->p2name, r->p2rid); |
|
148 |
|||
149 |
✗✓ | 109 |
if (r->tag) |
150 |
fprintf(fd, SET "[%s]:PF-Tag=%s force\n", r->p2name, r->tag); |
||
151 |
109 |
} |
|
152 |
|||
153 |
static int |
||
154 |
ike_section_p2(struct ipsec_rule *r, FILE *fd) |
||
155 |
{ |
||
156 |
218 |
char *exchange_type, *key_length, *transform, *p; |
|
157 |
char *enc_alg, *auth_alg, *group_desc, *encap; |
||
158 |
int needauth = 1; |
||
159 |
int num_print = 0; |
||
160 |
|||
161 |
✓✗ | 109 |
switch (r->p2ie) { |
162 |
case IKE_QM: |
||
163 |
exchange_type = "QUICK_MODE"; |
||
164 |
break; |
||
165 |
default: |
||
166 |
warnx("illegal phase 2 ike mode %d", r->p2ie); |
||
167 |
return (-1); |
||
168 |
} |
||
169 |
|||
170 |
109 |
fprintf(fd, SET "[phase2-%s]:EXCHANGE_TYPE=%s force\n", r->p2name, |
|
171 |
exchange_type); |
||
172 |
109 |
fprintf(fd, SET "[phase2-%s]:Suites=phase2-suite-%s force\n", r->p2name, |
|
173 |
r->p2name); |
||
174 |
|||
175 |
109 |
fprintf(fd, SET "[phase2-suite-%s]:Protocols=phase2-protocol-%s " |
|
176 |
109 |
"force\n", r->p2name, r->p2name); |
|
177 |
|||
178 |
109 |
fprintf(fd, SET "[phase2-protocol-%s]:PROTOCOL_ID=", r->p2name); |
|
179 |
|||
180 |
✓✓✗ | 109 |
switch (r->satype) { |
181 |
case IPSEC_ESP: |
||
182 |
105 |
fprintf(fd, "IPSEC_ESP"); |
|
183 |
105 |
break; |
|
184 |
case IPSEC_AH: |
||
185 |
4 |
fprintf(fd, "IPSEC_AH"); |
|
186 |
4 |
break; |
|
187 |
default: |
||
188 |
warnx("illegal satype %d", r->satype); |
||
189 |
return (-1); |
||
190 |
} |
||
191 |
109 |
fprintf(fd, " force\n"); |
|
192 |
|||
193 |
key_length = NULL; |
||
194 |
enc_alg = NULL; |
||
195 |
✓✓✓✓ |
122 |
if (r->p2xfs && r->p2xfs->encxf) { |
196 |
✓✓ | 10 |
if (r->satype == IPSEC_ESP) { |
197 |
✓✓✓✓ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗ |
9 |
switch (r->p2xfs->encxf->id) { |
198 |
case ENCXF_3DES_CBC: |
||
199 |
enc_alg = "3DES"; |
||
200 |
3 |
break; |
|
201 |
case ENCXF_AES: |
||
202 |
enc_alg = "AES"; |
||
203 |
key_length = "128,128:256"; |
||
204 |
3 |
break; |
|
205 |
case ENCXF_AES_128: |
||
206 |
enc_alg = "AES"; |
||
207 |
key_length = "128,128:128"; |
||
208 |
1 |
break; |
|
209 |
case ENCXF_AES_192: |
||
210 |
enc_alg = "AES"; |
||
211 |
key_length = "192,192:192"; |
||
212 |
1 |
break; |
|
213 |
case ENCXF_AES_256: |
||
214 |
enc_alg = "AES"; |
||
215 |
key_length = "256,256:256"; |
||
216 |
1 |
break; |
|
217 |
case ENCXF_AESCTR: |
||
218 |
enc_alg = "AES_CTR"; |
||
219 |
key_length = "128,128:128"; |
||
220 |
break; |
||
221 |
case ENCXF_AES_128_CTR: |
||
222 |
enc_alg = "AES_CTR"; |
||
223 |
key_length = "128,128:128"; |
||
224 |
break; |
||
225 |
case ENCXF_AES_192_CTR: |
||
226 |
enc_alg = "AES_CTR"; |
||
227 |
key_length = "192,192:192"; |
||
228 |
break; |
||
229 |
case ENCXF_AES_256_CTR: |
||
230 |
enc_alg = "AES_CTR"; |
||
231 |
key_length = "256,256:256"; |
||
232 |
break; |
||
233 |
case ENCXF_AES_128_GCM: |
||
234 |
enc_alg = "AES_GCM_16"; |
||
235 |
key_length = "128,128:128"; |
||
236 |
needauth = 0; |
||
237 |
break; |
||
238 |
case ENCXF_AES_192_GCM: |
||
239 |
enc_alg = "AES_GCM_16"; |
||
240 |
key_length = "192,192:192"; |
||
241 |
needauth = 0; |
||
242 |
break; |
||
243 |
case ENCXF_AES_256_GCM: |
||
244 |
enc_alg = "AES_GCM_16"; |
||
245 |
key_length = "256,256:256"; |
||
246 |
needauth = 0; |
||
247 |
break; |
||
248 |
case ENCXF_AES_128_GMAC: |
||
249 |
enc_alg = "AES_GMAC"; |
||
250 |
key_length = "128,128:128"; |
||
251 |
needauth = 0; |
||
252 |
break; |
||
253 |
case ENCXF_AES_192_GMAC: |
||
254 |
enc_alg = "AES_GMAC"; |
||
255 |
key_length = "192,192:192"; |
||
256 |
needauth = 0; |
||
257 |
break; |
||
258 |
case ENCXF_AES_256_GMAC: |
||
259 |
enc_alg = "AES_GMAC"; |
||
260 |
key_length = "256,256:256"; |
||
261 |
needauth = 0; |
||
262 |
break; |
||
263 |
case ENCXF_BLOWFISH: |
||
264 |
enc_alg = "BLOWFISH"; |
||
265 |
key_length = "128,96:192"; |
||
266 |
break; |
||
267 |
case ENCXF_CAST128: |
||
268 |
enc_alg = "CAST"; |
||
269 |
break; |
||
270 |
case ENCXF_NULL: |
||
271 |
enc_alg = "NULL"; |
||
272 |
needauth = 0; |
||
273 |
break; |
||
274 |
default: |
||
275 |
warnx("illegal transform %s", |
||
276 |
r->p2xfs->encxf->name); |
||
277 |
return (-1); |
||
278 |
} |
||
279 |
} else { |
||
280 |
1 |
warnx("illegal transform %s", r->p2xfs->encxf->name); |
|
281 |
1 |
return (-1); |
|
282 |
} |
||
283 |
✓✓ | 99 |
} else if (r->satype == IPSEC_ESP) { |
284 |
enc_alg = "AES"; |
||
285 |
key_length = "128,128:256"; |
||
286 |
96 |
} |
|
287 |
|||
288 |
✓✓✗ | 108 |
switch (r->tmode) { |
289 |
case IPSEC_TUNNEL: |
||
290 |
encap = "TUNNEL"; |
||
291 |
106 |
break; |
|
292 |
case IPSEC_TRANSPORT: |
||
293 |
encap = "TRANSPORT"; |
||
294 |
2 |
break; |
|
295 |
default: |
||
296 |
warnx("illegal encapsulation mode %d", r->tmode); |
||
297 |
return (-1); |
||
298 |
} |
||
299 |
|||
300 |
auth_alg = NULL; |
||
301 |
✓✓✓✓ |
120 |
if (r->p2xfs && r->p2xfs->authxf) { |
302 |
✓✓✗✓ ✗✗✗ |
7 |
switch (r->p2xfs->authxf->id) { |
303 |
case AUTHXF_HMAC_MD5: |
||
304 |
auth_alg = "MD5"; |
||
305 |
1 |
break; |
|
306 |
case AUTHXF_HMAC_SHA1: |
||
307 |
auth_alg = "SHA"; |
||
308 |
3 |
break; |
|
309 |
case AUTHXF_HMAC_RIPEMD160: |
||
310 |
auth_alg = "RIPEMD"; |
||
311 |
break; |
||
312 |
case AUTHXF_HMAC_SHA2_256: |
||
313 |
auth_alg = "SHA2_256"; |
||
314 |
3 |
break; |
|
315 |
case AUTHXF_HMAC_SHA2_384: |
||
316 |
auth_alg = "SHA2_384"; |
||
317 |
break; |
||
318 |
case AUTHXF_HMAC_SHA2_512: |
||
319 |
auth_alg = "SHA2_512"; |
||
320 |
break; |
||
321 |
default: |
||
322 |
warnx("illegal transform %s", r->p2xfs->authxf->name); |
||
323 |
return (-1); |
||
324 |
} |
||
325 |
✓✗ | 101 |
} else if (needauth) |
326 |
101 |
auth_alg = "SHA2_256"; |
|
327 |
|||
328 |
group_desc = NULL; |
||
329 |
✓✓✓✓ |
120 |
if (r->p2xfs && r->p2xfs->groupxf) { |
330 |
✗✗✗✗ ✓✗✗✗ ✗✓ |
12 |
switch (r->p2xfs->groupxf->id) { |
331 |
case GROUPXF_NONE: |
||
332 |
break; |
||
333 |
case GROUPXF_768: |
||
334 |
group_desc = "MODP_768"; |
||
335 |
break; |
||
336 |
case GROUPXF_1024: |
||
337 |
group_desc = "MODP_1024"; |
||
338 |
break; |
||
339 |
case GROUPXF_1536: |
||
340 |
group_desc = "MODP_1536"; |
||
341 |
break; |
||
342 |
case GROUPXF_2048: |
||
343 |
group_desc = "MODP_2048"; |
||
344 |
break; |
||
345 |
case GROUPXF_3072: |
||
346 |
group_desc = "MODP_3072"; |
||
347 |
6 |
break; |
|
348 |
case GROUPXF_4096: |
||
349 |
group_desc = "MODP_4096"; |
||
350 |
break; |
||
351 |
case GROUPXF_6144: |
||
352 |
group_desc = "MODP_6144"; |
||
353 |
break; |
||
354 |
case GROUPXF_8192: |
||
355 |
group_desc = "MODP_8192"; |
||
356 |
break; |
||
357 |
default: |
||
358 |
warnx("illegal group %s", r->p2xfs->groupxf->name); |
||
359 |
return (-1); |
||
360 |
} |
||
361 |
} else |
||
362 |
group_desc = "MODP_3072"; |
||
363 |
|||
364 |
/* the transform name must not include "," */ |
||
365 |
✓✓✓✗ |
210 |
if (key_length && (p = strchr(key_length, ',')) != NULL) |
366 |
102 |
num_print = p - key_length; |
|
367 |
/* |
||
368 |
* create a unique transform name, otherwise we cannot have |
||
369 |
* multiple transforms per p2name. |
||
370 |
*/ |
||
371 |
✗✓ | 216 |
if (asprintf(&transform, "phase2-transform-%s-%s%.*s-%s-%s-%s", |
372 |
108 |
r->p2name, |
|
373 |
108 |
enc_alg ? enc_alg : "NONE", |
|
374 |
108 |
num_print, key_length ? key_length : "", |
|
375 |
108 |
auth_alg ? auth_alg : "NONE", |
|
376 |
108 |
group_desc ? group_desc : "NONE", |
|
377 |
108 |
encap) == -1) |
|
378 |
errx(1, "asprintf phase2-transform"); |
||
379 |
|||
380 |
108 |
fprintf(fd, SET "[phase2-protocol-%s]:Transforms=%s force\n", |
|
381 |
108 |
r->p2name, transform); |
|
382 |
|||
383 |
216 |
fprintf(fd, SET "[%s]:TRANSFORM_ID=%s force\n", transform, |
|
384 |
108 |
r->satype == IPSEC_AH ? auth_alg : enc_alg); |
|
385 |
✓✓ | 108 |
if (key_length) |
386 |
102 |
fprintf(fd, SET "[%s]:KEY_LENGTH=%s force\n", transform, |
|
387 |
key_length); |
||
388 |
108 |
fprintf(fd, SET "[%s]:ENCAPSULATION_MODE=%s force\n", transform, encap); |
|
389 |
✓✗ | 108 |
if (auth_alg) |
390 |
108 |
fprintf(fd, SET "[%s]:AUTHENTICATION_ALGORITHM=HMAC_%s force\n", |
|
391 |
108 |
transform, auth_alg); |
|
392 |
✓✗ | 108 |
if (group_desc) |
393 |
108 |
fprintf(fd, SET "[%s]:GROUP_DESCRIPTION=%s force\n", transform, |
|
394 |
group_desc); |
||
395 |
|||
396 |
✓✓✓✓ |
120 |
if (r->p2life && r->p2life->lt_seconds != -1) { |
397 |
2 |
fprintf(fd, SET "[%s]:Life=%s-life force\n", |
|
398 |
2 |
transform, transform); |
|
399 |
2 |
fprintf(fd, SET "[%s-life]:LIFE_TYPE=SECONDS force\n", |
|
400 |
2 |
transform); |
|
401 |
2 |
fprintf(fd, SET "[%s-life]:LIFE_DURATION=%d force\n", |
|
402 |
2 |
transform, r->p2life->lt_seconds); |
|
403 |
2 |
} else |
|
404 |
106 |
fprintf(fd, SET "[%s]:Life=LIFE_QUICK_MODE force\n", |
|
405 |
106 |
transform); |
|
406 |
|||
407 |
108 |
free(transform); |
|
408 |
108 |
return (0); |
|
409 |
109 |
} |
|
410 |
|||
411 |
static int |
||
412 |
ike_section_p1(struct ipsec_rule *r, FILE *fd) |
||
413 |
{ |
||
414 |
218 |
char *exchange_type, *key_length, *transform, *p; |
|
415 |
char *enc_alg, *auth_alg, *group_desc, *auth_method; |
||
416 |
int num_print = 0; |
||
417 |
|||
418 |
✓✓✗ | 109 |
switch (r->p1ie) { |
419 |
case IKE_MM: |
||
420 |
exchange_type = "ID_PROT"; |
||
421 |
108 |
break; |
|
422 |
case IKE_AM: |
||
423 |
exchange_type = "AGGRESSIVE"; |
||
424 |
1 |
break; |
|
425 |
default: |
||
426 |
warnx("illegal phase 1 ike mode %d", r->p1ie); |
||
427 |
return (-1); |
||
428 |
} |
||
429 |
|||
430 |
109 |
fprintf(fd, SET "[%s]:Configuration=phase1-%s force\n", r->p1name, |
|
431 |
r->p1name); |
||
432 |
109 |
fprintf(fd, SET "[phase1-%s]:EXCHANGE_TYPE=%s force\n", r->p1name, |
|
433 |
exchange_type); |
||
434 |
|||
435 |
key_length = NULL; |
||
436 |
✓✓✓✓ |
123 |
if (r->p1xfs && r->p1xfs->encxf) { |
437 |
✓✓✓✓ ✓✗✗✗ |
9 |
switch (r->p1xfs->encxf->id) { |
438 |
case ENCXF_3DES_CBC: |
||
439 |
enc_alg = "3DES"; |
||
440 |
3 |
break; |
|
441 |
case ENCXF_AES: |
||
442 |
enc_alg = "AES"; |
||
443 |
key_length = "128,128:256"; |
||
444 |
3 |
break; |
|
445 |
case ENCXF_AES_128: |
||
446 |
enc_alg = "AES"; |
||
447 |
key_length = "128,128:128"; |
||
448 |
1 |
break; |
|
449 |
case ENCXF_AES_192: |
||
450 |
enc_alg = "AES"; |
||
451 |
key_length = "192,192:192"; |
||
452 |
1 |
break; |
|
453 |
case ENCXF_AES_256: |
||
454 |
enc_alg = "AES"; |
||
455 |
key_length = "256,256:256"; |
||
456 |
1 |
break; |
|
457 |
case ENCXF_BLOWFISH: |
||
458 |
enc_alg = "BLOWFISH"; |
||
459 |
key_length = "128,96:192"; |
||
460 |
break; |
||
461 |
case ENCXF_CAST128: |
||
462 |
enc_alg = "CAST"; |
||
463 |
break; |
||
464 |
default: |
||
465 |
warnx("illegal transform %s", r->p1xfs->encxf->name); |
||
466 |
return (-1); |
||
467 |
} |
||
468 |
} else { |
||
469 |
enc_alg = "AES"; |
||
470 |
key_length = "128,128:256"; |
||
471 |
} |
||
472 |
|||
473 |
✓✓✓✓ |
123 |
if (r->p1xfs && r->p1xfs->authxf) { |
474 |
✗✓✗✗ ✗✗ |
6 |
switch (r->p1xfs->authxf->id) { |
475 |
case AUTHXF_HMAC_MD5: |
||
476 |
auth_alg = "MD5"; |
||
477 |
break; |
||
478 |
case AUTHXF_HMAC_SHA1: |
||
479 |
auth_alg = "SHA"; |
||
480 |
6 |
break; |
|
481 |
case AUTHXF_HMAC_SHA2_256: |
||
482 |
auth_alg = "SHA2_256"; |
||
483 |
break; |
||
484 |
case AUTHXF_HMAC_SHA2_384: |
||
485 |
auth_alg = "SHA2_384"; |
||
486 |
break; |
||
487 |
case AUTHXF_HMAC_SHA2_512: |
||
488 |
auth_alg = "SHA2_512"; |
||
489 |
break; |
||
490 |
default: |
||
491 |
warnx("illegal transform %s", r->p1xfs->authxf->name); |
||
492 |
return (-1); |
||
493 |
} |
||
494 |
} else |
||
495 |
auth_alg = "SHA"; |
||
496 |
|||
497 |
✓✓✓✓ |
123 |
if (r->p1xfs && r->p1xfs->groupxf) { |
498 |
✗✗✗✗ ✓✗✗✗ ✗ |
6 |
switch (r->p1xfs->groupxf->id) { |
499 |
case GROUPXF_768: |
||
500 |
group_desc = "MODP_768"; |
||
501 |
break; |
||
502 |
case GROUPXF_1024: |
||
503 |
group_desc = "MODP_1024"; |
||
504 |
break; |
||
505 |
case GROUPXF_1536: |
||
506 |
group_desc = "MODP_1536"; |
||
507 |
break; |
||
508 |
case GROUPXF_2048: |
||
509 |
group_desc = "MODP_2048"; |
||
510 |
break; |
||
511 |
case GROUPXF_3072: |
||
512 |
group_desc = "MODP_3072"; |
||
513 |
6 |
break; |
|
514 |
case GROUPXF_4096: |
||
515 |
group_desc = "MODP_4096"; |
||
516 |
break; |
||
517 |
case GROUPXF_6144: |
||
518 |
group_desc = "MODP_6144"; |
||
519 |
break; |
||
520 |
case GROUPXF_8192: |
||
521 |
group_desc = "MODP_8192"; |
||
522 |
break; |
||
523 |
default: |
||
524 |
warnx("illegal group %s", r->p1xfs->groupxf->name); |
||
525 |
return (-1); |
||
526 |
}; |
||
527 |
} else |
||
528 |
group_desc = "MODP_3072"; |
||
529 |
|||
530 |
✓✓✗ | 109 |
switch (r->ikeauth->type) { |
531 |
case IKE_AUTH_PSK: |
||
532 |
auth_method = "PRE_SHARED"; |
||
533 |
7 |
break; |
|
534 |
case IKE_AUTH_RSA: |
||
535 |
auth_method = "RSA_SIG"; |
||
536 |
102 |
break; |
|
537 |
default: |
||
538 |
warnx("illegal authentication method %u", r->ikeauth->type); |
||
539 |
return (-1); |
||
540 |
} |
||
541 |
|||
542 |
/* the transform name must not include "," */ |
||
543 |
✓✓✓✗ |
215 |
if (key_length && (p = strchr(key_length, ',')) != NULL) |
544 |
106 |
num_print = p - key_length; |
|
545 |
/* create unique name for transform, see also ike_section_p2() */ |
||
546 |
✗✓ | 218 |
if (asprintf(&transform, "phase1-transform-%s-%s-%s-%s%.*s-%s", |
547 |
109 |
r->p1name, auth_method, auth_alg, enc_alg, |
|
548 |
109 |
num_print, key_length ? key_length : "", |
|
549 |
109 |
group_desc) == -1) |
|
550 |
errx(1, "asprintf phase1-transform"); |
||
551 |
|||
552 |
218 |
fprintf(fd, ADD "[phase1-%s]:Transforms=%s force\n", r->p1name, |
|
553 |
109 |
transform); |
|
554 |
109 |
fprintf(fd, SET "[%s]:AUTHENTICATION_METHOD=%s force\n", transform, |
|
555 |
auth_method); |
||
556 |
109 |
fprintf(fd, SET "[%s]:HASH_ALGORITHM=%s force\n", transform, auth_alg); |
|
557 |
109 |
fprintf(fd, SET "[%s]:ENCRYPTION_ALGORITHM=%s_CBC force\n", transform, |
|
558 |
enc_alg); |
||
559 |
✓✓ | 109 |
if (key_length) |
560 |
106 |
fprintf(fd, SET "[%s]:KEY_LENGTH=%s force\n", transform, |
|
561 |
key_length); |
||
562 |
109 |
fprintf(fd, SET "[%s]:GROUP_DESCRIPTION=%s force\n", transform, |
|
563 |
group_desc); |
||
564 |
|||
565 |
✓✓✓✓ |
123 |
if (r->p1life && r->p1life->lt_seconds != -1) { |
566 |
2 |
fprintf(fd, SET "[%s]:Life=%s-life force\n", |
|
567 |
2 |
transform, transform); |
|
568 |
2 |
fprintf(fd, SET "[%s-life]:LIFE_TYPE=SECONDS force\n", |
|
569 |
2 |
transform); |
|
570 |
2 |
fprintf(fd, SET "[%s-life]:LIFE_DURATION=%d force\n", |
|
571 |
2 |
transform, r->p1life->lt_seconds); |
|
572 |
2 |
} else |
|
573 |
107 |
fprintf(fd, SET "[%s]:Life=LIFE_MAIN_MODE force\n", transform); |
|
574 |
|||
575 |
109 |
free(transform); |
|
576 |
109 |
return (0); |
|
577 |
109 |
} |
|
578 |
|||
579 |
static void |
||
580 |
ike_section_p2ids_net(struct ipsec_addr *iamask, sa_family_t af, char *name, |
||
581 |
char *p2xid, FILE *fd) |
||
582 |
{ |
||
583 |
444 |
char mask[NI_MAXHOST], *network, *p; |
|
584 |
296 |
struct sockaddr_storage sas; |
|
585 |
296 |
struct sockaddr *sa = (struct sockaddr *)&sas; |
|
586 |
|||
587 |
296 |
bzero(&sas, sizeof(struct sockaddr_storage)); |
|
588 |
296 |
bzero(mask, sizeof(mask)); |
|
589 |
296 |
sa->sa_family = af; |
|
590 |
✓✓✓ | 296 |
switch (af) { |
591 |
case AF_INET: |
||
592 |
112 |
sa->sa_len = sizeof(struct sockaddr_in); |
|
593 |
224 |
bcopy(&iamask->ipa, |
|
594 |
112 |
&((struct sockaddr_in *)(sa))->sin_addr, |
|
595 |
sizeof(struct in6_addr)); |
||
596 |
112 |
break; |
|
597 |
case AF_INET6: |
||
598 |
36 |
sa->sa_len = sizeof(struct sockaddr_in6); |
|
599 |
72 |
bcopy(&iamask->ipa, |
|
600 |
36 |
&((struct sockaddr_in6 *)(sa))->sin6_addr, |
|
601 |
sizeof(struct in6_addr)); |
||
602 |
36 |
break; |
|
603 |
} |
||
604 |
✗✓ | 148 |
if (getnameinfo(sa, sa->sa_len, mask, sizeof(mask), NULL, 0, |
605 |
NI_NUMERICHOST)) |
||
606 |
errx(1, "could not get a numeric mask"); |
||
607 |
|||
608 |
✗✓ | 148 |
if ((network = strdup(name)) == NULL) |
609 |
err(1, "ike_section_p2ids: strdup"); |
||
610 |
✓✗ | 148 |
if ((p = strrchr(network, '/')) != NULL) |
611 |
148 |
*p = '\0'; |
|
612 |
|||
613 |
148 |
fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR_SUBNET force\n", |
|
614 |
148 |
p2xid, ((af == AF_INET) ? 4 : 6)); |
|
615 |
148 |
fprintf(fd, SET "[%s]:Network=%s force\n", p2xid, network); |
|
616 |
148 |
fprintf(fd, SET "[%s]:Netmask=%s force\n", p2xid, mask); |
|
617 |
|||
618 |
148 |
free(network); |
|
619 |
148 |
} |
|
620 |
|||
621 |
static void |
||
622 |
ike_section_p2ids(struct ipsec_rule *r, FILE *fd) |
||
623 |
{ |
||
624 |
char *p; |
||
625 |
216 |
struct ipsec_addr_wrap *src = r->src; |
|
626 |
108 |
struct ipsec_addr_wrap *dst = r->dst; |
|
627 |
|||
628 |
✓✓ | 108 |
if (src->netaddress) { |
629 |
130 |
ike_section_p2ids_net(&src->mask, src->af, src->name, |
|
630 |
65 |
r->p2lid, fd); |
|
631 |
65 |
} else { |
|
632 |
43 |
fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n", |
|
633 |
43 |
r->p2lid, ((src->af == AF_INET) ? 4 : 6)); |
|
634 |
✗✓ | 43 |
if ((p = strrchr(src->name, '/')) != NULL) |
635 |
*p = '\0'; |
||
636 |
86 |
fprintf(fd, SET "[%s]:Address=%s force\n", r->p2lid, |
|
637 |
43 |
src->name); |
|
638 |
} |
||
639 |
|||
640 |
✓✓✓✗ |
115 |
if (src->srcnat && src->srcnat->netaddress) { |
641 |
14 |
ike_section_p2ids_net(&src->srcnat->mask, src->af, src->srcnat->name, |
|
642 |
7 |
r->p2nid, fd); |
|
643 |
✗✓ | 108 |
} else if (src->srcnat) { |
644 |
fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n", |
||
645 |
r->p2nid, ((src->af == AF_INET) ? 4 : 6)); |
||
646 |
if ((p = strrchr(src->srcnat->name, '/')) != NULL) |
||
647 |
*p = '\0'; |
||
648 |
fprintf(fd, SET "[%s]:Address=%s force\n", r->p2nid, |
||
649 |
src->srcnat->name); |
||
650 |
} |
||
651 |
|||
652 |
✓✓ | 108 |
if (dst->netaddress) { |
653 |
152 |
ike_section_p2ids_net(&dst->mask, dst->af, dst->name, |
|
654 |
76 |
r->p2rid, fd); |
|
655 |
76 |
} else { |
|
656 |
32 |
fprintf(fd, SET "[%s]:ID-type=IPV%d_ADDR force\n", |
|
657 |
32 |
r->p2rid, ((dst->af == AF_INET) ? 4 : 6)); |
|
658 |
✗✓ | 32 |
if ((p = strrchr(dst->name, '/')) != NULL) |
659 |
*p = '\0'; |
||
660 |
64 |
fprintf(fd, SET "[%s]:Address=%s force\n", r->p2rid, |
|
661 |
32 |
dst->name); |
|
662 |
} |
||
663 |
✓✓ | 108 |
if (r->proto) { |
664 |
5 |
fprintf(fd, SET "[%s]:Protocol=%d force\n", |
|
665 |
5 |
r->p2lid, r->proto); |
|
666 |
5 |
fprintf(fd, SET "[%s]:Protocol=%d force\n", |
|
667 |
5 |
r->p2rid, r->proto); |
|
668 |
5 |
} |
|
669 |
✓✓ | 108 |
if (r->sport) |
670 |
6 |
fprintf(fd, SET "[%s]:Port=%d force\n", r->p2lid, |
|
671 |
3 |
ntohs(r->sport)); |
|
672 |
✓✓ | 108 |
if (r->dport) |
673 |
2 |
fprintf(fd, SET "[%s]:Port=%d force\n", r->p2rid, |
|
674 |
1 |
ntohs(r->dport)); |
|
675 |
108 |
} |
|
676 |
|||
677 |
static int |
||
678 |
ike_connect(struct ipsec_rule *r, FILE *fd) |
||
679 |
{ |
||
680 |
✗✓✓✗ |
216 |
switch (r->ikemode) { |
681 |
case IKE_ACTIVE: |
||
682 |
case IKE_DYNAMIC: |
||
683 |
100 |
fprintf(fd, ADD "[Phase 2]:Connections=%s\n", r->p2name); |
|
684 |
100 |
break; |
|
685 |
case IKE_PASSIVE: |
||
686 |
8 |
fprintf(fd, ADD "[Phase 2]:Passive-Connections=%s\n", |
|
687 |
8 |
r->p2name); |
|
688 |
8 |
break; |
|
689 |
default: |
||
690 |
return (-1); |
||
691 |
} |
||
692 |
108 |
return (0); |
|
693 |
108 |
} |
|
694 |
|||
695 |
static int |
||
696 |
ike_gen_config(struct ipsec_rule *r, FILE *fd) |
||
697 |
{ |
||
698 |
218 |
ike_setup_ids(r); |
|
699 |
109 |
ike_section_general(r, fd); |
|
700 |
109 |
ike_section_peer(r, fd); |
|
701 |
✗✓ | 109 |
if (ike_section_p1(r, fd) == -1) { |
702 |
return (-1); |
||
703 |
} |
||
704 |
109 |
ike_section_ids(r, fd); |
|
705 |
109 |
ike_section_ipsec(r, fd); |
|
706 |
✓✓ | 109 |
if (ike_section_p2(r, fd) == -1) { |
707 |
1 |
return (-1); |
|
708 |
} |
||
709 |
108 |
ike_section_p2ids(r, fd); |
|
710 |
|||
711 |
✗✓ | 108 |
if (ike_connect(r, fd) == -1) |
712 |
return (-1); |
||
713 |
108 |
return (0); |
|
714 |
109 |
} |
|
715 |
|||
716 |
static int |
||
717 |
ike_delete_config(struct ipsec_rule *r, FILE *fd) |
||
718 |
{ |
||
719 |
130 |
ike_setup_ids(r); |
|
720 |
#if 0 |
||
721 |
switch (r->ikemode) { |
||
722 |
case IKE_ACTIVE: |
||
723 |
case IKE_DYNAMIC: |
||
724 |
fprintf(fd, "t %s\n", r->p2name); |
||
725 |
break; |
||
726 |
case IKE_PASSIVE: |
||
727 |
fprintf(fd, DELETE "[Phase 2]\n"); |
||
728 |
fprintf(fd, "t %s\n", r->p2name); |
||
729 |
break; |
||
730 |
default: |
||
731 |
return (-1); |
||
732 |
} |
||
733 |
|||
734 |
if (r->peer) { |
||
735 |
fprintf(fd, DELETE "[%s]\n", r->p1name); |
||
736 |
fprintf(fd, DELETE "[phase1-%s]\n", r->p1name); |
||
737 |
} |
||
738 |
if (r->auth) { |
||
739 |
if (r->auth->srcid) |
||
740 |
fprintf(fd, DELETE "[%s-ID]\n", r->auth->srcid); |
||
741 |
if (r->auth->dstid) |
||
742 |
fprintf(fd, DELETE "[%s-ID]\n", r->auth->dstid); |
||
743 |
} |
||
744 |
fprintf(fd, DELETE "[%s]\n", r->p2name); |
||
745 |
fprintf(fd, DELETE "[phase2-%s]\n", r->p2name); |
||
746 |
fprintf(fd, DELETE "[%s]\n", r->p2lid); |
||
747 |
fprintf(fd, DELETE "[%s]\n", r->p2rid); |
||
748 |
#else |
||
749 |
65 |
fprintf(fd, "t %s\n", r->p2name); |
|
750 |
✗✓✓✗ |
65 |
switch (r->ikemode) { |
751 |
case IKE_ACTIVE: |
||
752 |
case IKE_DYNAMIC: |
||
753 |
59 |
fprintf(fd, RMV "[Phase 2]:Connections=%s\n", r->p2name); |
|
754 |
59 |
break; |
|
755 |
case IKE_PASSIVE: |
||
756 |
6 |
fprintf(fd, RMV "[Phase 2]:Passive-Connections=%s\n", |
|
757 |
6 |
r->p2name); |
|
758 |
6 |
break; |
|
759 |
default: |
||
760 |
return (-1); |
||
761 |
} |
||
762 |
65 |
fprintf(fd, DELETE "[%s]\n", r->p2name); |
|
763 |
65 |
fprintf(fd, DELETE "[phase2-%s]\n", r->p2name); |
|
764 |
#endif |
||
765 |
|||
766 |
65 |
return (0); |
|
767 |
65 |
} |
|
768 |
|||
769 |
static void |
||
770 |
ike_setup_ids(struct ipsec_rule *r) |
||
771 |
{ |
||
772 |
348 |
char sproto[10], ssport[10], sdport[10]; |
|
773 |
|||
774 |
/* phase 1 name is peer and local address */ |
||
775 |
✓✓ | 174 |
if (r->peer) { |
776 |
✓✓ | 152 |
if (r->local) { |
777 |
/* peer-dstaddr-local-srcaddr */ |
||
778 |
✗✓ | 16 |
if (asprintf(&r->p1name, "peer-%s-local-%s", |
779 |
16 |
r->peer->name, r->local->name) == -1) |
|
780 |
err(1, "ike_setup_ids"); |
||
781 |
} else |
||
782 |
/* peer-dstaddr */ |
||
783 |
✗✓ | 288 |
if (asprintf(&r->p1name, "peer-%s", |
784 |
144 |
r->peer->name) == -1) |
|
785 |
err(1, "ike_setup_ids"); |
||
786 |
} else |
||
787 |
✗✓ | 22 |
if ((r->p1name = strdup("peer-default")) == NULL) |
788 |
err(1, "ike_setup_ids"); |
||
789 |
|||
790 |
/* Phase 2 name is from and to network, protocol, port*/ |
||
791 |
174 |
sproto[0] = ssport[0] = sdport[0] = 0; |
|
792 |
✓✓ | 174 |
if (r->proto) |
793 |
9 |
snprintf(sproto, sizeof sproto, "=%u", r->proto); |
|
794 |
✓✓ | 174 |
if (r->sport) |
795 |
5 |
snprintf(ssport, sizeof ssport, ":%u", ntohs(r->sport)); |
|
796 |
✓✓ | 174 |
if (r->dport) |
797 |
2 |
snprintf(sdport, sizeof sdport, ":%u", ntohs(r->dport)); |
|
798 |
/* from-network/masklen=proto:port */ |
||
799 |
✗✓ | 348 |
if (asprintf(&r->p2lid, "from-%s%s%s", r->src->name, sproto, ssport) |
800 |
174 |
== -1) |
|
801 |
err(1, "ike_setup_ids"); |
||
802 |
/* to-network/masklen=proto:port */ |
||
803 |
✗✓ | 348 |
if (asprintf(&r->p2rid, "to-%s%s%s", r->dst->name, sproto, sdport) |
804 |
174 |
== -1) |
|
805 |
err(1, "ike_setup_ids"); |
||
806 |
/* from-network/masklen=proto:port-to-network/masklen=proto:port */ |
||
807 |
✗✓ | 174 |
if (asprintf(&r->p2name, "%s-%s", r->p2lid , r->p2rid) == -1) |
808 |
err(1, "ike_setup_ids"); |
||
809 |
/* nat-network/masklen=proto:port */ |
||
810 |
✓✓✓✗ |
181 |
if (r->src->srcnat && r->src->srcnat->name) { |
811 |
✗✓ | 14 |
if (asprintf(&r->p2nid, "nat-%s%s%s", r->src->srcnat->name, sproto, |
812 |
7 |
ssport) == -1) |
|
813 |
err(1, "ike_setup_ids"); |
||
814 |
} |
||
815 |
174 |
} |
|
816 |
|||
817 |
int |
||
818 |
ike_print_config(struct ipsec_rule *r, int opts) |
||
819 |
{ |
||
820 |
✓✓ | 348 |
if (opts & IPSECCTL_OPT_DELETE) |
821 |
65 |
return (ike_delete_config(r, stdout)); |
|
822 |
else |
||
823 |
109 |
return (ike_gen_config(r, stdout)); |
|
824 |
174 |
} |
|
825 |
|||
826 |
int |
||
827 |
ike_ipsec_establish(int action, struct ipsec_rule *r, const char *fifo) |
||
828 |
{ |
||
829 |
struct stat sb; |
||
830 |
FILE *fdp; |
||
831 |
int fd, ret = 0; |
||
832 |
|||
833 |
if ((fd = open(fifo, O_WRONLY)) == -1) |
||
834 |
err(1, "ike_ipsec_establish: open(%s)", fifo); |
||
835 |
if (fstat(fd, &sb) == -1) |
||
836 |
err(1, "ike_ipsec_establish: fstat(%s)", fifo); |
||
837 |
if (!S_ISFIFO(sb.st_mode)) |
||
838 |
errx(1, "ike_ipsec_establish: %s not a fifo", fifo); |
||
839 |
if ((fdp = fdopen(fd, "w")) == NULL) |
||
840 |
err(1, "ike_ipsec_establish: fdopen(%s)", fifo); |
||
841 |
|||
842 |
switch (action) { |
||
843 |
case ACTION_ADD: |
||
844 |
ret = ike_gen_config(r, fdp); |
||
845 |
break; |
||
846 |
case ACTION_DELETE: |
||
847 |
ret = ike_delete_config(r, fdp); |
||
848 |
break; |
||
849 |
default: |
||
850 |
ret = -1; |
||
851 |
} |
||
852 |
|||
853 |
fclose(fdp); |
||
854 |
return (ret); |
||
855 |
} |
Generated by: GCOVR (Version 3.3) |