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