Rebuild library.lo after changing ./configure options
[strongswan.git] / src / starter / starterwhack.c
1 /* strongSwan whack functions to communicate with pluto (whack.c)
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 *
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>.
8 *
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
12 * for more details.
13 */
14
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/un.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include <freeswan.h>
24
25 #include <constants.h>
26 #include <defs.h>
27 #include <log.h>
28 #include <whack.h>
29
30 #include "starterwhack.h"
31 #include "confread.h"
32 #include "files.h"
33
34 #define ip_version(string) (strchr(string, '.') ? AF_INET : AF_INET6)
35
36 static int pack_str (char **p, char **next, char **roof)
37 {
38 const char *s = (*p==NULL) ? "" : *p; /* note: NULL becomes ""! */
39 size_t len = strlen(s) + 1;
40
41 if ((*roof - *next) < len)
42 {
43 return 0; /* not enough space */
44 }
45 else
46 {
47 strcpy(*next, s);
48 *next += len;
49 *p = NULL; /* don't send pointers on the wire! */
50 return 1;
51 }
52 }
53
54 static int send_whack_msg (whack_message_t *msg)
55 {
56 struct sockaddr_un ctl_addr;
57 int sock;
58 ssize_t len;
59 char *str_next, *str_roof;
60
61 ctl_addr.sun_family = AF_UNIX;
62 strcpy(ctl_addr.sun_path, PLUTO_CTL_FILE);
63
64 /* pack strings */
65 str_next = (char *)msg->string;
66 str_roof = (char *)&msg->string[sizeof(msg->string)];
67
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))
98 {
99 plog("send_wack_msg(): can't pack strings");
100 return -1;
101 }
102 if (msg->keyval.ptr)
103 {
104 memcpy(str_next, msg->keyval.ptr, msg->keyval.len);
105 }
106 msg->keyval.ptr = NULL;
107 str_next += msg->keyval.len;
108 len = str_next - (char *)msg;
109
110 /* connect to pluto ctl */
111 sock = socket(AF_UNIX, SOCK_STREAM, 0);
112 if (sock < 0)
113 {
114 plog("socket() failed: %s", strerror(errno));
115 return -1;
116 }
117 if (connect(sock, (struct sockaddr *)&ctl_addr,
118 offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
119 {
120 plog("connect(pluto_ctl) failed: %s", strerror(errno));
121 close(sock);
122 return -1;
123 }
124
125 /* send message */
126 if (write(sock, msg, len) != len)
127 {
128 plog("write(pluto_ctl) failed: %s", strerror(errno));
129 close(sock);
130 return -1;
131 }
132
133 /* TODO: read reply */
134 close(sock);
135 return 0;
136 }
137
138 static void init_whack_msg(whack_message_t *msg)
139 {
140 memset(msg, 0, sizeof(whack_message_t));
141 msg->magic = WHACK_MAGIC;
142 }
143
144 static char *connection_name(starter_conn_t *conn, char *buf, size_t size)
145 {
146 /* if connection name is '%auto', create a new name like conn_xxxxx */
147 if (streq(conn->name, "%auto"))
148 {
149 snprintf(buf, size, "conn_%ld", conn->id);
150 return buf;
151 }
152 return conn->name;
153 }
154
155 static void set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family)
156 {
157 w->id = end->id;
158 w->cert = end->cert;
159 w->ca = end->ca;
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;
165
166 if (end->sourceip && end->sourceip_mask > 0)
167 {
168 ttoaddr(end->sourceip, 0, ip_version(end->sourceip), &w->host_srcip);
169 w->has_srcip = !end->has_natip;
170 }
171 else
172 {
173 anyaddr(AF_INET, &w->host_srcip);
174 }
175
176 if (family == AF_INET6 && isanyaddr(&end->nexthop))
177 {
178 anyaddr(AF_INET6, &end->nexthop);
179 }
180 w->host_nexthop = end->nexthop;
181
182 if (w->has_client)
183 {
184 char *pos;
185 int len = 0;
186
187 pos = strchr(end->subnet, ',');
188 if (pos)
189 {
190 len = pos - end->subnet;
191 }
192 ttosubnet(end->subnet, len, ip_version(end->subnet), &w->client);
193 }
194 else
195 {
196 if (end->has_virt)
197 {
198 w->virt = end->subnet;
199 }
200 w->client.addr.u.v4.sin_family = addrtypeof(&w->host_addr);
201 }
202
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;
212 w->port = end->port;
213 w->protocol = end->protocol;
214
215 if (w->port != 0)
216 {
217 int port = htons(w->port);
218
219 setportof(port, &w->host_addr);
220 setportof(port, &w->client.addr);
221 }
222 }
223
224 static int
225 starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
226 , const char *lr)
227 {
228 const char *err;
229 static char keyspace[1024 + 4];
230 char buf[ADDRTOT_BUF], name[32];
231 whack_message_t msg;
232
233 init_whack_msg(&msg);
234 connection_name(conn, name, sizeof(name));
235
236 msg.whack_key = TRUE;
237 msg.pubkey_alg = PUBKEY_ALG_RSA;
238 if (end->rsakey)
239 {
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"))
245 {
246 return 0;
247 }
248 err = atobytes(end->rsakey, 0, keyspace, sizeof(keyspace), &msg.keyval.len);
249 if (err)
250 {
251 plog("conn %s/%s: rsakey malformed [%s]", name, lr, err);
252 return 1;
253 }
254 if (end->id)
255 {
256 msg.keyid = end->id;
257 }
258 else
259 {
260 addrtot(&end->addr, 0, buf, sizeof(buf));
261 msg.keyid = buf;
262 }
263 msg.keyval.ptr = keyspace;
264 return send_whack_msg(&msg);
265 }
266 return 0;
267 }
268
269 int starter_whack_add_conn(starter_conn_t *conn)
270 {
271 char esp_buf[256], name[32];
272 whack_message_t msg;
273 int r;
274
275 init_whack_msg(&msg);
276
277 msg.whack_connection = TRUE;
278 msg.name = connection_name(conn, name, sizeof(name));
279
280 msg.ikev1 = conn->keyexchange != KEY_EXCHANGE_IKEV2;
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;
295
296 /*
297 * Make sure the IKEv2-only policy bits are unset for IKEv1 connections
298 */
299 msg.policy &= ~POLICY_DONT_REAUTH;
300 msg.policy &= ~POLICY_BEET;
301 msg.policy &= ~POLICY_MOBIKE;
302 msg.policy &= ~POLICY_FORCE_ENCAP;
303
304 set_whack_end(&msg.left, &conn->left, conn->addr_family);
305 set_whack_end(&msg.right, &conn->right, conn->addr_family);
306
307 msg.esp = conn->esp;
308 msg.ike = conn->ike;
309 msg.pfsgroup = conn->pfsgroup;
310
311 /* taken from pluto/whack.c */
312 if (msg.pfsgroup)
313 {
314 snprintf(esp_buf, sizeof (esp_buf), "%s;%s"
315 , msg.esp ? msg.esp : ""
316 , msg.pfsgroup ? msg.pfsgroup : "");
317 msg.esp = esp_buf;
318
319 DBG(DBG_CONTROL,
320 DBG_log("Setting --esp=%s", msg.esp)
321 )
322 }
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 */
327
328 r = send_whack_msg(&msg);
329
330 if (r == 0 && (conn->policy & POLICY_PUBKEY))
331 {
332 r += starter_whack_add_pubkey (conn, &conn->left, "left");
333 r += starter_whack_add_pubkey (conn, &conn->right, "right");
334 }
335
336 return r;
337 }
338
339 int starter_whack_del_conn(starter_conn_t *conn)
340 {
341 char name[32];
342 whack_message_t msg;
343
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);
348 }
349
350 int starter_whack_route_conn(starter_conn_t *conn)
351 {
352 char name[32];
353 whack_message_t msg;
354
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);
359 }
360
361 int starter_whack_initiate_conn(starter_conn_t *conn)
362 {
363 char name[32];
364 whack_message_t msg;
365
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);
371 }
372
373 int starter_whack_listen(void)
374 {
375 whack_message_t msg;
376 init_whack_msg(&msg);
377 msg.whack_listen = TRUE;
378 return send_whack_msg(&msg);
379 }
380
381 int starter_whack_shutdown(void)
382 {
383 whack_message_t msg;
384
385 init_whack_msg(&msg);
386 msg.whack_shutdown = TRUE;
387 return send_whack_msg(&msg);
388 }
389
390 int starter_whack_add_ca(starter_ca_t *ca)
391 {
392 whack_message_t msg;
393
394 init_whack_msg(&msg);
395
396 msg.whack_ca = TRUE;
397 msg.name = ca->name;
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;
405
406 return send_whack_msg(&msg);
407 }
408
409 int starter_whack_del_ca(starter_ca_t *ca)
410 {
411 whack_message_t msg;
412
413 init_whack_msg(&msg);
414
415 msg.whack_delete = TRUE;
416 msg.whack_ca = TRUE;
417 msg.name = ca->name;
418
419 return send_whack_msg(&msg);
420 }