1 /* Stroke for charon is the counterpart to whack from pluto
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
19 #include <sys/types.h>
20 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
31 #include <constants.h>
35 #include <stroke_msg.h>
37 #include "starterstroke.h"
42 * Authentication mehtods, must be the same values as in charon
51 static char* push_string(stroke_msg_t
*msg
, char *string
)
53 unsigned long string_start
= msg
->length
;
55 if (string
== NULL
|| msg
->length
+ strlen(string
) >= sizeof(stroke_msg_t
))
61 msg
->length
+= strlen(string
) + 1;
62 strcpy((char*)msg
+ string_start
, string
);
63 return (char*)string_start
;
67 static int send_stroke_msg (stroke_msg_t
*msg
)
69 struct sockaddr_un ctl_addr
= { AF_UNIX
, CHARON_CTL_FILE
};
73 /* starter is not called from commandline, and therefore absolutely silent */
74 msg
->output_verbosity
= -1;
76 int sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
80 plog("socket() failed: %s", strerror(errno
));
83 if (connect(sock
, (struct sockaddr
*)&ctl_addr
, offsetof(struct sockaddr_un
, sun_path
) + strlen(ctl_addr
.sun_path
)) < 0)
85 plog("connect(charon_ctl) failed: %s", strerror(errno
));
91 if (write(sock
, msg
, msg
->length
) != msg
->length
)
93 plog("write(charon_ctl) failed: %s", strerror(errno
));
97 while ((byte_count
= read(sock
, buffer
, sizeof(buffer
)-1)) > 0)
99 buffer
[byte_count
] = '\0';
104 plog("read() failed: %s", strerror(errno
));
111 static char* connection_name(starter_conn_t
*conn
)
113 /* if connection name is '%auto', create a new name like conn_xxxxx */
116 if (streq(conn
->name
, "%auto"))
118 sprintf(buf
, "conn_%ld", conn
->id
);
124 static void ip_address2string(ip_address
*addr
, char *buffer
, size_t len
)
126 switch (((struct sockaddr
*)addr
)->sa_family
)
130 struct sockaddr_in
* sin
= (struct sockaddr_in
*)addr
;
131 if (inet_ntop(AF_INET
, &sin
->sin_addr
, buffer
, len
))
139 struct sockaddr_in6
* sin6
= (struct sockaddr_in6
*)addr
;
140 if (inet_ntop(AF_INET6
, &sin6
->sin6_addr
, buffer
, len
))
150 snprintf(buffer
, len
, "0.0.0.0");
154 static void starter_stroke_add_end(stroke_msg_t
*msg
, stroke_end_t
*msg_end
, starter_end_t
*conn_end
)
156 char buffer
[INET6_ADDRSTRLEN
];
158 msg_end
->id
= push_string(msg
, conn_end
->id
);
159 msg_end
->cert
= push_string(msg
, conn_end
->cert
);
160 msg_end
->ca
= push_string(msg
, conn_end
->ca
);
161 msg_end
->groups
= push_string(msg
, conn_end
->groups
);
162 msg_end
->updown
= push_string(msg
, conn_end
->updown
);
163 ip_address2string(&conn_end
->addr
, buffer
, sizeof(buffer
));
164 msg_end
->address
= push_string(msg
, buffer
);
165 ip_address2string(&conn_end
->subnet
.addr
, buffer
, sizeof(buffer
));
166 msg_end
->subnet
= push_string(msg
, buffer
);
167 msg_end
->subnet_mask
= conn_end
->subnet
.maskbits
;
168 msg_end
->sendcert
= conn_end
->sendcert
;
169 msg_end
->hostaccess
= conn_end
->hostaccess
;
170 msg_end
->tohost
= !conn_end
->has_client
;
171 msg_end
->protocol
= conn_end
->protocol
;
172 msg_end
->port
= conn_end
->port
;
175 if (conn_end
->srcip
[0] == '%')
176 { /* %poolname, strip % */
177 msg_end
->sourceip_size
= 0;
178 msg_end
->sourceip
= push_string(msg
, conn_end
->srcip
+ 1);
182 char *pos
= strchr(conn_end
->srcip
, '/');
184 { /* CIDR subnet definition */
185 snprintf(buffer
, pos
- conn_end
->srcip
+ 1, "%s", conn_end
->srcip
);
186 msg_end
->sourceip
= push_string(msg
, buffer
);
187 msg_end
->sourceip_size
= atoi(pos
+ 1);
190 { /* a sigle address */
191 msg_end
->sourceip
= push_string(msg
, conn_end
->srcip
);
192 if (strchr(conn_end
->srcip
, ':'))
194 msg_end
->sourceip_size
= 128;
198 msg_end
->sourceip_size
= 32;
203 else if (conn_end
->modecfg
)
205 msg_end
->sourceip_size
= 1;
209 int starter_stroke_add_conn(starter_config_t
*cfg
, starter_conn_t
*conn
)
213 memset(&msg
, 0, sizeof(msg
));
214 msg
.type
= STR_ADD_CONN
;
215 msg
.length
= offsetof(stroke_msg_t
, buffer
);
216 msg
.add_conn
.ikev2
= conn
->keyexchange
== KEY_EXCHANGE_IKEV2
;
217 msg
.add_conn
.name
= push_string(&msg
, connection_name(conn
));
219 /* RSA is preferred before PSK and EAP */
220 if (conn
->policy
& POLICY_RSASIG
)
222 msg
.add_conn
.auth_method
= AUTH_RSA
;
224 else if (conn
->policy
& POLICY_PSK
)
226 msg
.add_conn
.auth_method
= AUTH_PSK
;
230 msg
.add_conn
.auth_method
= AUTH_EAP
;
232 msg
.add_conn
.eap_type
= conn
->eap_type
;
233 msg
.add_conn
.eap_vendor
= conn
->eap_vendor
;
235 if (conn
->policy
& POLICY_TUNNEL
)
237 msg
.add_conn
.mode
= 1; /* XFRM_MODE_TRANSPORT */
239 else if (conn
->policy
& POLICY_BEET
)
241 msg
.add_conn
.mode
= 4; /* XFRM_MODE_BEET */
245 msg
.add_conn
.mode
= 0; /* XFRM_MODE_TUNNEL */
248 if (!(conn
->policy
& POLICY_DONT_REKEY
))
250 msg
.add_conn
.rekey
.reauth
= (conn
->policy
& POLICY_DONT_REAUTH
) == LEMPTY
;
251 msg
.add_conn
.rekey
.ipsec_lifetime
= conn
->sa_ipsec_life_seconds
;
252 msg
.add_conn
.rekey
.ike_lifetime
= conn
->sa_ike_life_seconds
;
253 msg
.add_conn
.rekey
.margin
= conn
->sa_rekey_margin
;
254 msg
.add_conn
.rekey
.tries
= conn
->sa_keying_tries
;
255 msg
.add_conn
.rekey
.fuzz
= conn
->sa_rekey_fuzz
;
257 msg
.add_conn
.mobike
= conn
->policy
& POLICY_MOBIKE
;
258 msg
.add_conn
.force_encap
= conn
->policy
& POLICY_FORCE_ENCAP
;
259 msg
.add_conn
.crl_policy
= cfg
->setup
.strictcrlpolicy
;
260 msg
.add_conn
.unique
= cfg
->setup
.uniqueids
;
261 msg
.add_conn
.algorithms
.ike
= push_string(&msg
, conn
->ike
);
262 msg
.add_conn
.algorithms
.esp
= push_string(&msg
, conn
->esp
);
263 msg
.add_conn
.dpd
.delay
= conn
->dpd_delay
;
264 msg
.add_conn
.dpd
.action
= conn
->dpd_action
;
265 msg
.add_conn
.ikeme
.mediation
= conn
->me_mediation
;
266 msg
.add_conn
.ikeme
.mediated_by
= push_string(&msg
, conn
->me_mediated_by
);
267 msg
.add_conn
.ikeme
.peerid
= push_string(&msg
, conn
->me_peerid
);
269 starter_stroke_add_end(&msg
, &msg
.add_conn
.me
, &conn
->left
);
270 starter_stroke_add_end(&msg
, &msg
.add_conn
.other
, &conn
->right
);
272 return send_stroke_msg(&msg
);
275 int starter_stroke_del_conn(starter_conn_t
*conn
)
279 msg
.type
= STR_DEL_CONN
;
280 msg
.length
= offsetof(stroke_msg_t
, buffer
);
281 msg
.del_conn
.name
= push_string(&msg
, connection_name(conn
));
282 return send_stroke_msg(&msg
);
285 int starter_stroke_route_conn(starter_conn_t
*conn
)
289 msg
.type
= STR_ROUTE
;
290 msg
.length
= offsetof(stroke_msg_t
, buffer
);
291 msg
.route
.name
= push_string(&msg
, connection_name(conn
));
292 return send_stroke_msg(&msg
);
295 int starter_stroke_initiate_conn(starter_conn_t
*conn
)
299 msg
.type
= STR_INITIATE
;
300 msg
.length
= offsetof(stroke_msg_t
, buffer
);
301 msg
.initiate
.name
= push_string(&msg
, connection_name(conn
));
302 return send_stroke_msg(&msg
);
305 int starter_stroke_add_ca(starter_ca_t
*ca
)
309 msg
.type
= STR_ADD_CA
;
310 msg
.length
= offsetof(stroke_msg_t
, buffer
);
311 msg
.add_ca
.name
= push_string(&msg
, ca
->name
);
312 msg
.add_ca
.cacert
= push_string(&msg
, ca
->cacert
);
313 msg
.add_ca
.crluri
= push_string(&msg
, ca
->crluri
);
314 msg
.add_ca
.crluri2
= push_string(&msg
, ca
->crluri2
);
315 msg
.add_ca
.ocspuri
= push_string(&msg
, ca
->ocspuri
);
316 msg
.add_ca
.ocspuri2
= push_string(&msg
, ca
->ocspuri2
);
317 return send_stroke_msg(&msg
);
320 int starter_stroke_del_ca(starter_ca_t
*ca
)
324 msg
.type
= STR_DEL_CA
;
325 msg
.length
= offsetof(stroke_msg_t
, buffer
);
326 msg
.del_ca
.name
= push_string(&msg
, ca
->name
);
327 return send_stroke_msg(&msg
);
330 int starter_stroke_configure(starter_config_t
*cfg
)
334 if (cfg
->setup
.cachecrls
)
336 msg
.type
= STR_CONFIG
;
337 msg
.length
= offsetof(stroke_msg_t
, buffer
);
338 msg
.config
.cachecrl
= 1;
339 return send_stroke_msg(&msg
);