84c1972ed2f07d5562c2cb8b5627217fa245f9d4
[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 * RCSID $Id$
15 */
16
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/un.h>
20 #include <stddef.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 #include <freeswan.h>
25
26 #include <constants.h>
27 #include <defs.h>
28 #include <log.h>
29 #include <whack.h>
30
31 #include "starterwhack.h"
32 #include "confread.h"
33 #include "files.h"
34
35 static int
36 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
55 send_whack_msg (whack_message_t *msg)
56 {
57 struct sockaddr_un ctl_addr = { AF_UNIX, PLUTO_CTL_FILE };
58 int sock;
59 ssize_t len;
60 char *str_next, *str_roof;
61
62 /* pack strings */
63 str_next = (char *)msg->string;
64 str_roof = (char *)&msg->string[sizeof(msg->string)];
65
66 if (!pack_str(&msg->name, &str_next, &str_roof)
67 || !pack_str(&msg->left.id, &str_next, &str_roof)
68 || !pack_str(&msg->left.cert, &str_next, &str_roof)
69 || !pack_str(&msg->left.ca, &str_next, &str_roof)
70 || !pack_str(&msg->left.groups, &str_next, &str_roof)
71 || !pack_str(&msg->left.updown, &str_next, &str_roof)
72 || !pack_str(&msg->left.virt, &str_next, &str_roof)
73 || !pack_str(&msg->right.id, &str_next, &str_roof)
74 || !pack_str(&msg->right.cert, &str_next, &str_roof)
75 || !pack_str(&msg->right.ca, &str_next, &str_roof)
76 || !pack_str(&msg->right.groups, &str_next, &str_roof)
77 || !pack_str(&msg->right.updown, &str_next, &str_roof)
78 || !pack_str(&msg->right.virt, &str_next, &str_roof)
79 || !pack_str(&msg->keyid, &str_next, &str_roof)
80 || !pack_str(&msg->myid, &str_next, &str_roof)
81 || !pack_str(&msg->cacert, &str_next, &str_roof)
82 || !pack_str(&msg->ldaphost, &str_next, &str_roof)
83 || !pack_str(&msg->ldapbase, &str_next, &str_roof)
84 || !pack_str(&msg->crluri, &str_next, &str_roof)
85 || !pack_str(&msg->crluri2, &str_next, &str_roof)
86 || !pack_str(&msg->ocspuri, &str_next, &str_roof)
87 || !pack_str(&msg->ike, &str_next, &str_roof)
88 || !pack_str(&msg->esp, &str_next, &str_roof)
89 || !pack_str(&msg->sc_data, &str_next, &str_roof)
90 || (str_roof - str_next < msg->keyval.len))
91 {
92 plog("send_wack_msg(): can't pack strings");
93 return -1;
94 }
95 if (msg->keyval.ptr)
96 memcpy(str_next, msg->keyval.ptr, msg->keyval.len);
97 msg->keyval.ptr = NULL;
98 str_next += msg->keyval.len;
99 len = str_next - (char *)msg;
100
101 /* connect to pluto ctl */
102 sock = socket(AF_UNIX, SOCK_STREAM, 0);
103 if (sock < 0)
104 {
105 plog("socket() failed: %s", strerror(errno));
106 return -1;
107 }
108 if (connect(sock, (struct sockaddr *)&ctl_addr,
109 offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
110 {
111 plog("connect(pluto_ctl) failed: %s", strerror(errno));
112 close(sock);
113 return -1;
114 }
115
116 /* send message */
117 if (write(sock, msg, len) != len)
118 {
119 plog("write(pluto_ctl) failed: %s", strerror(errno));
120 close(sock);
121 return -1;
122 }
123
124 /* TODO: read reply */
125 close(sock);
126 return 0;
127 }
128
129 static void
130 init_whack_msg(whack_message_t *msg)
131 {
132 memset(msg, 0, sizeof(whack_message_t));
133 msg->magic = WHACK_MAGIC;
134 }
135
136 static char *
137 connection_name(starter_conn_t *conn)
138 {
139 /* if connection name is '%auto', create a new name like conn_xxxxx */
140 static char buf[32];
141
142 if (streq(conn->name, "%auto"))
143 {
144 sprintf(buf, "conn_%ld", conn->id);
145 return buf;
146 }
147 return conn->name;
148 }
149
150 static void
151 set_whack_end(whack_end_t *w, starter_end_t *end, sa_family_t family)
152 {
153 if (end->srcip && end->srcip[0] != '%')
154 {
155 int len = 0;
156 char *pos, *v6;
157
158 pos = strchr(end->srcip, '/');
159 v6 = strchr(end->srcip, ':');
160 if (pos)
161 {
162 /* use first address only for pluto */
163 len = pos - end->srcip;
164 }
165 w->has_srcip = !end->has_natip;
166 ttoaddr(end->srcip, len, v6 ? AF_INET6 : AF_INET, &w->host_srcip);
167 }
168 else
169 {
170 anyaddr(AF_INET, &w->host_srcip);
171 }
172 w->id = end->id;
173 w->cert = end->cert;
174 w->ca = end->ca;
175 w->groups = end->groups;
176 w->host_addr = end->addr;
177 w->has_client = end->has_client;
178
179 if (family == AF_INET6 && isanyaddr(&end->nexthop))
180 {
181 anyaddr(AF_INET6, &end->nexthop);
182 }
183 w->host_nexthop = end->nexthop;
184
185 if (w->has_client)
186 w->client = end->subnet;
187 else
188 w->client.addr.u.v4.sin_family = addrtypeof(&w->host_addr);
189
190 w->has_client_wildcard = end->has_client_wildcard;
191 w->has_port_wildcard = end->has_port_wildcard;
192 w->has_natip = end->has_natip;
193 w->allow_any = end->allow_any && !end->dns_failed;
194 w->modecfg = end->modecfg;
195 w->hostaccess = end->hostaccess;
196 w->sendcert = end->sendcert;
197 w->updown = end->updown;
198 w->host_port = IKE_UDP_PORT;
199 w->port = end->port;
200 w->protocol = end->protocol;
201 w->virt = end->virt;
202
203 if (w->port != 0)
204 {
205 int port = htons(w->port);
206
207 setportof(port, &w->host_addr);
208 setportof(port, &w->client.addr);
209 }
210 }
211
212 static int
213 starter_whack_add_pubkey (starter_conn_t *conn, starter_end_t *end
214 , const char *lr)
215 {
216 const char *err;
217 static char keyspace[1024 + 4];
218 whack_message_t msg;
219
220 init_whack_msg(&msg);
221
222 msg.whack_key = TRUE;
223 msg.pubkey_alg = PUBKEY_ALG_RSA;
224 if (end->id && end->rsakey)
225 {
226 /* special values to ignore */
227 if (streq(end->rsakey, "")
228 || streq(end->rsakey, "%none")
229 || streq(end->rsakey, "%cert")
230 || streq(end->rsakey, "0x00"))
231 {
232 return 0;
233 }
234 msg.keyid = end->id;
235 err = atobytes(end->rsakey, 0, keyspace, sizeof(keyspace), &msg.keyval.len);
236 if (err)
237 {
238 plog("conn %s/%s: rsakey malformed [%s]", connection_name(conn), lr, err);
239 return 1;
240 }
241 else
242 {
243 msg.keyval.ptr = keyspace;
244 return send_whack_msg(&msg);
245 }
246 }
247 return 0;
248 }
249
250 int
251 starter_whack_add_conn(starter_conn_t *conn)
252 {
253 whack_message_t msg;
254 int r;
255
256 init_whack_msg(&msg);
257
258 msg.whack_connection = TRUE;
259 msg.name = connection_name(conn);
260
261 msg.ikev1 = conn->keyexchange != KEY_EXCHANGE_IKEV2;
262 msg.addr_family = conn->addr_family;
263 msg.tunnel_addr_family = conn->tunnel_addr_family;
264 msg.sa_ike_life_seconds = conn->sa_ike_life_seconds;
265 msg.sa_ipsec_life_seconds = conn->sa_ipsec_life_seconds;
266 msg.sa_rekey_margin = conn->sa_rekey_margin;
267 msg.sa_rekey_fuzz = conn->sa_rekey_fuzz;
268 msg.sa_keying_tries = conn->sa_keying_tries;
269 msg.policy = conn->policy;
270
271 /*
272 * Make sure the IKEv2-only policy bits are unset for IKEv1 connections
273 */
274 msg.policy &= ~POLICY_DONT_REAUTH;
275 msg.policy &= ~POLICY_BEET;
276 msg.policy &= ~POLICY_MOBIKE;
277 msg.policy &= ~POLICY_FORCE_ENCAP;
278
279 set_whack_end(&msg.left, &conn->left, conn->addr_family);
280 set_whack_end(&msg.right, &conn->right, conn->addr_family);
281
282 msg.esp = conn->esp;
283 msg.ike = conn->ike;
284 msg.pfsgroup = conn->pfsgroup;
285
286 /* taken from pluto/whack.c */
287 if (msg.pfsgroup)
288 {
289 char esp_buf[256];
290
291 snprintf(esp_buf, sizeof (esp_buf), "%s;%s"
292 , msg.esp ? msg.esp : ""
293 , msg.pfsgroup ? msg.pfsgroup : "");
294 msg.esp = esp_buf;
295
296 DBG(DBG_CONTROL,
297 DBG_log("Setting --esp=%s", msg.esp)
298 )
299 }
300 msg.dpd_delay = conn->dpd_delay;
301 msg.dpd_timeout = conn->dpd_timeout;
302 msg.dpd_action = conn->dpd_action;
303 /* msg.dpd_count = conn->dpd_count; not supported yet by strongSwan */
304
305 r = send_whack_msg(&msg);
306
307 if (r == 0 && (conn->policy & POLICY_RSASIG))
308 {
309 r += starter_whack_add_pubkey (conn, &conn->left, "left");
310 r += starter_whack_add_pubkey (conn, &conn->right, "right");
311 }
312
313 return r;
314 }
315
316 int
317 starter_whack_del_conn(starter_conn_t *conn)
318 {
319 whack_message_t msg;
320
321 init_whack_msg(&msg);
322 msg.whack_delete = TRUE;
323 msg.name = connection_name(conn);
324 return send_whack_msg(&msg);
325 }
326
327 int
328 starter_whack_route_conn(starter_conn_t *conn)
329 {
330 whack_message_t msg;
331
332 init_whack_msg(&msg);
333 msg.whack_route = TRUE;
334 msg.name = connection_name(conn);
335 return send_whack_msg(&msg);
336 }
337
338 int
339 starter_whack_initiate_conn(starter_conn_t *conn)
340 {
341 whack_message_t msg;
342
343 init_whack_msg(&msg);
344 msg.whack_initiate = TRUE;
345 msg.whack_async = TRUE;
346 msg.name = connection_name(conn);
347 return send_whack_msg(&msg);
348 }
349
350 int
351 starter_whack_listen(void)
352 {
353 whack_message_t msg;
354 init_whack_msg(&msg);
355 msg.whack_listen = TRUE;
356 return send_whack_msg(&msg);
357 }
358
359 int starter_whack_shutdown(void)
360 {
361 whack_message_t msg;
362
363 init_whack_msg(&msg);
364 msg.whack_shutdown = TRUE;
365 return send_whack_msg(&msg);
366 }
367
368 int
369 starter_whack_add_ca(starter_ca_t *ca)
370 {
371 whack_message_t msg;
372
373 init_whack_msg(&msg);
374
375 msg.whack_ca = TRUE;
376 msg.name = ca->name;
377 msg.cacert = ca->cacert;
378 msg.ldaphost = ca->ldaphost;
379 msg.ldapbase = ca->ldapbase;
380 msg.crluri = ca->crluri;
381 msg.crluri2 = ca->crluri2;
382 msg.ocspuri = ca->ocspuri;
383 msg.whack_strict = ca->strict;
384
385 return send_whack_msg(&msg);
386 }
387
388 int
389 starter_whack_del_ca(starter_ca_t *ca)
390 {
391 whack_message_t msg;
392
393 init_whack_msg(&msg);
394
395 msg.whack_delete = TRUE;
396 msg.whack_ca = TRUE;
397 msg.name = ca->name;
398
399 return send_whack_msg(&msg);
400 }