summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/stroke/stroke_socket.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-10-17 21:23:38 +0200
committerYves-Alexis Perez <corsac@debian.org>2013-10-17 21:23:38 +0200
commit9d37ad77ef660b92ea51b69d74e14f931d2a04e2 (patch)
treed6bbb4a5fed1959f8675df9ee7c03713b543fcc9 /src/libcharon/plugins/stroke/stroke_socket.c
parent104f57d4b0fb6d7547d6898352eaa5fb4b222010 (diff)
parente5ee4e7fcdd58b7d86bf1b458da2c63e8e19627b (diff)
downloadvyos-strongswan-9d37ad77ef660b92ea51b69d74e14f931d2a04e2.tar.gz
vyos-strongswan-9d37ad77ef660b92ea51b69d74e14f931d2a04e2.zip
Merge tag 'v5.1.0-1' into sid
tag strongSwan 5.1.0-1
Diffstat (limited to 'src/libcharon/plugins/stroke/stroke_socket.c')
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c441
1 files changed, 177 insertions, 264 deletions
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 57648feb8..88f73f3b0 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -26,18 +26,15 @@
#include <hydra.h>
#include <daemon.h>
-#include <threading/mutex.h>
-#include <threading/thread.h>
-#include <threading/condvar.h>
-#include <utils/linked_list.h>
-#include <processing/jobs/callback_job.h>
#include "stroke_config.h"
#include "stroke_control.h"
#include "stroke_cred.h"
#include "stroke_ca.h"
#include "stroke_attribute.h"
+#include "stroke_handler.h"
#include "stroke_list.h"
+#include "stroke_counter.h"
/**
* To avoid clogging the thread pool with (blocking) jobs, we limit the number
@@ -59,44 +56,9 @@ struct private_stroke_socket_t {
stroke_socket_t public;
/**
- * Unix socket to listen for strokes
+ * Service accepting stroke connections
*/
- int socket;
-
- /**
- * job accepting stroke messages
- */
- callback_job_t *receiver;
-
- /**
- * job handling stroke messages
- */
- callback_job_t *handler;
-
- /**
- * queued stroke commands
- */
- linked_list_t *commands;
-
- /**
- * lock for command list
- */
- mutex_t *mutex;
-
- /**
- * condvar to signal the arrival or completion of commands
- */
- condvar_t *condvar;
-
- /**
- * the number of currently handled commands
- */
- u_int handling;
-
- /**
- * the maximum number of concurrently handled commands
- */
- u_int max_concurrent;
+ stream_service_t *service;
/**
* configuration backend
@@ -109,6 +71,11 @@ struct private_stroke_socket_t {
stroke_attribute_t *attribute;
/**
+ * attribute handler (requests only)
+ */
+ stroke_handler_t *handler;
+
+ /**
* controller to control daemon
*/
stroke_control_t *control;
@@ -127,22 +94,11 @@ struct private_stroke_socket_t {
* status information logging
*/
stroke_list_t *list;
-};
-
-/**
- * job context to pass to processing thread
- */
-struct stroke_job_context_t {
/**
- * file descriptor to read from
+ * Counter values for IKE events
*/
- int fd;
-
- /**
- * global stroke interface
- */
- private_stroke_socket_t *this;
+ stroke_counter_t *counter;
};
/**
@@ -181,6 +137,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->dns);
pop_string(msg, &end->auth);
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
@@ -191,12 +148,14 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->ca);
pop_string(msg, &end->ca2);
pop_string(msg, &end->groups);
+ pop_string(msg, &end->groups2);
pop_string(msg, &end->cert_policy);
pop_string(msg, &end->updown);
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
+ DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
@@ -207,6 +166,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
+ DBG2(DBG_CFG, " %sgroups2=%s", label, end->groups2);
DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
}
@@ -223,23 +183,28 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
pop_end(msg, "right", &msg->add_conn.other);
pop_string(msg, &msg->add_conn.eap_identity);
pop_string(msg, &msg->add_conn.aaa_identity);
+ pop_string(msg, &msg->add_conn.xauth_identity);
pop_string(msg, &msg->add_conn.algorithms.ike);
pop_string(msg, &msg->add_conn.algorithms.esp);
pop_string(msg, &msg->add_conn.ikeme.mediated_by);
pop_string(msg, &msg->add_conn.ikeme.peerid);
DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
+ DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
+ DBG2(DBG_CFG, " dpdtimeout=%d", msg->add_conn.dpd.timeout);
DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
+ DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg);
- this->attribute->add_pool(this->attribute, msg);
+ this->attribute->add_dns(this->attribute, msg);
+ this->handler->add_attributes(this->handler, msg);
}
/**
@@ -251,7 +216,8 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
this->config->del(this->config, msg);
- this->attribute->del_pool(this->attribute, msg);
+ this->attribute->del_dns(this->attribute, msg);
+ this->handler->del_attributes(this->handler, msg);
}
/**
@@ -376,7 +342,8 @@ static void stroke_status(private_stroke_socket_t *this,
/**
* list various information
*/
-static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
+ FILE *out)
{
if (msg->list.flags & LIST_CAINFOS)
{
@@ -419,6 +386,20 @@ static void stroke_purge(private_stroke_socket_t *this,
}
/**
+ * Print a certificate in PEM to out
+ */
+static void print_pem_cert(FILE *out, certificate_t *cert)
+{
+ chunk_t encoded;
+
+ if (cert->get_encoding(cert, CERT_PEM, &encoded))
+ {
+ fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
+ free(encoded.ptr);
+ }
+}
+
+/**
* Export in-memory credentials
*/
static void stroke_export(private_stroke_socket_t *this,
@@ -431,22 +412,67 @@ static void stroke_export(private_stroke_socket_t *this,
enumerator_t *enumerator;
identification_t *id;
certificate_t *cert;
- chunk_t encoded;
id = identification_create_from_string(msg->export.selector);
enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
CERT_X509, KEY_ANY, id, FALSE);
while (enumerator->enumerate(enumerator, &cert))
{
- if (cert->get_encoding(cert, CERT_PEM, &encoded))
- {
- fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
- free(encoded.ptr);
- }
+ print_pem_cert(out, cert);
}
enumerator->destroy(enumerator);
id->destroy(id);
}
+
+ if (msg->export.flags & (EXPORT_CONN_CERT | EXPORT_CONN_CHAIN))
+ {
+ enumerator_t *sas, *auths, *certs;
+ ike_sa_t *ike_sa;
+ auth_cfg_t *auth;
+ certificate_t *cert;
+ auth_rule_t rule;
+
+ sas = charon->ike_sa_manager->create_enumerator(
+ charon->ike_sa_manager, TRUE);
+ while (sas->enumerate(sas, &ike_sa))
+ {
+ if (streq(msg->export.selector, ike_sa->get_name(ike_sa)))
+ {
+ auths = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+ while (auths->enumerate(auths, &auth))
+ {
+ bool got_subject = FALSE;
+
+ certs = auth->create_enumerator(auth);
+ while (certs->enumerate(certs, &rule, &cert))
+ {
+ switch (rule)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ if (msg->export.flags & EXPORT_CONN_CHAIN)
+ {
+ print_pem_cert(out, cert);
+ }
+ break;
+ case AUTH_RULE_SUBJECT_CERT:
+ if (!got_subject)
+ {
+ print_pem_cert(out, cert);
+ got_subject = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ certs->destroy(certs);
+ }
+ auths->destroy(auths);
+ }
+ }
+ sas->destroy(sas);
+ }
}
/**
@@ -489,39 +515,49 @@ static void stroke_user_creds(private_stroke_socket_t *this,
}
/**
+ * Print stroke counter values
+ */
+static void stroke_counters(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->counters.name);
+
+ if (msg->counters.reset)
+ {
+ this->counter->reset(this->counter, msg->counters.name);
+ }
+ else
+ {
+ this->counter->print(this->counter, out, msg->counters.name);
+ }
+}
+
+/**
* set the verbosity debug output
*/
static void stroke_loglevel(private_stroke_socket_t *this,
stroke_msg_t *msg, FILE *out)
{
- enumerator_t *enumerator;
- sys_logger_t *sys_logger;
- file_logger_t *file_logger;
debug_t group;
pop_string(msg, &(msg->loglevel.type));
DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
msg->loglevel.level, msg->loglevel.type);
- group = enum_from_name(debug_names, msg->loglevel.type);
- if ((int)group < 0)
+ if (strcaseeq(msg->loglevel.type, "any"))
{
- fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
- return;
- }
- /* we set the loglevel on ALL sys- and file-loggers */
- enumerator = charon->sys_loggers->create_enumerator(charon->sys_loggers);
- while (enumerator->enumerate(enumerator, &sys_logger))
- {
- sys_logger->set_level(sys_logger, group, msg->loglevel.level);
+ group = DBG_ANY;
}
- enumerator->destroy(enumerator);
- enumerator = charon->file_loggers->create_enumerator(charon->file_loggers);
- while (enumerator->enumerate(enumerator, &file_logger))
+ else
{
- file_logger->set_level(file_logger, group, msg->loglevel.level);
+ group = enum_from_name(debug_names, msg->loglevel.type);
+ if ((int)group < 0)
+ {
+ fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
+ return;
+ }
}
- enumerator->destroy(enumerator);
+ charon->set_level(charon, group, msg->loglevel.level);
}
/**
@@ -534,68 +570,47 @@ static void stroke_config(private_stroke_socket_t *this,
}
/**
- * destroy a job context
+ * process a stroke request
*/
-static void stroke_job_context_destroy(stroke_job_context_t *this)
-{
- if (this->fd)
- {
- close(this->fd);
- }
- free(this);
-}
-
-/**
- * called to signal the completion of a command
- */
-static inline job_requeue_t job_processed(private_stroke_socket_t *this)
-{
- this->mutex->lock(this->mutex);
- this->handling--;
- this->condvar->signal(this->condvar);
- this->mutex->unlock(this->mutex);
- return JOB_REQUEUE_NONE;
-}
-
-/**
- * process a stroke request from the socket pointed by "fd"
- */
-static job_requeue_t process(stroke_job_context_t *ctx)
+static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
{
stroke_msg_t *msg;
- u_int16_t msg_length;
- ssize_t bytes_read;
+ u_int16_t len;
FILE *out;
- private_stroke_socket_t *this = ctx->this;
- int strokefd = ctx->fd;
- /* peek the length */
- bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
- if (bytes_read != sizeof(msg_length))
+ /* read length */
+ if (!stream->read_all(stream, &len, sizeof(len)))
{
- DBG1(DBG_CFG, "reading length of stroke message failed: %s",
- strerror(errno));
- return job_processed(this);
+ if (errno != EWOULDBLOCK)
+ {
+ DBG1(DBG_CFG, "reading length of stroke message failed: %s",
+ strerror(errno));
+ }
+ return FALSE;
}
/* read message */
- msg = alloca(msg_length);
- bytes_read = recv(strokefd, msg, msg_length, 0);
- if (bytes_read != msg_length)
+ msg = malloc(len);
+ msg->length = len;
+ if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
{
- DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
- return job_processed(this);
+ if (errno != EWOULDBLOCK)
+ {
+ DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
+ }
+ free(msg);
+ return FALSE;
}
- out = fdopen(strokefd, "w+");
- if (out == NULL)
+ DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
+
+ out = stream->get_file(stream);
+ if (!out)
{
- DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
- return job_processed(this);
+ DBG1(DBG_CFG, "creating stroke output stream failed");
+ free(msg);
+ return FALSE;
}
-
- DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
-
switch (msg->type)
{
case STR_INITIATE:
@@ -664,138 +679,36 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_USER_CREDS:
stroke_user_creds(this, msg, out);
break;
+ case STR_COUNTERS:
+ stroke_counters(this, msg, out);
+ break;
default:
DBG1(DBG_CFG, "received unknown stroke");
break;
}
+ free(msg);
fclose(out);
- /* fclose() closes underlying FD */
- ctx->fd = 0;
- return job_processed(this);
-}
-
-/**
- * Handle queued stroke commands
- */
-static job_requeue_t handle(private_stroke_socket_t *this)
-{
- stroke_job_context_t *ctx;
- callback_job_t *job;
- bool oldstate;
-
- this->mutex->lock(this->mutex);
- thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
- oldstate = thread_cancelability(TRUE);
- while (this->commands->get_count(this->commands) == 0 ||
- this->handling >= this->max_concurrent)
- {
- this->condvar->wait(this->condvar, this->mutex);
- }
- thread_cancelability(oldstate);
- this->commands->remove_first(this->commands, (void**)&ctx);
- this->handling++;
- thread_cleanup_pop(TRUE);
- job = callback_job_create_with_prio((callback_job_cb_t)process, ctx,
- (void*)stroke_job_context_destroy, this->handler, JOB_PRIO_HIGH);
- lib->processor->queue_job(lib->processor, (job_t*)job);
- return JOB_REQUEUE_DIRECT;
-}
-
-/**
- * Accept stroke commands and queue them to be handled
- */
-static job_requeue_t receive(private_stroke_socket_t *this)
-{
- struct sockaddr_un strokeaddr;
- int strokeaddrlen = sizeof(strokeaddr);
- int strokefd;
- bool oldstate;
- stroke_job_context_t *ctx;
-
- oldstate = thread_cancelability(TRUE);
- strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
- thread_cancelability(oldstate);
-
- if (strokefd < 0)
- {
- DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
- return JOB_REQUEUE_FAIR;
- }
-
- INIT(ctx,
- .fd = strokefd,
- .this = this,
- );
- this->mutex->lock(this->mutex);
- this->commands->insert_last(this->commands, ctx);
- this->condvar->signal(this->condvar);
- this->mutex->unlock(this->mutex);
-
- return JOB_REQUEUE_FAIR;
-}
-
-/**
- * initialize and open stroke socket
- */
-static bool open_socket(private_stroke_socket_t *this)
-{
- struct sockaddr_un socket_addr;
- mode_t old;
-
- socket_addr.sun_family = AF_UNIX;
- strcpy(socket_addr.sun_path, STROKE_SOCKET);
-
- /* set up unix socket */
- this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
- if (this->socket == -1)
- {
- DBG1(DBG_CFG, "could not create stroke socket");
- return FALSE;
- }
-
- unlink(socket_addr.sun_path);
- old = umask(~(S_IRWXU | S_IRWXG));
- if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
- {
- DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno));
- close(this->socket);
- return FALSE;
- }
- umask(old);
- if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
- {
- DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
- strerror(errno));
- }
-
- if (listen(this->socket, 10) < 0)
- {
- DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno));
- close(this->socket);
- unlink(socket_addr.sun_path);
- return FALSE;
- }
- return TRUE;
+ return FALSE;
}
METHOD(stroke_socket_t, destroy, void,
private_stroke_socket_t *this)
{
- this->handler->cancel(this->handler);
- this->receiver->cancel(this->receiver);
- this->commands->destroy_function(this->commands, (void*)stroke_job_context_destroy);
- this->condvar->destroy(this->condvar);
- this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->service);
lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ charon->bus->remove_listener(charon->bus, &this->counter->listener);
this->cred->destroy(this->cred);
this->ca->destroy(this->ca);
this->config->destroy(this->config);
this->attribute->destroy(this->attribute);
+ this->handler->destroy(this->handler);
this->control->destroy(this->control);
this->list->destroy(this->list);
+ this->counter->destroy(this->counter);
free(this);
}
@@ -805,6 +718,8 @@ METHOD(stroke_socket_t, destroy, void,
stroke_socket_t *stroke_socket_create()
{
private_stroke_socket_t *this;
+ int max_concurrent;
+ char *uri;
INIT(this,
.public = {
@@ -812,38 +727,36 @@ stroke_socket_t *stroke_socket_create()
},
);
- if (!open_socket(this))
- {
- free(this);
- return NULL;
- }
-
this->cred = stroke_cred_create();
this->attribute = stroke_attribute_create();
+ this->handler = stroke_handler_create();
this->ca = stroke_ca_create(this->cred);
- this->config = stroke_config_create(this->ca, this->cred);
+ this->config = stroke_config_create(this->ca, this->cred, this->attribute);
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
-
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
- this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
- this->commands = linked_list_create();
- this->max_concurrent = lib->settings->get_int(lib->settings,
- "charon.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT);
+ this->counter = stroke_counter_create();
lib->credmgr->add_set(lib->credmgr, &this->ca->set);
lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
-
- this->receiver = callback_job_create_with_prio((callback_job_cb_t)receive,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->receiver);
-
- this->handler = callback_job_create_with_prio((callback_job_cb_t)handle,
- this, NULL, NULL, JOB_PRIO_CRITICAL);
- lib->processor->queue_job(lib->processor, (job_t*)this->handler);
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+ charon->bus->add_listener(charon->bus, &this->counter->listener);
+
+ max_concurrent = lib->settings->get_int(lib->settings,
+ "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
+ charon->name);
+ uri = lib->settings->get_str(lib->settings,
+ "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, charon->name);
+ this->service = lib->streams->create_service(lib->streams, uri, 10);
+ if (!this->service)
+ {
+ DBG1(DBG_CFG, "creating stroke socket failed");
+ destroy(this);
+ return NULL;
+ }
+ this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
+ this, JOB_PRIO_CRITICAL, max_concurrent);
return &this->public;
}
-