1 /* Stroke for charon is the counterpart to whack from pluto
2 * Copyright (C) 2006 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include <sys/types.h>
17 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
27 #include <credentials/auth_cfg.h>
31 #include <constants.h>
35 #include <stroke_msg.h>
37 #include "starterstroke.h"
44 static char* push_string(stroke_msg_t
*msg
, char *string
)
46 unsigned long string_start
= msg
->length
;
48 if (string
== NULL
|| msg
->length
+ strlen(string
) >= sizeof(stroke_msg_t
))
54 msg
->length
+= strlen(string
) + 1;
55 strcpy((char*)msg
+ string_start
, string
);
56 return (char*)string_start
;
60 static int send_stroke_msg (stroke_msg_t
*msg
)
62 struct sockaddr_un ctl_addr
;
66 ctl_addr
.sun_family
= AF_UNIX
;
67 strcpy(ctl_addr
.sun_path
, CHARON_CTL_FILE
);
69 /* starter is not called from commandline, and therefore absolutely silent */
70 msg
->output_verbosity
= -1;
72 int sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
76 plog("socket() failed: %s", strerror(errno
));
79 if (connect(sock
, (struct sockaddr
*)&ctl_addr
, offsetof(struct sockaddr_un
, sun_path
) + strlen(ctl_addr
.sun_path
)) < 0)
81 plog("connect(charon_ctl) failed: %s", strerror(errno
));
87 if (write(sock
, msg
, msg
->length
) != msg
->length
)
89 plog("write(charon_ctl) failed: %s", strerror(errno
));
93 while ((byte_count
= read(sock
, buffer
, sizeof(buffer
)-1)) > 0)
95 buffer
[byte_count
] = '\0';
100 plog("read() failed: %s", strerror(errno
));
107 static char* connection_name(starter_conn_t
*conn
)
109 /* if connection name is '%auto', create a new name like conn_xxxxx */
112 if (streq(conn
->name
, "%auto"))
114 sprintf(buf
, "conn_%lu", conn
->id
);
120 static void ip_address2string(ip_address
*addr
, char *buffer
, size_t len
)
122 switch (((struct sockaddr
*)addr
)->sa_family
)
126 struct sockaddr_in6
* sin6
= (struct sockaddr_in6
*)addr
;
127 u_int8_t zeroes
[IPV6_LEN
];
129 memset(zeroes
, 0, IPV6_LEN
);
130 if (memcmp(zeroes
, &(sin6
->sin6_addr
.s6_addr
), IPV6_LEN
) &&
131 inet_ntop(AF_INET6
, &sin6
->sin6_addr
, buffer
, len
))
135 snprintf(buffer
, len
, "%%any6");
140 struct sockaddr_in
* sin
= (struct sockaddr_in
*)addr
;
141 u_int8_t zeroes
[IPV4_LEN
];
143 memset(zeroes
, 0, IPV4_LEN
);
144 if (memcmp(zeroes
, &(sin
->sin_addr
.s_addr
), IPV4_LEN
) &&
145 inet_ntop(AF_INET
, &sin
->sin_addr
, buffer
, len
))
149 /* fall through to default */
152 snprintf(buffer
, len
, "%%any");
157 static void starter_stroke_add_end(stroke_msg_t
*msg
, stroke_end_t
*msg_end
, starter_end_t
*conn_end
)
159 char buffer
[INET6_ADDRSTRLEN
];
161 msg_end
->auth
= push_string(msg
, conn_end
->auth
);
162 msg_end
->auth2
= push_string(msg
, conn_end
->auth2
);
163 msg_end
->id
= push_string(msg
, conn_end
->id
);
164 msg_end
->id2
= push_string(msg
, conn_end
->id2
);
165 msg_end
->cert
= push_string(msg
, conn_end
->cert
);
166 msg_end
->cert2
= push_string(msg
, conn_end
->cert2
);
167 msg_end
->cert_policy
= push_string(msg
, conn_end
->cert_policy
);
168 msg_end
->ca
= push_string(msg
, conn_end
->ca
);
169 msg_end
->ca2
= push_string(msg
, conn_end
->ca2
);
170 msg_end
->groups
= push_string(msg
, conn_end
->groups
);
171 msg_end
->updown
= push_string(msg
, conn_end
->updown
);
174 msg_end
->address
= push_string(msg
, conn_end
->host
);
178 ip_address2string(&conn_end
->addr
, buffer
, sizeof(buffer
));
179 msg_end
->address
= push_string(msg
, buffer
);
181 msg_end
->ikeport
= conn_end
->ikeport
;
182 msg_end
->subnets
= push_string(msg
, conn_end
->subnet
);
183 msg_end
->sourceip
= push_string(msg
, conn_end
->sourceip
);
184 msg_end
->sourceip_mask
= conn_end
->sourceip_mask
;
185 msg_end
->sendcert
= conn_end
->sendcert
;
186 msg_end
->hostaccess
= conn_end
->hostaccess
;
187 msg_end
->tohost
= !conn_end
->has_client
;
188 msg_end
->protocol
= conn_end
->protocol
;
189 msg_end
->port
= conn_end
->port
;
192 int starter_stroke_add_conn(starter_config_t
*cfg
, starter_conn_t
*conn
)
196 memset(&msg
, 0, sizeof(msg
));
197 msg
.type
= STR_ADD_CONN
;
198 msg
.length
= offsetof(stroke_msg_t
, buffer
);
199 msg
.add_conn
.version
= conn
->keyexchange
;
200 msg
.add_conn
.name
= push_string(&msg
, connection_name(conn
));
202 /* PUBKEY is preferred to PSK and EAP */
203 if (conn
->policy
& POLICY_PUBKEY
)
205 msg
.add_conn
.auth_method
= AUTH_CLASS_PUBKEY
;
207 else if (conn
->policy
& POLICY_PSK
)
209 msg
.add_conn
.auth_method
= AUTH_CLASS_PSK
;
211 else if (conn
->policy
& POLICY_XAUTH_PSK
)
213 msg
.add_conn
.auth_method
= AUTH_CLASS_EAP
;
217 msg
.add_conn
.auth_method
= AUTH_CLASS_ANY
;
219 msg
.add_conn
.eap_type
= conn
->eap_type
;
220 msg
.add_conn
.eap_vendor
= conn
->eap_vendor
;
221 msg
.add_conn
.eap_identity
= push_string(&msg
, conn
->eap_identity
);
222 msg
.add_conn
.aaa_identity
= push_string(&msg
, conn
->aaa_identity
);
223 msg
.add_conn
.xauth_identity
= push_string(&msg
, conn
->xauth_identity
);
225 if (conn
->policy
& POLICY_TUNNEL
)
227 msg
.add_conn
.mode
= MODE_TUNNEL
;
229 else if (conn
->policy
& POLICY_BEET
)
231 msg
.add_conn
.mode
= MODE_BEET
;
233 else if (conn
->policy
& POLICY_PROXY
)
235 msg
.add_conn
.mode
= MODE_TRANSPORT
;
236 msg
.add_conn
.proxy_mode
= TRUE
;
238 else if (conn
->policy
& POLICY_SHUNT_PASS
)
240 msg
.add_conn
.mode
= MODE_PASS
;
242 else if (conn
->policy
& (POLICY_SHUNT_DROP
| POLICY_SHUNT_REJECT
))
244 msg
.add_conn
.mode
= MODE_DROP
;
248 msg
.add_conn
.mode
= MODE_TRANSPORT
;
251 if (!(conn
->policy
& POLICY_DONT_REKEY
))
253 msg
.add_conn
.rekey
.reauth
= (conn
->policy
& POLICY_DONT_REAUTH
) == LEMPTY
;
254 msg
.add_conn
.rekey
.ipsec_lifetime
= conn
->sa_ipsec_life_seconds
;
255 msg
.add_conn
.rekey
.ike_lifetime
= conn
->sa_ike_life_seconds
;
256 msg
.add_conn
.rekey
.margin
= conn
->sa_rekey_margin
;
257 msg
.add_conn
.rekey
.life_bytes
= conn
->sa_ipsec_life_bytes
;
258 msg
.add_conn
.rekey
.margin_bytes
= conn
->sa_ipsec_margin_bytes
;
259 msg
.add_conn
.rekey
.life_packets
= conn
->sa_ipsec_life_packets
;
260 msg
.add_conn
.rekey
.margin_packets
= conn
->sa_ipsec_margin_packets
;
261 msg
.add_conn
.rekey
.tries
= conn
->sa_keying_tries
;
262 msg
.add_conn
.rekey
.fuzz
= conn
->sa_rekey_fuzz
;
264 msg
.add_conn
.mobike
= (conn
->policy
& POLICY_MOBIKE
) != 0;
265 msg
.add_conn
.force_encap
= (conn
->policy
& POLICY_FORCE_ENCAP
) != 0;
266 msg
.add_conn
.ipcomp
= (conn
->policy
& POLICY_COMPRESS
) != 0;
267 msg
.add_conn
.install_policy
= conn
->install_policy
;
268 msg
.add_conn
.aggressive
= conn
->aggressive
;
269 msg
.add_conn
.crl_policy
= cfg
->setup
.strictcrlpolicy
;
270 msg
.add_conn
.unique
= cfg
->setup
.uniqueids
;
271 msg
.add_conn
.algorithms
.ike
= push_string(&msg
, conn
->ike
);
272 msg
.add_conn
.algorithms
.esp
= push_string(&msg
, conn
->esp
);
273 msg
.add_conn
.dpd
.delay
= conn
->dpd_delay
;
274 msg
.add_conn
.dpd
.action
= conn
->dpd_action
;
275 msg
.add_conn
.close_action
= conn
->close_action
;
276 msg
.add_conn
.inactivity
= conn
->inactivity
;
277 msg
.add_conn
.ikeme
.mediation
= conn
->me_mediation
;
278 msg
.add_conn
.ikeme
.mediated_by
= push_string(&msg
, conn
->me_mediated_by
);
279 msg
.add_conn
.ikeme
.peerid
= push_string(&msg
, conn
->me_peerid
);
280 msg
.add_conn
.reqid
= conn
->reqid
;
281 msg
.add_conn
.mark_in
.value
= conn
->mark_in
.value
;
282 msg
.add_conn
.mark_in
.mask
= conn
->mark_in
.mask
;
283 msg
.add_conn
.mark_out
.value
= conn
->mark_out
.value
;
284 msg
.add_conn
.mark_out
.mask
= conn
->mark_out
.mask
;
285 msg
.add_conn
.tfc
= conn
->tfc
;
287 starter_stroke_add_end(&msg
, &msg
.add_conn
.me
, &conn
->left
);
288 starter_stroke_add_end(&msg
, &msg
.add_conn
.other
, &conn
->right
);
290 return send_stroke_msg(&msg
);
293 int starter_stroke_del_conn(starter_conn_t
*conn
)
297 msg
.type
= STR_DEL_CONN
;
298 msg
.length
= offsetof(stroke_msg_t
, buffer
);
299 msg
.del_conn
.name
= push_string(&msg
, connection_name(conn
));
300 return send_stroke_msg(&msg
);
303 int starter_stroke_route_conn(starter_conn_t
*conn
)
307 msg
.type
= STR_ROUTE
;
308 msg
.length
= offsetof(stroke_msg_t
, buffer
);
309 msg
.route
.name
= push_string(&msg
, connection_name(conn
));
310 return send_stroke_msg(&msg
);
313 int starter_stroke_initiate_conn(starter_conn_t
*conn
)
317 msg
.type
= STR_INITIATE
;
318 msg
.length
= offsetof(stroke_msg_t
, buffer
);
319 msg
.initiate
.name
= push_string(&msg
, connection_name(conn
));
320 return send_stroke_msg(&msg
);
323 int starter_stroke_add_ca(starter_ca_t
*ca
)
327 msg
.type
= STR_ADD_CA
;
328 msg
.length
= offsetof(stroke_msg_t
, buffer
);
329 msg
.add_ca
.name
= push_string(&msg
, ca
->name
);
330 msg
.add_ca
.cacert
= push_string(&msg
, ca
->cacert
);
331 msg
.add_ca
.crluri
= push_string(&msg
, ca
->crluri
);
332 msg
.add_ca
.crluri2
= push_string(&msg
, ca
->crluri2
);
333 msg
.add_ca
.ocspuri
= push_string(&msg
, ca
->ocspuri
);
334 msg
.add_ca
.ocspuri2
= push_string(&msg
, ca
->ocspuri2
);
335 msg
.add_ca
.certuribase
= push_string(&msg
, ca
->certuribase
);
336 return send_stroke_msg(&msg
);
339 int starter_stroke_del_ca(starter_ca_t
*ca
)
343 msg
.type
= STR_DEL_CA
;
344 msg
.length
= offsetof(stroke_msg_t
, buffer
);
345 msg
.del_ca
.name
= push_string(&msg
, ca
->name
);
346 return send_stroke_msg(&msg
);
349 int starter_stroke_configure(starter_config_t
*cfg
)
353 if (cfg
->setup
.cachecrls
)
355 msg
.type
= STR_CONFIG
;
356 msg
.length
= offsetof(stroke_msg_t
, buffer
);
357 msg
.config
.cachecrl
= 1;
358 return send_stroke_msg(&msg
);