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