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