diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-08-25 15:37:26 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-08-25 15:37:26 +0200 |
commit | 6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (patch) | |
tree | 009fc492961e13860d2a4bc2de8caf2bbe2975e7 /src/libcharon/plugins/stroke | |
parent | c83921a2b566aa9d55d8ccc7258f04fca6292ee6 (diff) | |
download | vyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.tar.gz vyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.zip |
Imported Upstream version 5.1.0
Diffstat (limited to 'src/libcharon/plugins/stroke')
-rw-r--r-- | src/libcharon/plugins/stroke/Makefile.am | 14 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/Makefile.in | 83 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_config.c | 136 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_control.c | 2 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_cred.c | 241 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_cred.h | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_list.c | 14 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_plugin.c | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_socket.c | 346 |
9 files changed, 503 insertions, 344 deletions
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am index 39b3e79d2..9509b1bd3 100644 --- a/src/libcharon/plugins/stroke/Makefile.am +++ b/src/libcharon/plugins/stroke/Makefile.am @@ -1,11 +1,13 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/stroke +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/stroke \ + -DIPSEC_CONFDIR=\"${sysconfdir}\" \ + -DIPSEC_PIDDIR=\"${piddir}\" AM_CFLAGS = \ --rdynamic \ --DIPSEC_CONFDIR=\"${sysconfdir}\" \ --DIPSEC_PIDDIR=\"${piddir}\" + -rdynamic if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-stroke.la diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index 7d1100c08..151e7ba69 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -62,7 +62,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -105,9 +105,13 @@ am_libstrongswan_stroke_la_OBJECTS = stroke_plugin.lo stroke_socket.lo \ stroke_list.lo libstrongswan_stroke_la_OBJECTS = \ $(am_libstrongswan_stroke_la_OBJECTS) -libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libstrongswan_stroke_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libstrongswan_stroke_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_stroke_la_LDFLAGS) \ + $(LDFLAGS) -o $@ @MONOLITHIC_FALSE@am_libstrongswan_stroke_la_rpath = -rpath \ @MONOLITHIC_FALSE@ $(plugindir) @MONOLITHIC_TRUE@am_libstrongswan_stroke_la_rpath = @@ -117,13 +121,26 @@ am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libstrongswan_stroke_la_SOURCES) DIST_SOURCES = $(libstrongswan_stroke_la_SOURCES) am__can_run_installinfo = \ @@ -137,6 +154,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -149,6 +167,8 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -164,6 +184,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ @@ -172,6 +193,7 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -218,6 +240,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -246,6 +269,7 @@ charon_natt_port = @charon_natt_port@ charon_plugins = @charon_plugins@ charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -323,13 +347,16 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/stroke +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/stroke \ + -DIPSEC_CONFDIR=\"${sysconfdir}\" \ + -DIPSEC_PIDDIR=\"${piddir}\" AM_CFLAGS = \ --rdynamic \ --DIPSEC_CONFDIR=\"${sysconfdir}\" \ --DIPSEC_PIDDIR=\"${piddir}\" + -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-stroke.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-stroke.la @@ -422,7 +449,7 @@ clean-pluginLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libstrongswan-stroke.la: $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_DEPENDENCIES) $(EXTRA_libstrongswan_stroke_la_DEPENDENCIES) - $(libstrongswan_stroke_la_LINK) $(am_libstrongswan_stroke_la_rpath) $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(libstrongswan_stroke_la_LINK) $(am_libstrongswan_stroke_la_rpath) $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -442,25 +469,25 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 86f0fe431..079e65f11 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -21,6 +21,8 @@ #include <threading/mutex.h> #include <utils/lexparser.h> +#include <netdb.h> + typedef struct private_stroke_config_t private_stroke_config_t; /** @@ -489,8 +491,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, pubkey = end->rsakey; if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert")) { - certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey, - identity); + certificate = this->cred->load_pubkey(this->cred, pubkey, identity); if (certificate) { cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate); @@ -558,9 +559,9 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } /* authentication metod (class, actually) */ - if (strneq(auth, "pubkey", strlen("pubkey")) || - strneq(auth, "rsa", strlen("rsa")) || - strneq(auth, "ecdsa", strlen("ecdsa"))) + if (strpfx(auth, "pubkey") || + strpfx(auth, "rsa") || + strpfx(auth, "ecdsa")) { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); build_crl_policy(cfg, local, msg->add_conn.crl_policy); @@ -571,7 +572,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); } - else if (strneq(auth, "xauth", 5)) + else if (strpfx(auth, "xauth")) { char *pos; @@ -587,7 +588,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, identification_create_from_string(msg->add_conn.xauth_identity)); } } - else if (strneq(auth, "eap", 3)) + else if (strpfx(auth, "eap")) { eap_vendor_type_t *type; @@ -884,6 +885,96 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, } /** + * Parse a protoport specifier + */ +static bool parse_protoport(char *token, u_int16_t *from_port, + u_int16_t *to_port, u_int8_t *protocol) +{ + char *sep, *port = "", *endptr; + struct protoent *proto; + struct servent *svc; + long int p; + + sep = strrchr(token, ']'); + if (!sep) + { + return FALSE; + } + *sep = '\0'; + + sep = strchr(token, '/'); + if (sep) + { /* protocol/port */ + *sep = '\0'; + port = sep + 1; + } + + if (streq(token, "%any")) + { + *protocol = 0; + } + else + { + proto = getprotobyname(token); + if (proto) + { + *protocol = proto->p_proto; + } + else + { + p = strtol(token, &endptr, 0); + if ((*token && *endptr) || p < 0 || p > 0xff) + { + return FALSE; + } + *protocol = (u_int8_t)p; + } + } + if (streq(port, "%any")) + { + *from_port = 0; + *to_port = 0xffff; + } + else if (streq(port, "%opaque")) + { + *from_port = 0xffff; + *to_port = 0; + } + else if (*port) + { + svc = getservbyname(port, NULL); + if (svc) + { + *from_port = *to_port = ntohs(svc->s_port); + } + else + { + p = strtol(port, &endptr, 0); + if (p < 0 || p > 0xffff) + { + return FALSE; + } + *from_port = p; + if (*endptr == '-') + { + port = endptr + 1; + p = strtol(port, &endptr, 0); + if (p < 0 || p > 0xffff) + { + return FALSE; + } + } + *to_port = p; + if (*endptr) + { + return FALSE; + } + } + } + return TRUE; +} + +/** * build a traffic selector from a stroke_end */ static void add_ts(private_stroke_config_t *this, @@ -914,13 +1005,38 @@ static void add_ts(private_stroke_config_t *this, else { enumerator_t *enumerator; - char *subnet; + char *subnet, *pos; + u_int16_t from_port, to_port; + u_int8_t proto; enumerator = enumerator_create_token(end->subnets, ",", " "); while (enumerator->enumerate(enumerator, &subnet)) { - ts = traffic_selector_create_from_cidr(subnet, end->protocol, - end->from_port, end->to_port); + from_port = end->from_port; + to_port = end->to_port; + proto = end->protocol; + + pos = strchr(subnet, '['); + if (pos) + { + *(pos++) = '\0'; + if (!parse_protoport(pos, &from_port, &to_port, &proto)) + { + DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet", + pos); + continue; + } + } + if (streq(subnet, "%dynamic")) + { + ts = traffic_selector_create_dynamic(proto, + from_port, to_port); + } + else + { + ts = traffic_selector_create_from_cidr(subnet, proto, + from_port, to_port); + } if (ts) { child_cfg->add_traffic_selector(child_cfg, local, ts); diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index 91130d1ee..fdd1635a6 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -603,7 +603,7 @@ static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, } else { - if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) + if (charon->traps->install(charon->traps, peer_cfg, child_cfg, 0)) { fprintf(out, "'%s' routed\n", name); } diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index eda746f7e..8d0001271 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 Tobias Brunner + * Copyright (C) 2008-2013 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -32,6 +32,7 @@ #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> #include <credentials/certificates/ac.h> +#include <credentials/containers/pkcs12.h> #include <credentials/sets/mem_cred.h> #include <credentials/sets/callback_cred.h> #include <collections/linked_list.h> @@ -72,7 +73,7 @@ struct private_stroke_cred_t { /** * ignore missing CA basic constraint (i.e. treat all certificates in - * ipsec.conf ca sections and ipsec.d/cacert as CA certificates) + * ipsec.conf ca sections and ipsec.d/cacerts as CA certificates) */ bool force_ca_cert; @@ -174,7 +175,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, certificate_t *cert = NULL; char path[PATH_MAX]; - if (strneq(filename, "%smartcard", strlen("%smartcard"))) + if (strpfx(filename, "%smartcard")) { smartcard_format_t format; char module[SC_PART_LEN], keyid[SC_PART_LEN]; @@ -225,7 +226,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, cert->destroy(cert); return NULL; } - DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s", + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", cert->get_subject(cert), filename); return this->creds->add_cert_ref(this->creds, TRUE, cert); } @@ -238,7 +239,7 @@ METHOD(stroke_cred_t, load_peer, certificate_t*, certificate_t *cert = NULL; char path[PATH_MAX]; - if (strneq(filename, "%smartcard", strlen("%smartcard"))) + if (strpfx(filename, "%smartcard")) { smartcard_format_t format; char module[SC_PART_LEN], keyid[SC_PART_LEN]; @@ -279,29 +280,45 @@ METHOD(stroke_cred_t, load_peer, certificate_t*, } METHOD(stroke_cred_t, load_pubkey, certificate_t*, - private_stroke_cred_t *this, key_type_t type, char *filename, - identification_t *identity) + private_stroke_cred_t *this, char *filename, identification_t *identity) { certificate_t *cert; + public_key_t *key; char path[PATH_MAX]; + builder_part_t build_part; + key_type_t type = KEY_ANY; if (streq(filename, "%dns")) { - + return NULL; + } + if (strncaseeq(filename, "dns:", 4)) + { /* RFC 3110 format */ + build_part = BUILD_BLOB_DNSKEY; + /* not a complete RR, only RSA supported */ + type = KEY_RSA; + filename += 4; + } + else if (strncaseeq(filename, "ssh:", 4)) + { /* SSH key */ + build_part = BUILD_BLOB_SSHKEY; + filename += 4; + } + else + { /* try PKCS#1 by default */ + build_part = BUILD_BLOB_ASN1_DER; } - else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) + if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) { - chunk_t printable_key, rfc3110_key; - public_key_t *key; + chunk_t printable_key, raw_key; printable_key = chunk_create(filename + 2, strlen(filename) - 2); - rfc3110_key = strncaseeq(filename, "0x", 2) ? + raw_key = strncaseeq(filename, "0x", 2) ? chunk_from_hex(printable_key, NULL) : chunk_from_base64(printable_key, NULL); - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_BLOB_DNSKEY, rfc3110_key, - BUILD_END); - free(rfc3110_key.ptr); + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type, + build_part, raw_key, BUILD_END); + chunk_free(&raw_key); if (key) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, @@ -309,6 +326,7 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, BUILD_PUBLIC_KEY, key, BUILD_SUBJECT, identity, BUILD_END); + type = key->get_type(key); key->destroy(key); if (cert) { @@ -318,8 +336,7 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, return cert; } } - DBG1(DBG_CFG, " loading %N public key for \"%Y\" failed", - key_type_names, type, identity); + DBG1(DBG_CFG, " loading public key for \"%Y\" failed", identity); } else { @@ -340,12 +357,15 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, if (cert) { cert = this->creds->add_cert_ref(this->creds, TRUE, cert); + key = cert->get_public_key(cert); + type = key->get_type(key); + key->destroy(key); DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'", key_type_names, type, identity, filename); return cert; } - DBG1(DBG_CFG, " loading %N public key for \"%Y\" from '%s' failed", - key_type_names, type, identity, filename); + DBG1(DBG_CFG, " loading public key for \"%Y\" from '%s' failed", + identity, filename); } return NULL; } @@ -580,8 +600,12 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line) * Data for passphrase callback */ typedef struct { + /** cached passphrases */ + mem_cred_t *cache; /** socket we use for prompting */ FILE *prompt; + /** type of secret to unlock */ + int type; /** private key file */ char *path; /** number of tries */ @@ -589,13 +613,15 @@ typedef struct { } passphrase_cb_data_t; /** - * Callback function to receive Passphrases + * Callback function to receive passphrases */ static shared_key_t* passphrase_cb(passphrase_cb_data_t *data, - shared_key_type_t type, - identification_t *me, identification_t *other, - id_match_t *match_me, id_match_t *match_other) + shared_key_type_t type, identification_t *me, + identification_t *other, id_match_t *match_me, + id_match_t *match_other) { + static const int max_tries = 3; + shared_key_t *shared; chunk_t secret; char buf[256]; @@ -604,17 +630,23 @@ static shared_key_t* passphrase_cb(passphrase_cb_data_t *data, return NULL; } + data->try++; + if (data->try > max_tries + 1) + { /* another builder might call this after we gave up, fail silently */ + return NULL; + } + if (data->try > max_tries) + { + fprintf(data->prompt, "Passphrase invalid, giving up.\n"); + return NULL; + } if (data->try > 1) { - if (data->try > 5) - { - fprintf(data->prompt, "PIN invalid, giving up.\n"); - return NULL; - } - fprintf(data->prompt, "PIN invalid!\n"); + fprintf(data->prompt, "Passphrase invalid!\n"); } - data->try++; - fprintf(data->prompt, "Private key '%s' is encrypted.\n", data->path); + fprintf(data->prompt, "%s '%s' is encrypted.\n", + data->type == CRED_PRIVATE_KEY ? "Private key" : "PKCS#12 file", + data->path); fprintf(data->prompt, "Passphrase:\n"); if (fgets(buf, sizeof(buf), data->prompt)) { @@ -630,7 +662,10 @@ static shared_key_t* passphrase_cb(passphrase_cb_data_t *data, { *match_other = ID_MATCH_NONE; } - return shared_key_create(SHARED_PRIVATE_KEY_PASS, chunk_clone(secret)); + shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, + chunk_clone(secret)); + data->cache->add_shared(data->cache, shared->get_ref(shared), NULL); + return shared; } } return NULL; @@ -670,12 +705,12 @@ static shared_key_t* pin_cb(pin_cb_data_t *data, shared_key_type_t type, return NULL; } + data->try++; if (data->try > 1) { fprintf(data->prompt, "PIN invalid, aborting.\n"); return NULL; } - data->try++; fprintf(data->prompt, "Login to '%s' required\n", data->card); fprintf(data->prompt, "PIN:\n"); if (fgets(buf, sizeof(buf), data->prompt)) @@ -752,7 +787,7 @@ static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, } chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); - if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7)) + if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) { free(secret.ptr); if (!prompt) @@ -764,7 +799,7 @@ static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, pin_data.prompt = prompt; pin_data.card = smartcard; pin_data.keyid = chunk; - pin_data.try = 1; + pin_data.try = 0; cb = callback_cred_create_shared((void*)pin_cb, &pin_data); lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE); } @@ -802,15 +837,14 @@ static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, } /** - * Load a private key + * Load a private key or PKCS#12 container from a file */ -static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, - FILE *prompt, key_type_t key_type) +static bool load_from_file(chunk_t line, int line_nr, FILE *prompt, + char *path, int type, int subtype, + void **result) { - char path[PATH_MAX]; chunk_t filename; chunk_t secret = chunk_empty; - private_key_t *key; err_t ugh = extract_value(&filename, &line); @@ -827,12 +861,12 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, if (*filename.ptr == '/') { /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", (int)filename.len, filename.ptr); + snprintf(path, PATH_MAX, "%.*s", (int)filename.len, filename.ptr); } else { /* relative path name */ - snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, + snprintf(path, PATH_MAX, "%s/%.*s", PRIVATE_KEY_DIR, (int)filename.len, filename.ptr); } @@ -846,32 +880,37 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, return FALSE; } } - if (secret.len == 7 && strneq(secret.ptr, "%prompt", 7)) + if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) { - callback_cred_t *cb = NULL; + callback_cred_t *cb; passphrase_cb_data_t pp_data = { .prompt = prompt, + .type = type, .path = path, - .try = 1, + .try = 0, }; free(secret.ptr); if (!prompt) { + *result = NULL; return TRUE; } + /* add cache first so if valid passphrases are needed multiple times + * the callback is not called anymore */ + pp_data.cache = mem_cred_create(); + lib->credmgr->add_local_set(lib->credmgr, &pp_data.cache->set, FALSE); /* use callback credential set to prompt for the passphrase */ - pp_data.prompt = prompt; - pp_data.path = path; - pp_data.try = 1; cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data); lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE); - key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, - BUILD_FROM_FILE, path, BUILD_END); + *result = lib->creds->create(lib->creds, type, subtype, + BUILD_FROM_FILE, path, BUILD_END); lib->credmgr->remove_local_set(lib->credmgr, &cb->set); cb->destroy(cb); + lib->credmgr->remove_local_set(lib->credmgr, &pp_data.cache->set); + pp_data.cache->destroy(pp_data.cache); } else { @@ -882,14 +921,44 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret); mem = mem_cred_create(); mem->add_shared(mem, shared, NULL); + if (eat_whitespace(&line)) + { /* if there is a second passphrase add that too, could be needed for + * PKCS#12 files using different passwords for MAC and encryption */ + ugh = extract_secret(&secret, &line); + if (ugh != NULL) + { + DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); + mem->destroy(mem); + return FALSE; + } + shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret); + mem->add_shared(mem, shared, NULL); + } lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE); - key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, - BUILD_FROM_FILE, path, BUILD_END); + *result = lib->creds->create(lib->creds, type, subtype, + BUILD_FROM_FILE, path, BUILD_END); lib->credmgr->remove_local_set(lib->credmgr, &mem->set); mem->destroy(mem); } + return TRUE; +} + +/** + * Load a private key + */ +static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, + FILE *prompt, key_type_t key_type) +{ + char path[PATH_MAX]; + private_key_t *key; + + if (!load_from_file(line, line_nr, prompt, path, CRED_PRIVATE_KEY, + key_type, (void**)&key)) + { + return FALSE; + } if (key) { DBG1(DBG_CFG, " loaded %N private key from '%s'", @@ -904,6 +973,58 @@ static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, } /** + * Load a PKCS#12 container + */ +static bool load_pkcs12(private_stroke_cred_t *this, mem_cred_t *secrets, + chunk_t line, int line_nr, FILE *prompt) +{ + enumerator_t *enumerator; + char path[PATH_MAX]; + certificate_t *cert; + private_key_t *key; + pkcs12_t *pkcs12; + + if (!load_from_file(line, line_nr, prompt, path, CRED_CONTAINER, + CONTAINER_PKCS12, (void**)&pkcs12)) + { + return FALSE; + } + if (!pkcs12) + { + DBG1(DBG_CFG, " loading credentials from '%s' failed", path); + return TRUE; + } + enumerator = pkcs12->create_cert_enumerator(pkcs12); + while (enumerator->enumerate(enumerator, &cert)) + { + x509_t *x509 = (x509_t*)cert; + + if (x509->get_flags(x509) & X509_CA) + { + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", + cert->get_subject(cert), path); + } + else + { + DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", + cert->get_subject(cert), path); + } + this->creds->add_cert(this->creds, TRUE, cert->get_ref(cert)); + } + enumerator->destroy(enumerator); + enumerator = pkcs12->create_key_enumerator(pkcs12); + while (enumerator->enumerate(enumerator, &key)) + { + DBG1(DBG_CFG, " loaded %N private key from '%s'", + key_type_names, key->get_type(key), path); + secrets->add_key(secrets, key->get_ref(key)); + } + enumerator->destroy(enumerator); + pkcs12->container.destroy(&pkcs12->container); + return TRUE; +} + +/** * Load a shared key */ static bool load_shared(mem_cred_t *secrets, chunk_t line, int line_nr, @@ -1021,8 +1142,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, { continue; } - if (line.len > strlen("include ") && - strneq(line.ptr, "include ", strlen("include "))) + if (line.len > strlen("include ") && strpfx(line.ptr, "include ")) { char **expanded, *dir, pattern[PATH_MAX]; u_char *pos; @@ -1090,7 +1210,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, continue; } - if (line.len > 2 && strneq(": ", line.ptr, 2)) + if (line.len > 2 && strpfx(line.ptr, ": ")) { /* no ids, skip the ':' */ ids = chunk_empty; @@ -1121,6 +1241,13 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, break; } } + else if (match("P12", &token)) + { + if (!load_pkcs12(this, secrets, line, line_nr, prompt)) + { + break; + } + } else if (match("PIN", &token)) { if (!load_pin(secrets, line, line_nr, prompt)) @@ -1141,7 +1268,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, else { DBG1(DBG_CFG, "line %d: token must be either " - "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr); + "RSA, ECDSA, P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr); break; } } diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h index c37d05808..f6fbb96d3 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.h +++ b/src/libcharon/plugins/stroke/stroke_cred.h @@ -68,13 +68,12 @@ struct stroke_cred_t { /** * Load a raw public key and serve it through the credential_set. * - * @param type type of the raw public key (RSA or ECDSA) - * @param filename file to load raw public key from + * @param filename encoding or file to load raw public key from * @param identity identity of the raw public key owner * @return reference to loaded raw public key, or NULL */ - certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type, - char *filename, identification_t *identity); + certificate_t* (*load_pubkey)(stroke_cred_t *this, char *filename, + identification_t *identity); /** * Add a shared secret to serve through the credential_set. diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index a2e1c80a5..e81f3fc32 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -207,8 +207,10 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) time_t use_in, use_out, rekey, now; u_int64_t bytes_in, bytes_out, packets_in, packets_out; proposal_t *proposal; - child_cfg_t *config = child_sa->get_config(child_sa); + linked_list_t *my_ts, *other_ts; + child_cfg_t *config; + config = child_sa->get_config(child_sa); now = time_monotonic(NULL); fprintf(out, "%12s{%d}: %N, %N%s", @@ -319,10 +321,15 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) fprintf(out, ", expires in %V", &now, &rekey); } + my_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, FALSE)); fprintf(out, "\n%12s{%d}: %#R=== %#R\n", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + my_ts, other_ts); + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); } /** @@ -1364,6 +1371,7 @@ static void list_plugins(FILE *out) free(str); } } + list->destroy(list); } enumerator->destroy(enumerator); } diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c index 4e47a120d..31df1f99b 100644 --- a/src/libcharon/plugins/stroke/stroke_plugin.c +++ b/src/libcharon/plugins/stroke/stroke_plugin.c @@ -51,12 +51,13 @@ static bool register_stroke(private_stroke_plugin_t *this, if (reg) { this->socket = stroke_socket_create(); + return this->socket != NULL; } else { DESTROY_IF(this->socket); + return TRUE; } - return TRUE; } METHOD(plugin_t, get_features, int, @@ -104,4 +105,3 @@ plugin_t *stroke_plugin_create() return &this->public.plugin; } - diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index aa5c73b8b..88f73f3b0 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -26,11 +26,6 @@ #include <hydra.h> #include <daemon.h> -#include <threading/mutex.h> -#include <threading/thread.h> -#include <threading/condvar.h> -#include <collections/linked_list.h> -#include <processing/jobs/callback_job.h> #include "stroke_config.h" #include "stroke_control.h" @@ -61,34 +56,9 @@ struct private_stroke_socket_t { stroke_socket_t public; /** - * Unix socket to listen for strokes + * Service accepting stroke connections */ - int socket; - - /** - * 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 @@ -132,22 +102,6 @@ struct private_stroke_socket_t { }; /** - * 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 @@ -432,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, @@ -444,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); + } } /** @@ -557,68 +570,47 @@ static void stroke_config(private_stroke_socket_t *this, } /** - * destroy a job context - */ -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" + * process a stroke request */ -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: @@ -694,123 +686,15 @@ static job_requeue_t process(stroke_job_context_t *ctx) 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, NULL, 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->caps->get_uid(charon->caps), - charon->caps->get_gid(charon->caps)) != 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->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); @@ -834,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 = { @@ -841,12 +727,6 @@ 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(); @@ -856,13 +736,6 @@ stroke_socket_t *stroke_socket_create() this->list = stroke_list_create(this->attribute); this->counter = stroke_counter_create(); - 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, - "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT, - charon->name); - 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); @@ -870,13 +743,20 @@ stroke_socket_t *stroke_socket_create() hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); charon->bus->add_listener(charon->bus, &this->counter->listener); - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this, - NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); - - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((callback_job_cb_t)handle, this, - NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); + 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; } |