2 * Copyright (C) 2008 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 "stroke_socket.h"
19 #include <sys/types.h>
21 #include <sys/socket.h>
23 #include <sys/fcntl.h>
29 #include <threading/thread.h>
30 #include <processing/jobs/callback_job.h>
32 #include "stroke_config.h"
33 #include "stroke_control.h"
34 #include "stroke_cred.h"
35 #include "stroke_ca.h"
36 #include "stroke_attribute.h"
37 #include "stroke_list.h"
39 typedef struct stroke_job_context_t stroke_job_context_t
;
40 typedef struct private_stroke_socket_t private_stroke_socket_t
;
43 * private data of stroke_socket
45 struct private_stroke_socket_t
{
50 stroke_socket_t
public;
53 * Unix socket to listen for strokes
58 * job accepting stroke messages
63 * configuration backend
65 stroke_config_t
*config
;
70 stroke_attribute_t
*attribute
;
73 * controller to control daemon
75 stroke_control_t
*control
;
88 * Status information logging
94 * job context to pass to processing thread
96 struct stroke_job_context_t
{
99 * file descriptor to read from
104 * global stroke interface
106 private_stroke_socket_t
*this;
110 * Helper function which corrects the string pointers
111 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
112 * contains RELATIVE addresses (relative to the beginning of the
113 * stroke_msg). They must be corrected if they reach our address
116 static void pop_string(stroke_msg_t
*msg
, char **string
)
123 /* check for sanity of string pointer and string */
124 if (string
< (char**)msg
||
125 string
> (char**)((char*)msg
+ sizeof(stroke_msg_t
)) ||
126 (unsigned long)*string
< (unsigned long)((char*)msg
->buffer
- (char*)msg
) ||
127 (unsigned long)*string
> msg
->length
)
129 *string
= "(invalid pointer in stroke msg)";
133 *string
= (char*)msg
+ (unsigned long)*string
;
138 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
140 static void pop_end(stroke_msg_t
*msg
, const char* label
, stroke_end_t
*end
)
142 pop_string(msg
, &end
->address
);
143 pop_string(msg
, &end
->subnets
);
144 pop_string(msg
, &end
->sourceip
);
145 pop_string(msg
, &end
->auth
);
146 pop_string(msg
, &end
->auth2
);
147 pop_string(msg
, &end
->id
);
148 pop_string(msg
, &end
->id2
);
149 pop_string(msg
, &end
->cert
);
150 pop_string(msg
, &end
->cert2
);
151 pop_string(msg
, &end
->ca
);
152 pop_string(msg
, &end
->ca2
);
153 pop_string(msg
, &end
->groups
);
154 pop_string(msg
, &end
->cert_policy
);
155 pop_string(msg
, &end
->updown
);
157 DBG2(DBG_CFG
, " %s=%s", label
, end
->address
);
158 DBG2(DBG_CFG
, " %ssubnet=%s", label
, end
->subnets
);
159 DBG2(DBG_CFG
, " %ssourceip=%s", label
, end
->sourceip
);
160 DBG2(DBG_CFG
, " %sauth=%s", label
, end
->auth
);
161 DBG2(DBG_CFG
, " %sauth2=%s", label
, end
->auth2
);
162 DBG2(DBG_CFG
, " %sid=%s", label
, end
->id
);
163 DBG2(DBG_CFG
, " %sid2=%s", label
, end
->id2
);
164 DBG2(DBG_CFG
, " %scert=%s", label
, end
->cert
);
165 DBG2(DBG_CFG
, " %scert2=%s", label
, end
->cert2
);
166 DBG2(DBG_CFG
, " %sca=%s", label
, end
->ca
);
167 DBG2(DBG_CFG
, " %sca2=%s", label
, end
->ca2
);
168 DBG2(DBG_CFG
, " %sgroups=%s", label
, end
->groups
);
169 DBG2(DBG_CFG
, " %supdown=%s", label
, end
->updown
);
173 * Add a connection to the configuration list
175 static void stroke_add_conn(private_stroke_socket_t
*this, stroke_msg_t
*msg
)
177 pop_string(msg
, &msg
->add_conn
.name
);
178 DBG1(DBG_CFG
, "received stroke: add connection '%s'", msg
->add_conn
.name
);
180 DBG2(DBG_CFG
, "conn %s", msg
->add_conn
.name
);
181 pop_end(msg
, "left", &msg
->add_conn
.me
);
182 pop_end(msg
, "right", &msg
->add_conn
.other
);
183 pop_string(msg
, &msg
->add_conn
.eap_identity
);
184 pop_string(msg
, &msg
->add_conn
.aaa_identity
);
185 pop_string(msg
, &msg
->add_conn
.algorithms
.ike
);
186 pop_string(msg
, &msg
->add_conn
.algorithms
.esp
);
187 pop_string(msg
, &msg
->add_conn
.ikeme
.mediated_by
);
188 pop_string(msg
, &msg
->add_conn
.ikeme
.peerid
);
189 DBG2(DBG_CFG
, " eap_identity=%s", msg
->add_conn
.eap_identity
);
190 DBG2(DBG_CFG
, " aaa_identity=%s", msg
->add_conn
.aaa_identity
);
191 DBG2(DBG_CFG
, " ike=%s", msg
->add_conn
.algorithms
.ike
);
192 DBG2(DBG_CFG
, " esp=%s", msg
->add_conn
.algorithms
.esp
);
193 DBG2(DBG_CFG
, " mediation=%s", msg
->add_conn
.ikeme
.mediation ?
"yes" : "no");
194 DBG2(DBG_CFG
, " mediated_by=%s", msg
->add_conn
.ikeme
.mediated_by
);
195 DBG2(DBG_CFG
, " me_peerid=%s", msg
->add_conn
.ikeme
.peerid
);
197 this->config
->add(this->config
, msg
);
198 this->attribute
->add_pool(this->attribute
, msg
);
202 * Delete a connection from the list
204 static void stroke_del_conn(private_stroke_socket_t
*this, stroke_msg_t
*msg
)
206 pop_string(msg
, &msg
->del_conn
.name
);
207 DBG1(DBG_CFG
, "received stroke: delete connection '%s'", msg
->del_conn
.name
);
209 this->config
->del(this->config
, msg
);
210 this->attribute
->del_pool(this->attribute
, msg
);
214 * initiate a connection by name
216 static void stroke_initiate(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
218 pop_string(msg
, &msg
->initiate
.name
);
219 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
221 this->control
->initiate(this->control
, msg
, out
);
225 * terminate a connection by name
227 static void stroke_terminate(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
229 pop_string(msg
, &msg
->terminate
.name
);
230 DBG1(DBG_CFG
, "received stroke: terminate '%s'", msg
->terminate
.name
);
232 this->control
->terminate(this->control
, msg
, out
);
236 * terminate a connection by peers virtual IP
238 static void stroke_terminate_srcip(private_stroke_socket_t
*this,
239 stroke_msg_t
*msg
, FILE *out
)
241 pop_string(msg
, &msg
->terminate_srcip
.start
);
242 pop_string(msg
, &msg
->terminate_srcip
.end
);
243 DBG1(DBG_CFG
, "received stroke: terminate-srcip %s-%s",
244 msg
->terminate_srcip
.start
, msg
->terminate_srcip
.end
);
246 this->control
->terminate_srcip(this->control
, msg
, out
);
250 * rekey a connection by name/id
252 static void stroke_rekey(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
254 pop_string(msg
, &msg
->terminate
.name
);
255 DBG1(DBG_CFG
, "received stroke: rekey '%s'", msg
->rekey
.name
);
257 this->control
->rekey(this->control
, msg
, out
);
261 * route a policy (install SPD entries)
263 static void stroke_route(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
265 pop_string(msg
, &msg
->route
.name
);
266 DBG1(DBG_CFG
, "received stroke: route '%s'", msg
->route
.name
);
268 this->control
->route(this->control
, msg
, out
);
274 static void stroke_unroute(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
276 pop_string(msg
, &msg
->terminate
.name
);
277 DBG1(DBG_CFG
, "received stroke: unroute '%s'", msg
->route
.name
);
279 this->control
->unroute(this->control
, msg
, out
);
283 * Add a ca information record to the cainfo list
285 static void stroke_add_ca(private_stroke_socket_t
*this,
286 stroke_msg_t
*msg
, FILE *out
)
288 pop_string(msg
, &msg
->add_ca
.name
);
289 DBG1(DBG_CFG
, "received stroke: add ca '%s'", msg
->add_ca
.name
);
291 pop_string(msg
, &msg
->add_ca
.cacert
);
292 pop_string(msg
, &msg
->add_ca
.crluri
);
293 pop_string(msg
, &msg
->add_ca
.crluri2
);
294 pop_string(msg
, &msg
->add_ca
.ocspuri
);
295 pop_string(msg
, &msg
->add_ca
.ocspuri2
);
296 pop_string(msg
, &msg
->add_ca
.certuribase
);
297 DBG2(DBG_CFG
, "ca %s", msg
->add_ca
.name
);
298 DBG2(DBG_CFG
, " cacert=%s", msg
->add_ca
.cacert
);
299 DBG2(DBG_CFG
, " crluri=%s", msg
->add_ca
.crluri
);
300 DBG2(DBG_CFG
, " crluri2=%s", msg
->add_ca
.crluri2
);
301 DBG2(DBG_CFG
, " ocspuri=%s", msg
->add_ca
.ocspuri
);
302 DBG2(DBG_CFG
, " ocspuri2=%s", msg
->add_ca
.ocspuri2
);
303 DBG2(DBG_CFG
, " certuribase=%s", msg
->add_ca
.certuribase
);
305 this->ca
->add(this->ca
, msg
);
309 * Delete a ca information record from the cainfo list
311 static void stroke_del_ca(private_stroke_socket_t
*this,
312 stroke_msg_t
*msg
, FILE *out
)
314 pop_string(msg
, &msg
->del_ca
.name
);
315 DBG1(DBG_CFG
, "received stroke: delete ca '%s'", msg
->del_ca
.name
);
317 this->ca
->del(this->ca
, msg
);
322 * show status of daemon
324 static void stroke_status(private_stroke_socket_t
*this,
325 stroke_msg_t
*msg
, FILE *out
, bool all
)
327 pop_string(msg
, &(msg
->status
.name
));
329 this->list
->status(this->list
, msg
, out
, all
);
333 * list various information
335 static void stroke_list(private_stroke_socket_t
*this, stroke_msg_t
*msg
, FILE *out
)
337 if (msg
->list
.flags
& LIST_CAINFOS
)
339 this->ca
->list(this->ca
, msg
, out
);
341 this->list
->list(this->list
, msg
, out
);
345 * reread various information
347 static void stroke_reread(private_stroke_socket_t
*this,
348 stroke_msg_t
*msg
, FILE *out
)
350 this->cred
->reread(this->cred
, msg
, out
);
354 * purge various information
356 static void stroke_purge(private_stroke_socket_t
*this,
357 stroke_msg_t
*msg
, FILE *out
)
359 if (msg
->purge
.flags
& PURGE_OCSP
)
361 lib
->credmgr
->flush_cache(lib
->credmgr
, CERT_X509_OCSP_RESPONSE
);
363 if (msg
->purge
.flags
& PURGE_CRLS
)
365 lib
->credmgr
->flush_cache(lib
->credmgr
, CERT_X509_CRL
);
367 if (msg
->purge
.flags
& PURGE_CERTS
)
369 lib
->credmgr
->flush_cache(lib
->credmgr
, CERT_X509
);
371 if (msg
->purge
.flags
& PURGE_IKE
)
373 this->control
->purge_ike(this->control
, msg
, out
);
378 * Export in-memory credentials
380 static void stroke_export(private_stroke_socket_t
*this,
381 stroke_msg_t
*msg
, FILE *out
)
383 pop_string(msg
, &msg
->export
.selector
);
385 if (msg
->purge
.flags
& EXPORT_X509
)
387 enumerator_t
*enumerator
;
388 identification_t
*id
;
392 id
= identification_create_from_string(msg
->export
.selector
);
393 enumerator
= lib
->credmgr
->create_cert_enumerator(lib
->credmgr
,
394 CERT_X509
, KEY_ANY
, id
, FALSE
);
395 while (enumerator
->enumerate(enumerator
, &cert
))
397 if (cert
->get_encoding(cert
, CERT_PEM
, &encoded
))
399 fprintf(out
, "%.*s", (int)encoded
.len
, encoded
.ptr
);
403 enumerator
->destroy(enumerator
);
411 static void stroke_leases(private_stroke_socket_t
*this,
412 stroke_msg_t
*msg
, FILE *out
)
414 pop_string(msg
, &msg
->leases
.pool
);
415 pop_string(msg
, &msg
->leases
.address
);
417 this->list
->leases(this->list
, msg
, out
);
423 static void stroke_memusage(private_stroke_socket_t
*this,
424 stroke_msg_t
*msg
, FILE *out
)
426 if (lib
->leak_detective
)
428 lib
->leak_detective
->usage(lib
->leak_detective
, out
);
433 * set the verbosity debug output
435 static void stroke_loglevel(private_stroke_socket_t
*this,
436 stroke_msg_t
*msg
, FILE *out
)
438 enumerator_t
*enumerator
;
439 sys_logger_t
*sys_logger
;
440 file_logger_t
*file_logger
;
443 pop_string(msg
, &(msg
->loglevel
.type
));
444 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
445 msg
->loglevel
.level
, msg
->loglevel
.type
);
447 group
= enum_from_name(debug_names
, msg
->loglevel
.type
);
450 fprintf(out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
453 /* we set the loglevel on ALL sys- and file-loggers */
454 enumerator
= charon
->sys_loggers
->create_enumerator(charon
->sys_loggers
);
455 while (enumerator
->enumerate(enumerator
, &sys_logger
))
457 sys_logger
->set_level(sys_logger
, group
, msg
->loglevel
.level
);
459 enumerator
->destroy(enumerator
);
460 enumerator
= charon
->file_loggers
->create_enumerator(charon
->file_loggers
);
461 while (enumerator
->enumerate(enumerator
, &file_logger
))
463 file_logger
->set_level(file_logger
, group
, msg
->loglevel
.level
);
465 enumerator
->destroy(enumerator
);
469 * set various config options
471 static void stroke_config(private_stroke_socket_t
*this,
472 stroke_msg_t
*msg
, FILE *out
)
474 this->cred
->cachecrl(this->cred
, msg
->config
.cachecrl
);
478 * destroy a job context
480 static void stroke_job_context_destroy(stroke_job_context_t
*this)
490 * process a stroke request from the socket pointed by "fd"
492 static job_requeue_t
process(stroke_job_context_t
*ctx
)
495 u_int16_t msg_length
;
498 private_stroke_socket_t
*this = ctx
->this;
499 int strokefd
= ctx
->fd
;
501 /* peek the length */
502 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
503 if (bytes_read
!= sizeof(msg_length
))
505 DBG1(DBG_CFG
, "reading length of stroke message failed: %s",
507 return JOB_REQUEUE_NONE
;
511 msg
= alloca(msg_length
);
512 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
513 if (bytes_read
!= msg_length
)
515 DBG1(DBG_CFG
, "reading stroke message failed: %s", strerror(errno
));
516 return JOB_REQUEUE_NONE
;
519 out
= fdopen(strokefd
, "w+");
522 DBG1(DBG_CFG
, "opening stroke output channel failed: %s", strerror(errno
));
523 return JOB_REQUEUE_NONE
;
526 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
531 stroke_initiate(this, msg
, out
);
534 stroke_route(this, msg
, out
);
537 stroke_unroute(this, msg
, out
);
540 stroke_terminate(this, msg
, out
);
542 case STR_TERMINATE_SRCIP
:
543 stroke_terminate_srcip(this, msg
, out
);
546 stroke_rekey(this, msg
, out
);
549 stroke_status(this, msg
, out
, FALSE
);
552 stroke_status(this, msg
, out
, TRUE
);
555 stroke_add_conn(this, msg
);
558 stroke_del_conn(this, msg
);
561 stroke_add_ca(this, msg
, out
);
564 stroke_del_ca(this, msg
, out
);
567 stroke_loglevel(this, msg
, out
);
570 stroke_config(this, msg
, out
);
573 stroke_list(this, msg
, out
);
576 stroke_reread(this, msg
, out
);
579 stroke_purge(this, msg
, out
);
582 stroke_export(this, msg
, out
);
585 stroke_leases(this, msg
, out
);
588 stroke_memusage(this, msg
, out
);
591 DBG1(DBG_CFG
, "received unknown stroke");
595 /* fclose() closes underlying FD */
597 return JOB_REQUEUE_NONE
;
601 * Implementation of private_stroke_socket_t.stroke_receive.
603 static job_requeue_t
receive(private_stroke_socket_t
*this)
605 struct sockaddr_un strokeaddr
;
606 int strokeaddrlen
= sizeof(strokeaddr
);
610 stroke_job_context_t
*ctx
;
612 oldstate
= thread_cancelability(TRUE
);
613 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
614 thread_cancelability(oldstate
);
618 DBG1(DBG_CFG
, "accepting stroke connection failed: %s", strerror(errno
));
619 return JOB_REQUEUE_FAIR
;
622 ctx
= malloc_thing(stroke_job_context_t
);
625 job
= callback_job_create((callback_job_cb_t
)process
,
626 ctx
, (void*)stroke_job_context_destroy
, this->job
);
627 lib
->processor
->queue_job(lib
->processor
, (job_t
*)job
);
629 return JOB_REQUEUE_FAIR
;
634 * initialize and open stroke socket
636 static bool open_socket(private_stroke_socket_t
*this)
638 struct sockaddr_un socket_addr
;
641 socket_addr
.sun_family
= AF_UNIX
;
642 strcpy(socket_addr
.sun_path
, STROKE_SOCKET
);
644 /* set up unix socket */
645 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
646 if (this->socket
== -1)
648 DBG1(DBG_CFG
, "could not create stroke socket");
652 unlink(socket_addr
.sun_path
);
653 old
= umask(~(S_IRWXU
| S_IRWXG
));
654 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
656 DBG1(DBG_CFG
, "could not bind stroke socket: %s", strerror(errno
));
661 if (chown(socket_addr
.sun_path
, charon
->uid
, charon
->gid
) != 0)
663 DBG1(DBG_CFG
, "changing stroke socket permissions failed: %s",
667 if (listen(this->socket
, 10) < 0)
669 DBG1(DBG_CFG
, "could not listen on stroke socket: %s", strerror(errno
));
671 unlink(socket_addr
.sun_path
);
678 * Implementation of stroke_socket_t.destroy
680 static void destroy(private_stroke_socket_t
*this)
682 this->job
->cancel(this->job
);
683 lib
->credmgr
->remove_set(lib
->credmgr
, &this->ca
->set
);
684 lib
->credmgr
->remove_set(lib
->credmgr
, &this->cred
->set
);
685 charon
->backends
->remove_backend(charon
->backends
, &this->config
->backend
);
686 hydra
->attributes
->remove_provider(hydra
->attributes
, &this->attribute
->provider
);
687 this->cred
->destroy(this->cred
);
688 this->ca
->destroy(this->ca
);
689 this->config
->destroy(this->config
);
690 this->attribute
->destroy(this->attribute
);
691 this->control
->destroy(this->control
);
692 this->list
->destroy(this->list
);
699 stroke_socket_t
*stroke_socket_create()
701 private_stroke_socket_t
*this = malloc_thing(private_stroke_socket_t
);
703 this->public.destroy
= (void(*)(stroke_socket_t
*))destroy
;
705 if (!open_socket(this))
711 this->cred
= stroke_cred_create();
712 this->attribute
= stroke_attribute_create();
713 this->ca
= stroke_ca_create(this->cred
);
714 this->config
= stroke_config_create(this->ca
, this->cred
);
715 this->control
= stroke_control_create();
716 this->list
= stroke_list_create(this->attribute
);
718 lib
->credmgr
->add_set(lib
->credmgr
, &this->ca
->set
);
719 lib
->credmgr
->add_set(lib
->credmgr
, &this->cred
->set
);
720 charon
->backends
->add_backend(charon
->backends
, &this->config
->backend
);
721 hydra
->attributes
->add_provider(hydra
->attributes
, &this->attribute
->provider
);
723 this->job
= callback_job_create((callback_job_cb_t
)receive
,
725 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
727 return &this->public;