1 /* strongSwan whack functions to communicate with pluto (whack.c)
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 #include <sys/types.h>
16 #include <sys/socket.h>
25 #include <constants.h>
30 #include "starterwhack.h"
34 #define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
36 static int pack_str (char **p
, char **next
, char **roof
)
38 const char *s
= (*p
==NULL
) ?
"" : *p
; /* note: NULL becomes ""! */
39 size_t len
= strlen(s
) + 1;
41 if ((*roof
- *next
) < len
)
43 return 0; /* not enough space */
49 *p
= NULL
; /* don't send pointers on the wire! */
54 static int send_whack_msg (whack_message_t
*msg
)
56 struct sockaddr_un ctl_addr
;
59 char *str_next
, *str_roof
;
61 ctl_addr
.sun_family
= AF_UNIX
;
62 strcpy(ctl_addr
.sun_path
, PLUTO_CTL_FILE
);
65 str_next
= (char *)msg
->string
;
66 str_roof
= (char *)&msg
->string
[sizeof(msg
->string
)];
68 if (!pack_str(&msg
->name
, &str_next
, &str_roof
)
69 || !pack_str(&msg
->left
.id
, &str_next
, &str_roof
)
70 || !pack_str(&msg
->left
.cert
, &str_next
, &str_roof
)
71 || !pack_str(&msg
->left
.ca
, &str_next
, &str_roof
)
72 || !pack_str(&msg
->left
.groups
, &str_next
, &str_roof
)
73 || !pack_str(&msg
->left
.updown
, &str_next
, &str_roof
)
74 || !pack_str(&msg
->left
.sourceip
, &str_next
, &str_roof
)
75 || !pack_str(&msg
->left
.virt
, &str_next
, &str_roof
)
76 || !pack_str(&msg
->right
.id
, &str_next
, &str_roof
)
77 || !pack_str(&msg
->right
.cert
, &str_next
, &str_roof
)
78 || !pack_str(&msg
->right
.ca
, &str_next
, &str_roof
)
79 || !pack_str(&msg
->right
.groups
, &str_next
, &str_roof
)
80 || !pack_str(&msg
->right
.updown
, &str_next
, &str_roof
)
81 || !pack_str(&msg
->right
.sourceip
, &str_next
, &str_roof
)
82 || !pack_str(&msg
->right
.virt
, &str_next
, &str_roof
)
83 || !pack_str(&msg
->keyid
, &str_next
, &str_roof
)
84 || !pack_str(&msg
->myid
, &str_next
, &str_roof
)
85 || !pack_str(&msg
->cacert
, &str_next
, &str_roof
)
86 || !pack_str(&msg
->ldaphost
, &str_next
, &str_roof
)
87 || !pack_str(&msg
->ldapbase
, &str_next
, &str_roof
)
88 || !pack_str(&msg
->crluri
, &str_next
, &str_roof
)
89 || !pack_str(&msg
->crluri2
, &str_next
, &str_roof
)
90 || !pack_str(&msg
->ocspuri
, &str_next
, &str_roof
)
91 || !pack_str(&msg
->ike
, &str_next
, &str_roof
)
92 || !pack_str(&msg
->esp
, &str_next
, &str_roof
)
93 || !pack_str(&msg
->sc_data
, &str_next
, &str_roof
)
94 || !pack_str(&msg
->whack_lease_ip
, &str_next
, &str_roof
)
95 || !pack_str(&msg
->whack_lease_id
, &str_next
, &str_roof
)
96 || !pack_str(&msg
->xauth_identity
, &str_next
, &str_roof
)
97 || (str_roof
- str_next
< msg
->keyval
.len
))
99 plog("send_wack_msg(): can't pack strings");
104 memcpy(str_next
, msg
->keyval
.ptr
, msg
->keyval
.len
);
106 msg
->keyval
.ptr
= NULL
;
107 str_next
+= msg
->keyval
.len
;
108 len
= str_next
- (char *)msg
;
110 /* connect to pluto ctl */
111 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
114 plog("socket() failed: %s", strerror(errno
));
117 if (connect(sock
, (struct sockaddr
*)&ctl_addr
,
118 offsetof(struct sockaddr_un
, sun_path
) + strlen(ctl_addr
.sun_path
)) < 0)
120 plog("connect(pluto_ctl) failed: %s", strerror(errno
));
126 if (write(sock
, msg
, len
) != len
)
128 plog("write(pluto_ctl) failed: %s", strerror(errno
));
133 /* TODO: read reply */
138 static void init_whack_msg(whack_message_t
*msg
)
140 memset(msg
, 0, sizeof(whack_message_t
));
141 msg
->magic
= WHACK_MAGIC
;
144 static char *connection_name(starter_conn_t
*conn
, char *buf
, size_t size
)
146 /* if connection name is '%auto', create a new name like conn_xxxxx */
147 if (streq(conn
->name
, "%auto"))
149 snprintf(buf
, size
, "conn_%ld", conn
->id
);
155 static void set_whack_end(whack_end_t
*w
, starter_end_t
*end
, sa_family_t family
)
160 w
->groups
= end
->groups
;
161 w
->host_addr
= end
->addr
;
162 w
->has_client
= end
->has_client
;
163 w
->sourceip
= end
->sourceip
;
164 w
->sourceip_mask
= end
->sourceip_mask
;
166 if (end
->sourceip
&& end
->sourceip_mask
> 0)
168 ttoaddr(end
->sourceip
, 0, ip_version(end
->sourceip
), &w
->host_srcip
);
169 w
->has_srcip
= !end
->has_natip
;
173 anyaddr(AF_INET
, &w
->host_srcip
);
176 if (family
== AF_INET6
&& isanyaddr(&end
->nexthop
))
178 anyaddr(AF_INET6
, &end
->nexthop
);
180 w
->host_nexthop
= end
->nexthop
;
187 pos
= strchr(end
->subnet
, ',');
190 len
= pos
- end
->subnet
;
192 ttosubnet(end
->subnet
, len
, ip_version(end
->subnet
), &w
->client
);
198 w
->virt
= end
->subnet
;
200 w
->client
.addr
.u
.v4
.sin_family
= addrtypeof(&w
->host_addr
);
203 w
->has_client_wildcard
= end
->has_client_wildcard
;
204 w
->has_port_wildcard
= end
->has_port_wildcard
;
205 w
->has_natip
= end
->has_natip
;
206 w
->allow_any
= end
->allow_any
&& !end
->dns_failed
;
207 w
->modecfg
= end
->modecfg
;
208 w
->hostaccess
= end
->hostaccess
;
209 w
->sendcert
= end
->sendcert
;
210 w
->updown
= end
->updown
;
211 w
->host_port
= IKE_UDP_PORT
;
213 w
->protocol
= end
->protocol
;
217 int port
= htons(w
->port
);
219 setportof(port
, &w
->host_addr
);
220 setportof(port
, &w
->client
.addr
);
225 starter_whack_add_pubkey (starter_conn_t
*conn
, starter_end_t
*end
229 static char keyspace
[1024 + 4];
230 char buf
[ADDRTOT_BUF
], name
[32];
233 init_whack_msg(&msg
);
234 connection_name(conn
, name
, sizeof(name
));
236 msg
.whack_key
= TRUE
;
237 msg
.pubkey_alg
= PUBKEY_ALG_RSA
;
240 /* special values to ignore */
241 if (streq(end
->rsakey
, "")
242 || streq(end
->rsakey
, "%none")
243 || streq(end
->rsakey
, "%cert")
244 || streq(end
->rsakey
, "0x00"))
248 err
= atobytes(end
->rsakey
, 0, keyspace
, sizeof(keyspace
), &msg
.keyval
.len
);
251 plog("conn %s/%s: rsakey malformed [%s]", name
, lr
, err
);
260 addrtot(&end
->addr
, 0, buf
, sizeof(buf
));
263 msg
.keyval
.ptr
= keyspace
;
264 return send_whack_msg(&msg
);
269 int starter_whack_add_conn(starter_conn_t
*conn
)
271 char esp_buf
[256], name
[32];
275 init_whack_msg(&msg
);
277 msg
.whack_connection
= TRUE
;
278 msg
.name
= connection_name(conn
, name
, sizeof(name
));
280 msg
.ikev1
= conn
->keyexchange
== KEY_EXCHANGE_IKEV1
;
281 msg
.addr_family
= conn
->addr_family
;
282 msg
.tunnel_addr_family
= conn
->tunnel_addr_family
;
283 msg
.sa_ike_life_seconds
= conn
->sa_ike_life_seconds
;
284 msg
.sa_ipsec_life_seconds
= conn
->sa_ipsec_life_seconds
;
285 msg
.sa_rekey_margin
= conn
->sa_rekey_margin
;
286 msg
.sa_rekey_fuzz
= conn
->sa_rekey_fuzz
;
287 msg
.sa_keying_tries
= conn
->sa_keying_tries
;
288 msg
.policy
= conn
->policy
;
289 msg
.xauth_identity
= conn
->xauth_identity
;
290 msg
.reqid
= conn
->reqid
;
291 msg
.mark_in
.value
= conn
->mark_in
.value
;
292 msg
.mark_in
.mask
= conn
->mark_in
.mask
;
293 msg
.mark_out
.value
= conn
->mark_out
.value
;
294 msg
.mark_out
.mask
= conn
->mark_out
.mask
;
297 * Make sure the IKEv2-only policy bits are unset for IKEv1 connections
299 msg
.policy
&= ~POLICY_DONT_REAUTH
;
300 msg
.policy
&= ~POLICY_BEET
;
301 msg
.policy
&= ~POLICY_MOBIKE
;
302 msg
.policy
&= ~POLICY_FORCE_ENCAP
;
304 set_whack_end(&msg
.left
, &conn
->left
, conn
->addr_family
);
305 set_whack_end(&msg
.right
, &conn
->right
, conn
->addr_family
);
309 msg
.pfsgroup
= conn
->pfsgroup
;
311 /* taken from pluto/whack.c */
314 snprintf(esp_buf
, sizeof (esp_buf
), "%s;%s"
315 , msg
.esp ? msg
.esp
: ""
316 , msg
.pfsgroup ? msg
.pfsgroup
: "");
320 DBG_log("Setting --esp=%s", msg
.esp
)
323 msg
.dpd_delay
= conn
->dpd_delay
;
324 msg
.dpd_timeout
= conn
->dpd_timeout
;
325 msg
.dpd_action
= conn
->dpd_action
;
326 /* msg.dpd_count = conn->dpd_count; not supported yet by strongSwan */
328 r
= send_whack_msg(&msg
);
330 if (r
== 0 && (conn
->policy
& POLICY_PUBKEY
))
332 r
+= starter_whack_add_pubkey (conn
, &conn
->left
, "left");
333 r
+= starter_whack_add_pubkey (conn
, &conn
->right
, "right");
339 int starter_whack_del_conn(starter_conn_t
*conn
)
344 init_whack_msg(&msg
);
345 msg
.whack_delete
= TRUE
;
346 msg
.name
= connection_name(conn
, name
, sizeof(name
));
347 return send_whack_msg(&msg
);
350 int starter_whack_route_conn(starter_conn_t
*conn
)
355 init_whack_msg(&msg
);
356 msg
.whack_route
= TRUE
;
357 msg
.name
= connection_name(conn
, name
, sizeof(name
));
358 return send_whack_msg(&msg
);
361 int starter_whack_initiate_conn(starter_conn_t
*conn
)
366 init_whack_msg(&msg
);
367 msg
.whack_initiate
= TRUE
;
368 msg
.whack_async
= TRUE
;
369 msg
.name
= connection_name(conn
, name
, sizeof(name
));
370 return send_whack_msg(&msg
);
373 int starter_whack_listen(void)
376 init_whack_msg(&msg
);
377 msg
.whack_listen
= TRUE
;
378 return send_whack_msg(&msg
);
381 int starter_whack_shutdown(void)
385 init_whack_msg(&msg
);
386 msg
.whack_shutdown
= TRUE
;
387 return send_whack_msg(&msg
);
390 int starter_whack_add_ca(starter_ca_t
*ca
)
394 init_whack_msg(&msg
);
398 msg
.cacert
= ca
->cacert
;
399 msg
.ldaphost
= ca
->ldaphost
;
400 msg
.ldapbase
= ca
->ldapbase
;
401 msg
.crluri
= ca
->crluri
;
402 msg
.crluri2
= ca
->crluri2
;
403 msg
.ocspuri
= ca
->ocspuri
;
404 msg
.whack_strict
= ca
->strict
;
406 return send_whack_msg(&msg
);
409 int starter_whack_del_ca(starter_ca_t
*ca
)
413 init_whack_msg(&msg
);
415 msg
.whack_delete
= TRUE
;
419 return send_whack_msg(&msg
);