From fb56df5c98649d9a4b313fdee24d5dc6c189c1e1 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sat, 10 Feb 2024 18:44:41 +0100 Subject: [PATCH] ocspd: Created an OCSP responder daemon --- configure.ac | 4 + src/Makefile.am | 4 + src/ocspd/.gitignore | 1 + src/ocspd/Makefile.am | 16 ++ src/ocspd/ocspd.8 | 135 ++++++++++++ src/ocspd/ocspd.8.in | 135 ++++++++++++ src/ocspd/ocspd.c | 499 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 794 insertions(+) create mode 100644 src/ocspd/.gitignore create mode 100644 src/ocspd/Makefile.am create mode 100644 src/ocspd/ocspd.8 create mode 100644 src/ocspd/ocspd.8.in create mode 100644 src/ocspd/ocspd.c diff --git a/configure.ac b/configure.ac index 32eae7889d..e48cf9c594 100644 --- a/configure.ac +++ b/configure.ac @@ -309,6 +309,7 @@ ARG_ENABL_SET([systemd], [enable systemd specific IKE daemon charon-syste ARG_DISBL_SET([swanctl], [disable swanctl configuration and control tool.]) ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.]) ARG_ENABL_SET([cert-enroll], [enable automatic certificate enrollment via EST or SCEP.]) +ARG_ENABL_SET([ocspd],[enable OCSP responder daemon.]) # optional features ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.]) ARG_ENABL_SET([dbghelp-backtraces],[use dbghlp.dll on Windows to create and print backtraces for memory leaks and segfaults.]) @@ -1906,6 +1907,7 @@ AM_CONDITIONAL(USE_SYSTEMD, test x$systemd = xtrue) AM_CONDITIONAL(USE_LEGACY_SYSTEMD, test -n "$systemdsystemunitdir" -a "x$systemdsystemunitdir" != xno) AM_CONDITIONAL(USE_CERT_ENROLL, test x$cert_enroll = xtrue) AM_CONDITIONAL(USE_CERT_ENROLL_TIMER, test x$cert_enroll_timer = xtrue) +AM_CONDITIONAL(USE_OCSPD, test x$ocspd = xtrue) AM_CONDITIONAL(USE_RUBY_GEMS, test x$ruby_gems = xtrue) AM_CONDITIONAL(USE_PYTHON_EGGS, test x$python_eggs = xtrue) AM_CONDITIONAL(USE_PERL_CPAN, test x$perl_cpan = xtrue) @@ -2182,6 +2184,7 @@ AC_CONFIG_FILES([ src/sec-updater/Makefile src/swanctl/Makefile src/cert-enroll/Makefile + src/ocspd/Makefile src/xfrmi/Makefile scripts/Makefile testing/Makefile @@ -2223,6 +2226,7 @@ AC_CONFIG_FILES([ src/sw-collector/sw-collector.8 src/sec-updater/sec-updater.8 src/cert-enroll/cert-enroll.8 + src/ocspd/ocspd.8 ]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 8abcbcf672..cf45631a01 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -146,3 +146,7 @@ endif if USE_CERT_ENROLL SUBDIRS += cert-enroll endif + +if USE_OCSPD + SUBDIRS += ocspd +endif diff --git a/src/ocspd/.gitignore b/src/ocspd/.gitignore new file mode 100644 index 0000000000..32d094dc2a --- /dev/null +++ b/src/ocspd/.gitignore @@ -0,0 +1 @@ +ocspd diff --git a/src/ocspd/Makefile.am b/src/ocspd/Makefile.am new file mode 100644 index 0000000000..24c7139c05 --- /dev/null +++ b/src/ocspd/Makefile.am @@ -0,0 +1,16 @@ +sbin_PROGRAMS = ocspd + +ocspd_SOURCES = ocspd.c + +ocspd.o : $(top_builddir)/config.status + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -DPLUGINS="\"pem pkcs1 x509 openssl wolfssl\"" + +ocspd_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la + +man8_MANS = ocspd.8 + +CLEANFILES = $(man8_MANS) diff --git a/src/ocspd/ocspd.8 b/src/ocspd/ocspd.8 new file mode 100644 index 0000000000..0398648517 --- /dev/null +++ b/src/ocspd/ocspd.8 @@ -0,0 +1,135 @@ +.TH PT-TLS-CLIENT 1 "2018-11-20" "5.9.13" "strongSwan" +. +.SH "NAME" +. +pt-tls-client \- Simple client using PT-TLS to collect integrity information +. +.SH "SYNOPSIS" +. +.SY "pt-tls-client" +.BI \-\-connect +.IR hostname |\fIaddress +.OP \-\-port port +.RB [ \-\-certid +.IR hex |\fB\-\-cert +.IR file ]+ +.RB [ \-\-keyid +.IR hex |\fB\-\-key +.IR file ] +.RB [ \-\-key-type +.BR rsa |\fBecdsa\fR] +.OP \-\-client client-id +.OP \-\-secret password +.OP \-\-mutual +.OP \-\-options filename +.OP \-\-quiet +.OP \-\-debug level +.YS +. +.SY "pt-tls-client" +.B \-h +| +.B \-\-help +.YS +. +.SH "DESCRIPTION" +. +.B pt-tls-client +is a simple client using the PT-TLS (RFC 6876) transport protocol to collect +integrity measurements on the client platform. PT-TLS does an initial TLS +handshake with certificate-based server authentication and optional +certificate-based client authentication. Alternatively simple password-based +SASL client authentication protected by TLS can be used. +.P +Attribute requests and integrity measurements are exchanged via the PA-TNC (RFC +5792) message protocol between any number of Integrity Measurement Verifiers +(IMVs) residing on the remote PT-TLS server and multiple Integrity Measurement +Collectors (IMCs) loaded dynamically by the PT-TLS client according to a list +defined by \fI/etc/tnc_config\fR. PA-TNC messages that contain one or several +PA-TNC attributes are multiplexed into PB-TNC (RFC 5793) client or server data +batches which in turn are transported via PT-TLS. +. +.SH "OPTIONS" +. +.TP +.B "\-h, \-\-help" +Prints usage information and a short summary of the available commands. +.TP +.BI "\-c, \-\-connect " hostname\fR|\fIaddress +Set the hostname or IP address of the PT-TLS server. +.TP +.BI "\-p, \-\-port " port +Set the port of the PT-TLS server, default: 271. +.TP +.BI "\-x, \-\-cert " file +Set the path to an X.509 certificate file. This option can be repeated to load +multiple client and CA certificates. +.TP +.BI "\-X, \-\-certid " hex +Set the handle of the certificate stored in a smartcard or a TPM 2.0 Trusted +Platform Module. +.TP +.BI "\-k, \-\-key " file +Set the path to the client's PKCS#1 or PKCS#8 private key file +.TP +.BI "\-t, \-\-key\-type " type +Define the type of the private key if stored in PKCS#1 format. Can be omitted +with PKCS#8 keys. +.TP +.BI "\-K, \-\-keyid " hex +Set the keyid of the private key stored in a smartcard or a TPM 2.0 Trusted +Platform Module. +.TP +.BI "\-i, \-\-client " client-id +Set the username or client ID of the client required for password-based SASL +authentication. +.TP +.BI "\-s, \-\-secret " password +Set the preshared secret or client password required for password-based SASL +authentication. +.TP +.B "\-q, \-\-mutual +Enable mutual attestation between PT-TLS client and PT-TLS server. +.TP +.BI "\-v, \-\-debug " level +Set debug level, default: 1. +.TP +.B "\-q, \-\-quiet +Disable debug output to stderr. +.TP +.BI "\-+, \-\-options " file +Read command line options from \fIfile\fR. +. +.SH "EXAMPLES" +. +Connect to a PT-TLS server using certificate-based authentication, +storing the private ECDSA key in a file: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com \-\-cert ca.crt \\ + \-\-cert client.crt \-\-key client.key \-\-key\-type ecdsa +.EE +.PP +Connect to a PT-TLS server using certificate-based authentication, +storing the private key in a smartcard or a TPM 2.0 Trusted Platform Module: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com \-\-cert ca.crt \\ + \-\-cert client.crt \-\-keyid 0x81010002 +.EE +.PP +Connect to a PT-TLS server listening on port 443, using SASL password-based +authentication: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com --port 443 \-\-cert ca.crt \\ + \-\-client jane \-\-password p2Nl9trKlb +.EE +.SH FILES +.TP +/etc/tnc_config +. +.SH "SEE ALSO" +. +.BR strongswan.conf (5) + diff --git a/src/ocspd/ocspd.8.in b/src/ocspd/ocspd.8.in new file mode 100644 index 0000000000..6bd3c642e4 --- /dev/null +++ b/src/ocspd/ocspd.8.in @@ -0,0 +1,135 @@ +.TH PT-TLS-CLIENT 1 "2018-11-20" "@PACKAGE_VERSION@" "strongSwan" +. +.SH "NAME" +. +pt-tls-client \- Simple client using PT-TLS to collect integrity information +. +.SH "SYNOPSIS" +. +.SY "pt-tls-client" +.BI \-\-connect +.IR hostname |\fIaddress +.OP \-\-port port +.RB [ \-\-certid +.IR hex |\fB\-\-cert +.IR file ]+ +.RB [ \-\-keyid +.IR hex |\fB\-\-key +.IR file ] +.RB [ \-\-key-type +.BR rsa |\fBecdsa\fR] +.OP \-\-client client-id +.OP \-\-secret password +.OP \-\-mutual +.OP \-\-options filename +.OP \-\-quiet +.OP \-\-debug level +.YS +. +.SY "pt-tls-client" +.B \-h +| +.B \-\-help +.YS +. +.SH "DESCRIPTION" +. +.B pt-tls-client +is a simple client using the PT-TLS (RFC 6876) transport protocol to collect +integrity measurements on the client platform. PT-TLS does an initial TLS +handshake with certificate-based server authentication and optional +certificate-based client authentication. Alternatively simple password-based +SASL client authentication protected by TLS can be used. +.P +Attribute requests and integrity measurements are exchanged via the PA-TNC (RFC +5792) message protocol between any number of Integrity Measurement Verifiers +(IMVs) residing on the remote PT-TLS server and multiple Integrity Measurement +Collectors (IMCs) loaded dynamically by the PT-TLS client according to a list +defined by \fI/etc/tnc_config\fR. PA-TNC messages that contain one or several +PA-TNC attributes are multiplexed into PB-TNC (RFC 5793) client or server data +batches which in turn are transported via PT-TLS. +. +.SH "OPTIONS" +. +.TP +.B "\-h, \-\-help" +Prints usage information and a short summary of the available commands. +.TP +.BI "\-c, \-\-connect " hostname\fR|\fIaddress +Set the hostname or IP address of the PT-TLS server. +.TP +.BI "\-p, \-\-port " port +Set the port of the PT-TLS server, default: 271. +.TP +.BI "\-x, \-\-cert " file +Set the path to an X.509 certificate file. This option can be repeated to load +multiple client and CA certificates. +.TP +.BI "\-X, \-\-certid " hex +Set the handle of the certificate stored in a smartcard or a TPM 2.0 Trusted +Platform Module. +.TP +.BI "\-k, \-\-key " file +Set the path to the client's PKCS#1 or PKCS#8 private key file +.TP +.BI "\-t, \-\-key\-type " type +Define the type of the private key if stored in PKCS#1 format. Can be omitted +with PKCS#8 keys. +.TP +.BI "\-K, \-\-keyid " hex +Set the keyid of the private key stored in a smartcard or a TPM 2.0 Trusted +Platform Module. +.TP +.BI "\-i, \-\-client " client-id +Set the username or client ID of the client required for password-based SASL +authentication. +.TP +.BI "\-s, \-\-secret " password +Set the preshared secret or client password required for password-based SASL +authentication. +.TP +.B "\-q, \-\-mutual +Enable mutual attestation between PT-TLS client and PT-TLS server. +.TP +.BI "\-v, \-\-debug " level +Set debug level, default: 1. +.TP +.B "\-q, \-\-quiet +Disable debug output to stderr. +.TP +.BI "\-+, \-\-options " file +Read command line options from \fIfile\fR. +. +.SH "EXAMPLES" +. +Connect to a PT-TLS server using certificate-based authentication, +storing the private ECDSA key in a file: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com \-\-cert ca.crt \\ + \-\-cert client.crt \-\-key client.key \-\-key\-type ecdsa +.EE +.PP +Connect to a PT-TLS server using certificate-based authentication, +storing the private key in a smartcard or a TPM 2.0 Trusted Platform Module: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com \-\-cert ca.crt \\ + \-\-cert client.crt \-\-keyid 0x81010002 +.EE +.PP +Connect to a PT-TLS server listening on port 443, using SASL password-based +authentication: +.PP +.EX + pt-tls-client \-\-connect pdp.example.com --port 443 \-\-cert ca.crt \\ + \-\-client jane \-\-password p2Nl9trKlb +.EE +.SH FILES +.TP +/etc/tnc_config +. +.SH "SEE ALSO" +. +.BR strongswan.conf (5) + diff --git a/src/ocspd/ocspd.c b/src/ocspd/ocspd.c new file mode 100644 index 0000000000..9f60daddbd --- /dev/null +++ b/src/ocspd/ocspd.c @@ -0,0 +1,499 @@ +/* + * Copyright (C) 2024 Andreas Steffen + * + * Copyright (C) secunet Security Networks AG + * + * 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 . + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + * Print usage information + */ +static void usage(FILE *out, char *cmd) +{ + fprintf(out, "usage:\n"); + fprintf(out, " %s --ipv4
|--ipv6
[--port ]\n", cmd); + fprintf(out, "\n"); + fprintf(out, "options:\n"); + fprintf(out, " --help print help and exit\n"); + fprintf(out, " --ipv4
specify IPv4 address to use \n"); + fprintf(out, " --ipv6
specify IPv6 address to use\n"); + fprintf(out, " --port specify the port to use\n"); + fprintf(out, " --threads specify the number of threads to spawn\n"); + fprintf(out, " --debug set debug level, default is 1\n"); +} + +/** + * In-Memory credential set + */ +static mem_cred_t *creds; + +/** + * IPv4/IPv6 sockets + */ +static int ipv4_socket, ipv6_socket; + +/** + * Signing key + */ +private_key_t *key = NULL; + +/** + * TLS debug level + */ +static level_t debug_level = 1; + +static void dbg_ocspd(debug_t group, level_t level, char *fmt, ...) +{ + if (level <= debug_level) + { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +/** + * Cleanup + */ +static void cleanup() +{ + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + library_deinit(); +} + +/** + * Initialize library + */ +static void init() +{ + library_init(NULL, "ocspd"); + dbg = dbg_ocspd; + + /* load ocspd plugins */ + if (!lib->plugins->load(lib->plugins, + lib->settings->get_str(lib->settings, "%s.load", PLUGINS, lib->ns))) + { + exit(SS_RC_INITIALIZATION_FAILED); + } + + creds = mem_cred_create(); + lib->credmgr->add_set(lib->credmgr, &creds->set); + + atexit(cleanup); +} + +/** + * Open IPv4 or IPv6 TCP socket + */ +static int open_tcp_socket(int family, uint16_t port) +{ + int on = TRUE; + struct sockaddr_storage addr; + socklen_t addrlen; + int skt; + + memset(&addr, 0, sizeof(addr)); + addr.ss_family = family; + + /* precalculate constants depending on address family */ + switch (family) + { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *)&addr; + + htoun32(&sin->sin_addr.s_addr, INADDR_ANY); + htoun16(&sin->sin_port, port); + addrlen = sizeof(struct sockaddr_in); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; + + memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); + htoun16(&sin6->sin6_port, port); + addrlen = sizeof(struct sockaddr_in6); + break; + } + default: + return 0; + } + + /* open the socket */ + skt = socket(family, SOCK_STREAM, IPPROTO_TCP); + if (skt < 0) + { + DBG1(DBG_CFG, "opening TCP socket failed: %s", strerror(errno)); + return 0; + } + if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "unable to set SO_REUSEADDR on socket: %s", + strerror(errno)); + close(skt); + return 0; + } + if (family == AF_INET6) + { + if (setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "unable to set IPV6_V6ONLY on socket: %s", + strerror(errno)); + close(skt); + return 0; + } + } + + /* bind the socket */ + if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0) + { + DBG1(DBG_CFG, "unable to bind TCP socket: %s", strerror(errno)); + close(skt); + return 0; + } + + /* start listening on socket */ + if (listen(skt, 5) == -1) + { + DBG1(DBG_TNC, "listen on TCP socket failed: %s", strerror(errno)); + close(skt); + return 0; + } + + return skt; +} + +static bool parse_http_header(chunk_t *in, u_int *content_len) +{ + chunk_t line, method, path, parameter; + u_int len; + + /*initialize output parameters */ + *content_len = 0; + + /* Process HTTP protocol version and HTTP status code */ + if (!fetchline(in, &line) || + !extract_token(&method, ' ', &line) || !match("POST", &method) || + !extract_token(&path, ' ', &line) || + !(match("HTTP/1.1", &line) || match("HTTP/1.0", &line))) + { + DBG1(DBG_APP, "malformed http response header"); + return FALSE; + } + + /* Process HTTP header line by line until the HTTP body is reached */ + while (fetchline(in, &line)) + { + if (line.len == 0) + { + break; + } + if (extract_token(¶meter, ':', &line) && eat_whitespace(&line)) + { + if (matchcase("Content-Length", ¶meter)) + { + if (sscanf(line.ptr, "%u", &len) == 1) + { + *content_len = len; + } + } + else if (matchcase("Content-Type", ¶meter)) + { + if (!matchcase("application/ocsp-request", &line)) + { + DBG1(DBG_APP, "wrong Content-Type '%.*s", line.len, line.ptr); + return FALSE; + } + } + } + } + return TRUE; +} + +/** + * Accept TCP connection received on the PT-TLS listening socket + */ +static bool ocsp_receive(void *this, int fd, watcher_event_t event) +{ + int ocsp_fd, flags = 0; + chunk_t request; + u_int len; + ssize_t in; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + char buf[4096]; + host_t *client; + + ocsp_fd = accept(fd, (sockaddr_t*)&addr, &addrlen); + if (ocsp_fd == -1) + { + DBG1(DBG_APP, "accepting OCSP stream failed: %s", strerror(errno)); + return FALSE; + } + client = host_create_from_sockaddr((sockaddr_t*)&addr); + DBG1(DBG_APP, "accepting OCSP stream %d from %H", ocsp_fd, client); + client->destroy(client); + + in = recv(ocsp_fd, buf, sizeof(buf), flags); + + if (in < 0) + { + DBG1(DBG_APP, "recv error"); + } + else + { + chunk_t signature = chunk_empty; + chunk_t data = chunk_from_chars( + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + ); + + request = chunk_create(buf, in); + if (parse_http_header(&request, &len)) + { + DBG1(DBG_APP, "Content-Length: %u bytes, remaining %d bytes", len, + request.len); + + if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_SHA2_384, NULL, + data, &signature)) + { + DBG1(DBG_APP, "creating OCSP response signature failed"); + } + else + { + DBG1(DBG_APP, "creating OCSP response signature successful"); + } + chunk_free(&signature); + } + } + close(ocsp_fd); + + /* + pt_tls = pt_tls_server_create(this->server, pt_tls_fd, auth, tnccs); + if (!pt_tls) + { + DBG1(DBG_TNC, "could not create PT-TLS connection instance"); + close(pt_tls_fd); + return FALSE; + } + lib->watcher->add(lib->watcher, ocsp_fd, WATCHER_READ, + (watcher_cb_t)ocsp_receive_more, NULL); + */ + return TRUE; +} + +/** + * Run the daemon and handle unix signals + */ +static void run() +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGTERM); + sigprocmask(SIG_BLOCK, &set, NULL); + + while (TRUE) + { + int sig; + + /* wait for signal */ + sig = sigwaitinfo(&set, NULL); + if (sig == -1) + { + if (errno == EINTR) + { /* ignore signals we didn't wait for */ + continue; + } + DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno)); + return; + } + + switch (sig) + { + case SIGHUP: + DBG1(DBG_APP, "received SIGHUP, updating configuration"); + continue; + case SIGINT: + case SIGTERM: + DBG1(DBG_APP, "received %s, shutting down", + (sig == SIGINT) ? "SIGINT" : "SIGTERM"); + return; + } + } +} + + +int main(int argc, char *argv[]) +{ + mem_cred_t *creds; + chunk_t handle = chunk_empty; + shared_key_t *shared = NULL; + identification_t *owner; + char keyid[] = "10", pin[] = "272841"; + struct sigaction action; + bool has_ipv4 = FALSE, has_ipv6 = FALSE; + int port = 80, threads = 4, res = 1; + + init(); + + while (TRUE) + { + struct option long_opts[] = { + {"help", no_argument, NULL, 'h' }, + {"port", required_argument, NULL, 'p' }, + {"ipv4", no_argument, NULL, '4' }, + {"ipv6", no_argument, NULL, '6' }, + {"threads", required_argument, NULL, 't' }, + {"debug", required_argument, NULL, 'd' }, + {0,0,0,0 } + }; + + switch (getopt_long(argc, argv, "hp;46t:d:", long_opts, NULL)) + { + case EOF: + break; + case 'h': + usage(stdout, argv[0]); + return 0; + case 'p': + port = atoi(optarg); + continue; + case 'd': + debug_level = atoi(optarg); + continue; + case '4': + has_ipv4 = TRUE; + continue; + case '6': + has_ipv6 = TRUE; + continue; + case 't': + threads = atoi(optarg); + continue; + default: + usage(stderr, argv[0]); + return 1; + } + break; + } + + creds = mem_cred_create(); + lib->credmgr->add_local_set(lib->credmgr, &creds->set, FALSE); + + handle = chunk_from_hex(chunk_from_str(keyid), NULL); + shared = shared_key_create(SHARED_PIN, chunk_clone(chunk_from_str(pin))); + owner = identification_create_from_encoding(ID_KEY_ID, handle); + creds->add_shared(creds, shared->get_ref(shared), owner, NULL); + + key = lib->creds->create(lib->creds, + CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, handle, BUILD_END); + chunk_free(&handle); + if (!key) + { + DBG1(DBG_APP, "attaching to private key handle %s failed", keyid); + goto end; + } + creds->add_key(creds, key); + + if (has_ipv4) + { + ipv4_socket = open_tcp_socket(AF_INET, port); + if (ipv4_socket) + { + lib->watcher->add(lib->watcher, ipv4_socket, WATCHER_READ, + (watcher_cb_t)ocsp_receive, NULL); + } + else + { + DBG1(DBG_APP, "could not open IPv4 TCP socket, IPv4 disabled"); + } + } + if (has_ipv6) + { + ipv6_socket = open_tcp_socket(AF_INET6, port); + if (ipv6_socket) + { + lib->watcher->add(lib->watcher, ipv6_socket, WATCHER_READ, + (watcher_cb_t)ocsp_receive, NULL); + } + else + { + DBG1(DBG_APP, "could not open IPv6 TCP socket, IPv6 disabled"); + } + } + if (!ipv4_socket && !ipv6_socket) + { + DBG1(DBG_APP, "could not create any listening sockets, exiting"); + goto end; + } + + /* add handler for fatal signals, + * INT, TERM and HUP are handled by sigwaitinfo() in run() + */ + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGINT); + sigaddset(&action.sa_mask, SIGTERM); + sigaddset(&action.sa_mask, SIGHUP); + + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + + pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); + + lib->processor->set_threads(lib->processor, threads); + res = 0; + + /* main thread goes to run loop */ + run(); + +end: + if (ipv4_socket) + { + lib->watcher->remove(lib->watcher, ipv4_socket); + close(ipv4_socket); + } + if (ipv6_socket) + { + lib->watcher->remove(lib->watcher, ipv6_socket); + close(ipv6_socket); + } + + lib->credmgr->remove_local_set(lib->credmgr, &creds->set); + creds->destroy(creds); + exit(res); +} -- 2.47.2