diff options
-rw-r--r-- | usr.sbin/relayd/parse.y | 15 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 23 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.conf.5 | 26 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 6 | ||||
-rw-r--r-- | usr.sbin/relayd/ssl_privsep.c | 85 |
5 files changed, 140 insertions, 15 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index ded18cde6a9..09e99fb082f 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.130 2009/04/01 15:07:38 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.131 2009/04/02 14:30:51 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org> @@ -127,7 +127,7 @@ typedef struct { %} -%token ALL APPEND BACKLOG BACKUP BUFFER CACHE CHANGE CHECK +%token ALL APPEND BACKLOG BACKUP BUFFER CA CACHE CHANGE CHECK %token CIPHERS CODE COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT %token EXTERNAL FILENAME FILTER FORWARD FROM HASH HEADER HOST ICMP %token INCLUDE INET INET6 INTERFACE INTERVAL IP LABEL LISTEN @@ -136,7 +136,7 @@ typedef struct { %token QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST RESPONSE RETRY %token RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION SOCKET %token SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO -%token TRANSPARENT TRAP UPDATES URL VIRTUAL WITH +%token TRANSPARENT TRAP UPDATES URL VIRTUAL WITH %token <v.string> STRING %token <v.number> NUMBER %type <v.string> hostname interface table @@ -886,6 +886,14 @@ sslflags : SESSION CACHE sslcache { proto->cache = $3; } } free($2); } + | CA FILENAME STRING { + if (proto->sslca != NULL) { + yyerror("sslca already specified"); + free($3); + YYERROR; + } + proto->sslca = $3; + } | NO flag { proto->sslflags &= ~($2); } | flag { proto->sslflags |= $1; } ; @@ -1466,6 +1474,7 @@ lookup(char *s) { "backlog", BACKLOG }, { "backup", BACKUP }, { "buffer", BUFFER }, + { "ca", CA }, { "cache", CACHE }, { "change", CHANGE }, { "check", CHECK }, diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c index a0b45fa4803..8117c8e21cf 100644 --- a/usr.sbin/relayd/relay.c +++ b/usr.sbin/relayd/relay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relay.c,v 1.108 2009/04/01 14:56:38 reyk Exp $ */ +/* $OpenBSD: relay.c,v 1.109 2009/04/02 14:30:51 reyk Exp $ */ /* * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> @@ -2615,6 +2615,15 @@ relay_ssl_ctx_create(struct relay *rlay) if (!SSL_CTX_set_cipher_list(ctx, proto->sslciphers)) goto err; + /* Verify the server certificate if we have a CA chain */ + if ((rlay->rl_conf.flags & F_SSLCLIENT) && + (rlay->rl_ssl_ca != NULL)) { + if (!ssl_ctx_load_verify_memory(ctx, + rlay->rl_ssl_ca, rlay->rl_ssl_ca_len)) + goto err; + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + } + if ((rlay->rl_conf.flags & F_SSL) == 0) return (ctx); @@ -3113,9 +3122,17 @@ relay_load_file(const char *name, off_t *len) int relay_load_certfiles(struct relay *rlay) { + struct protocol *proto = rlay->rl_proto; char certfile[PATH_MAX]; char hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + if ((rlay->rl_conf.flags & F_SSLCLIENT) && (proto->sslca != NULL)) { + if ((rlay->rl_ssl_ca = relay_load_file(proto->sslca, + &rlay->rl_ssl_ca_len)) == NULL) + return (-1); + log_debug("relay_load_certfiles: using ca %s", proto->sslca); + } + if ((rlay->rl_conf.flags & F_SSL) == 0) return (0); @@ -3128,7 +3145,7 @@ relay_load_certfiles(struct relay *rlay) if ((rlay->rl_ssl_cert = relay_load_file(certfile, &rlay->rl_ssl_cert_len)) == NULL) return (-1); - log_debug("relay_load_certfile: using certificate %s", certfile); + log_debug("relay_load_certfiles: using certificate %s", certfile); if (snprintf(certfile, sizeof(certfile), "/etc/ssl/private/%s.key", hbuf) == -1) @@ -3136,7 +3153,7 @@ relay_load_certfiles(struct relay *rlay) if ((rlay->rl_ssl_key = relay_load_file(certfile, &rlay->rl_ssl_key_len)) == NULL) return (-1); - log_debug("relay_load_certfile: using private key %s", certfile); + log_debug("relay_load_certfiles: using private key %s", certfile); return (0); } diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index 3a08596fd07..22e1e731086 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.101 2009/04/01 14:56:38 reyk Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.102 2009/04/02 14:30:51 reyk Exp $ .\" .\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org> .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 1 2009 $ +.Dd $Mdocdate: April 2 2009 $ .Dt RELAYD.CONF 5 .Os .Sh NAME @@ -521,9 +521,9 @@ client will be retained in this case. The .Ic with ssl directive enables client-side SSL mode to connect to the remote host. -Note that -.Xr relayd 8 -will not verify the remote SSL certificate. +Verification of server certificates can be enabled by setting the +.Ic ca file +option in the protocol section. .Pp The following options may be specified for forward directives: .Pp @@ -945,6 +945,13 @@ Set the SSL options and session settings. This is only used if SSL is enabled in the relay. Valid options are: .Bl -tag -width Ds +.It Ic ca file Ar path +This option enables CA verification in SSL client mode. +The daemon will load the CA (Certificate Authority) certificates from +the specified path to verify the server certificates. +.Ox +provides a default CA bundle in +.Pa /etc/ssl/cert.pem . .It Ic ciphers Ar string Set the string defining the SSL cipher suite. If not specified, the default value @@ -1036,6 +1043,9 @@ Service name database. Location of the relay SSL server certificates, where .Ar address is the configured IP address of the relay. +.It Pa /etc/ssl/cert.pem +Default location of the CA bundle that can be used with +.Xr relayd 8 . .El .Sh EXAMPLES This configuration file would create a service @@ -1142,5 +1152,7 @@ and .An Reyk Floeter Aq reyk@openbsd.org . .Sh CAVEATS .Xr relayd 8 -does not support verification of server certificates when connecting -to a remote host using the SSL protocol. +Verification of SSL server certificates is based on a static CA bundle +and +.Xr relayd 8 +currently does not support CRLs (Certificate Revocation Lists). diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index 5a0813250da..f436f871523 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.114 2009/04/01 14:56:38 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.115 2009/04/02 14:30:51 reyk Exp $ */ /* * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -601,6 +601,7 @@ struct protocol { u_int8_t tcpipminttl; u_int8_t sslflags; char sslciphers[768]; + char *sslca; char name[MAX_NAME_SIZE]; int cache; enum prototype type; @@ -664,6 +665,8 @@ struct relay { off_t rl_ssl_cert_len; char *rl_ssl_key; off_t rl_ssl_key_len; + char *rl_ssl_ca; + off_t rl_ssl_ca_len; struct ctl_stats rl_stats[RELAY_MAXPROC + 1]; @@ -884,6 +887,7 @@ void ssl_error(const char *, const char *); /* ssl_privsep.c */ int ssl_ctx_use_private_key(SSL_CTX *, char *, off_t); int ssl_ctx_use_certificate_chain(SSL_CTX *, char *, off_t); +int ssl_ctx_load_verify_memory(SSL_CTX *, char *, off_t); /* relayd.c */ struct host *host_find(struct relayd *, objid_t); diff --git a/usr.sbin/relayd/ssl_privsep.c b/usr.sbin/relayd/ssl_privsep.c index ed01d55db5a..41983c0d441 100644 --- a/usr.sbin/relayd/ssl_privsep.c +++ b/usr.sbin/relayd/ssl_privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_privsep.c,v 1.6 2007/11/24 17:07:28 reyk Exp $ */ +/* $OpenBSD: ssl_privsep.c,v 1.7 2009/04/02 14:30:51 reyk Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. @@ -62,6 +62,9 @@ * Adapted from openssl's ssl_rsa.c by Pierre-Yves Ritschard . */ +#include <sys/types.h> +#include <sys/uio.h> + #include <unistd.h> #include <stdio.h> @@ -75,6 +78,23 @@ int ssl_ctx_use_private_key(SSL_CTX *, char *, off_t); int ssl_ctx_use_certificate_chain(SSL_CTX *, char *, off_t); +int ssl_ctx_load_verify_memory(SSL_CTX *, char *, off_t); +int ssl_by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **); + +X509_LOOKUP_METHOD x509_mem_lookup = { + "Load cert from memory", + NULL, /* new */ + NULL, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + ssl_by_mem_ctrl, /* ctrl */ + NULL, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +#define X509_L_ADD_MEM 3 int ssl_ctx_use_private_key(SSL_CTX *ctx, char *buf, off_t len) @@ -168,3 +188,66 @@ end: BIO_free(in); return (ret); } + +int +ssl_ctx_load_verify_memory(SSL_CTX *ctx, char *buf, off_t len) +{ + X509_LOOKUP *lu; + struct iovec iov; + + if ((lu = X509_STORE_add_lookup(ctx->cert_store, + &x509_mem_lookup)) == NULL) + return (0); + + iov.iov_base = buf; + iov.iov_len = len; + + if (!ssl_by_mem_ctrl(lu, X509_L_ADD_MEM, + (const char *)&iov, X509_FILETYPE_PEM, NULL)) + return (0); + + return (1); +} + +int +ssl_by_mem_ctrl(X509_LOOKUP *lu, int cmd, const char *buf, + long type, char **ret) +{ + STACK_OF(X509_INFO) *inf; + const struct iovec *iov; + X509_INFO *itmp; + BIO *in = NULL; + int i, count = 0; + + iov = (const struct iovec *)buf; + + if (type != X509_FILETYPE_PEM) + goto done; + + if ((in = BIO_new_mem_buf(iov->iov_base, iov->iov_len)) == NULL) + goto done; + + if ((inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) + goto done; + + for(i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + X509_STORE_add_cert(lu->store_ctx, itmp->x509); + count++; + } + if(itmp->crl) { + X509_STORE_add_crl(lu->store_ctx, itmp->crl); + count++; + } + } + sk_X509_INFO_pop_free(inf, X509_INFO_free); + + done: + if (!count) + X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB); + + if (in != NULL) + BIO_free(in); + return (count); +} |