Unify format of HSR copyright statements
[strongswan.git] / src / starter / starterstroke.c
1 /*
2 * Copyright (C) 2007-2015 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <string.h>
21
22 #include <credentials/auth_cfg.h>
23
24 #include <library.h>
25 #include <utils/debug.h>
26
27 #include <stroke_msg.h>
28
29 #include "starterstroke.h"
30 #include "confread.h"
31 #include "files.h"
32
33 #define IPV4_LEN 4
34 #define IPV6_LEN 16
35
36 static stroke_msg_t *create_stroke_msg(int type)
37 {
38 stroke_msg_t *msg;
39
40 INIT(msg,
41 .type = type,
42 .length = offsetof(stroke_msg_t, buffer),
43 );
44 return msg;
45 }
46
47 #define push_string(msg, field, str) \
48 push_string_impl(msg, offsetof(stroke_msg_t, field), str)
49 #define push_string_end(msg, offset, field, str) \
50 push_string_impl(msg, offset + offsetof(stroke_end_t, field), str)
51
52 static void push_string_impl(stroke_msg_t **msg, size_t offset, char *string)
53 {
54 size_t cur_len = (*msg)->length, str_len;
55
56 if (!string)
57 {
58 return;
59 }
60 str_len = strlen(string) + 1;
61 if (cur_len + str_len >= UINT16_MAX)
62 {
63 (*msg)->length = UINT16_MAX;
64 return;
65 }
66 while (cur_len + str_len > sizeof(stroke_msg_t) + (*msg)->buflen)
67 {
68 *msg = realloc(*msg, sizeof(stroke_msg_t) + (*msg)->buflen +
69 STROKE_BUF_LEN_INC);
70 (*msg)->buflen += STROKE_BUF_LEN_INC;
71 }
72 (*msg)->length += str_len;
73 strcpy((char*)*msg + cur_len, string);
74 *(char**)((char*)*msg + offset) = (char*)cur_len;
75 }
76
77 static int send_stroke_msg(stroke_msg_t *msg)
78 {
79 stream_t *stream;
80 char *uri, buffer[64];
81 int count;
82
83 if (msg->length == UINT16_MAX)
84 {
85 DBG1(DBG_APP, "stroke message exceeds maximum buffer size");
86 free(msg);
87 return -1;
88 }
89
90 /* starter is not called from commandline, and therefore absolutely silent */
91 msg->output_verbosity = -1;
92
93 uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket",
94 "unix://" CHARON_CTL_FILE, daemon_name);
95 stream = lib->streams->connect(lib->streams, uri);
96 if (!stream)
97 {
98 DBG1(DBG_APP, "failed to connect to stroke socket '%s'", uri);
99 free(msg);
100 return -1;
101 }
102
103 if (!stream->write_all(stream, msg, msg->length))
104 {
105 DBG1(DBG_APP, "sending stroke message failed");
106 stream->destroy(stream);
107 free(msg);
108 return -1;
109 }
110 while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0)
111 {
112 buffer[count] = '\0';
113 DBG1(DBG_APP, "%s", buffer);
114 }
115 if (count < 0)
116 {
117 DBG1(DBG_APP, "reading stroke response failed");
118 }
119 stream->destroy(stream);
120 free(msg);
121 return 0;
122 }
123
124 static char* connection_name(starter_conn_t *conn)
125 {
126 /* if connection name is '%auto', create a new name like conn_xxxxx */
127 static char buf[32];
128
129 if (streq(conn->name, "%auto"))
130 {
131 sprintf(buf, "conn_%lu", conn->id);
132 return buf;
133 }
134 return conn->name;
135 }
136
137 static void add_end(stroke_msg_t **msg, size_t offset, starter_end_t *conn_end)
138 {
139 stroke_end_t *msg_end;
140
141 push_string_end(msg, offset, auth, conn_end->auth);
142 push_string_end(msg, offset, auth2, conn_end->auth2);
143 push_string_end(msg, offset, id, conn_end->id);
144 push_string_end(msg, offset, id2, conn_end->id2);
145 push_string_end(msg, offset, rsakey, conn_end->rsakey);
146 push_string_end(msg, offset, cert, conn_end->cert);
147 push_string_end(msg, offset, cert2, conn_end->cert2);
148 push_string_end(msg, offset, cert_policy, conn_end->cert_policy);
149 push_string_end(msg, offset, ca, conn_end->ca);
150 push_string_end(msg, offset, ca2, conn_end->ca2);
151 push_string_end(msg, offset, groups, conn_end->groups);
152 push_string_end(msg, offset, groups2, conn_end->groups2);
153 push_string_end(msg, offset, updown, conn_end->updown);
154 if (conn_end->host)
155 {
156 push_string_end(msg, offset, address, conn_end->host);
157 }
158 else
159 {
160 push_string_end(msg, offset, address, "%any");
161 }
162 push_string_end(msg, offset, subnets, conn_end->subnet);
163 push_string_end(msg, offset, sourceip, conn_end->sourceip);
164 push_string_end(msg, offset, dns, conn_end->dns);
165
166 /* we can't assign it earlier as msg might change */
167 msg_end = (stroke_end_t*)((char*)(*msg) + offset);
168 msg_end->ikeport = conn_end->ikeport;
169 msg_end->sendcert = conn_end->sendcert;
170 msg_end->hostaccess = conn_end->hostaccess;
171 msg_end->tohost = !conn_end->subnet;
172 msg_end->allow_any = conn_end->allow_any;
173 msg_end->protocol = conn_end->protocol;
174 msg_end->from_port = conn_end->from_port;
175 msg_end->to_port = conn_end->to_port;
176 }
177
178 int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
179 {
180 stroke_msg_t *msg;
181
182 msg = create_stroke_msg(STR_ADD_CONN);
183 msg->add_conn.version = conn->keyexchange;
184 push_string(&msg, add_conn.name, connection_name(conn));
185 push_string(&msg, add_conn.eap_identity, conn->eap_identity);
186 push_string(&msg, add_conn.aaa_identity, conn->aaa_identity);
187 push_string(&msg, add_conn.xauth_identity, conn->xauth_identity);
188
189 msg->add_conn.mode = conn->mode;
190 msg->add_conn.proxy_mode = conn->proxy_mode;
191
192 if (!(conn->options & SA_OPTION_DONT_REKEY))
193 {
194 msg->add_conn.rekey.reauth = !(conn->options & SA_OPTION_DONT_REAUTH);
195 msg->add_conn.rekey.ipsec_lifetime = conn->sa_ipsec_life_seconds;
196 msg->add_conn.rekey.ike_lifetime = conn->sa_ike_life_seconds;
197 msg->add_conn.rekey.margin = conn->sa_rekey_margin;
198 msg->add_conn.rekey.life_bytes = conn->sa_ipsec_life_bytes;
199 msg->add_conn.rekey.margin_bytes = conn->sa_ipsec_margin_bytes;
200 msg->add_conn.rekey.life_packets = conn->sa_ipsec_life_packets;
201 msg->add_conn.rekey.margin_packets = conn->sa_ipsec_margin_packets;
202 msg->add_conn.rekey.fuzz = conn->sa_rekey_fuzz;
203 }
204 msg->add_conn.rekey.tries = conn->sa_keying_tries;
205
206 msg->add_conn.mobike = conn->options & SA_OPTION_MOBIKE;
207 msg->add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP;
208 msg->add_conn.fragmentation = conn->fragmentation;
209 msg->add_conn.ikedscp = conn->ikedscp;
210 msg->add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS;
211 msg->add_conn.install_policy = conn->install_policy;
212 msg->add_conn.aggressive = conn->aggressive;
213 msg->add_conn.pushmode = conn->options & SA_OPTION_MODECFG_PUSH;
214 msg->add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy;
215 msg->add_conn.unique = cfg->setup.uniqueids;
216 push_string(&msg, add_conn.algorithms.ike, conn->ike);
217 push_string(&msg, add_conn.algorithms.esp, conn->esp);
218 push_string(&msg, add_conn.algorithms.ah, conn->ah);
219 msg->add_conn.dpd.delay = conn->dpd_delay;
220 msg->add_conn.dpd.timeout = conn->dpd_timeout;
221 msg->add_conn.dpd.action = conn->dpd_action;
222 msg->add_conn.close_action = conn->close_action;
223 msg->add_conn.sha256_96 = conn->sha256_96;
224 msg->add_conn.inactivity = conn->inactivity;
225 msg->add_conn.ikeme.mediation = conn->me_mediation;
226 push_string(&msg, add_conn.ikeme.mediated_by, conn->me_mediated_by);
227 push_string(&msg, add_conn.ikeme.peerid, conn->me_peerid);
228 msg->add_conn.reqid = conn->reqid;
229 msg->add_conn.replay_window = conn->replay_window;
230 msg->add_conn.mark_in.value = conn->mark_in.value;
231 msg->add_conn.mark_in.mask = conn->mark_in.mask;
232 msg->add_conn.mark_out.value = conn->mark_out.value;
233 msg->add_conn.mark_out.mask = conn->mark_out.mask;
234 msg->add_conn.tfc = conn->tfc;
235
236 add_end(&msg, offsetof(stroke_msg_t, add_conn.me), &conn->left);
237 add_end(&msg, offsetof(stroke_msg_t, add_conn.other), &conn->right);
238
239 if (!msg->add_conn.me.auth && !msg->add_conn.other.auth &&
240 conn->authby)
241 { /* leftauth/rightauth not set, use legacy options */
242 if (streq(conn->authby, "rsa") || streq(conn->authby, "rsasig") ||
243 streq(conn->authby, "ecdsa") || streq(conn->authby, "ecdsasig") ||
244 streq(conn->authby, "pubkey"))
245 {
246 push_string(&msg, add_conn.me.auth, "pubkey");
247 push_string(&msg, add_conn.other.auth, "pubkey");
248 }
249 else if (streq(conn->authby, "secret") || streq(conn->authby, "psk"))
250 {
251 push_string(&msg, add_conn.me.auth, "psk");
252 push_string(&msg, add_conn.other.auth, "psk");
253 }
254 else if (streq(conn->authby, "xauthrsasig"))
255 {
256 push_string(&msg, add_conn.me.auth, "pubkey");
257 push_string(&msg, add_conn.other.auth, "pubkey");
258 if (conn->options & SA_OPTION_XAUTH_SERVER)
259 {
260 push_string(&msg, add_conn.other.auth2, "xauth");
261 }
262 else
263 {
264 push_string(&msg, add_conn.me.auth2, "xauth");
265 }
266 }
267 else if (streq(conn->authby, "xauthpsk"))
268 {
269 push_string(&msg, add_conn.me.auth, "psk");
270 push_string(&msg, add_conn.other.auth, "psk");
271 if (conn->options & SA_OPTION_XAUTH_SERVER)
272 {
273 push_string(&msg, add_conn.other.auth2, "xauth");
274 }
275 else
276 {
277 push_string(&msg, add_conn.me.auth2, "xauth");
278 }
279 }
280 }
281 return send_stroke_msg(msg);
282 }
283
284 int starter_stroke_del_conn(starter_conn_t *conn)
285 {
286 stroke_msg_t *msg;
287
288 msg = create_stroke_msg(STR_DEL_CONN);
289 push_string(&msg, del_conn.name, connection_name(conn));
290 return send_stroke_msg(msg);
291 }
292
293 int starter_stroke_route_conn(starter_conn_t *conn)
294 {
295 stroke_msg_t *msg;
296
297 msg = create_stroke_msg(STR_ROUTE);
298 push_string(&msg, route.name, connection_name(conn));
299 return send_stroke_msg(msg);
300 }
301
302 int starter_stroke_unroute_conn(starter_conn_t *conn)
303 {
304 stroke_msg_t *msg;
305
306 msg = create_stroke_msg(STR_UNROUTE);
307 push_string(&msg, route.name, connection_name(conn));
308 return send_stroke_msg(msg);
309 }
310
311 int starter_stroke_initiate_conn(starter_conn_t *conn)
312 {
313 stroke_msg_t *msg;
314
315 msg = create_stroke_msg(STR_INITIATE);
316 push_string(&msg, initiate.name, connection_name(conn));
317 return send_stroke_msg(msg);
318 }
319
320 int starter_stroke_add_ca(starter_ca_t *ca)
321 {
322 stroke_msg_t *msg;
323
324 msg = create_stroke_msg(STR_ADD_CA);
325 push_string(&msg, add_ca.name, ca->name);
326 push_string(&msg, add_ca.cacert, ca->cacert);
327 push_string(&msg, add_ca.crluri, ca->crluri);
328 push_string(&msg, add_ca.crluri2, ca->crluri2);
329 push_string(&msg, add_ca.ocspuri, ca->ocspuri);
330 push_string(&msg, add_ca.ocspuri2, ca->ocspuri2);
331 push_string(&msg, add_ca.certuribase, ca->certuribase);
332 return send_stroke_msg(msg);
333 }
334
335 int starter_stroke_del_ca(starter_ca_t *ca)
336 {
337 stroke_msg_t *msg;
338
339 msg = create_stroke_msg(STR_DEL_CA);
340 push_string(&msg, del_ca.name, ca->name);
341 return send_stroke_msg(msg);
342 }
343
344 int starter_stroke_configure(starter_config_t *cfg)
345 {
346 stroke_msg_t *msg;
347
348 if (cfg->setup.cachecrls)
349 {
350 msg = create_stroke_msg(STR_CONFIG);
351 msg->config.cachecrl = 1;
352 return send_stroke_msg(msg);
353 }
354 return 0;
355 }