diff options
Diffstat (limited to 'src/charon/plugins/stroke/stroke_socket.c')
-rw-r--r-- | src/charon/plugins/stroke/stroke_socket.c | 670 |
1 files changed, 0 insertions, 670 deletions
diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c deleted file mode 100644 index 820e097f1..000000000 --- a/src/charon/plugins/stroke/stroke_socket.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "stroke_socket.h" - -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/fcntl.h> -#include <unistd.h> -#include <errno.h> - -#include <processing/jobs/callback_job.h> -#include <daemon.h> -#include <threading/thread.h> - -#include "stroke_config.h" -#include "stroke_control.h" -#include "stroke_cred.h" -#include "stroke_ca.h" -#include "stroke_attribute.h" -#include "stroke_list.h" - -typedef struct stroke_job_context_t stroke_job_context_t; -typedef struct private_stroke_socket_t private_stroke_socket_t; - -/** - * private data of stroke_socket - */ -struct private_stroke_socket_t { - - /** - * public functions - */ - stroke_socket_t public; - - /** - * Unix socket to listen for strokes - */ - int socket; - - /** - * job accepting stroke messages - */ - callback_job_t *job; - - /** - * configuration backend - */ - stroke_config_t *config; - - /** - * attribute provider - */ - stroke_attribute_t *attribute; - - /** - * controller to control daemon - */ - stroke_control_t *control; - - /** - * credential set - */ - stroke_cred_t *cred; - - /** - * CA sections - */ - stroke_ca_t *ca; - - /** - * Status information logging - */ - stroke_list_t *list; -}; - -/** - * job context to pass to processing thread - */ -struct stroke_job_context_t { - - /** - * file descriptor to read from - */ - int fd; - - /** - * global stroke interface - */ - private_stroke_socket_t *this; -}; - -/** - * Helper function which corrects the string pointers - * in a stroke_msg_t. Strings in a stroke_msg sent over "wire" - * contains RELATIVE addresses (relative to the beginning of the - * stroke_msg). They must be corrected if they reach our address - * space... - */ -static void pop_string(stroke_msg_t *msg, char **string) -{ - if (*string == NULL) - { - return; - } - - /* check for sanity of string pointer and string */ - if (string < (char**)msg || - string > (char**)msg + sizeof(stroke_msg_t) || - (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) || - (unsigned long)*string > msg->length) - { - *string = "(invalid pointer in stroke msg)"; - } - else - { - *string = (char*)msg + (unsigned long)*string; - } -} - -/** - * Pop the strings of a stroke_end_t struct and log them for debugging purposes - */ -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->auth); - pop_string(msg, &end->auth2); - pop_string(msg, &end->id); - pop_string(msg, &end->id2); - pop_string(msg, &end->cert); - pop_string(msg, &end->cert2); - pop_string(msg, &end->ca); - pop_string(msg, &end->ca2); - pop_string(msg, &end->groups); - 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, " %sauth=%s", label, end->auth); - DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2); - DBG2(DBG_CFG, " %sid=%s", label, end->id); - DBG2(DBG_CFG, " %sid2=%s", label, end->id2); - DBG2(DBG_CFG, " %scert=%s", label, end->cert); - DBG2(DBG_CFG, " %scert2=%s", label, end->cert2); - 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, " %supdown=%s", label, end->updown); -} - -/** - * Add a connection to the configuration list - */ -static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) -{ - pop_string(msg, &msg->add_conn.name); - DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name); - - DBG2(DBG_CFG, "conn %s", msg->add_conn.name); - pop_end(msg, "left", &msg->add_conn.me); - pop_end(msg, "right", &msg->add_conn.other); - pop_string(msg, &msg->add_conn.eap_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, " ike=%s", msg->add_conn.algorithms.ike); - DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp); - 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); - - this->config->add(this->config, msg); - this->attribute->add_pool(this->attribute, msg); -} - -/** - * Delete a connection from the list - */ -static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg) -{ - pop_string(msg, &msg->del_conn.name); - 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); -} - -/** - * initiate a connection by name - */ -static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->initiate.name); - DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name); - - this->control->initiate(this->control, msg, out); -} - -/** - * terminate a connection by name - */ -static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->terminate.name); - DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name); - - this->control->terminate(this->control, msg, out); -} - -/** - * terminate a connection by peers virtual IP - */ -static void stroke_terminate_srcip(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->terminate_srcip.start); - pop_string(msg, &msg->terminate_srcip.end); - DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s", - msg->terminate_srcip.start, msg->terminate_srcip.end); - - this->control->terminate_srcip(this->control, msg, out); -} - -/** - * route a policy (install SPD entries) - */ -static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->route.name); - DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name); - - this->control->route(this->control, msg, out); -} - -/** - * unroute a policy - */ -static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->terminate.name); - DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name); - - this->control->unroute(this->control, msg, out); -} - -/** - * Add a ca information record to the cainfo list - */ -static void stroke_add_ca(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->add_ca.name); - DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name); - - pop_string(msg, &msg->add_ca.cacert); - pop_string(msg, &msg->add_ca.crluri); - pop_string(msg, &msg->add_ca.crluri2); - pop_string(msg, &msg->add_ca.ocspuri); - pop_string(msg, &msg->add_ca.ocspuri2); - pop_string(msg, &msg->add_ca.certuribase); - DBG2(DBG_CFG, "ca %s", msg->add_ca.name); - DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert); - DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri); - DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2); - DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri); - DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2); - DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase); - - this->ca->add(this->ca, msg); -} - -/** - * Delete a ca information record from the cainfo list - */ -static void stroke_del_ca(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->del_ca.name); - DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name); - - this->ca->del(this->ca, msg); -} - - -/** - * show status of daemon - */ -static void stroke_status(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out, bool all) -{ - pop_string(msg, &(msg->status.name)); - - this->list->status(this->list, msg, out, all); -} - -/** - * list various information - */ -static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) -{ - if (msg->list.flags & LIST_CAINFOS) - { - this->ca->list(this->ca, msg, out); - } - this->list->list(this->list, msg, out); -} - -/** - * reread various information - */ -static void stroke_reread(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - this->cred->reread(this->cred, msg, out); -} - -/** - * purge various information - */ -static void stroke_purge(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - if (msg->purge.flags & PURGE_OCSP) - { - charon->credentials->flush_cache(charon->credentials, - CERT_X509_OCSP_RESPONSE); - } - if (msg->purge.flags & PURGE_IKE) - { - this->control->purge_ike(this->control, msg, out); - } -} - -/** - * list pool leases - */ -static void stroke_leases(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - pop_string(msg, &msg->leases.pool); - pop_string(msg, &msg->leases.address); - - this->list->leases(this->list, msg, out); -} - -debug_t get_group_from_name(char *type) -{ - if (strcaseeq(type, "any")) return DBG_ANY; - else if (strcaseeq(type, "mgr")) return DBG_MGR; - else if (strcaseeq(type, "ike")) return DBG_IKE; - else if (strcaseeq(type, "chd")) return DBG_CHD; - else if (strcaseeq(type, "job")) return DBG_JOB; - else if (strcaseeq(type, "cfg")) return DBG_CFG; - else if (strcaseeq(type, "knl")) return DBG_KNL; - else if (strcaseeq(type, "net")) return DBG_NET; - else if (strcaseeq(type, "enc")) return DBG_ENC; - else if (strcaseeq(type, "lib")) return DBG_LIB; - else return -1; -} - -/** - * 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 = get_group_from_name(msg->loglevel.type); - if (group < 0) - { - 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); - } - enumerator->destroy(enumerator); - enumerator = charon->file_loggers->create_enumerator(charon->file_loggers); - while (enumerator->enumerate(enumerator, &file_logger)) - { - file_logger->set_level(file_logger, group, msg->loglevel.level); - } - enumerator->destroy(enumerator); -} - -/** - * set various config options - */ -static void stroke_config(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out) -{ - this->cred->cachecrl(this->cred, msg->config.cachecrl); -} - -/** - * destroy a job context - */ -static void stroke_job_context_destroy(stroke_job_context_t *this) -{ - if (this->fd) - { - close(this->fd); - } - free(this); -} - -/** - * process a stroke request from the socket pointed by "fd" - */ -static job_requeue_t process(stroke_job_context_t *ctx) -{ - stroke_msg_t *msg; - u_int16_t msg_length; - ssize_t bytes_read; - 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)) - { - DBG1(DBG_CFG, "reading length of stroke message failed: %s", - strerror(errno)); - return JOB_REQUEUE_NONE; - } - - /* read message */ - msg = alloca(msg_length); - bytes_read = recv(strokefd, msg, msg_length, 0); - if (bytes_read != msg_length) - { - DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno)); - return JOB_REQUEUE_NONE; - } - - out = fdopen(strokefd, "w+"); - if (out == NULL) - { - DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno)); - return JOB_REQUEUE_NONE; - } - - DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length); - - switch (msg->type) - { - case STR_INITIATE: - stroke_initiate(this, msg, out); - break; - case STR_ROUTE: - stroke_route(this, msg, out); - break; - case STR_UNROUTE: - stroke_unroute(this, msg, out); - break; - case STR_TERMINATE: - stroke_terminate(this, msg, out); - break; - case STR_TERMINATE_SRCIP: - stroke_terminate_srcip(this, msg, out); - break; - case STR_STATUS: - stroke_status(this, msg, out, FALSE); - break; - case STR_STATUS_ALL: - stroke_status(this, msg, out, TRUE); - break; - case STR_ADD_CONN: - stroke_add_conn(this, msg); - break; - case STR_DEL_CONN: - stroke_del_conn(this, msg); - break; - case STR_ADD_CA: - stroke_add_ca(this, msg, out); - break; - case STR_DEL_CA: - stroke_del_ca(this, msg, out); - break; - case STR_LOGLEVEL: - stroke_loglevel(this, msg, out); - break; - case STR_CONFIG: - stroke_config(this, msg, out); - break; - case STR_LIST: - stroke_list(this, msg, out); - break; - case STR_REREAD: - stroke_reread(this, msg, out); - break; - case STR_PURGE: - stroke_purge(this, msg, out); - break; - case STR_LEASES: - stroke_leases(this, msg, out); - break; - default: - DBG1(DBG_CFG, "received unknown stroke"); - break; - } - fclose(out); - /* fclose() closes underlying FD */ - ctx->fd = 0; - return JOB_REQUEUE_NONE; -} - -/** - * Implementation of private_stroke_socket_t.stroke_receive. - */ -static job_requeue_t receive(private_stroke_socket_t *this) -{ - struct sockaddr_un strokeaddr; - int strokeaddrlen = sizeof(strokeaddr); - int strokefd; - bool oldstate; - callback_job_t *job; - 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; - } - - ctx = malloc_thing(stroke_job_context_t); - ctx->fd = strokefd; - ctx->this = this; - job = callback_job_create((callback_job_cb_t)process, - ctx, (void*)stroke_job_context_destroy, this->job); - charon->processor->queue_job(charon->processor, (job_t*)job); - - 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; -} - -/** - * Implementation of stroke_socket_t.destroy - */ -static void destroy(private_stroke_socket_t *this) -{ - this->job->cancel(this->job); - charon->credentials->remove_set(charon->credentials, &this->ca->set); - charon->credentials->remove_set(charon->credentials, &this->cred->set); - charon->backends->remove_backend(charon->backends, &this->config->backend); - lib->attributes->remove_provider(lib->attributes, &this->attribute->provider); - this->cred->destroy(this->cred); - this->ca->destroy(this->ca); - this->config->destroy(this->config); - this->attribute->destroy(this->attribute); - this->control->destroy(this->control); - this->list->destroy(this->list); - free(this); -} - -/* - * see header file - */ -stroke_socket_t *stroke_socket_create() -{ - private_stroke_socket_t *this = malloc_thing(private_stroke_socket_t); - - this->public.destroy = (void(*)(stroke_socket_t*))destroy; - - if (!open_socket(this)) - { - free(this); - return NULL; - } - - this->cred = stroke_cred_create(); - this->attribute = stroke_attribute_create(); - this->ca = stroke_ca_create(this->cred); - this->config = stroke_config_create(this->ca, this->cred); - this->control = stroke_control_create(); - this->list = stroke_list_create(this->attribute); - - charon->credentials->add_set(charon->credentials, &this->ca->set); - charon->credentials->add_set(charon->credentials, &this->cred->set); - charon->backends->add_backend(charon->backends, &this->config->backend); - lib->attributes->add_provider(lib->attributes, &this->attribute->provider); - - this->job = callback_job_create((callback_job_cb_t)receive, - this, NULL, NULL); - charon->processor->queue_job(charon->processor, (job_t*)this->job); - - return &this->public; -} - |