summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/relayd/parse.y15
-rw-r--r--usr.sbin/relayd/relay.c23
-rw-r--r--usr.sbin/relayd/relayd.conf.526
-rw-r--r--usr.sbin/relayd/relayd.h6
-rw-r--r--usr.sbin/relayd/ssl_privsep.c85
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);
+}