use libtls in ldapd

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

use libtls in ldapd

Jonathan Matthew-4
A while back (s2k15?), reyk@ suggested I take a look at converting ldapd to use
libtls rather than the openssl api.  Today I finally got around to it,
resulting in the diff below.  Most of the diff just removes ssl.c and
ssl_privsep.c, and replaces some of it with evbuffer_tls.c (copied from
syslogd, unmodified).  A reasonable amount of code just went away because
libtls is sensible.  The few remaining bits of ssl.c moved to wherever seemed
most suitable.

I've tested a few things with the openldap clients, which apparently only do
starttls, and otherwise checked that it negotiates ssl successfully.

ok?


Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 Makefile
--- Makefile 16 Jul 2014 20:07:03 -0000 1.12
+++ Makefile 10 Apr 2016 06:15:50 -0000
@@ -5,11 +5,11 @@ MAN= ldapd.8 ldapd.conf.5
 SRCS= ber.c log.c control.c \
  util.c ldapd.c ldape.c conn.c attributes.c namespace.c \
  btree.c filter.c search.c parse.y \
- auth.c modify.c index.c ssl.c ssl_privsep.c \
+ auth.c modify.c index.c evbuffer_tls.c \
  validate.c uuid.c schema.c imsgev.c syntax.c matching.c
 
-LDADD= -levent -lssl -lcrypto -lz -lutil
-DPADD= ${LIBEVENT} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
+LDADD= -ltls -levent -lz -lutil
+DPADD= ${LIBEVENT} ${LIBTLS} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
 CFLAGS+= -I${.CURDIR} -g
 CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes
 CFLAGS+= -Wmissing-declarations
Index: btree.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/btree.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 btree.c
--- btree.c 20 Mar 2016 00:01:22 -0000 1.36
+++ btree.c 10 Apr 2016 06:15:51 -0000
@@ -34,6 +34,8 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <openssl/sha.h>
+
 #include "btree.h"
 
 /* #define DEBUG */
Index: btree.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/btree.h,v
retrieving revision 1.6
diff -u -p -u -p -r1.6 btree.h
--- btree.h 2 Jul 2010 01:43:00 -0000 1.6
+++ btree.h 10 Apr 2016 06:15:51 -0000
@@ -19,8 +19,6 @@
 #ifndef _btree_h_
 #define _btree_h_
 
-#include <openssl/sha.h>
-
 struct mpage;
 struct cursor;
 struct btree_txn;
Index: conn.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/conn.c,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 conn.c
--- conn.c 2 Nov 2015 06:32:51 -0000 1.12
+++ conn.c 10 Apr 2016 06:15:51 -0000
@@ -26,6 +26,7 @@
 #include "ldapd.h"
 
 int conn_dispatch(struct conn *conn);
+int conn_tls_init(struct conn *);
 unsigned long ldap_application(struct ber_element *elm);
 
 struct conn_list conn_list;
@@ -61,7 +62,7 @@ conn_close(struct conn *conn)
  /* Cancel any queued requests on this connection. */
  namespace_cancel_conn(conn);
 
- ssl_session_destroy(conn);
+ tls_free(conn->tls);
 
  TAILQ_REMOVE(&conn_list, conn, next);
  ber_free(&conn->ber);
@@ -225,9 +226,8 @@ conn_write(struct bufferevent *bev, void
  conn_close(conn);
  else if (conn->s_flags & F_STARTTLS) {
  conn->s_flags &= ~F_STARTTLS;
- bufferevent_free(conn->bev);
- conn->bev = NULL;
- ssl_session_init(conn);
+ if (conn_tls_init(conn) == -1)
+ conn_close(conn);
  }
 }
 
@@ -296,24 +296,22 @@ conn_accept(int fd, short event, void *d
  goto giveup;
  }
  conn->ber.fd = -1;
- conn->s_l = l;
  ber_set_application(&conn->ber, ldap_application);
  conn->fd = afd;
  conn->listener = l;
 
- if (l->flags & F_LDAPS) {
- ssl_session_init(conn);
- } else {
- conn->bev = bufferevent_new(afd, conn_read, conn_write,
-    conn_err, conn);
- if (conn->bev == NULL) {
- log_warn("conn_accept: bufferevent_new");
- free(conn);
- goto giveup;
- }
- bufferevent_enable(conn->bev, EV_READ);
- bufferevent_settimeout(conn->bev, 0, 60);
+ conn->bev = bufferevent_new(afd, conn_read, conn_write,
+    conn_err, conn);
+ if (conn->bev == NULL) {
+ log_warn("conn_accept: bufferevent_new");
+ free(conn);
+ goto giveup;
  }
+ bufferevent_enable(conn->bev, EV_READ);
+ bufferevent_settimeout(conn->bev, 0, 60);
+ if (conn->s_flags & F_LDAPS)
+ if (conn_tls_init(conn) == -1)
+ conn_close(conn);
 
  TAILQ_INIT(&conn->searches);
  TAILQ_INSERT_HEAD(&conn_list, conn, next);
@@ -365,4 +363,25 @@ conn_close_any()
  }
 
  return -1;
+}
+
+int
+conn_tls_init(struct conn *conn)
+{
+ struct listener *l = conn->listener;
+
+ if (!(l->flags & F_SSL))
+ return 0;
+
+ log_debug("conn_tls_init: switching to TLS");
+
+ if (tls_accept_socket(l->tls, &conn->tls, conn->fd) < 0) {
+ log_debug("tls_accept_socket failed");
+ return -1;
+ }
+
+ conn->s_flags |= F_SECURE;
+ buffertls_set(&conn->buftls, conn->bev, conn->tls, conn->fd);
+ buffertls_accept(&conn->buftls, conn->fd);
+ return 0;
 }
Index: evbuffer_tls.c
===================================================================
RCS file: evbuffer_tls.c
diff -N evbuffer_tls.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ evbuffer_tls.c 10 Apr 2016 06:15:51 -0000
@@ -0,0 +1,350 @@
+/* $OpenBSD: evbuffer_tls.c,v 1.9 2015/10/09 16:58:25 bluhm Exp $ */
+
+/*
+ * Copyright (c) 2002-2004 Niels Provos <[hidden email]>
+ * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <event.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tls.h>
+
+#include "evbuffer_tls.h"
+
+/* prototypes */
+
+void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
+static void buffertls_readcb(int, short, void *);
+static void buffertls_writecb(int, short, void *);
+static void buffertls_handshakecb(int, short, void *);
+int evtls_read(struct evbuffer *, int, int, struct tls *);
+int evtls_write(struct evbuffer *, int, struct tls *);
+
+static int
+bufferevent_add(struct event *ev, int timeout)
+{
+ struct timeval tv, *ptv = NULL;
+
+ if (timeout) {
+ timerclear(&tv);
+ tv.tv_sec = timeout;
+ ptv = &tv;
+ }
+
+ return (event_add(ev, ptv));
+}
+
+static void
+buffertls_readcb(int fd, short event, void *arg)
+{
+ struct buffertls *buftls = arg;
+ struct bufferevent *bufev = buftls->bt_bufev;
+ struct tls *ctx = buftls->bt_ctx;
+ int res = 0;
+ short what = EVBUFFER_READ;
+ size_t len;
+ int howmuch = -1;
+
+ if (event == EV_TIMEOUT) {
+ what |= EVBUFFER_TIMEOUT;
+ goto error;
+ }
+
+ /*
+ * If we have a high watermark configured then we don't want to
+ * read more data than would make us reach the watermark.
+ */
+ if (bufev->wm_read.high != 0) {
+ howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
+ /* we might have lowered the watermark, stop reading */
+ if (howmuch <= 0) {
+ struct evbuffer *buf = bufev->input;
+ event_del(&bufev->ev_read);
+ evbuffer_setcb(buf,
+    bufferevent_read_pressure_cb, bufev);
+ return;
+ }
+ }
+
+ res = evtls_read(bufev->input, fd, howmuch, ctx);
+ switch (res) {
+ case TLS_WANT_POLLIN:
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ return;
+ case TLS_WANT_POLLOUT:
+ event_del(&bufev->ev_write);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb,
+    buftls);
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+ return;
+ case -1:
+ what |= EVBUFFER_ERROR;
+ break;
+ case 0:
+ what |= EVBUFFER_EOF;
+ break;
+ }
+ if (res <= 0)
+ goto error;
+
+ event_del(&bufev->ev_write);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
+ if (bufev->enabled & EV_READ)
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+
+ /* See if this callbacks meets the water marks */
+ len = EVBUFFER_LENGTH(bufev->input);
+ if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
+ return;
+ if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
+ struct evbuffer *buf = bufev->input;
+ event_del(&bufev->ev_read);
+
+ /* Now schedule a callback for us when the buffer changes */
+ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
+ }
+
+ /* Invoke the user callback - must always be called last */
+ if (bufev->readcb != NULL)
+ (*bufev->readcb)(bufev, bufev->cbarg);
+ return;
+
+ error:
+ (*bufev->errorcb)(bufev, what, bufev->cbarg);
+}
+
+static void
+buffertls_writecb(int fd, short event, void *arg)
+{
+ struct buffertls *buftls = arg;
+ struct bufferevent *bufev = buftls->bt_bufev;
+ struct tls *ctx = buftls->bt_ctx;
+ int res = 0;
+ short what = EVBUFFER_WRITE;
+
+ if (event == EV_TIMEOUT) {
+ what |= EVBUFFER_TIMEOUT;
+ goto error;
+ }
+
+ if (EVBUFFER_LENGTH(bufev->output) != 0) {
+ res = evtls_write(bufev->output, fd, ctx);
+ switch (res) {
+ case TLS_WANT_POLLIN:
+ event_del(&bufev->ev_read);
+ event_set(&bufev->ev_read, fd, EV_READ,
+    buffertls_writecb, buftls);
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ return;
+ case TLS_WANT_POLLOUT:
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+ return;
+ case -1:
+ what |= EVBUFFER_ERROR;
+ break;
+ case 0:
+ what |= EVBUFFER_EOF;
+ break;
+ }
+ if (res <= 0)
+ goto error;
+ }
+
+ event_del(&bufev->ev_read);
+ event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
+ if (bufev->enabled & EV_READ)
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+
+ /*
+ * Invoke the user callback if our buffer is drained or below the
+ * low watermark.
+ */
+ if (bufev->writecb != NULL &&
+    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
+ (*bufev->writecb)(bufev, bufev->cbarg);
+
+ return;
+
+ error:
+ (*bufev->errorcb)(bufev, what, bufev->cbarg);
+}
+
+static void
+buffertls_handshakecb(int fd, short event, void *arg)
+{
+ struct buffertls *buftls = arg;
+ struct bufferevent *bufev = buftls->bt_bufev;
+ struct tls *ctx = buftls->bt_ctx;
+ int res = 0;
+ short what = EVBUFFER_HANDSHAKE;
+
+ if (event == EV_TIMEOUT) {
+ what |= EVBUFFER_TIMEOUT;
+ goto error;
+ }
+
+ res = tls_handshake(ctx);
+ switch (res) {
+ case TLS_WANT_POLLIN:
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ return;
+ case TLS_WANT_POLLOUT:
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+ return;
+ case -1:
+ what |= EVBUFFER_ERROR;
+ break;
+ }
+ if (res < 0)
+ goto error;
+
+ /* Handshake was successful, change to read and write callback. */
+ event_del(&bufev->ev_read);
+ event_del(&bufev->ev_write);
+ event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
+ if (bufev->enabled & EV_READ)
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+
+ return;
+
+ error:
+ (*bufev->errorcb)(bufev, what, bufev->cbarg);
+}
+
+void
+buffertls_set(struct buffertls *buftls, struct bufferevent *bufev,
+    struct tls *ctx, int fd)
+{
+ bufferevent_setfd(bufev, fd);
+ event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
+ buftls->bt_bufev = bufev;
+ buftls->bt_ctx = ctx;
+}
+
+void
+buffertls_accept(struct buffertls *buftls, int fd)
+{
+ struct bufferevent *bufev = buftls->bt_bufev;
+
+ event_del(&bufev->ev_read);
+ event_del(&bufev->ev_write);
+ event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
+    buftls);
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+}
+
+void
+buffertls_connect(struct buffertls *buftls, int fd)
+{
+ struct bufferevent *bufev = buftls->bt_bufev;
+
+ event_del(&bufev->ev_read);
+ event_del(&bufev->ev_write);
+ event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
+ event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
+    buftls);
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+}
+
+/*
+ * Reads data from a file descriptor into a buffer.
+ */
+
+#define EVBUFFER_MAX_READ 4096
+
+int
+evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx)
+{
+ u_char *p;
+ size_t oldoff = buf->off;
+ int n = EVBUFFER_MAX_READ;
+
+ if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
+ n = EVBUFFER_MAX_READ;
+ } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
+ /*
+ * It's possible that a lot of data is available for
+ * reading.  We do not want to exhaust resources
+ * before the reader has a chance to do something
+ * about it.  If the reader does not tell us how much
+ * data we should read, we artifically limit it.
+ */
+ if ((size_t)n > buf->totallen << 2)
+ n = buf->totallen << 2;
+ if (n < EVBUFFER_MAX_READ)
+ n = EVBUFFER_MAX_READ;
+ }
+ if (howmuch < 0 || howmuch > n)
+ howmuch = n;
+
+ /* If we don't have FIONREAD, we might waste some space here */
+ if (evbuffer_expand(buf, howmuch) == -1)
+ return (-1);
+
+ /* We can append new data at this point */
+ p = buf->buffer + buf->off;
+
+ n = tls_read(ctx, p, howmuch);
+ if (n <= 0)
+ return (n);
+
+ buf->off += n;
+
+ /* Tell someone about changes in this buffer */
+ if (buf->off != oldoff && buf->cb != NULL)
+ (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
+
+ return (n);
+}
+
+int
+evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx)
+{
+ int n;
+
+ n = tls_write(ctx, buffer->buffer, buffer->off);
+ if (n <= 0)
+ return (n);
+ evbuffer_drain(buffer, n);
+
+ return (n);
+}
Index: evbuffer_tls.h
===================================================================
RCS file: evbuffer_tls.h
diff -N evbuffer_tls.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ evbuffer_tls.h 10 Apr 2016 06:15:51 -0000
@@ -0,0 +1,37 @@
+/* $OpenBSD: evbuffer_tls.h,v 1.5 2015/10/09 16:58:25 bluhm Exp $ */
+
+/*
+ * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _EVBUFFER_TLS_H_
+#define _EVBUFFER_TLS_H_
+
+#define EVBUFFER_HANDSHAKE 0x04
+
+struct bufferevent;
+struct tls;
+
+struct buffertls {
+ struct bufferevent *bt_bufev;
+ struct tls *bt_ctx;
+};
+
+void buffertls_set(struct buffertls *, struct bufferevent *, struct tls *,
+    int);
+void buffertls_accept(struct buffertls *, int);
+void buffertls_connect(struct buffertls *, int);
+
+#endif /* _EVBUFFER_TLS_H_ */
Index: ldapd.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ldapd.c,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 ldapd.c
--- ldapd.c 4 Feb 2016 12:48:06 -0000 1.19
+++ ldapd.c 10 Apr 2016 06:15:51 -0000
@@ -163,7 +163,7 @@ main(int argc, char *argv[])
 
  log_verbose(verbose);
  stats.started_at = time(0);
- ssl_init();
+ tls_init();
 
  if (parse_config(conffile) != 0)
  exit(2);
Index: ldapd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ldapd.h,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 ldapd.h
--- ldapd.h 2 Nov 2015 06:32:51 -0000 1.25
+++ ldapd.h 10 Apr 2016 06:15:51 -0000
@@ -30,11 +30,13 @@
 #include <limits.h>
 #include <pwd.h>
 #include <stdarg.h>
+#include <tls.h>
 
 #include "aldap.h"
 #include "schema.h"
 #include "btree.h"
 #include "imsgev.h"
+#include "evbuffer_tls.h"
 
 #define CONFFILE "/etc/ldapd.conf"
 #define LDAPD_USER "_ldapd"
@@ -203,7 +205,7 @@ struct listener {
  struct event evt;
  char ssl_cert_name[PATH_MAX];
  struct ssl *ssl;
- void *ssl_ctx;
+ struct tls *tls;
  TAILQ_ENTRY(listener) entry;
 };
 TAILQ_HEAD(listenerlist, listener);
@@ -223,12 +225,8 @@ struct conn {
  struct listener *listener; /* where it connected from */
 
  /* SSL support */
- struct event s_ev;
- struct timeval s_tv;
- struct listener *s_l;
- void *s_ssl;
- unsigned char *s_buf;
- int s_buflen;
+ struct tls *tls;
+ struct buffertls buftls;
  unsigned int s_flags;
 };
 TAILQ_HEAD(conn_list, conn) conn_list;
@@ -236,11 +234,12 @@ TAILQ_HEAD(conn_list, conn) conn_list;
 struct ssl {
  SPLAY_ENTRY(ssl) ssl_nodes;
  char ssl_name[PATH_MAX];
- char *ssl_cert;
- off_t ssl_cert_len;
- char *ssl_key;
- off_t ssl_key_len;
+ uint8_t *ssl_cert;
+ size_t ssl_cert_len;
+ uint8_t *ssl_key;
+ size_t ssl_key_len;
  uint8_t flags;
+ struct tls_config *config;
 };
 
 struct ldapd_config
@@ -461,6 +460,9 @@ int authorized(struct conn *conn, str
 /* parse.y */
 int parse_config(char *filename);
 int cmdline_symset(char *s);
+int ssl_cmp(struct ssl *, struct ssl *);
+SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
+
 
 /* log.c */
 void log_init(int);
@@ -498,21 +500,6 @@ int unindex_entry(struct namespace *n
  struct ber_element *elm);
 int index_to_dn(struct namespace *ns, struct btval *indx,
  struct btval *dn);
-
-/* ssl.c */
-void ssl_init(void);
-void ssl_transaction(struct conn *);
-
-void ssl_session_init(struct conn *);
-void ssl_session_destroy(struct conn *);
-int ssl_load_certfile(struct ldapd_config *, const char *, u_int8_t);
-void ssl_setup(struct ldapd_config *, struct listener *);
-int ssl_cmp(struct ssl *, struct ssl *);
-SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
-
-/* ssl_privsep.c */
-int ssl_ctx_use_private_key(void *, char *, off_t);
-int ssl_ctx_use_certificate_chain(void *, char *, off_t);
 
 /* validate.c */
 int validate_entry(const char *dn, struct ber_element *entry, int relax);
Index: ldape.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ldape.c,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 ldape.c
--- ldape.c 24 Dec 2015 17:47:57 -0000 1.23
+++ ldape.c 10 Apr 2016 06:15:51 -0000
@@ -341,6 +341,7 @@ ldape(struct passwd *pw, char *csockpath
  struct event ev_sigterm;
  struct event ev_sigchld;
  struct event ev_sighup;
+ struct ssl key;
  char host[128];
  mode_t old_umask = 0;
 
@@ -424,7 +425,24 @@ ldape(struct passwd *pw, char *csockpath
  event_add(&l->ev, NULL);
  evtimer_set(&l->evt, conn_accept, l);
 
- ssl_setup(conf, l);
+ if (l->flags & F_SSL) {
+ if (strlcpy(key.ssl_name, l->ssl_cert_name,
+    sizeof(key.ssl_name)) >= sizeof(key.ssl_name))
+ fatal("ldape: certificate name truncated");
+
+ l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key);
+ if (l->ssl == NULL)
+ fatal("ldape: certificate tree corrupted");
+
+ l->tls = tls_server();
+ if (l->tls == NULL)
+ fatal("ldape: couldn't allocate tls context");
+
+ if (tls_configure(l->tls, l->ssl->config)) {
+ log_warn("ldape: %s", tls_error(l->tls));
+ fatal("ldape: couldn't configure tls");
+ }
+ }
  }
 
  TAILQ_FOREACH(ns, &conf->namespaces, next) {
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/parse.y,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 parse.y
--- parse.y 20 Nov 2014 05:51:20 -0000 1.16
+++ parse.y 10 Apr 2016 06:15:51 -0000
@@ -77,6 +77,7 @@ int host(const char *, const char *,
     struct listenerlist *, int, in_port_t, u_int8_t);
 int interface(const char *, const char *,
     struct listenerlist *, int, in_port_t, u_int8_t);
+int load_certfile(struct ldapd_config *, const char *, u_int8_t);
 
 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
 struct sym {
@@ -91,6 +92,8 @@ char *symget(const char *);
 
 struct ldapd_config *conf;
 
+SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
+
 static struct aci *mk_aci(int type, int rights, enum scope scope,
  char *target, char *subject);
 
@@ -181,7 +184,7 @@ conf_main : LISTEN ON STRING port ssl ce
  cert = ($6 != NULL) ? $6 : $3;
 
  if (($5 == F_STARTTLS || $5 == F_LDAPS) &&
-    ssl_load_certfile(conf, cert, F_SCERT) < 0) {
+    load_certfile(conf, cert, F_SCERT) < 0) {
  yyerror("cannot load certificate: %s", cert);
  free($6);
  free($3);
@@ -1167,3 +1170,84 @@ namespace_new(const char *suffix)
  return ns;
 }
 
+int
+ssl_cmp(struct ssl *s1, struct ssl *s2)
+{
+ return (strcmp(s1->ssl_name, s2->ssl_name));
+}
+
+int
+load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
+{
+ struct ssl *s;
+ struct ssl key;
+ char certfile[PATH_MAX];
+
+ if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
+    >= sizeof(key.ssl_name)) {
+ log_warn("load_certfile: certificate name truncated");
+ return -1;
+ }
+
+ s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
+ if (s != NULL) {
+ s->flags |= flags;
+ return 0;
+ }
+
+ if ((s = calloc(1, sizeof(*s))) == NULL)
+ fatal(NULL);
+
+ s->flags = flags;
+ (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
+
+ s->config = tls_config_new();
+ if (s->config == NULL)
+ goto err;
+
+ tls_config_set_protocols(s->config, TLS_PROTOCOLS_ALL);
+ if (tls_config_set_ciphers(s->config, "compat"))
+ goto err;
+
+ if ((name[0] == '/' &&
+     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
+    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
+ name)) {
+ log_warn("load_certfile: path truncated");
+ goto err;
+ }
+
+ log_debug("loading certificate file %s", certfile);
+ s->ssl_cert = tls_load_file(certfile, &s->ssl_cert_len, NULL);
+ if (s->ssl_cert == NULL)
+ goto err;
+
+ if (tls_config_set_cert_mem(s->config, s->ssl_cert, s->ssl_cert_len))
+ goto err;
+
+ if ((name[0] == '/' &&
+     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
+    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
+ name)) {
+ log_warn("load_certfile: path truncated");
+ goto err;
+ }
+
+ log_debug("loading key file %s", certfile);
+ s->ssl_key = tls_load_file(certfile, &s->ssl_key_len, NULL);
+ if (s->ssl_key == NULL)
+ goto err;
+
+ if (tls_config_set_key_mem(s->config, s->ssl_key, s->ssl_key_len))
+ goto err;
+
+ SPLAY_INSERT(ssltree, env->sc_ssl, s);
+
+ return (0);
+err:
+ free(s->ssl_cert);
+ free(s->ssl_key);
+ tls_config_free(s->config);
+ free(s);
+ return (-1);
+}
Index: ssl.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ssl.c,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 ssl.c
--- ssl.c 30 Dec 2015 15:59:55 -0000 1.10
+++ ssl.c 10 Apr 2016 06:15:51 -0000
@@ -1,565 +0,0 @@
-/* $OpenBSD: ssl.c,v 1.10 2015/12/30 15:59:55 benno Exp $ */
-
-/*
- * Copyright (c) 2008 Pierre-Yves Ritschard <[hidden email]>
- * Copyright (c) 2008 Reyk Floeter <[hidden email]>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <ctype.h>
-#include <event.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/ssl.h>
-#include <openssl/engine.h>
-#include <openssl/err.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-
-#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
-
-#include "ldapd.h"
-
-#define SSL_CIPHERS "HIGH:!aNULL"
-
-void ssl_error(const char *);
-char *ssl_load_file(const char *, off_t *);
-SSL_CTX *ssl_ctx_create(void);
-void ssl_session_accept(int, short, void *);
-void ssl_read(int, short, void *);
-void ssl_write(int, short, void *);
-int ssl_bufferevent_add(struct event *, int);
-
-DH *get_dh1024(void);
-void ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *);
-
-extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
-    size_t, void *);
-
-void
-ssl_read(int fd, short event, void *p)
-{
- struct bufferevent *bufev = p;
- struct conn *s = bufev->cbarg;
- int ret;
- int ssl_err;
- short what;
- size_t len;
- char rbuf[IBUF_READ_SIZE];
- int howmuch = IBUF_READ_SIZE;
-
- what = EVBUFFER_READ;
-
- if (event == EV_TIMEOUT) {
- what |= EVBUFFER_TIMEOUT;
- goto err;
- }
-
- if (bufev->wm_read.high != 0)
- howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
-
- ret = SSL_read(s->s_ssl, rbuf, howmuch);
- if (ret <= 0) {
- ssl_err = SSL_get_error(s->s_ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error("ssl_read");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
- }
-
- if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
- what |= EVBUFFER_ERROR;
- goto err;
- }
-
- ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
-
- len = EVBUFFER_LENGTH(bufev->input);
- if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
- return;
- if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
- struct evbuffer *buf = bufev->input;
- event_del(&bufev->ev_read);
- evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
- return;
- }
-
- if (bufev->readcb != NULL)
- (*bufev->readcb)(bufev, bufev->cbarg);
- return;
-
-retry:
- ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
- return;
-
-err:
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-
-void
-ssl_write(int fd, short event, void *p)
-{
- struct bufferevent *bufev = p;
- struct conn *s = bufev->cbarg;
- int ret;
- int ssl_err;
- short what;
-
- what = EVBUFFER_WRITE;
-
- if (event == EV_TIMEOUT) {
- what |= EV_TIMEOUT;
- goto err;
- }
-
- if (EVBUFFER_LENGTH(bufev->output)) {
- if (s->s_buf == NULL) {
- s->s_buflen = EVBUFFER_LENGTH(bufev->output);
- if ((s->s_buf = malloc(s->s_buflen)) == NULL) {
- what |= EVBUFFER_ERROR;
- goto err;
- }
- memcpy(s->s_buf, EVBUFFER_DATA(bufev->output),
-    s->s_buflen);
- }
-
- ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen);
- if (ret <= 0) {
- ssl_err = SSL_get_error(s->s_ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error("ssl_write");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
- }
- evbuffer_drain(bufev->output, ret);
- }
- if (s->s_buf != NULL) {
- free(s->s_buf);
- s->s_buf = NULL;
- s->s_buflen = 0;
- }
- if (EVBUFFER_LENGTH(bufev->output) != 0)
- ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
-
- if (bufev->writecb != NULL &&
-    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
- (*bufev->writecb)(bufev, bufev->cbarg);
- return;
-
-retry:
- if (s->s_buflen != 0)
- ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
- return;
-
-err:
- if (s->s_buf != NULL) {
- free(s->s_buf);
- s->s_buf = NULL;
- s->s_buflen = 0;
- }
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-int
-ssl_bufferevent_add(struct event *ev, int timeout)
-{
- struct timeval tv;
- struct timeval *ptv = NULL;
-
- if (timeout) {
- timerclear(&tv);
- tv.tv_sec = timeout;
- ptv = &tv;
- }
-
- return (event_add(ev, ptv));
-}
-
-int
-ssl_cmp(struct ssl *s1, struct ssl *s2)
-{
- return (strcmp(s1->ssl_name, s2->ssl_name));
-}
-
-SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
-
-char *
-ssl_load_file(const char *name, off_t *len)
-{
- struct stat st;
- off_t size;
- char *buf = NULL;
- int fd;
-
- if ((fd = open(name, O_RDONLY)) == -1)
- return (NULL);
- if (fstat(fd, &st) != 0)
- goto fail;
- size = st.st_size;
- if ((buf = calloc(1, size + 1)) == NULL)
- goto fail;
- if (read(fd, buf, size) != size)
- goto fail;
- close(fd);
-
- *len = size + 1;
- return (buf);
-
-fail:
- free(buf);
- close(fd);
- return (NULL);
-}
-
-SSL_CTX *
-ssl_ctx_create(void)
-{
- SSL_CTX *ctx;
-
- ctx = SSL_CTX_new(SSLv23_method());
- if (ctx == NULL) {
- ssl_error("ssl_ctx_create");
- fatal("ssl_ctx_create: could not create SSL context");
- }
-
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
- SSL_CTX_set_timeout(ctx, LDAPD_SESSION_TIMEOUT);
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- SSL_CTX_set_options(ctx,
-    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-
- if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
- ssl_error("ssl_ctx_create");
- fatal("ssl_ctx_create: could not set cipher list");
- }
- return (ctx);
-}
-
-int
-ssl_load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
-{
- struct ssl *s;
- struct ssl key;
- char certfile[PATH_MAX];
-
- if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
-    >= sizeof(key.ssl_name)) {
- log_warn("ssl_load_certfile: certificate name truncated");
- return -1;
- }
-
- s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
- if (s != NULL) {
- s->flags |= flags;
- return 0;
- }
-
- if ((s = calloc(1, sizeof(*s))) == NULL)
- fatal(NULL);
-
- s->flags = flags;
- (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
-
- if ((name[0] == '/' &&
-     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
-    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
- name)) {
- log_warn("ssl_load_certfile: path truncated");
- free(s);
- return -1;
- }
-
- log_debug("loading certificate file %s", certfile);
- if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) {
- free(s);
- return (-1);
- }
-
- if ((name[0] == '/' &&
-     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
-    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
- name)) {
- log_warn("ssl_load_certfile: path truncated");
- free(s->ssl_cert);
- free(s);
- return -1;
- }
-
- log_debug("loading key file %s", certfile);
- if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) {
- free(s->ssl_cert);
- free(s);
- return (-1);
- }
-
- SPLAY_INSERT(ssltree, env->sc_ssl, s);
-
- return (0);
-}
-
-void
-ssl_init(void)
-{
- SSL_library_init();
- SSL_load_error_strings();
-
- OpenSSL_add_all_algorithms();
-
- /* Init hardware crypto engines. */
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-}
-
-void
-ssl_setup(struct ldapd_config *env, struct listener *l)
-{
- struct ssl key;
-
- if (!(l->flags & F_SSL))
- return;
-
- if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name))
-    >= sizeof(key.ssl_name))
- fatal("ssl_setup: certificate name truncated");
-
- if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL)
- fatal("ssl_setup: certificate tree corrupted");
-
- l->ssl_ctx = ssl_ctx_create();
-
- if (!ssl_ctx_use_certificate_chain(l->ssl_ctx,
-    l->ssl->ssl_cert, l->ssl->ssl_cert_len))
- goto err;
- if (!ssl_ctx_use_private_key(l->ssl_ctx,
-    l->ssl->ssl_key, l->ssl->ssl_key_len))
- goto err;
-
- if (!SSL_CTX_check_private_key(l->ssl_ctx))
- goto err;
- if (!SSL_CTX_set_session_id_context(l->ssl_ctx,
- (const unsigned char *)l->ssl_cert_name, strlen(l->ssl_cert_name) + 1))
- goto err;
-
- ssl_set_ephemeral_key_exchange(l->ssl_ctx, get_dh1024());
-
- log_debug("ssl_setup: ssl setup finished for listener: %p", l);
- return;
-
-err:
- SSL_CTX_free(l->ssl_ctx);
- ssl_error("ssl_setup");
- fatal("ssl_setup: cannot set SSL up");
-}
-
-void
-ssl_error(const char *where)
-{
- unsigned long code;
- char errbuf[128];
- extern int debug;
-
- if (!debug)
- return;
- for (; (code = ERR_get_error()) != 0 ;) {
- ERR_error_string_n(code, errbuf, sizeof(errbuf));
- log_debug("SSL library error: %s: %s", where, errbuf);
- }
-}
-
-void
-ssl_session_accept(int fd, short event, void *p)
-{
- struct conn *s = p;
- int ret;
- int ssl_err;
-
- if (event == EV_TIMEOUT) {
- log_debug("ssl_session_accept: session timed out");
- conn_close(s);
- return;
- }
-
- log_debug("ssl_session_accept: accepting client");
- ret = SSL_accept(s->s_ssl);
- if (ret <= 0) {
- ssl_err = SSL_get_error(s->s_ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- goto retry;
- case SSL_ERROR_ZERO_RETURN:
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- conn_close(s);
- return;
- }
- /* FALLTHROUGH */
- default:
- ssl_error("ssl_session_accept");
- conn_close(s);
- return;
- }
- }
-
- log_debug("ssl_session_accept: accepted ssl client");
- s->s_flags |= F_SECURE;
-
- s->bev = bufferevent_new(s->fd, conn_read, conn_write, conn_err, s);
- if (s->bev == NULL) {
-                log_warn("ssl_session_accept: bufferevent_new");
-                conn_close(s);
-                return;
- }
- bufferevent_settimeout(s->bev, 0, 60);
-
- event_set(&s->bev->ev_read, s->fd, EV_READ, ssl_read, s->bev);
- event_set(&s->bev->ev_write, s->fd, EV_WRITE, ssl_write, s->bev);
- bufferevent_enable(s->bev, EV_READ);
-
- return;
-retry:
- event_add(&s->s_ev, &s->s_tv);
-}
-
-void
-ssl_session_init(struct conn *s)
-{
- struct listener *l;
- SSL             *ssl;
-
- l = s->s_l;
-
- if (!(l->flags & F_SSL))
- return;
-
- log_debug("ssl_session_init: switching to SSL");
- ssl = SSL_new(l->ssl_ctx);
- if (ssl == NULL)
- goto err;
-
- if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
- goto err;
- if (!SSL_set_fd(ssl, s->fd))
- goto err;
- SSL_set_accept_state(ssl);
-
- s->s_ssl = ssl;
-
- s->s_tv.tv_sec = LDAPD_SESSION_TIMEOUT;
- s->s_tv.tv_usec = 0;
- event_set(&s->s_ev, s->fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s);
- event_add(&s->s_ev, &s->s_tv);
- return;
-
- err:
- SSL_free(ssl);
- ssl_error("ssl_session_init");
-}
-
-void
-ssl_session_destroy(struct conn *s)
-{
- SSL_free(s->s_ssl);
-}
-
-/* From OpenSSL's documentation:
- *
- * If "strong" primes were used to generate the DH parameters, it is
- * not strictly necessary to generate a new key for each handshake
- * but it does improve forward secrecy.
- *
- * -- gilles@
- */
-DH *
-get_dh1024(void)
-{
- DH *dh;
- unsigned char dh1024_p[] = {
- 0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75,
- 0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51,
- 0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E,
- 0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D,
- 0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89,
- 0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC,
- 0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02,
- 0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93,
- 0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D,
- 0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65,
- 0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6,
- 0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1,
- 0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9,
- 0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59,
- 0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7,
- 0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B
- };
- unsigned char dh1024_g[] = {
- 0x02
- };
-
- if ((dh = DH_new()) == NULL)
- return NULL;
-
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
- if (dh->p == NULL || dh->g == NULL) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-
-void
-ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh)
-{
- if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh))
- fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh");
-}
Index: ssl_privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldapd/ssl_privsep.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 ssl_privsep.c
--- ssl_privsep.c 28 Jan 2015 15:50:30 -0000 1.4
+++ ssl_privsep.c 10 Apr 2016 06:15:51 -0000
@@ -1,172 +0,0 @@
-/*      $OpenBSD: ssl_privsep.c,v 1.4 2015/01/28 15:50:30 reyk Exp $    */
-
-/* Copyright (C) 1995-1998 Eric Young ([hidden email])
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young ([hidden email]).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson ([hidden email]).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young ([hidden email])"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson ([hidden email])"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-/*
- * SSL operations needed when running in a privilege separated environment.
- * 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>
-
-#include <openssl/err.h>
-#include <openssl/bio.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/ssl.h>
-
-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_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
-{
- int ret;
- BIO *in;
- EVP_PKEY *pkey;
-
- ret = 0;
-
- if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
- return 0;
- }
-
- pkey = PEM_read_bio_PrivateKey(in, NULL,
-    ctx->default_passwd_callback,
-    ctx->default_passwd_callback_userdata);
-
- if (pkey == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
- goto end;
- }
- ret = SSL_CTX_use_PrivateKey(ctx, pkey);
- EVP_PKEY_free(pkey);
-end:
- if (in != NULL)
- BIO_free(in);
- return ret;
-}
-
-int
-ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
-{
- int ret;
- BIO *in;
- X509 *x;
- X509 *ca;
- unsigned long err;
-
- ret = 0;
- x = ca = NULL;
-
- if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
- goto end;
- }
-
- if ((x = PEM_read_bio_X509(in, NULL,
-    ctx->default_passwd_callback,
-    ctx->default_passwd_callback_userdata)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
- goto end;
- }
-
- if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
- goto end;
-
- /* If we could set up our certificate, now proceed to
- * the CA certificates.
- */
-
- if (ctx->extra_certs != NULL) {
- sk_X509_pop_free(ctx->extra_certs, X509_free);
- ctx->extra_certs = NULL;
- }
-
- while ((ca = PEM_read_bio_X509(in, NULL,
-    ctx->default_passwd_callback,
-    ctx->default_passwd_callback_userdata)) != NULL) {
-
- if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
- goto end;
- }
-
- err = ERR_peek_last_error();
- if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
-    ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
- ERR_clear_error();
- else
- goto end;
-
- ret = 1;
-end:
- if (ca != NULL)
- X509_free(ca);
- if (x != NULL)
- X509_free(x);
- if (in != NULL)
- BIO_free(in);
- return (ret);
-}

Reply | Threaded
Open this post in threaded view
|

Re: use libtls in ldapd

Jonathan Matthew-4
On Sun, Apr 10, 2016 at 04:36:15PM +1000, Jonathan Matthew wrote:

> A while back (s2k15?), reyk@ suggested I take a look at converting ldapd to use
> libtls rather than the openssl api.  Today I finally got around to it,
> resulting in the diff below.  Most of the diff just removes ssl.c and
> ssl_privsep.c, and replaces some of it with evbuffer_tls.c (copied from
> syslogd, unmodified).  A reasonable amount of code just went away because
> libtls is sensible.  The few remaining bits of ssl.c moved to wherever seemed
> most suitable.
>
> I've tested a few things with the openldap clients, which apparently only do
> starttls, and otherwise checked that it negotiates ssl successfully.
>
> ok?

ldapd is too boring?

>
>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
> retrieving revision 1.12
> diff -u -p -u -p -r1.12 Makefile
> --- Makefile 16 Jul 2014 20:07:03 -0000 1.12
> +++ Makefile 10 Apr 2016 06:15:50 -0000
> @@ -5,11 +5,11 @@ MAN= ldapd.8 ldapd.conf.5
>  SRCS= ber.c log.c control.c \
>   util.c ldapd.c ldape.c conn.c attributes.c namespace.c \
>   btree.c filter.c search.c parse.y \
> - auth.c modify.c index.c ssl.c ssl_privsep.c \
> + auth.c modify.c index.c evbuffer_tls.c \
>   validate.c uuid.c schema.c imsgev.c syntax.c matching.c
>  
> -LDADD= -levent -lssl -lcrypto -lz -lutil
> -DPADD= ${LIBEVENT} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
> +LDADD= -ltls -levent -lz -lutil
> +DPADD= ${LIBEVENT} ${LIBTLS} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
>  CFLAGS+= -I${.CURDIR} -g
>  CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes
>  CFLAGS+= -Wmissing-declarations
> Index: btree.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/btree.c,v
> retrieving revision 1.36
> diff -u -p -u -p -r1.36 btree.c
> --- btree.c 20 Mar 2016 00:01:22 -0000 1.36
> +++ btree.c 10 Apr 2016 06:15:51 -0000
> @@ -34,6 +34,8 @@
>  #include <time.h>
>  #include <unistd.h>
>  
> +#include <openssl/sha.h>
> +
>  #include "btree.h"
>  
>  /* #define DEBUG */
> Index: btree.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/btree.h,v
> retrieving revision 1.6
> diff -u -p -u -p -r1.6 btree.h
> --- btree.h 2 Jul 2010 01:43:00 -0000 1.6
> +++ btree.h 10 Apr 2016 06:15:51 -0000
> @@ -19,8 +19,6 @@
>  #ifndef _btree_h_
>  #define _btree_h_
>  
> -#include <openssl/sha.h>
> -
>  struct mpage;
>  struct cursor;
>  struct btree_txn;
> Index: conn.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/conn.c,v
> retrieving revision 1.12
> diff -u -p -u -p -r1.12 conn.c
> --- conn.c 2 Nov 2015 06:32:51 -0000 1.12
> +++ conn.c 10 Apr 2016 06:15:51 -0000
> @@ -26,6 +26,7 @@
>  #include "ldapd.h"
>  
>  int conn_dispatch(struct conn *conn);
> +int conn_tls_init(struct conn *);
>  unsigned long ldap_application(struct ber_element *elm);
>  
>  struct conn_list conn_list;
> @@ -61,7 +62,7 @@ conn_close(struct conn *conn)
>   /* Cancel any queued requests on this connection. */
>   namespace_cancel_conn(conn);
>  
> - ssl_session_destroy(conn);
> + tls_free(conn->tls);
>  
>   TAILQ_REMOVE(&conn_list, conn, next);
>   ber_free(&conn->ber);
> @@ -225,9 +226,8 @@ conn_write(struct bufferevent *bev, void
>   conn_close(conn);
>   else if (conn->s_flags & F_STARTTLS) {
>   conn->s_flags &= ~F_STARTTLS;
> - bufferevent_free(conn->bev);
> - conn->bev = NULL;
> - ssl_session_init(conn);
> + if (conn_tls_init(conn) == -1)
> + conn_close(conn);
>   }
>  }
>  
> @@ -296,24 +296,22 @@ conn_accept(int fd, short event, void *d
>   goto giveup;
>   }
>   conn->ber.fd = -1;
> - conn->s_l = l;
>   ber_set_application(&conn->ber, ldap_application);
>   conn->fd = afd;
>   conn->listener = l;
>  
> - if (l->flags & F_LDAPS) {
> - ssl_session_init(conn);
> - } else {
> - conn->bev = bufferevent_new(afd, conn_read, conn_write,
> -    conn_err, conn);
> - if (conn->bev == NULL) {
> - log_warn("conn_accept: bufferevent_new");
> - free(conn);
> - goto giveup;
> - }
> - bufferevent_enable(conn->bev, EV_READ);
> - bufferevent_settimeout(conn->bev, 0, 60);
> + conn->bev = bufferevent_new(afd, conn_read, conn_write,
> +    conn_err, conn);
> + if (conn->bev == NULL) {
> + log_warn("conn_accept: bufferevent_new");
> + free(conn);
> + goto giveup;
>   }
> + bufferevent_enable(conn->bev, EV_READ);
> + bufferevent_settimeout(conn->bev, 0, 60);
> + if (conn->s_flags & F_LDAPS)
> + if (conn_tls_init(conn) == -1)
> + conn_close(conn);
>  
>   TAILQ_INIT(&conn->searches);
>   TAILQ_INSERT_HEAD(&conn_list, conn, next);
> @@ -365,4 +363,25 @@ conn_close_any()
>   }
>  
>   return -1;
> +}
> +
> +int
> +conn_tls_init(struct conn *conn)
> +{
> + struct listener *l = conn->listener;
> +
> + if (!(l->flags & F_SSL))
> + return 0;
> +
> + log_debug("conn_tls_init: switching to TLS");
> +
> + if (tls_accept_socket(l->tls, &conn->tls, conn->fd) < 0) {
> + log_debug("tls_accept_socket failed");
> + return -1;
> + }
> +
> + conn->s_flags |= F_SECURE;
> + buffertls_set(&conn->buftls, conn->bev, conn->tls, conn->fd);
> + buffertls_accept(&conn->buftls, conn->fd);
> + return 0;
>  }
> Index: evbuffer_tls.c
> ===================================================================
> RCS file: evbuffer_tls.c
> diff -N evbuffer_tls.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ evbuffer_tls.c 10 Apr 2016 06:15:51 -0000
> @@ -0,0 +1,350 @@
> +/* $OpenBSD: evbuffer_tls.c,v 1.9 2015/10/09 16:58:25 bluhm Exp $ */
> +
> +/*
> + * Copyright (c) 2002-2004 Niels Provos <[hidden email]>
> + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/time.h>
> +#include <sys/ioctl.h>
> +
> +#include <errno.h>
> +#include <event.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <tls.h>
> +
> +#include "evbuffer_tls.h"
> +
> +/* prototypes */
> +
> +void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
> +static void buffertls_readcb(int, short, void *);
> +static void buffertls_writecb(int, short, void *);
> +static void buffertls_handshakecb(int, short, void *);
> +int evtls_read(struct evbuffer *, int, int, struct tls *);
> +int evtls_write(struct evbuffer *, int, struct tls *);
> +
> +static int
> +bufferevent_add(struct event *ev, int timeout)
> +{
> + struct timeval tv, *ptv = NULL;
> +
> + if (timeout) {
> + timerclear(&tv);
> + tv.tv_sec = timeout;
> + ptv = &tv;
> + }
> +
> + return (event_add(ev, ptv));
> +}
> +
> +static void
> +buffertls_readcb(int fd, short event, void *arg)
> +{
> + struct buffertls *buftls = arg;
> + struct bufferevent *bufev = buftls->bt_bufev;
> + struct tls *ctx = buftls->bt_ctx;
> + int res = 0;
> + short what = EVBUFFER_READ;
> + size_t len;
> + int howmuch = -1;
> +
> + if (event == EV_TIMEOUT) {
> + what |= EVBUFFER_TIMEOUT;
> + goto error;
> + }
> +
> + /*
> + * If we have a high watermark configured then we don't want to
> + * read more data than would make us reach the watermark.
> + */
> + if (bufev->wm_read.high != 0) {
> + howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
> + /* we might have lowered the watermark, stop reading */
> + if (howmuch <= 0) {
> + struct evbuffer *buf = bufev->input;
> + event_del(&bufev->ev_read);
> + evbuffer_setcb(buf,
> +    bufferevent_read_pressure_cb, bufev);
> + return;
> + }
> + }
> +
> + res = evtls_read(bufev->input, fd, howmuch, ctx);
> + switch (res) {
> + case TLS_WANT_POLLIN:
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + return;
> + case TLS_WANT_POLLOUT:
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb,
> +    buftls);
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> + return;
> + case -1:
> + what |= EVBUFFER_ERROR;
> + break;
> + case 0:
> + what |= EVBUFFER_EOF;
> + break;
> + }
> + if (res <= 0)
> + goto error;
> +
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> + if (bufev->enabled & EV_READ)
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> +
> + /* See if this callbacks meets the water marks */
> + len = EVBUFFER_LENGTH(bufev->input);
> + if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> + return;
> + if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
> + struct evbuffer *buf = bufev->input;
> + event_del(&bufev->ev_read);
> +
> + /* Now schedule a callback for us when the buffer changes */
> + evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> + }
> +
> + /* Invoke the user callback - must always be called last */
> + if (bufev->readcb != NULL)
> + (*bufev->readcb)(bufev, bufev->cbarg);
> + return;
> +
> + error:
> + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> +}
> +
> +static void
> +buffertls_writecb(int fd, short event, void *arg)
> +{
> + struct buffertls *buftls = arg;
> + struct bufferevent *bufev = buftls->bt_bufev;
> + struct tls *ctx = buftls->bt_ctx;
> + int res = 0;
> + short what = EVBUFFER_WRITE;
> +
> + if (event == EV_TIMEOUT) {
> + what |= EVBUFFER_TIMEOUT;
> + goto error;
> + }
> +
> + if (EVBUFFER_LENGTH(bufev->output) != 0) {
> + res = evtls_write(bufev->output, fd, ctx);
> + switch (res) {
> + case TLS_WANT_POLLIN:
> + event_del(&bufev->ev_read);
> + event_set(&bufev->ev_read, fd, EV_READ,
> +    buffertls_writecb, buftls);
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + return;
> + case TLS_WANT_POLLOUT:
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> + return;
> + case -1:
> + what |= EVBUFFER_ERROR;
> + break;
> + case 0:
> + what |= EVBUFFER_EOF;
> + break;
> + }
> + if (res <= 0)
> + goto error;
> + }
> +
> + event_del(&bufev->ev_read);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> + if (bufev->enabled & EV_READ)
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> +
> + /*
> + * Invoke the user callback if our buffer is drained or below the
> + * low watermark.
> + */
> + if (bufev->writecb != NULL &&
> +    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> + (*bufev->writecb)(bufev, bufev->cbarg);
> +
> + return;
> +
> + error:
> + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> +}
> +
> +static void
> +buffertls_handshakecb(int fd, short event, void *arg)
> +{
> + struct buffertls *buftls = arg;
> + struct bufferevent *bufev = buftls->bt_bufev;
> + struct tls *ctx = buftls->bt_ctx;
> + int res = 0;
> + short what = EVBUFFER_HANDSHAKE;
> +
> + if (event == EV_TIMEOUT) {
> + what |= EVBUFFER_TIMEOUT;
> + goto error;
> + }
> +
> + res = tls_handshake(ctx);
> + switch (res) {
> + case TLS_WANT_POLLIN:
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + return;
> + case TLS_WANT_POLLOUT:
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> + return;
> + case -1:
> + what |= EVBUFFER_ERROR;
> + break;
> + }
> + if (res < 0)
> + goto error;
> +
> + /* Handshake was successful, change to read and write callback. */
> + event_del(&bufev->ev_read);
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> + if (bufev->enabled & EV_READ)
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> +
> + return;
> +
> + error:
> + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> +}
> +
> +void
> +buffertls_set(struct buffertls *buftls, struct bufferevent *bufev,
> +    struct tls *ctx, int fd)
> +{
> + bufferevent_setfd(bufev, fd);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> + buftls->bt_bufev = bufev;
> + buftls->bt_ctx = ctx;
> +}
> +
> +void
> +buffertls_accept(struct buffertls *buftls, int fd)
> +{
> + struct bufferevent *bufev = buftls->bt_bufev;
> +
> + event_del(&bufev->ev_read);
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> +    buftls);
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> +}
> +
> +void
> +buffertls_connect(struct buffertls *buftls, int fd)
> +{
> + struct bufferevent *bufev = buftls->bt_bufev;
> +
> + event_del(&bufev->ev_read);
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> +    buftls);
> + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> +}
> +
> +/*
> + * Reads data from a file descriptor into a buffer.
> + */
> +
> +#define EVBUFFER_MAX_READ 4096
> +
> +int
> +evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx)
> +{
> + u_char *p;
> + size_t oldoff = buf->off;
> + int n = EVBUFFER_MAX_READ;
> +
> + if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
> + n = EVBUFFER_MAX_READ;
> + } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
> + /*
> + * It's possible that a lot of data is available for
> + * reading.  We do not want to exhaust resources
> + * before the reader has a chance to do something
> + * about it.  If the reader does not tell us how much
> + * data we should read, we artifically limit it.
> + */
> + if ((size_t)n > buf->totallen << 2)
> + n = buf->totallen << 2;
> + if (n < EVBUFFER_MAX_READ)
> + n = EVBUFFER_MAX_READ;
> + }
> + if (howmuch < 0 || howmuch > n)
> + howmuch = n;
> +
> + /* If we don't have FIONREAD, we might waste some space here */
> + if (evbuffer_expand(buf, howmuch) == -1)
> + return (-1);
> +
> + /* We can append new data at this point */
> + p = buf->buffer + buf->off;
> +
> + n = tls_read(ctx, p, howmuch);
> + if (n <= 0)
> + return (n);
> +
> + buf->off += n;
> +
> + /* Tell someone about changes in this buffer */
> + if (buf->off != oldoff && buf->cb != NULL)
> + (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
> +
> + return (n);
> +}
> +
> +int
> +evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx)
> +{
> + int n;
> +
> + n = tls_write(ctx, buffer->buffer, buffer->off);
> + if (n <= 0)
> + return (n);
> + evbuffer_drain(buffer, n);
> +
> + return (n);
> +}
> Index: evbuffer_tls.h
> ===================================================================
> RCS file: evbuffer_tls.h
> diff -N evbuffer_tls.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ evbuffer_tls.h 10 Apr 2016 06:15:51 -0000
> @@ -0,0 +1,37 @@
> +/* $OpenBSD: evbuffer_tls.h,v 1.5 2015/10/09 16:58:25 bluhm Exp $ */
> +
> +/*
> + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _EVBUFFER_TLS_H_
> +#define _EVBUFFER_TLS_H_
> +
> +#define EVBUFFER_HANDSHAKE 0x04
> +
> +struct bufferevent;
> +struct tls;
> +
> +struct buffertls {
> + struct bufferevent *bt_bufev;
> + struct tls *bt_ctx;
> +};
> +
> +void buffertls_set(struct buffertls *, struct bufferevent *, struct tls *,
> +    int);
> +void buffertls_accept(struct buffertls *, int);
> +void buffertls_connect(struct buffertls *, int);
> +
> +#endif /* _EVBUFFER_TLS_H_ */
> Index: ldapd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/ldapd.c,v
> retrieving revision 1.19
> diff -u -p -u -p -r1.19 ldapd.c
> --- ldapd.c 4 Feb 2016 12:48:06 -0000 1.19
> +++ ldapd.c 10 Apr 2016 06:15:51 -0000
> @@ -163,7 +163,7 @@ main(int argc, char *argv[])
>  
>   log_verbose(verbose);
>   stats.started_at = time(0);
> - ssl_init();
> + tls_init();
>  
>   if (parse_config(conffile) != 0)
>   exit(2);
> Index: ldapd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/ldapd.h,v
> retrieving revision 1.25
> diff -u -p -u -p -r1.25 ldapd.h
> --- ldapd.h 2 Nov 2015 06:32:51 -0000 1.25
> +++ ldapd.h 10 Apr 2016 06:15:51 -0000
> @@ -30,11 +30,13 @@
>  #include <limits.h>
>  #include <pwd.h>
>  #include <stdarg.h>
> +#include <tls.h>
>  
>  #include "aldap.h"
>  #include "schema.h"
>  #include "btree.h"
>  #include "imsgev.h"
> +#include "evbuffer_tls.h"
>  
>  #define CONFFILE "/etc/ldapd.conf"
>  #define LDAPD_USER "_ldapd"
> @@ -203,7 +205,7 @@ struct listener {
>   struct event evt;
>   char ssl_cert_name[PATH_MAX];
>   struct ssl *ssl;
> - void *ssl_ctx;
> + struct tls *tls;
>   TAILQ_ENTRY(listener) entry;
>  };
>  TAILQ_HEAD(listenerlist, listener);
> @@ -223,12 +225,8 @@ struct conn {
>   struct listener *listener; /* where it connected from */
>  
>   /* SSL support */
> - struct event s_ev;
> - struct timeval s_tv;
> - struct listener *s_l;
> - void *s_ssl;
> - unsigned char *s_buf;
> - int s_buflen;
> + struct tls *tls;
> + struct buffertls buftls;
>   unsigned int s_flags;
>  };
>  TAILQ_HEAD(conn_list, conn) conn_list;
> @@ -236,11 +234,12 @@ TAILQ_HEAD(conn_list, conn) conn_list;
>  struct ssl {
>   SPLAY_ENTRY(ssl) ssl_nodes;
>   char ssl_name[PATH_MAX];
> - char *ssl_cert;
> - off_t ssl_cert_len;
> - char *ssl_key;
> - off_t ssl_key_len;
> + uint8_t *ssl_cert;
> + size_t ssl_cert_len;
> + uint8_t *ssl_key;
> + size_t ssl_key_len;
>   uint8_t flags;
> + struct tls_config *config;
>  };
>  
>  struct ldapd_config
> @@ -461,6 +460,9 @@ int authorized(struct conn *conn, str
>  /* parse.y */
>  int parse_config(char *filename);
>  int cmdline_symset(char *s);
> +int ssl_cmp(struct ssl *, struct ssl *);
> +SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> +
>  
>  /* log.c */
>  void log_init(int);
> @@ -498,21 +500,6 @@ int unindex_entry(struct namespace *n
>   struct ber_element *elm);
>  int index_to_dn(struct namespace *ns, struct btval *indx,
>   struct btval *dn);
> -
> -/* ssl.c */
> -void ssl_init(void);
> -void ssl_transaction(struct conn *);
> -
> -void ssl_session_init(struct conn *);
> -void ssl_session_destroy(struct conn *);
> -int ssl_load_certfile(struct ldapd_config *, const char *, u_int8_t);
> -void ssl_setup(struct ldapd_config *, struct listener *);
> -int ssl_cmp(struct ssl *, struct ssl *);
> -SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> -
> -/* ssl_privsep.c */
> -int ssl_ctx_use_private_key(void *, char *, off_t);
> -int ssl_ctx_use_certificate_chain(void *, char *, off_t);
>  
>  /* validate.c */
>  int validate_entry(const char *dn, struct ber_element *entry, int relax);
> Index: ldape.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/ldape.c,v
> retrieving revision 1.23
> diff -u -p -u -p -r1.23 ldape.c
> --- ldape.c 24 Dec 2015 17:47:57 -0000 1.23
> +++ ldape.c 10 Apr 2016 06:15:51 -0000
> @@ -341,6 +341,7 @@ ldape(struct passwd *pw, char *csockpath
>   struct event ev_sigterm;
>   struct event ev_sigchld;
>   struct event ev_sighup;
> + struct ssl key;
>   char host[128];
>   mode_t old_umask = 0;
>  
> @@ -424,7 +425,24 @@ ldape(struct passwd *pw, char *csockpath
>   event_add(&l->ev, NULL);
>   evtimer_set(&l->evt, conn_accept, l);
>  
> - ssl_setup(conf, l);
> + if (l->flags & F_SSL) {
> + if (strlcpy(key.ssl_name, l->ssl_cert_name,
> +    sizeof(key.ssl_name)) >= sizeof(key.ssl_name))
> + fatal("ldape: certificate name truncated");
> +
> + l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key);
> + if (l->ssl == NULL)
> + fatal("ldape: certificate tree corrupted");
> +
> + l->tls = tls_server();
> + if (l->tls == NULL)
> + fatal("ldape: couldn't allocate tls context");
> +
> + if (tls_configure(l->tls, l->ssl->config)) {
> + log_warn("ldape: %s", tls_error(l->tls));
> + fatal("ldape: couldn't configure tls");
> + }
> + }
>   }
>  
>   TAILQ_FOREACH(ns, &conf->namespaces, next) {
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/parse.y,v
> retrieving revision 1.16
> diff -u -p -u -p -r1.16 parse.y
> --- parse.y 20 Nov 2014 05:51:20 -0000 1.16
> +++ parse.y 10 Apr 2016 06:15:51 -0000
> @@ -77,6 +77,7 @@ int host(const char *, const char *,
>      struct listenerlist *, int, in_port_t, u_int8_t);
>  int interface(const char *, const char *,
>      struct listenerlist *, int, in_port_t, u_int8_t);
> +int load_certfile(struct ldapd_config *, const char *, u_int8_t);
>  
>  TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
>  struct sym {
> @@ -91,6 +92,8 @@ char *symget(const char *);
>  
>  struct ldapd_config *conf;
>  
> +SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> +
>  static struct aci *mk_aci(int type, int rights, enum scope scope,
>   char *target, char *subject);
>  
> @@ -181,7 +184,7 @@ conf_main : LISTEN ON STRING port ssl ce
>   cert = ($6 != NULL) ? $6 : $3;
>  
>   if (($5 == F_STARTTLS || $5 == F_LDAPS) &&
> -    ssl_load_certfile(conf, cert, F_SCERT) < 0) {
> +    load_certfile(conf, cert, F_SCERT) < 0) {
>   yyerror("cannot load certificate: %s", cert);
>   free($6);
>   free($3);
> @@ -1167,3 +1170,84 @@ namespace_new(const char *suffix)
>   return ns;
>  }
>  
> +int
> +ssl_cmp(struct ssl *s1, struct ssl *s2)
> +{
> + return (strcmp(s1->ssl_name, s2->ssl_name));
> +}
> +
> +int
> +load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
> +{
> + struct ssl *s;
> + struct ssl key;
> + char certfile[PATH_MAX];
> +
> + if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> +    >= sizeof(key.ssl_name)) {
> + log_warn("load_certfile: certificate name truncated");
> + return -1;
> + }
> +
> + s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> + if (s != NULL) {
> + s->flags |= flags;
> + return 0;
> + }
> +
> + if ((s = calloc(1, sizeof(*s))) == NULL)
> + fatal(NULL);
> +
> + s->flags = flags;
> + (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> +
> + s->config = tls_config_new();
> + if (s->config == NULL)
> + goto err;
> +
> + tls_config_set_protocols(s->config, TLS_PROTOCOLS_ALL);
> + if (tls_config_set_ciphers(s->config, "compat"))
> + goto err;
> +
> + if ((name[0] == '/' &&
> +     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> +    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
> + name)) {
> + log_warn("load_certfile: path truncated");
> + goto err;
> + }
> +
> + log_debug("loading certificate file %s", certfile);
> + s->ssl_cert = tls_load_file(certfile, &s->ssl_cert_len, NULL);
> + if (s->ssl_cert == NULL)
> + goto err;
> +
> + if (tls_config_set_cert_mem(s->config, s->ssl_cert, s->ssl_cert_len))
> + goto err;
> +
> + if ((name[0] == '/' &&
> +     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> +    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
> + name)) {
> + log_warn("load_certfile: path truncated");
> + goto err;
> + }
> +
> + log_debug("loading key file %s", certfile);
> + s->ssl_key = tls_load_file(certfile, &s->ssl_key_len, NULL);
> + if (s->ssl_key == NULL)
> + goto err;
> +
> + if (tls_config_set_key_mem(s->config, s->ssl_key, s->ssl_key_len))
> + goto err;
> +
> + SPLAY_INSERT(ssltree, env->sc_ssl, s);
> +
> + return (0);
> +err:
> + free(s->ssl_cert);
> + free(s->ssl_key);
> + tls_config_free(s->config);
> + free(s);
> + return (-1);
> +}
> Index: ssl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/ssl.c,v
> retrieving revision 1.10
> diff -u -p -u -p -r1.10 ssl.c
> --- ssl.c 30 Dec 2015 15:59:55 -0000 1.10
> +++ ssl.c 10 Apr 2016 06:15:51 -0000
> @@ -1,565 +0,0 @@
> -/* $OpenBSD: ssl.c,v 1.10 2015/12/30 15:59:55 benno Exp $ */
> -
> -/*
> - * Copyright (c) 2008 Pierre-Yves Ritschard <[hidden email]>
> - * Copyright (c) 2008 Reyk Floeter <[hidden email]>
> - *
> - * Permission to use, copy, modify, and distribute this software for any
> - * purpose with or without fee is hereby granted, provided that the above
> - * copyright notice and this permission notice appear in all copies.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> - */
> -
> -#include <sys/types.h>
> -#include <sys/queue.h>
> -#include <sys/tree.h>
> -#include <sys/socket.h>
> -#include <sys/stat.h>
> -#include <sys/time.h>
> -
> -#include <ctype.h>
> -#include <event.h>
> -#include <fcntl.h>
> -#include <pwd.h>
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <unistd.h>
> -
> -#include <openssl/ssl.h>
> -#include <openssl/engine.h>
> -#include <openssl/err.h>
> -#include <openssl/dh.h>
> -#include <openssl/bn.h>
> -
> -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
> -
> -#include "ldapd.h"
> -
> -#define SSL_CIPHERS "HIGH:!aNULL"
> -
> -void ssl_error(const char *);
> -char *ssl_load_file(const char *, off_t *);
> -SSL_CTX *ssl_ctx_create(void);
> -void ssl_session_accept(int, short, void *);
> -void ssl_read(int, short, void *);
> -void ssl_write(int, short, void *);
> -int ssl_bufferevent_add(struct event *, int);
> -
> -DH *get_dh1024(void);
> -void ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *);
> -
> -extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
> -    size_t, void *);
> -
> -void
> -ssl_read(int fd, short event, void *p)
> -{
> - struct bufferevent *bufev = p;
> - struct conn *s = bufev->cbarg;
> - int ret;
> - int ssl_err;
> - short what;
> - size_t len;
> - char rbuf[IBUF_READ_SIZE];
> - int howmuch = IBUF_READ_SIZE;
> -
> - what = EVBUFFER_READ;
> -
> - if (event == EV_TIMEOUT) {
> - what |= EVBUFFER_TIMEOUT;
> - goto err;
> - }
> -
> - if (bufev->wm_read.high != 0)
> - howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
> -
> - ret = SSL_read(s->s_ssl, rbuf, howmuch);
> - if (ret <= 0) {
> - ssl_err = SSL_get_error(s->s_ssl, ret);
> -
> - switch (ssl_err) {
> - case SSL_ERROR_WANT_READ:
> - goto retry;
> - case SSL_ERROR_WANT_WRITE:
> - goto retry;
> - default:
> - if (ret == 0)
> - what |= EVBUFFER_EOF;
> - else {
> - ssl_error("ssl_read");
> - what |= EVBUFFER_ERROR;
> - }
> - goto err;
> - }
> - }
> -
> - if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
> - what |= EVBUFFER_ERROR;
> - goto err;
> - }
> -
> - ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> -
> - len = EVBUFFER_LENGTH(bufev->input);
> - if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> - return;
> - if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
> - struct evbuffer *buf = bufev->input;
> - event_del(&bufev->ev_read);
> - evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> - return;
> - }
> -
> - if (bufev->readcb != NULL)
> - (*bufev->readcb)(bufev, bufev->cbarg);
> - return;
> -
> -retry:
> - ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> - return;
> -
> -err:
> - (*bufev->errorcb)(bufev, what, bufev->cbarg);
> -}
> -
> -
> -void
> -ssl_write(int fd, short event, void *p)
> -{
> - struct bufferevent *bufev = p;
> - struct conn *s = bufev->cbarg;
> - int ret;
> - int ssl_err;
> - short what;
> -
> - what = EVBUFFER_WRITE;
> -
> - if (event == EV_TIMEOUT) {
> - what |= EV_TIMEOUT;
> - goto err;
> - }
> -
> - if (EVBUFFER_LENGTH(bufev->output)) {
> - if (s->s_buf == NULL) {
> - s->s_buflen = EVBUFFER_LENGTH(bufev->output);
> - if ((s->s_buf = malloc(s->s_buflen)) == NULL) {
> - what |= EVBUFFER_ERROR;
> - goto err;
> - }
> - memcpy(s->s_buf, EVBUFFER_DATA(bufev->output),
> -    s->s_buflen);
> - }
> -
> - ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen);
> - if (ret <= 0) {
> - ssl_err = SSL_get_error(s->s_ssl, ret);
> -
> - switch (ssl_err) {
> - case SSL_ERROR_WANT_READ:
> - goto retry;
> - case SSL_ERROR_WANT_WRITE:
> - goto retry;
> - default:
> - if (ret == 0)
> - what |= EVBUFFER_EOF;
> - else {
> - ssl_error("ssl_write");
> - what |= EVBUFFER_ERROR;
> - }
> - goto err;
> - }
> - }
> - evbuffer_drain(bufev->output, ret);
> - }
> - if (s->s_buf != NULL) {
> - free(s->s_buf);
> - s->s_buf = NULL;
> - s->s_buflen = 0;
> - }
> - if (EVBUFFER_LENGTH(bufev->output) != 0)
> - ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> -
> - if (bufev->writecb != NULL &&
> -    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> - (*bufev->writecb)(bufev, bufev->cbarg);
> - return;
> -
> -retry:
> - if (s->s_buflen != 0)
> - ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> - return;
> -
> -err:
> - if (s->s_buf != NULL) {
> - free(s->s_buf);
> - s->s_buf = NULL;
> - s->s_buflen = 0;
> - }
> - (*bufev->errorcb)(bufev, what, bufev->cbarg);
> -}
> -
> -int
> -ssl_bufferevent_add(struct event *ev, int timeout)
> -{
> - struct timeval tv;
> - struct timeval *ptv = NULL;
> -
> - if (timeout) {
> - timerclear(&tv);
> - tv.tv_sec = timeout;
> - ptv = &tv;
> - }
> -
> - return (event_add(ev, ptv));
> -}
> -
> -int
> -ssl_cmp(struct ssl *s1, struct ssl *s2)
> -{
> - return (strcmp(s1->ssl_name, s2->ssl_name));
> -}
> -
> -SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> -
> -char *
> -ssl_load_file(const char *name, off_t *len)
> -{
> - struct stat st;
> - off_t size;
> - char *buf = NULL;
> - int fd;
> -
> - if ((fd = open(name, O_RDONLY)) == -1)
> - return (NULL);
> - if (fstat(fd, &st) != 0)
> - goto fail;
> - size = st.st_size;
> - if ((buf = calloc(1, size + 1)) == NULL)
> - goto fail;
> - if (read(fd, buf, size) != size)
> - goto fail;
> - close(fd);
> -
> - *len = size + 1;
> - return (buf);
> -
> -fail:
> - free(buf);
> - close(fd);
> - return (NULL);
> -}
> -
> -SSL_CTX *
> -ssl_ctx_create(void)
> -{
> - SSL_CTX *ctx;
> -
> - ctx = SSL_CTX_new(SSLv23_method());
> - if (ctx == NULL) {
> - ssl_error("ssl_ctx_create");
> - fatal("ssl_ctx_create: could not create SSL context");
> - }
> -
> - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
> - SSL_CTX_set_timeout(ctx, LDAPD_SESSION_TIMEOUT);
> - SSL_CTX_set_options(ctx, SSL_OP_ALL);
> - SSL_CTX_set_options(ctx,
> -    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
> -
> - if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
> - ssl_error("ssl_ctx_create");
> - fatal("ssl_ctx_create: could not set cipher list");
> - }
> - return (ctx);
> -}
> -
> -int
> -ssl_load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
> -{
> - struct ssl *s;
> - struct ssl key;
> - char certfile[PATH_MAX];
> -
> - if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> -    >= sizeof(key.ssl_name)) {
> - log_warn("ssl_load_certfile: certificate name truncated");
> - return -1;
> - }
> -
> - s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> - if (s != NULL) {
> - s->flags |= flags;
> - return 0;
> - }
> -
> - if ((s = calloc(1, sizeof(*s))) == NULL)
> - fatal(NULL);
> -
> - s->flags = flags;
> - (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> -
> - if ((name[0] == '/' &&
> -     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> -    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
> - name)) {
> - log_warn("ssl_load_certfile: path truncated");
> - free(s);
> - return -1;
> - }
> -
> - log_debug("loading certificate file %s", certfile);
> - if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) {
> - free(s);
> - return (-1);
> - }
> -
> - if ((name[0] == '/' &&
> -     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> -    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
> - name)) {
> - log_warn("ssl_load_certfile: path truncated");
> - free(s->ssl_cert);
> - free(s);
> - return -1;
> - }
> -
> - log_debug("loading key file %s", certfile);
> - if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) {
> - free(s->ssl_cert);
> - free(s);
> - return (-1);
> - }
> -
> - SPLAY_INSERT(ssltree, env->sc_ssl, s);
> -
> - return (0);
> -}
> -
> -void
> -ssl_init(void)
> -{
> - SSL_library_init();
> - SSL_load_error_strings();
> -
> - OpenSSL_add_all_algorithms();
> -
> - /* Init hardware crypto engines. */
> - ENGINE_load_builtin_engines();
> - ENGINE_register_all_complete();
> -}
> -
> -void
> -ssl_setup(struct ldapd_config *env, struct listener *l)
> -{
> - struct ssl key;
> -
> - if (!(l->flags & F_SSL))
> - return;
> -
> - if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name))
> -    >= sizeof(key.ssl_name))
> - fatal("ssl_setup: certificate name truncated");
> -
> - if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL)
> - fatal("ssl_setup: certificate tree corrupted");
> -
> - l->ssl_ctx = ssl_ctx_create();
> -
> - if (!ssl_ctx_use_certificate_chain(l->ssl_ctx,
> -    l->ssl->ssl_cert, l->ssl->ssl_cert_len))
> - goto err;
> - if (!ssl_ctx_use_private_key(l->ssl_ctx,
> -    l->ssl->ssl_key, l->ssl->ssl_key_len))
> - goto err;
> -
> - if (!SSL_CTX_check_private_key(l->ssl_ctx))
> - goto err;
> - if (!SSL_CTX_set_session_id_context(l->ssl_ctx,
> - (const unsigned char *)l->ssl_cert_name, strlen(l->ssl_cert_name) + 1))
> - goto err;
> -
> - ssl_set_ephemeral_key_exchange(l->ssl_ctx, get_dh1024());
> -
> - log_debug("ssl_setup: ssl setup finished for listener: %p", l);
> - return;
> -
> -err:
> - SSL_CTX_free(l->ssl_ctx);
> - ssl_error("ssl_setup");
> - fatal("ssl_setup: cannot set SSL up");
> -}
> -
> -void
> -ssl_error(const char *where)
> -{
> - unsigned long code;
> - char errbuf[128];
> - extern int debug;
> -
> - if (!debug)
> - return;
> - for (; (code = ERR_get_error()) != 0 ;) {
> - ERR_error_string_n(code, errbuf, sizeof(errbuf));
> - log_debug("SSL library error: %s: %s", where, errbuf);
> - }
> -}
> -
> -void
> -ssl_session_accept(int fd, short event, void *p)
> -{
> - struct conn *s = p;
> - int ret;
> - int ssl_err;
> -
> - if (event == EV_TIMEOUT) {
> - log_debug("ssl_session_accept: session timed out");
> - conn_close(s);
> - return;
> - }
> -
> - log_debug("ssl_session_accept: accepting client");
> - ret = SSL_accept(s->s_ssl);
> - if (ret <= 0) {
> - ssl_err = SSL_get_error(s->s_ssl, ret);
> -
> - switch (ssl_err) {
> - case SSL_ERROR_WANT_READ:
> - goto retry;
> - case SSL_ERROR_WANT_WRITE:
> - goto retry;
> - case SSL_ERROR_ZERO_RETURN:
> - case SSL_ERROR_SYSCALL:
> - if (ret == 0) {
> - conn_close(s);
> - return;
> - }
> - /* FALLTHROUGH */
> - default:
> - ssl_error("ssl_session_accept");
> - conn_close(s);
> - return;
> - }
> - }
> -
> - log_debug("ssl_session_accept: accepted ssl client");
> - s->s_flags |= F_SECURE;
> -
> - s->bev = bufferevent_new(s->fd, conn_read, conn_write, conn_err, s);
> - if (s->bev == NULL) {
> -                log_warn("ssl_session_accept: bufferevent_new");
> -                conn_close(s);
> -                return;
> - }
> - bufferevent_settimeout(s->bev, 0, 60);
> -
> - event_set(&s->bev->ev_read, s->fd, EV_READ, ssl_read, s->bev);
> - event_set(&s->bev->ev_write, s->fd, EV_WRITE, ssl_write, s->bev);
> - bufferevent_enable(s->bev, EV_READ);
> -
> - return;
> -retry:
> - event_add(&s->s_ev, &s->s_tv);
> -}
> -
> -void
> -ssl_session_init(struct conn *s)
> -{
> - struct listener *l;
> - SSL             *ssl;
> -
> - l = s->s_l;
> -
> - if (!(l->flags & F_SSL))
> - return;
> -
> - log_debug("ssl_session_init: switching to SSL");
> - ssl = SSL_new(l->ssl_ctx);
> - if (ssl == NULL)
> - goto err;
> -
> - if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
> - goto err;
> - if (!SSL_set_fd(ssl, s->fd))
> - goto err;
> - SSL_set_accept_state(ssl);
> -
> - s->s_ssl = ssl;
> -
> - s->s_tv.tv_sec = LDAPD_SESSION_TIMEOUT;
> - s->s_tv.tv_usec = 0;
> - event_set(&s->s_ev, s->fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s);
> - event_add(&s->s_ev, &s->s_tv);
> - return;
> -
> - err:
> - SSL_free(ssl);
> - ssl_error("ssl_session_init");
> -}
> -
> -void
> -ssl_session_destroy(struct conn *s)
> -{
> - SSL_free(s->s_ssl);
> -}
> -
> -/* From OpenSSL's documentation:
> - *
> - * If "strong" primes were used to generate the DH parameters, it is
> - * not strictly necessary to generate a new key for each handshake
> - * but it does improve forward secrecy.
> - *
> - * -- gilles@
> - */
> -DH *
> -get_dh1024(void)
> -{
> - DH *dh;
> - unsigned char dh1024_p[] = {
> - 0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75,
> - 0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51,
> - 0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E,
> - 0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D,
> - 0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89,
> - 0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC,
> - 0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02,
> - 0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93,
> - 0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D,
> - 0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65,
> - 0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6,
> - 0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1,
> - 0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9,
> - 0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59,
> - 0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7,
> - 0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B
> - };
> - unsigned char dh1024_g[] = {
> - 0x02
> - };
> -
> - if ((dh = DH_new()) == NULL)
> - return NULL;
> -
> - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
> - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
> - if (dh->p == NULL || dh->g == NULL) {
> - DH_free(dh);
> - return NULL;
> - }
> -
> - return dh;
> -}
> -
> -void
> -ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh)
> -{
> - if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh))
> - fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh");
> -}
> Index: ssl_privsep.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ldapd/ssl_privsep.c,v
> retrieving revision 1.4
> diff -u -p -u -p -r1.4 ssl_privsep.c
> --- ssl_privsep.c 28 Jan 2015 15:50:30 -0000 1.4
> +++ ssl_privsep.c 10 Apr 2016 06:15:51 -0000
> @@ -1,172 +0,0 @@
> -/*      $OpenBSD: ssl_privsep.c,v 1.4 2015/01/28 15:50:30 reyk Exp $    */
> -
> -/* Copyright (C) 1995-1998 Eric Young ([hidden email])
> - * All rights reserved.
> - *
> - * This package is an SSL implementation written
> - * by Eric Young ([hidden email]).
> - * The implementation was written so as to conform with Netscapes SSL.
> - *
> - * This library is free for commercial and non-commercial use as long as
> - * the following conditions are aheared to.  The following conditions
> - * apply to all code found in this distribution, be it the RC4, RSA,
> - * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
> - * included with this distribution is covered by the same copyright terms
> - * except that the holder is Tim Hudson ([hidden email]).
> - *
> - * Copyright remains Eric Young's, and as such any Copyright notices in
> - * the code are not to be removed.
> - * If this package is used in a product, Eric Young should be given attribution
> - * as the author of the parts of the library used.
> - * This can be in the form of a textual message at program startup or
> - * in documentation (online or textual) provided with the package.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions
> - * are met:
> - * 1. Redistributions of source code must retain the copyright
> - *    notice, this list of conditions and the following disclaimer.
> - * 2. Redistributions in binary form must reproduce the above copyright
> - *    notice, this list of conditions and the following disclaimer in the
> - *    documentation and/or other materials provided with the distribution.
> - * 3. All advertising materials mentioning features or use of this software
> - *    must display the following acknowledgement:
> - *    "This product includes cryptographic software written by
> - *     Eric Young ([hidden email])"
> - *    The word 'cryptographic' can be left out if the rouines from the library
> - *    being used are not cryptographic related :-).
> - * 4. If you include any Windows specific code (or a derivative thereof) from
> - *    the apps directory (application code) you must include an acknowledgement:
> - *    "This product includes software written by Tim Hudson ([hidden email])"
> - *
> - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
> - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> - * SUCH DAMAGE.
> - *
> - * The licence and distribution terms for any publically available version or
> - * derivative of this code cannot be changed.  i.e. this code cannot simply be
> - * copied and put under another distribution licence
> - * [including the GNU Public Licence.]
> - */
> -
> -/*
> - * SSL operations needed when running in a privilege separated environment.
> - * 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>
> -
> -#include <openssl/err.h>
> -#include <openssl/bio.h>
> -#include <openssl/objects.h>
> -#include <openssl/evp.h>
> -#include <openssl/x509.h>
> -#include <openssl/pem.h>
> -#include <openssl/ssl.h>
> -
> -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_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
> -{
> - int ret;
> - BIO *in;
> - EVP_PKEY *pkey;
> -
> - ret = 0;
> -
> - if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
> - return 0;
> - }
> -
> - pkey = PEM_read_bio_PrivateKey(in, NULL,
> -    ctx->default_passwd_callback,
> -    ctx->default_passwd_callback_userdata);
> -
> - if (pkey == NULL) {
> - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
> - goto end;
> - }
> - ret = SSL_CTX_use_PrivateKey(ctx, pkey);
> - EVP_PKEY_free(pkey);
> -end:
> - if (in != NULL)
> - BIO_free(in);
> - return ret;
> -}
> -
> -int
> -ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
> -{
> - int ret;
> - BIO *in;
> - X509 *x;
> - X509 *ca;
> - unsigned long err;
> -
> - ret = 0;
> - x = ca = NULL;
> -
> - if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
> - goto end;
> - }
> -
> - if ((x = PEM_read_bio_X509(in, NULL,
> -    ctx->default_passwd_callback,
> -    ctx->default_passwd_callback_userdata)) == NULL) {
> - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
> - goto end;
> - }
> -
> - if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
> - goto end;
> -
> - /* If we could set up our certificate, now proceed to
> - * the CA certificates.
> - */
> -
> - if (ctx->extra_certs != NULL) {
> - sk_X509_pop_free(ctx->extra_certs, X509_free);
> - ctx->extra_certs = NULL;
> - }
> -
> - while ((ca = PEM_read_bio_X509(in, NULL,
> -    ctx->default_passwd_callback,
> -    ctx->default_passwd_callback_userdata)) != NULL) {
> -
> - if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
> - goto end;
> - }
> -
> - err = ERR_peek_last_error();
> - if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
> -    ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
> - ERR_clear_error();
> - else
> - goto end;
> -
> - ret = 1;
> -end:
> - if (ca != NULL)
> - X509_free(ca);
> - if (x != NULL)
> - X509_free(x);
> - if (in != NULL)
> - BIO_free(in);
> - return (ret);
> -}

Reply | Threaded
Open this post in threaded view
|

Re: use libtls in ldapd

Sebastian Benoit-3
Jonathan Matthew([hidden email]) on 2016.04.18 07:17:55 +1000:

> On Sun, Apr 10, 2016 at 04:36:15PM +1000, Jonathan Matthew wrote:
> > A while back (s2k15?), reyk@ suggested I take a look at converting ldapd to use
> > libtls rather than the openssl api.  Today I finally got around to it,
> > resulting in the diff below.  Most of the diff just removes ssl.c and
> > ssl_privsep.c, and replaces some of it with evbuffer_tls.c (copied from
> > syslogd, unmodified).  A reasonable amount of code just went away because
> > libtls is sensible.  The few remaining bits of ssl.c moved to wherever seemed
> > most suitable.
> >
> > I've tested a few things with the openldap clients, which apparently only do
> > starttls, and otherwise checked that it negotiates ssl successfully.
> >
> > ok?
>
> ldapd is too boring?

:)

ok from me, but i cant test it.

>
> >
> >
> > Index: Makefile
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
> > retrieving revision 1.12
> > diff -u -p -u -p -r1.12 Makefile
> > --- Makefile 16 Jul 2014 20:07:03 -0000 1.12
> > +++ Makefile 10 Apr 2016 06:15:50 -0000
> > @@ -5,11 +5,11 @@ MAN= ldapd.8 ldapd.conf.5
> >  SRCS= ber.c log.c control.c \
> >   util.c ldapd.c ldape.c conn.c attributes.c namespace.c \
> >   btree.c filter.c search.c parse.y \
> > - auth.c modify.c index.c ssl.c ssl_privsep.c \
> > + auth.c modify.c index.c evbuffer_tls.c \
> >   validate.c uuid.c schema.c imsgev.c syntax.c matching.c
> >  
> > -LDADD= -levent -lssl -lcrypto -lz -lutil
> > -DPADD= ${LIBEVENT} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
> > +LDADD= -ltls -levent -lz -lutil
> > +DPADD= ${LIBEVENT} ${LIBTLS} ${LIBCRYPTO} ${LIBSSL} ${LIBZ} ${LIBUTIL}
> >  CFLAGS+= -I${.CURDIR} -g
> >  CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes
> >  CFLAGS+= -Wmissing-declarations
> > Index: btree.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/btree.c,v
> > retrieving revision 1.36
> > diff -u -p -u -p -r1.36 btree.c
> > --- btree.c 20 Mar 2016 00:01:22 -0000 1.36
> > +++ btree.c 10 Apr 2016 06:15:51 -0000
> > @@ -34,6 +34,8 @@
> >  #include <time.h>
> >  #include <unistd.h>
> >  
> > +#include <openssl/sha.h>
> > +
> >  #include "btree.h"
> >  
> >  /* #define DEBUG */
> > Index: btree.h
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/btree.h,v
> > retrieving revision 1.6
> > diff -u -p -u -p -r1.6 btree.h
> > --- btree.h 2 Jul 2010 01:43:00 -0000 1.6
> > +++ btree.h 10 Apr 2016 06:15:51 -0000
> > @@ -19,8 +19,6 @@
> >  #ifndef _btree_h_
> >  #define _btree_h_
> >  
> > -#include <openssl/sha.h>
> > -
> >  struct mpage;
> >  struct cursor;
> >  struct btree_txn;
> > Index: conn.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/conn.c,v
> > retrieving revision 1.12
> > diff -u -p -u -p -r1.12 conn.c
> > --- conn.c 2 Nov 2015 06:32:51 -0000 1.12
> > +++ conn.c 10 Apr 2016 06:15:51 -0000
> > @@ -26,6 +26,7 @@
> >  #include "ldapd.h"
> >  
> >  int conn_dispatch(struct conn *conn);
> > +int conn_tls_init(struct conn *);
> >  unsigned long ldap_application(struct ber_element *elm);
> >  
> >  struct conn_list conn_list;
> > @@ -61,7 +62,7 @@ conn_close(struct conn *conn)
> >   /* Cancel any queued requests on this connection. */
> >   namespace_cancel_conn(conn);
> >  
> > - ssl_session_destroy(conn);
> > + tls_free(conn->tls);
> >  
> >   TAILQ_REMOVE(&conn_list, conn, next);
> >   ber_free(&conn->ber);
> > @@ -225,9 +226,8 @@ conn_write(struct bufferevent *bev, void
> >   conn_close(conn);
> >   else if (conn->s_flags & F_STARTTLS) {
> >   conn->s_flags &= ~F_STARTTLS;
> > - bufferevent_free(conn->bev);
> > - conn->bev = NULL;
> > - ssl_session_init(conn);
> > + if (conn_tls_init(conn) == -1)
> > + conn_close(conn);
> >   }
> >  }
> >  
> > @@ -296,24 +296,22 @@ conn_accept(int fd, short event, void *d
> >   goto giveup;
> >   }
> >   conn->ber.fd = -1;
> > - conn->s_l = l;
> >   ber_set_application(&conn->ber, ldap_application);
> >   conn->fd = afd;
> >   conn->listener = l;
> >  
> > - if (l->flags & F_LDAPS) {
> > - ssl_session_init(conn);
> > - } else {
> > - conn->bev = bufferevent_new(afd, conn_read, conn_write,
> > -    conn_err, conn);
> > - if (conn->bev == NULL) {
> > - log_warn("conn_accept: bufferevent_new");
> > - free(conn);
> > - goto giveup;
> > - }
> > - bufferevent_enable(conn->bev, EV_READ);
> > - bufferevent_settimeout(conn->bev, 0, 60);
> > + conn->bev = bufferevent_new(afd, conn_read, conn_write,
> > +    conn_err, conn);
> > + if (conn->bev == NULL) {
> > + log_warn("conn_accept: bufferevent_new");
> > + free(conn);
> > + goto giveup;
> >   }
> > + bufferevent_enable(conn->bev, EV_READ);
> > + bufferevent_settimeout(conn->bev, 0, 60);
> > + if (conn->s_flags & F_LDAPS)
> > + if (conn_tls_init(conn) == -1)
> > + conn_close(conn);
> >  
> >   TAILQ_INIT(&conn->searches);
> >   TAILQ_INSERT_HEAD(&conn_list, conn, next);
> > @@ -365,4 +363,25 @@ conn_close_any()
> >   }
> >  
> >   return -1;
> > +}
> > +
> > +int
> > +conn_tls_init(struct conn *conn)
> > +{
> > + struct listener *l = conn->listener;
> > +
> > + if (!(l->flags & F_SSL))
> > + return 0;
> > +
> > + log_debug("conn_tls_init: switching to TLS");
> > +
> > + if (tls_accept_socket(l->tls, &conn->tls, conn->fd) < 0) {
> > + log_debug("tls_accept_socket failed");
> > + return -1;
> > + }
> > +
> > + conn->s_flags |= F_SECURE;
> > + buffertls_set(&conn->buftls, conn->bev, conn->tls, conn->fd);
> > + buffertls_accept(&conn->buftls, conn->fd);
> > + return 0;
> >  }
> > Index: evbuffer_tls.c
> > ===================================================================
> > RCS file: evbuffer_tls.c
> > diff -N evbuffer_tls.c
> > --- /dev/null 1 Jan 1970 00:00:00 -0000
> > +++ evbuffer_tls.c 10 Apr 2016 06:15:51 -0000
> > @@ -0,0 +1,350 @@
> > +/* $OpenBSD: evbuffer_tls.c,v 1.9 2015/10/09 16:58:25 bluhm Exp $ */
> > +
> > +/*
> > + * Copyright (c) 2002-2004 Niels Provos <[hidden email]>
> > + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> > + * All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. The name of the author may not be used to endorse or promote products
> > + *    derived from this software without specific prior written permission.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#include <sys/types.h>
> > +#include <sys/time.h>
> > +#include <sys/ioctl.h>
> > +
> > +#include <errno.h>
> > +#include <event.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <tls.h>
> > +
> > +#include "evbuffer_tls.h"
> > +
> > +/* prototypes */
> > +
> > +void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
> > +static void buffertls_readcb(int, short, void *);
> > +static void buffertls_writecb(int, short, void *);
> > +static void buffertls_handshakecb(int, short, void *);
> > +int evtls_read(struct evbuffer *, int, int, struct tls *);
> > +int evtls_write(struct evbuffer *, int, struct tls *);
> > +
> > +static int
> > +bufferevent_add(struct event *ev, int timeout)
> > +{
> > + struct timeval tv, *ptv = NULL;
> > +
> > + if (timeout) {
> > + timerclear(&tv);
> > + tv.tv_sec = timeout;
> > + ptv = &tv;
> > + }
> > +
> > + return (event_add(ev, ptv));
> > +}
> > +
> > +static void
> > +buffertls_readcb(int fd, short event, void *arg)
> > +{
> > + struct buffertls *buftls = arg;
> > + struct bufferevent *bufev = buftls->bt_bufev;
> > + struct tls *ctx = buftls->bt_ctx;
> > + int res = 0;
> > + short what = EVBUFFER_READ;
> > + size_t len;
> > + int howmuch = -1;
> > +
> > + if (event == EV_TIMEOUT) {
> > + what |= EVBUFFER_TIMEOUT;
> > + goto error;
> > + }
> > +
> > + /*
> > + * If we have a high watermark configured then we don't want to
> > + * read more data than would make us reach the watermark.
> > + */
> > + if (bufev->wm_read.high != 0) {
> > + howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
> > + /* we might have lowered the watermark, stop reading */
> > + if (howmuch <= 0) {
> > + struct evbuffer *buf = bufev->input;
> > + event_del(&bufev->ev_read);
> > + evbuffer_setcb(buf,
> > +    bufferevent_read_pressure_cb, bufev);
> > + return;
> > + }
> > + }
> > +
> > + res = evtls_read(bufev->input, fd, howmuch, ctx);
> > + switch (res) {
> > + case TLS_WANT_POLLIN:
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + return;
> > + case TLS_WANT_POLLOUT:
> > + event_del(&bufev->ev_write);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb,
> > +    buftls);
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > + return;
> > + case -1:
> > + what |= EVBUFFER_ERROR;
> > + break;
> > + case 0:
> > + what |= EVBUFFER_EOF;
> > + break;
> > + }
> > + if (res <= 0)
> > + goto error;
> > +
> > + event_del(&bufev->ev_write);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> > + if (bufev->enabled & EV_READ)
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > +
> > + /* See if this callbacks meets the water marks */
> > + len = EVBUFFER_LENGTH(bufev->input);
> > + if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> > + return;
> > + if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
> > + struct evbuffer *buf = bufev->input;
> > + event_del(&bufev->ev_read);
> > +
> > + /* Now schedule a callback for us when the buffer changes */
> > + evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> > + }
> > +
> > + /* Invoke the user callback - must always be called last */
> > + if (bufev->readcb != NULL)
> > + (*bufev->readcb)(bufev, bufev->cbarg);
> > + return;
> > +
> > + error:
> > + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > +}
> > +
> > +static void
> > +buffertls_writecb(int fd, short event, void *arg)
> > +{
> > + struct buffertls *buftls = arg;
> > + struct bufferevent *bufev = buftls->bt_bufev;
> > + struct tls *ctx = buftls->bt_ctx;
> > + int res = 0;
> > + short what = EVBUFFER_WRITE;
> > +
> > + if (event == EV_TIMEOUT) {
> > + what |= EVBUFFER_TIMEOUT;
> > + goto error;
> > + }
> > +
> > + if (EVBUFFER_LENGTH(bufev->output) != 0) {
> > + res = evtls_write(bufev->output, fd, ctx);
> > + switch (res) {
> > + case TLS_WANT_POLLIN:
> > + event_del(&bufev->ev_read);
> > + event_set(&bufev->ev_read, fd, EV_READ,
> > +    buffertls_writecb, buftls);
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + return;
> > + case TLS_WANT_POLLOUT:
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > + return;
> > + case -1:
> > + what |= EVBUFFER_ERROR;
> > + break;
> > + case 0:
> > + what |= EVBUFFER_EOF;
> > + break;
> > + }
> > + if (res <= 0)
> > + goto error;
> > + }
> > +
> > + event_del(&bufev->ev_read);
> > + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > + if (bufev->enabled & EV_READ)
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > +
> > + /*
> > + * Invoke the user callback if our buffer is drained or below the
> > + * low watermark.
> > + */
> > + if (bufev->writecb != NULL &&
> > +    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> > + (*bufev->writecb)(bufev, bufev->cbarg);
> > +
> > + return;
> > +
> > + error:
> > + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > +}
> > +
> > +static void
> > +buffertls_handshakecb(int fd, short event, void *arg)
> > +{
> > + struct buffertls *buftls = arg;
> > + struct bufferevent *bufev = buftls->bt_bufev;
> > + struct tls *ctx = buftls->bt_ctx;
> > + int res = 0;
> > + short what = EVBUFFER_HANDSHAKE;
> > +
> > + if (event == EV_TIMEOUT) {
> > + what |= EVBUFFER_TIMEOUT;
> > + goto error;
> > + }
> > +
> > + res = tls_handshake(ctx);
> > + switch (res) {
> > + case TLS_WANT_POLLIN:
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + return;
> > + case TLS_WANT_POLLOUT:
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > + return;
> > + case -1:
> > + what |= EVBUFFER_ERROR;
> > + break;
> > + }
> > + if (res < 0)
> > + goto error;
> > +
> > + /* Handshake was successful, change to read and write callback. */
> > + event_del(&bufev->ev_read);
> > + event_del(&bufev->ev_write);
> > + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> > + if (bufev->enabled & EV_READ)
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > + if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE)
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > +
> > + return;
> > +
> > + error:
> > + (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > +}
> > +
> > +void
> > +buffertls_set(struct buffertls *buftls, struct bufferevent *bufev,
> > +    struct tls *ctx, int fd)
> > +{
> > + bufferevent_setfd(bufev, fd);
> > + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls);
> > + buftls->bt_bufev = bufev;
> > + buftls->bt_ctx = ctx;
> > +}
> > +
> > +void
> > +buffertls_accept(struct buffertls *buftls, int fd)
> > +{
> > + struct bufferevent *bufev = buftls->bt_bufev;
> > +
> > + event_del(&bufev->ev_read);
> > + event_del(&bufev->ev_write);
> > + event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> > +    buftls);
> > + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > +}
> > +
> > +void
> > +buffertls_connect(struct buffertls *buftls, int fd)
> > +{
> > + struct bufferevent *bufev = buftls->bt_bufev;
> > +
> > + event_del(&bufev->ev_read);
> > + event_del(&bufev->ev_write);
> > + event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls);
> > + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> > +    buftls);
> > + bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > +}
> > +
> > +/*
> > + * Reads data from a file descriptor into a buffer.
> > + */
> > +
> > +#define EVBUFFER_MAX_READ 4096
> > +
> > +int
> > +evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx)
> > +{
> > + u_char *p;
> > + size_t oldoff = buf->off;
> > + int n = EVBUFFER_MAX_READ;
> > +
> > + if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
> > + n = EVBUFFER_MAX_READ;
> > + } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
> > + /*
> > + * It's possible that a lot of data is available for
> > + * reading.  We do not want to exhaust resources
> > + * before the reader has a chance to do something
> > + * about it.  If the reader does not tell us how much
> > + * data we should read, we artifically limit it.
> > + */
> > + if ((size_t)n > buf->totallen << 2)
> > + n = buf->totallen << 2;
> > + if (n < EVBUFFER_MAX_READ)
> > + n = EVBUFFER_MAX_READ;
> > + }
> > + if (howmuch < 0 || howmuch > n)
> > + howmuch = n;
> > +
> > + /* If we don't have FIONREAD, we might waste some space here */
> > + if (evbuffer_expand(buf, howmuch) == -1)
> > + return (-1);
> > +
> > + /* We can append new data at this point */
> > + p = buf->buffer + buf->off;
> > +
> > + n = tls_read(ctx, p, howmuch);
> > + if (n <= 0)
> > + return (n);
> > +
> > + buf->off += n;
> > +
> > + /* Tell someone about changes in this buffer */
> > + if (buf->off != oldoff && buf->cb != NULL)
> > + (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
> > +
> > + return (n);
> > +}
> > +
> > +int
> > +evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx)
> > +{
> > + int n;
> > +
> > + n = tls_write(ctx, buffer->buffer, buffer->off);
> > + if (n <= 0)
> > + return (n);
> > + evbuffer_drain(buffer, n);
> > +
> > + return (n);
> > +}
> > Index: evbuffer_tls.h
> > ===================================================================
> > RCS file: evbuffer_tls.h
> > diff -N evbuffer_tls.h
> > --- /dev/null 1 Jan 1970 00:00:00 -0000
> > +++ evbuffer_tls.h 10 Apr 2016 06:15:51 -0000
> > @@ -0,0 +1,37 @@
> > +/* $OpenBSD: evbuffer_tls.h,v 1.5 2015/10/09 16:58:25 bluhm Exp $ */
> > +
> > +/*
> > + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> > + *
> > + * Permission to use, copy, modify, and distribute this software for any
> > + * purpose with or without fee is hereby granted, provided that the above
> > + * copyright notice and this permission notice appear in all copies.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > + */
> > +
> > +#ifndef _EVBUFFER_TLS_H_
> > +#define _EVBUFFER_TLS_H_
> > +
> > +#define EVBUFFER_HANDSHAKE 0x04
> > +
> > +struct bufferevent;
> > +struct tls;
> > +
> > +struct buffertls {
> > + struct bufferevent *bt_bufev;
> > + struct tls *bt_ctx;
> > +};
> > +
> > +void buffertls_set(struct buffertls *, struct bufferevent *, struct tls *,
> > +    int);
> > +void buffertls_accept(struct buffertls *, int);
> > +void buffertls_connect(struct buffertls *, int);
> > +
> > +#endif /* _EVBUFFER_TLS_H_ */
> > Index: ldapd.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/ldapd.c,v
> > retrieving revision 1.19
> > diff -u -p -u -p -r1.19 ldapd.c
> > --- ldapd.c 4 Feb 2016 12:48:06 -0000 1.19
> > +++ ldapd.c 10 Apr 2016 06:15:51 -0000
> > @@ -163,7 +163,7 @@ main(int argc, char *argv[])
> >  
> >   log_verbose(verbose);
> >   stats.started_at = time(0);
> > - ssl_init();
> > + tls_init();
> >  
> >   if (parse_config(conffile) != 0)
> >   exit(2);
> > Index: ldapd.h
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/ldapd.h,v
> > retrieving revision 1.25
> > diff -u -p -u -p -r1.25 ldapd.h
> > --- ldapd.h 2 Nov 2015 06:32:51 -0000 1.25
> > +++ ldapd.h 10 Apr 2016 06:15:51 -0000
> > @@ -30,11 +30,13 @@
> >  #include <limits.h>
> >  #include <pwd.h>
> >  #include <stdarg.h>
> > +#include <tls.h>
> >  
> >  #include "aldap.h"
> >  #include "schema.h"
> >  #include "btree.h"
> >  #include "imsgev.h"
> > +#include "evbuffer_tls.h"
> >  
> >  #define CONFFILE "/etc/ldapd.conf"
> >  #define LDAPD_USER "_ldapd"
> > @@ -203,7 +205,7 @@ struct listener {
> >   struct event evt;
> >   char ssl_cert_name[PATH_MAX];
> >   struct ssl *ssl;
> > - void *ssl_ctx;
> > + struct tls *tls;
> >   TAILQ_ENTRY(listener) entry;
> >  };
> >  TAILQ_HEAD(listenerlist, listener);
> > @@ -223,12 +225,8 @@ struct conn {
> >   struct listener *listener; /* where it connected from */
> >  
> >   /* SSL support */
> > - struct event s_ev;
> > - struct timeval s_tv;
> > - struct listener *s_l;
> > - void *s_ssl;
> > - unsigned char *s_buf;
> > - int s_buflen;
> > + struct tls *tls;
> > + struct buffertls buftls;
> >   unsigned int s_flags;
> >  };
> >  TAILQ_HEAD(conn_list, conn) conn_list;
> > @@ -236,11 +234,12 @@ TAILQ_HEAD(conn_list, conn) conn_list;
> >  struct ssl {
> >   SPLAY_ENTRY(ssl) ssl_nodes;
> >   char ssl_name[PATH_MAX];
> > - char *ssl_cert;
> > - off_t ssl_cert_len;
> > - char *ssl_key;
> > - off_t ssl_key_len;
> > + uint8_t *ssl_cert;
> > + size_t ssl_cert_len;
> > + uint8_t *ssl_key;
> > + size_t ssl_key_len;
> >   uint8_t flags;
> > + struct tls_config *config;
> >  };
> >  
> >  struct ldapd_config
> > @@ -461,6 +460,9 @@ int authorized(struct conn *conn, str
> >  /* parse.y */
> >  int parse_config(char *filename);
> >  int cmdline_symset(char *s);
> > +int ssl_cmp(struct ssl *, struct ssl *);
> > +SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > +
> >  
> >  /* log.c */
> >  void log_init(int);
> > @@ -498,21 +500,6 @@ int unindex_entry(struct namespace *n
> >   struct ber_element *elm);
> >  int index_to_dn(struct namespace *ns, struct btval *indx,
> >   struct btval *dn);
> > -
> > -/* ssl.c */
> > -void ssl_init(void);
> > -void ssl_transaction(struct conn *);
> > -
> > -void ssl_session_init(struct conn *);
> > -void ssl_session_destroy(struct conn *);
> > -int ssl_load_certfile(struct ldapd_config *, const char *, u_int8_t);
> > -void ssl_setup(struct ldapd_config *, struct listener *);
> > -int ssl_cmp(struct ssl *, struct ssl *);
> > -SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > -
> > -/* ssl_privsep.c */
> > -int ssl_ctx_use_private_key(void *, char *, off_t);
> > -int ssl_ctx_use_certificate_chain(void *, char *, off_t);
> >  
> >  /* validate.c */
> >  int validate_entry(const char *dn, struct ber_element *entry, int relax);
> > Index: ldape.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/ldape.c,v
> > retrieving revision 1.23
> > diff -u -p -u -p -r1.23 ldape.c
> > --- ldape.c 24 Dec 2015 17:47:57 -0000 1.23
> > +++ ldape.c 10 Apr 2016 06:15:51 -0000
> > @@ -341,6 +341,7 @@ ldape(struct passwd *pw, char *csockpath
> >   struct event ev_sigterm;
> >   struct event ev_sigchld;
> >   struct event ev_sighup;
> > + struct ssl key;
> >   char host[128];
> >   mode_t old_umask = 0;
> >  
> > @@ -424,7 +425,24 @@ ldape(struct passwd *pw, char *csockpath
> >   event_add(&l->ev, NULL);
> >   evtimer_set(&l->evt, conn_accept, l);
> >  
> > - ssl_setup(conf, l);
> > + if (l->flags & F_SSL) {
> > + if (strlcpy(key.ssl_name, l->ssl_cert_name,
> > +    sizeof(key.ssl_name)) >= sizeof(key.ssl_name))
> > + fatal("ldape: certificate name truncated");
> > +
> > + l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key);
> > + if (l->ssl == NULL)
> > + fatal("ldape: certificate tree corrupted");
> > +
> > + l->tls = tls_server();
> > + if (l->tls == NULL)
> > + fatal("ldape: couldn't allocate tls context");
> > +
> > + if (tls_configure(l->tls, l->ssl->config)) {
> > + log_warn("ldape: %s", tls_error(l->tls));
> > + fatal("ldape: couldn't configure tls");
> > + }
> > + }
> >   }
> >  
> >   TAILQ_FOREACH(ns, &conf->namespaces, next) {
> > Index: parse.y
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/parse.y,v
> > retrieving revision 1.16
> > diff -u -p -u -p -r1.16 parse.y
> > --- parse.y 20 Nov 2014 05:51:20 -0000 1.16
> > +++ parse.y 10 Apr 2016 06:15:51 -0000
> > @@ -77,6 +77,7 @@ int host(const char *, const char *,
> >      struct listenerlist *, int, in_port_t, u_int8_t);
> >  int interface(const char *, const char *,
> >      struct listenerlist *, int, in_port_t, u_int8_t);
> > +int load_certfile(struct ldapd_config *, const char *, u_int8_t);
> >  
> >  TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
> >  struct sym {
> > @@ -91,6 +92,8 @@ char *symget(const char *);
> >  
> >  struct ldapd_config *conf;
> >  
> > +SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > +
> >  static struct aci *mk_aci(int type, int rights, enum scope scope,
> >   char *target, char *subject);
> >  
> > @@ -181,7 +184,7 @@ conf_main : LISTEN ON STRING port ssl ce
> >   cert = ($6 != NULL) ? $6 : $3;
> >  
> >   if (($5 == F_STARTTLS || $5 == F_LDAPS) &&
> > -    ssl_load_certfile(conf, cert, F_SCERT) < 0) {
> > +    load_certfile(conf, cert, F_SCERT) < 0) {
> >   yyerror("cannot load certificate: %s", cert);
> >   free($6);
> >   free($3);
> > @@ -1167,3 +1170,84 @@ namespace_new(const char *suffix)
> >   return ns;
> >  }
> >  
> > +int
> > +ssl_cmp(struct ssl *s1, struct ssl *s2)
> > +{
> > + return (strcmp(s1->ssl_name, s2->ssl_name));
> > +}
> > +
> > +int
> > +load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
> > +{
> > + struct ssl *s;
> > + struct ssl key;
> > + char certfile[PATH_MAX];
> > +
> > + if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> > +    >= sizeof(key.ssl_name)) {
> > + log_warn("load_certfile: certificate name truncated");
> > + return -1;
> > + }
> > +
> > + s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> > + if (s != NULL) {
> > + s->flags |= flags;
> > + return 0;
> > + }
> > +
> > + if ((s = calloc(1, sizeof(*s))) == NULL)
> > + fatal(NULL);
> > +
> > + s->flags = flags;
> > + (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> > +
> > + s->config = tls_config_new();
> > + if (s->config == NULL)
> > + goto err;
> > +
> > + tls_config_set_protocols(s->config, TLS_PROTOCOLS_ALL);
> > + if (tls_config_set_ciphers(s->config, "compat"))
> > + goto err;
> > +
> > + if ((name[0] == '/' &&
> > +     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> > +    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
> > + name)) {
> > + log_warn("load_certfile: path truncated");
> > + goto err;
> > + }
> > +
> > + log_debug("loading certificate file %s", certfile);
> > + s->ssl_cert = tls_load_file(certfile, &s->ssl_cert_len, NULL);
> > + if (s->ssl_cert == NULL)
> > + goto err;
> > +
> > + if (tls_config_set_cert_mem(s->config, s->ssl_cert, s->ssl_cert_len))
> > + goto err;
> > +
> > + if ((name[0] == '/' &&
> > +     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> > +    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
> > + name)) {
> > + log_warn("load_certfile: path truncated");
> > + goto err;
> > + }
> > +
> > + log_debug("loading key file %s", certfile);
> > + s->ssl_key = tls_load_file(certfile, &s->ssl_key_len, NULL);
> > + if (s->ssl_key == NULL)
> > + goto err;
> > +
> > + if (tls_config_set_key_mem(s->config, s->ssl_key, s->ssl_key_len))
> > + goto err;
> > +
> > + SPLAY_INSERT(ssltree, env->sc_ssl, s);
> > +
> > + return (0);
> > +err:
> > + free(s->ssl_cert);
> > + free(s->ssl_key);
> > + tls_config_free(s->config);
> > + free(s);
> > + return (-1);
> > +}
> > Index: ssl.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/ssl.c,v
> > retrieving revision 1.10
> > diff -u -p -u -p -r1.10 ssl.c
> > --- ssl.c 30 Dec 2015 15:59:55 -0000 1.10
> > +++ ssl.c 10 Apr 2016 06:15:51 -0000
> > @@ -1,565 +0,0 @@
> > -/* $OpenBSD: ssl.c,v 1.10 2015/12/30 15:59:55 benno Exp $ */
> > -
> > -/*
> > - * Copyright (c) 2008 Pierre-Yves Ritschard <[hidden email]>
> > - * Copyright (c) 2008 Reyk Floeter <[hidden email]>
> > - *
> > - * Permission to use, copy, modify, and distribute this software for any
> > - * purpose with or without fee is hereby granted, provided that the above
> > - * copyright notice and this permission notice appear in all copies.
> > - *
> > - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> > - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > - */
> > -
> > -#include <sys/types.h>
> > -#include <sys/queue.h>
> > -#include <sys/tree.h>
> > -#include <sys/socket.h>
> > -#include <sys/stat.h>
> > -#include <sys/time.h>
> > -
> > -#include <ctype.h>
> > -#include <event.h>
> > -#include <fcntl.h>
> > -#include <pwd.h>
> > -#include <stdio.h>
> > -#include <stdlib.h>
> > -#include <string.h>
> > -#include <unistd.h>
> > -
> > -#include <openssl/ssl.h>
> > -#include <openssl/engine.h>
> > -#include <openssl/err.h>
> > -#include <openssl/dh.h>
> > -#include <openssl/bn.h>
> > -
> > -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
> > -
> > -#include "ldapd.h"
> > -
> > -#define SSL_CIPHERS "HIGH:!aNULL"
> > -
> > -void ssl_error(const char *);
> > -char *ssl_load_file(const char *, off_t *);
> > -SSL_CTX *ssl_ctx_create(void);
> > -void ssl_session_accept(int, short, void *);
> > -void ssl_read(int, short, void *);
> > -void ssl_write(int, short, void *);
> > -int ssl_bufferevent_add(struct event *, int);
> > -
> > -DH *get_dh1024(void);
> > -void ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *);
> > -
> > -extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
> > -    size_t, void *);
> > -
> > -void
> > -ssl_read(int fd, short event, void *p)
> > -{
> > - struct bufferevent *bufev = p;
> > - struct conn *s = bufev->cbarg;
> > - int ret;
> > - int ssl_err;
> > - short what;
> > - size_t len;
> > - char rbuf[IBUF_READ_SIZE];
> > - int howmuch = IBUF_READ_SIZE;
> > -
> > - what = EVBUFFER_READ;
> > -
> > - if (event == EV_TIMEOUT) {
> > - what |= EVBUFFER_TIMEOUT;
> > - goto err;
> > - }
> > -
> > - if (bufev->wm_read.high != 0)
> > - howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
> > -
> > - ret = SSL_read(s->s_ssl, rbuf, howmuch);
> > - if (ret <= 0) {
> > - ssl_err = SSL_get_error(s->s_ssl, ret);
> > -
> > - switch (ssl_err) {
> > - case SSL_ERROR_WANT_READ:
> > - goto retry;
> > - case SSL_ERROR_WANT_WRITE:
> > - goto retry;
> > - default:
> > - if (ret == 0)
> > - what |= EVBUFFER_EOF;
> > - else {
> > - ssl_error("ssl_read");
> > - what |= EVBUFFER_ERROR;
> > - }
> > - goto err;
> > - }
> > - }
> > -
> > - if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
> > - what |= EVBUFFER_ERROR;
> > - goto err;
> > - }
> > -
> > - ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > -
> > - len = EVBUFFER_LENGTH(bufev->input);
> > - if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> > - return;
> > - if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
> > - struct evbuffer *buf = bufev->input;
> > - event_del(&bufev->ev_read);
> > - evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> > - return;
> > - }
> > -
> > - if (bufev->readcb != NULL)
> > - (*bufev->readcb)(bufev, bufev->cbarg);
> > - return;
> > -
> > -retry:
> > - ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > - return;
> > -
> > -err:
> > - (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > -}
> > -
> > -
> > -void
> > -ssl_write(int fd, short event, void *p)
> > -{
> > - struct bufferevent *bufev = p;
> > - struct conn *s = bufev->cbarg;
> > - int ret;
> > - int ssl_err;
> > - short what;
> > -
> > - what = EVBUFFER_WRITE;
> > -
> > - if (event == EV_TIMEOUT) {
> > - what |= EV_TIMEOUT;
> > - goto err;
> > - }
> > -
> > - if (EVBUFFER_LENGTH(bufev->output)) {
> > - if (s->s_buf == NULL) {
> > - s->s_buflen = EVBUFFER_LENGTH(bufev->output);
> > - if ((s->s_buf = malloc(s->s_buflen)) == NULL) {
> > - what |= EVBUFFER_ERROR;
> > - goto err;
> > - }
> > - memcpy(s->s_buf, EVBUFFER_DATA(bufev->output),
> > -    s->s_buflen);
> > - }
> > -
> > - ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen);
> > - if (ret <= 0) {
> > - ssl_err = SSL_get_error(s->s_ssl, ret);
> > -
> > - switch (ssl_err) {
> > - case SSL_ERROR_WANT_READ:
> > - goto retry;
> > - case SSL_ERROR_WANT_WRITE:
> > - goto retry;
> > - default:
> > - if (ret == 0)
> > - what |= EVBUFFER_EOF;
> > - else {
> > - ssl_error("ssl_write");
> > - what |= EVBUFFER_ERROR;
> > - }
> > - goto err;
> > - }
> > - }
> > - evbuffer_drain(bufev->output, ret);
> > - }
> > - if (s->s_buf != NULL) {
> > - free(s->s_buf);
> > - s->s_buf = NULL;
> > - s->s_buflen = 0;
> > - }
> > - if (EVBUFFER_LENGTH(bufev->output) != 0)
> > - ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > -
> > - if (bufev->writecb != NULL &&
> > -    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> > - (*bufev->writecb)(bufev, bufev->cbarg);
> > - return;
> > -
> > -retry:
> > - if (s->s_buflen != 0)
> > - ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > - return;
> > -
> > -err:
> > - if (s->s_buf != NULL) {
> > - free(s->s_buf);
> > - s->s_buf = NULL;
> > - s->s_buflen = 0;
> > - }
> > - (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > -}
> > -
> > -int
> > -ssl_bufferevent_add(struct event *ev, int timeout)
> > -{
> > - struct timeval tv;
> > - struct timeval *ptv = NULL;
> > -
> > - if (timeout) {
> > - timerclear(&tv);
> > - tv.tv_sec = timeout;
> > - ptv = &tv;
> > - }
> > -
> > - return (event_add(ev, ptv));
> > -}
> > -
> > -int
> > -ssl_cmp(struct ssl *s1, struct ssl *s2)
> > -{
> > - return (strcmp(s1->ssl_name, s2->ssl_name));
> > -}
> > -
> > -SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > -
> > -char *
> > -ssl_load_file(const char *name, off_t *len)
> > -{
> > - struct stat st;
> > - off_t size;
> > - char *buf = NULL;
> > - int fd;
> > -
> > - if ((fd = open(name, O_RDONLY)) == -1)
> > - return (NULL);
> > - if (fstat(fd, &st) != 0)
> > - goto fail;
> > - size = st.st_size;
> > - if ((buf = calloc(1, size + 1)) == NULL)
> > - goto fail;
> > - if (read(fd, buf, size) != size)
> > - goto fail;
> > - close(fd);
> > -
> > - *len = size + 1;
> > - return (buf);
> > -
> > -fail:
> > - free(buf);
> > - close(fd);
> > - return (NULL);
> > -}
> > -
> > -SSL_CTX *
> > -ssl_ctx_create(void)
> > -{
> > - SSL_CTX *ctx;
> > -
> > - ctx = SSL_CTX_new(SSLv23_method());
> > - if (ctx == NULL) {
> > - ssl_error("ssl_ctx_create");
> > - fatal("ssl_ctx_create: could not create SSL context");
> > - }
> > -
> > - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
> > - SSL_CTX_set_timeout(ctx, LDAPD_SESSION_TIMEOUT);
> > - SSL_CTX_set_options(ctx, SSL_OP_ALL);
> > - SSL_CTX_set_options(ctx,
> > -    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
> > -
> > - if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
> > - ssl_error("ssl_ctx_create");
> > - fatal("ssl_ctx_create: could not set cipher list");
> > - }
> > - return (ctx);
> > -}
> > -
> > -int
> > -ssl_load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags)
> > -{
> > - struct ssl *s;
> > - struct ssl key;
> > - char certfile[PATH_MAX];
> > -
> > - if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> > -    >= sizeof(key.ssl_name)) {
> > - log_warn("ssl_load_certfile: certificate name truncated");
> > - return -1;
> > - }
> > -
> > - s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> > - if (s != NULL) {
> > - s->flags |= flags;
> > - return 0;
> > - }
> > -
> > - if ((s = calloc(1, sizeof(*s))) == NULL)
> > - fatal(NULL);
> > -
> > - s->flags = flags;
> > - (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> > -
> > - if ((name[0] == '/' &&
> > -     !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> > -    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt",
> > - name)) {
> > - log_warn("ssl_load_certfile: path truncated");
> > - free(s);
> > - return -1;
> > - }
> > -
> > - log_debug("loading certificate file %s", certfile);
> > - if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) {
> > - free(s);
> > - return (-1);
> > - }
> > -
> > - if ((name[0] == '/' &&
> > -     !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> > -    !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key",
> > - name)) {
> > - log_warn("ssl_load_certfile: path truncated");
> > - free(s->ssl_cert);
> > - free(s);
> > - return -1;
> > - }
> > -
> > - log_debug("loading key file %s", certfile);
> > - if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) {
> > - free(s->ssl_cert);
> > - free(s);
> > - return (-1);
> > - }
> > -
> > - SPLAY_INSERT(ssltree, env->sc_ssl, s);
> > -
> > - return (0);
> > -}
> > -
> > -void
> > -ssl_init(void)
> > -{
> > - SSL_library_init();
> > - SSL_load_error_strings();
> > -
> > - OpenSSL_add_all_algorithms();
> > -
> > - /* Init hardware crypto engines. */
> > - ENGINE_load_builtin_engines();
> > - ENGINE_register_all_complete();
> > -}
> > -
> > -void
> > -ssl_setup(struct ldapd_config *env, struct listener *l)
> > -{
> > - struct ssl key;
> > -
> > - if (!(l->flags & F_SSL))
> > - return;
> > -
> > - if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name))
> > -    >= sizeof(key.ssl_name))
> > - fatal("ssl_setup: certificate name truncated");
> > -
> > - if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL)
> > - fatal("ssl_setup: certificate tree corrupted");
> > -
> > - l->ssl_ctx = ssl_ctx_create();
> > -
> > - if (!ssl_ctx_use_certificate_chain(l->ssl_ctx,
> > -    l->ssl->ssl_cert, l->ssl->ssl_cert_len))
> > - goto err;
> > - if (!ssl_ctx_use_private_key(l->ssl_ctx,
> > -    l->ssl->ssl_key, l->ssl->ssl_key_len))
> > - goto err;
> > -
> > - if (!SSL_CTX_check_private_key(l->ssl_ctx))
> > - goto err;
> > - if (!SSL_CTX_set_session_id_context(l->ssl_ctx,
> > - (const unsigned char *)l->ssl_cert_name, strlen(l->ssl_cert_name) + 1))
> > - goto err;
> > -
> > - ssl_set_ephemeral_key_exchange(l->ssl_ctx, get_dh1024());
> > -
> > - log_debug("ssl_setup: ssl setup finished for listener: %p", l);
> > - return;
> > -
> > -err:
> > - SSL_CTX_free(l->ssl_ctx);
> > - ssl_error("ssl_setup");
> > - fatal("ssl_setup: cannot set SSL up");
> > -}
> > -
> > -void
> > -ssl_error(const char *where)
> > -{
> > - unsigned long code;
> > - char errbuf[128];
> > - extern int debug;
> > -
> > - if (!debug)
> > - return;
> > - for (; (code = ERR_get_error()) != 0 ;) {
> > - ERR_error_string_n(code, errbuf, sizeof(errbuf));
> > - log_debug("SSL library error: %s: %s", where, errbuf);
> > - }
> > -}
> > -
> > -void
> > -ssl_session_accept(int fd, short event, void *p)
> > -{
> > - struct conn *s = p;
> > - int ret;
> > - int ssl_err;
> > -
> > - if (event == EV_TIMEOUT) {
> > - log_debug("ssl_session_accept: session timed out");
> > - conn_close(s);
> > - return;
> > - }
> > -
> > - log_debug("ssl_session_accept: accepting client");
> > - ret = SSL_accept(s->s_ssl);
> > - if (ret <= 0) {
> > - ssl_err = SSL_get_error(s->s_ssl, ret);
> > -
> > - switch (ssl_err) {
> > - case SSL_ERROR_WANT_READ:
> > - goto retry;
> > - case SSL_ERROR_WANT_WRITE:
> > - goto retry;
> > - case SSL_ERROR_ZERO_RETURN:
> > - case SSL_ERROR_SYSCALL:
> > - if (ret == 0) {
> > - conn_close(s);
> > - return;
> > - }
> > - /* FALLTHROUGH */
> > - default:
> > - ssl_error("ssl_session_accept");
> > - conn_close(s);
> > - return;
> > - }
> > - }
> > -
> > - log_debug("ssl_session_accept: accepted ssl client");
> > - s->s_flags |= F_SECURE;
> > -
> > - s->bev = bufferevent_new(s->fd, conn_read, conn_write, conn_err, s);
> > - if (s->bev == NULL) {
> > -                log_warn("ssl_session_accept: bufferevent_new");
> > -                conn_close(s);
> > -                return;
> > - }
> > - bufferevent_settimeout(s->bev, 0, 60);
> > -
> > - event_set(&s->bev->ev_read, s->fd, EV_READ, ssl_read, s->bev);
> > - event_set(&s->bev->ev_write, s->fd, EV_WRITE, ssl_write, s->bev);
> > - bufferevent_enable(s->bev, EV_READ);
> > -
> > - return;
> > -retry:
> > - event_add(&s->s_ev, &s->s_tv);
> > -}
> > -
> > -void
> > -ssl_session_init(struct conn *s)
> > -{
> > - struct listener *l;
> > - SSL             *ssl;
> > -
> > - l = s->s_l;
> > -
> > - if (!(l->flags & F_SSL))
> > - return;
> > -
> > - log_debug("ssl_session_init: switching to SSL");
> > - ssl = SSL_new(l->ssl_ctx);
> > - if (ssl == NULL)
> > - goto err;
> > -
> > - if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
> > - goto err;
> > - if (!SSL_set_fd(ssl, s->fd))
> > - goto err;
> > - SSL_set_accept_state(ssl);
> > -
> > - s->s_ssl = ssl;
> > -
> > - s->s_tv.tv_sec = LDAPD_SESSION_TIMEOUT;
> > - s->s_tv.tv_usec = 0;
> > - event_set(&s->s_ev, s->fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s);
> > - event_add(&s->s_ev, &s->s_tv);
> > - return;
> > -
> > - err:
> > - SSL_free(ssl);
> > - ssl_error("ssl_session_init");
> > -}
> > -
> > -void
> > -ssl_session_destroy(struct conn *s)
> > -{
> > - SSL_free(s->s_ssl);
> > -}
> > -
> > -/* From OpenSSL's documentation:
> > - *
> > - * If "strong" primes were used to generate the DH parameters, it is
> > - * not strictly necessary to generate a new key for each handshake
> > - * but it does improve forward secrecy.
> > - *
> > - * -- gilles@
> > - */
> > -DH *
> > -get_dh1024(void)
> > -{
> > - DH *dh;
> > - unsigned char dh1024_p[] = {
> > - 0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75,
> > - 0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51,
> > - 0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E,
> > - 0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D,
> > - 0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89,
> > - 0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC,
> > - 0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02,
> > - 0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93,
> > - 0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D,
> > - 0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65,
> > - 0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6,
> > - 0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1,
> > - 0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9,
> > - 0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59,
> > - 0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7,
> > - 0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B
> > - };
> > - unsigned char dh1024_g[] = {
> > - 0x02
> > - };
> > -
> > - if ((dh = DH_new()) == NULL)
> > - return NULL;
> > -
> > - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
> > - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
> > - if (dh->p == NULL || dh->g == NULL) {
> > - DH_free(dh);
> > - return NULL;
> > - }
> > -
> > - return dh;
> > -}
> > -
> > -void
> > -ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh)
> > -{
> > - if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh))
> > - fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh");
> > -}
> > Index: ssl_privsep.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/ldapd/ssl_privsep.c,v
> > retrieving revision 1.4
> > diff -u -p -u -p -r1.4 ssl_privsep.c
> > --- ssl_privsep.c 28 Jan 2015 15:50:30 -0000 1.4
> > +++ ssl_privsep.c 10 Apr 2016 06:15:51 -0000
> > @@ -1,172 +0,0 @@
> > -/*      $OpenBSD: ssl_privsep.c,v 1.4 2015/01/28 15:50:30 reyk Exp $    */
> > -
> > -/* Copyright (C) 1995-1998 Eric Young ([hidden email])
> > - * All rights reserved.
> > - *
> > - * This package is an SSL implementation written
> > - * by Eric Young ([hidden email]).
> > - * The implementation was written so as to conform with Netscapes SSL.
> > - *
> > - * This library is free for commercial and non-commercial use as long as
> > - * the following conditions are aheared to.  The following conditions
> > - * apply to all code found in this distribution, be it the RC4, RSA,
> > - * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
> > - * included with this distribution is covered by the same copyright terms
> > - * except that the holder is Tim Hudson ([hidden email]).
> > - *
> > - * Copyright remains Eric Young's, and as such any Copyright notices in
> > - * the code are not to be removed.
> > - * If this package is used in a product, Eric Young should be given attribution
> > - * as the author of the parts of the library used.
> > - * This can be in the form of a textual message at program startup or
> > - * in documentation (online or textual) provided with the package.
> > - *
> > - * Redistribution and use in source and binary forms, with or without
> > - * modification, are permitted provided that the following conditions
> > - * are met:
> > - * 1. Redistributions of source code must retain the copyright
> > - *    notice, this list of conditions and the following disclaimer.
> > - * 2. Redistributions in binary form must reproduce the above copyright
> > - *    notice, this list of conditions and the following disclaimer in the
> > - *    documentation and/or other materials provided with the distribution.
> > - * 3. All advertising materials mentioning features or use of this software
> > - *    must display the following acknowledgement:
> > - *    "This product includes cryptographic software written by
> > - *     Eric Young ([hidden email])"
> > - *    The word 'cryptographic' can be left out if the rouines from the library
> > - *    being used are not cryptographic related :-).
> > - * 4. If you include any Windows specific code (or a derivative thereof) from
> > - *    the apps directory (application code) you must include an acknowledgement:
> > - *    "This product includes software written by Tim Hudson ([hidden email])"
> > - *
> > - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
> > - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> > - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> > - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> > - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> > - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> > - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> > - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> > - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> > - * SUCH DAMAGE.
> > - *
> > - * The licence and distribution terms for any publically available version or
> > - * derivative of this code cannot be changed.  i.e. this code cannot simply be
> > - * copied and put under another distribution licence
> > - * [including the GNU Public Licence.]
> > - */
> > -
> > -/*
> > - * SSL operations needed when running in a privilege separated environment.
> > - * 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>
> > -
> > -#include <openssl/err.h>
> > -#include <openssl/bio.h>
> > -#include <openssl/objects.h>
> > -#include <openssl/evp.h>
> > -#include <openssl/x509.h>
> > -#include <openssl/pem.h>
> > -#include <openssl/ssl.h>
> > -
> > -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_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
> > -{
> > - int ret;
> > - BIO *in;
> > - EVP_PKEY *pkey;
> > -
> > - ret = 0;
> > -
> > - if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> > - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
> > - return 0;
> > - }
> > -
> > - pkey = PEM_read_bio_PrivateKey(in, NULL,
> > -    ctx->default_passwd_callback,
> > -    ctx->default_passwd_callback_userdata);
> > -
> > - if (pkey == NULL) {
> > - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
> > - goto end;
> > - }
> > - ret = SSL_CTX_use_PrivateKey(ctx, pkey);
> > - EVP_PKEY_free(pkey);
> > -end:
> > - if (in != NULL)
> > - BIO_free(in);
> > - return ret;
> > -}
> > -
> > -int
> > -ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
> > -{
> > - int ret;
> > - BIO *in;
> > - X509 *x;
> > - X509 *ca;
> > - unsigned long err;
> > -
> > - ret = 0;
> > - x = ca = NULL;
> > -
> > - if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> > - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
> > - goto end;
> > - }
> > -
> > - if ((x = PEM_read_bio_X509(in, NULL,
> > -    ctx->default_passwd_callback,
> > -    ctx->default_passwd_callback_userdata)) == NULL) {
> > - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
> > - goto end;
> > - }
> > -
> > - if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
> > - goto end;
> > -
> > - /* If we could set up our certificate, now proceed to
> > - * the CA certificates.
> > - */
> > -
> > - if (ctx->extra_certs != NULL) {
> > - sk_X509_pop_free(ctx->extra_certs, X509_free);
> > - ctx->extra_certs = NULL;
> > - }
> > -
> > - while ((ca = PEM_read_bio_X509(in, NULL,
> > -    ctx->default_passwd_callback,
> > -    ctx->default_passwd_callback_userdata)) != NULL) {
> > -
> > - if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
> > - goto end;
> > - }
> > -
> > - err = ERR_peek_last_error();
> > - if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
> > -    ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
> > - ERR_clear_error();
> > - else
> > - goto end;
> > -
> > - ret = 1;
> > -end:
> > - if (ca != NULL)
> > - X509_free(ca);
> > - if (x != NULL)
> > - X509_free(x);
> > - if (in != NULL)
> > - BIO_free(in);
> > - return (ret);
> > -}
>

--

Reply | Threaded
Open this post in threaded view
|

Re: use libtls in ldapd

Bob Beck-2
just go for it.  see who screams

ok beck@

On Sunday, 24 April 2016, Sebastian Benoit <[hidden email]> wrote:

> Jonathan Matthew([hidden email] <javascript:;>) on 2016.04.18 07:17:55
> +1000:
> > On Sun, Apr 10, 2016 at 04:36:15PM +1000, Jonathan Matthew wrote:
> > > A while back (s2k15?), reyk@ suggested I take a look at converting
> ldapd to use
> > > libtls rather than the openssl api.  Today I finally got around to it,
> > > resulting in the diff below.  Most of the diff just removes ssl.c and
> > > ssl_privsep.c, and replaces some of it with evbuffer_tls.c (copied from
> > > syslogd, unmodified).  A reasonable amount of code just went away
> because
> > > libtls is sensible.  The few remaining bits of ssl.c moved to wherever
> seemed
> > > most suitable.
> > >
> > > I've tested a few things with the openldap clients, which apparently
> only do
> > > starttls, and otherwise checked that it negotiates ssl successfully.
> > >
> > > ok?
> >
> > ldapd is too boring?
>
> :)
>
> ok from me, but i cant test it.
>
> >
> > >
> > >
> > > Index: Makefile
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
> > > retrieving revision 1.12
> > > diff -u -p -u -p -r1.12 Makefile
> > > --- Makefile        16 Jul 2014 20:07:03 -0000      1.12
> > > +++ Makefile        10 Apr 2016 06:15:50 -0000
> > > @@ -5,11 +5,11 @@ MAN=              ldapd.8 ldapd.conf.5
> > >  SRCS=              ber.c log.c control.c \
> > >             util.c ldapd.c ldape.c conn.c attributes.c namespace.c \
> > >             btree.c filter.c search.c parse.y \
> > > -           auth.c modify.c index.c ssl.c ssl_privsep.c \
> > > +           auth.c modify.c index.c evbuffer_tls.c \
> > >             validate.c uuid.c schema.c imsgev.c syntax.c matching.c
> > >
> > > -LDADD=             -levent -lssl -lcrypto -lz -lutil
> > > -DPADD=             ${LIBEVENT} ${LIBCRYPTO} ${LIBSSL} ${LIBZ}
> ${LIBUTIL}
> > > +LDADD=             -ltls -levent -lz -lutil
> > > +DPADD=             ${LIBEVENT} ${LIBTLS} ${LIBCRYPTO} ${LIBSSL}
> ${LIBZ} ${LIBUTIL}
> > >  CFLAGS+=   -I${.CURDIR} -g
> > >  CFLAGS+=   -Wall -Wstrict-prototypes -Wmissing-prototypes
> > >  CFLAGS+=   -Wmissing-declarations
> > > Index: btree.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/btree.c,v
> > > retrieving revision 1.36
> > > diff -u -p -u -p -r1.36 btree.c
> > > --- btree.c 20 Mar 2016 00:01:22 -0000      1.36
> > > +++ btree.c 10 Apr 2016 06:15:51 -0000
> > > @@ -34,6 +34,8 @@
> > >  #include <time.h>
> > >  #include <unistd.h>
> > >
> > > +#include <openssl/sha.h>
> > > +
> > >  #include "btree.h"
> > >
> > >  /* #define DEBUG */
> > > Index: btree.h
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/btree.h,v
> > > retrieving revision 1.6
> > > diff -u -p -u -p -r1.6 btree.h
> > > --- btree.h 2 Jul 2010 01:43:00 -0000       1.6
> > > +++ btree.h 10 Apr 2016 06:15:51 -0000
> > > @@ -19,8 +19,6 @@
> > >  #ifndef _btree_h_
> > >  #define _btree_h_
> > >
> > > -#include <openssl/sha.h>
> > > -
> > >  struct mpage;
> > >  struct cursor;
> > >  struct btree_txn;
> > > Index: conn.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/conn.c,v
> > > retrieving revision 1.12
> > > diff -u -p -u -p -r1.12 conn.c
> > > --- conn.c  2 Nov 2015 06:32:51 -0000       1.12
> > > +++ conn.c  10 Apr 2016 06:15:51 -0000
> > > @@ -26,6 +26,7 @@
> > >  #include "ldapd.h"
> > >
> > >  int                         conn_dispatch(struct conn *conn);
> > > +int                         conn_tls_init(struct conn *);
> > >  unsigned long               ldap_application(struct ber_element *elm);
> > >
> > >  struct conn_list    conn_list;
> > > @@ -61,7 +62,7 @@ conn_close(struct conn *conn)
> > >     /* Cancel any queued requests on this connection. */
> > >     namespace_cancel_conn(conn);
> > >
> > > -   ssl_session_destroy(conn);
> > > +   tls_free(conn->tls);
> > >
> > >     TAILQ_REMOVE(&conn_list, conn, next);
> > >     ber_free(&conn->ber);
> > > @@ -225,9 +226,8 @@ conn_write(struct bufferevent *bev, void
> > >             conn_close(conn);
> > >     else if (conn->s_flags & F_STARTTLS) {
> > >             conn->s_flags &= ~F_STARTTLS;
> > > -           bufferevent_free(conn->bev);
> > > -           conn->bev = NULL;
> > > -           ssl_session_init(conn);
> > > +           if (conn_tls_init(conn) == -1)
> > > +                   conn_close(conn);
> > >     }
> > >  }
> > >
> > > @@ -296,24 +296,22 @@ conn_accept(int fd, short event, void *d
> > >             goto giveup;
> > >     }
> > >     conn->ber.fd = -1;
> > > -   conn->s_l = l;
> > >     ber_set_application(&conn->ber, ldap_application);
> > >     conn->fd = afd;
> > >     conn->listener = l;
> > >
> > > -   if (l->flags & F_LDAPS) {
> > > -           ssl_session_init(conn);
> > > -   } else {
> > > -           conn->bev = bufferevent_new(afd, conn_read, conn_write,
> > > -               conn_err, conn);
> > > -           if (conn->bev == NULL) {
> > > -                   log_warn("conn_accept: bufferevent_new");
> > > -                   free(conn);
> > > -                   goto giveup;
> > > -           }
> > > -           bufferevent_enable(conn->bev, EV_READ);
> > > -           bufferevent_settimeout(conn->bev, 0, 60);
> > > +   conn->bev = bufferevent_new(afd, conn_read, conn_write,
> > > +       conn_err, conn);
> > > +   if (conn->bev == NULL) {
> > > +           log_warn("conn_accept: bufferevent_new");
> > > +           free(conn);
> > > +           goto giveup;
> > >     }
> > > +   bufferevent_enable(conn->bev, EV_READ);
> > > +   bufferevent_settimeout(conn->bev, 0, 60);
> > > +   if (conn->s_flags & F_LDAPS)
> > > +           if (conn_tls_init(conn) == -1)
> > > +                   conn_close(conn);
> > >
> > >     TAILQ_INIT(&conn->searches);
> > >     TAILQ_INSERT_HEAD(&conn_list, conn, next);
> > > @@ -365,4 +363,25 @@ conn_close_any()
> > >     }
> > >
> > >     return -1;
> > > +}
> > > +
> > > +int
> > > +conn_tls_init(struct conn *conn)
> > > +{
> > > +   struct listener *l = conn->listener;
> > > +
> > > +   if (!(l->flags & F_SSL))
> > > +           return 0;
> > > +
> > > +   log_debug("conn_tls_init: switching to TLS");
> > > +
> > > +   if (tls_accept_socket(l->tls, &conn->tls, conn->fd) < 0) {
> > > +           log_debug("tls_accept_socket failed");
> > > +           return -1;
> > > +   }
> > > +
> > > +   conn->s_flags |= F_SECURE;
> > > +   buffertls_set(&conn->buftls, conn->bev, conn->tls, conn->fd);
> > > +   buffertls_accept(&conn->buftls, conn->fd);
> > > +   return 0;
> > >  }
> > > Index: evbuffer_tls.c
> > > ===================================================================
> > > RCS file: evbuffer_tls.c
> > > diff -N evbuffer_tls.c
> > > --- /dev/null       1 Jan 1970 00:00:00 -0000
> > > +++ evbuffer_tls.c  10 Apr 2016 06:15:51 -0000
> > > @@ -0,0 +1,350 @@
> > > +/* $OpenBSD: evbuffer_tls.c,v 1.9 2015/10/09 16:58:25 bluhm Exp $ */
> > > +
> > > +/*
> > > + * Copyright (c) 2002-2004 Niels Provos <[hidden email]>
> > > + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> > > + * All rights reserved.
> > > + *
> > > + * Redistribution and use in source and binary forms, with or without
> > > + * modification, are permitted provided that the following conditions
> > > + * are met:
> > > + * 1. Redistributions of source code must retain the above copyright
> > > + *    notice, this list of conditions and the following disclaimer.
> > > + * 2. Redistributions in binary form must reproduce the above
> copyright
> > > + *    notice, this list of conditions and the following disclaimer in
> the
> > > + *    documentation and/or other materials provided with the
> distribution.
> > > + * 3. The name of the author may not be used to endorse or promote
> products
> > > + *    derived from this software without specific prior written
> permission.
> > > + *
> > > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
> OR
> > > + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> WARRANTIES
> > > + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> DISCLAIMED.
> > > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> > > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> (INCLUDING, BUT
> > > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> > > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> > > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE OF
> > > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > > + */
> > > +
> > > +#include <sys/types.h>
> > > +#include <sys/time.h>
> > > +#include <sys/ioctl.h>
> > > +
> > > +#include <errno.h>
> > > +#include <event.h>
> > > +#include <stdio.h>
> > > +#include <stdlib.h>
> > > +#include <string.h>
> > > +#include <tls.h>
> > > +
> > > +#include "evbuffer_tls.h"
> > > +
> > > +/* prototypes */
> > > +
> > > +void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t,
> void *);
> > > +static void buffertls_readcb(int, short, void *);
> > > +static void buffertls_writecb(int, short, void *);
> > > +static void buffertls_handshakecb(int, short, void *);
> > > +int evtls_read(struct evbuffer *, int, int, struct tls *);
> > > +int evtls_write(struct evbuffer *, int, struct tls *);
> > > +
> > > +static int
> > > +bufferevent_add(struct event *ev, int timeout)
> > > +{
> > > +   struct timeval tv, *ptv = NULL;
> > > +
> > > +   if (timeout) {
> > > +           timerclear(&tv);
> > > +           tv.tv_sec = timeout;
> > > +           ptv = &tv;
> > > +   }
> > > +
> > > +   return (event_add(ev, ptv));
> > > +}
> > > +
> > > +static void
> > > +buffertls_readcb(int fd, short event, void *arg)
> > > +{
> > > +   struct buffertls *buftls = arg;
> > > +   struct bufferevent *bufev = buftls->bt_bufev;
> > > +   struct tls *ctx = buftls->bt_ctx;
> > > +   int res = 0;
> > > +   short what = EVBUFFER_READ;
> > > +   size_t len;
> > > +   int howmuch = -1;
> > > +
> > > +   if (event == EV_TIMEOUT) {
> > > +           what |= EVBUFFER_TIMEOUT;
> > > +           goto error;
> > > +   }
> > > +
> > > +   /*
> > > +    * If we have a high watermark configured then we don't want to
> > > +    * read more data than would make us reach the watermark.
> > > +    */
> > > +   if (bufev->wm_read.high != 0) {
> > > +           howmuch = bufev->wm_read.high -
> EVBUFFER_LENGTH(bufev->input);
> > > +           /* we might have lowered the watermark, stop reading */
> > > +           if (howmuch <= 0) {
> > > +                   struct evbuffer *buf = bufev->input;
> > > +                   event_del(&bufev->ev_read);
> > > +                   evbuffer_setcb(buf,
> > > +                       bufferevent_read_pressure_cb, bufev);
> > > +                   return;
> > > +           }
> > > +   }
> > > +
> > > +   res = evtls_read(bufev->input, fd, howmuch, ctx);
> > > +   switch (res) {
> > > +   case TLS_WANT_POLLIN:
> > > +           bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +           return;
> > > +   case TLS_WANT_POLLOUT:
> > > +           event_del(&bufev->ev_write);
> > > +           event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb,
> > > +               buftls);
> > > +           bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +           return;
> > > +   case -1:
> > > +           what |= EVBUFFER_ERROR;
> > > +           break;
> > > +   case 0:
> > > +           what |= EVBUFFER_EOF;
> > > +           break;
> > > +   }
> > > +   if (res <= 0)
> > > +           goto error;
> > > +
> > > +   event_del(&bufev->ev_write);
> > > +   event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb,
> buftls);
> > > +   if (bufev->enabled & EV_READ)
> > > +           bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +   if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled &
> EV_WRITE)
> > > +           bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +
> > > +   /* See if this callbacks meets the water marks */
> > > +   len = EVBUFFER_LENGTH(bufev->input);
> > > +   if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> > > +           return;
> > > +   if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
> > > +           struct evbuffer *buf = bufev->input;
> > > +           event_del(&bufev->ev_read);
> > > +
> > > +           /* Now schedule a callback for us when the buffer changes
> */
> > > +           evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> > > +   }
> > > +
> > > +   /* Invoke the user callback - must always be called last */
> > > +   if (bufev->readcb != NULL)
> > > +           (*bufev->readcb)(bufev, bufev->cbarg);
> > > +   return;
> > > +
> > > + error:
> > > +   (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > > +}
> > > +
> > > +static void
> > > +buffertls_writecb(int fd, short event, void *arg)
> > > +{
> > > +   struct buffertls *buftls = arg;
> > > +   struct bufferevent *bufev = buftls->bt_bufev;
> > > +   struct tls *ctx = buftls->bt_ctx;
> > > +   int res = 0;
> > > +   short what = EVBUFFER_WRITE;
> > > +
> > > +   if (event == EV_TIMEOUT) {
> > > +           what |= EVBUFFER_TIMEOUT;
> > > +           goto error;
> > > +   }
> > > +
> > > +   if (EVBUFFER_LENGTH(bufev->output) != 0) {
> > > +           res = evtls_write(bufev->output, fd, ctx);
> > > +           switch (res) {
> > > +           case TLS_WANT_POLLIN:
> > > +                   event_del(&bufev->ev_read);
> > > +                   event_set(&bufev->ev_read, fd, EV_READ,
> > > +                       buffertls_writecb, buftls);
> > > +                   bufferevent_add(&bufev->ev_read,
> bufev->timeout_read);
> > > +                   return;
> > > +           case TLS_WANT_POLLOUT:
> > > +                   bufferevent_add(&bufev->ev_write,
> bufev->timeout_write);
> > > +                   return;
> > > +           case -1:
> > > +                   what |= EVBUFFER_ERROR;
> > > +                   break;
> > > +           case 0:
> > > +                   what |= EVBUFFER_EOF;
> > > +                   break;
> > > +           }
> > > +           if (res <= 0)
> > > +                   goto error;
> > > +   }
> > > +
> > > +   event_del(&bufev->ev_read);
> > > +   event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > > +   if (bufev->enabled & EV_READ)
> > > +           bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +   if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled &
> EV_WRITE)
> > > +           bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +
> > > +   /*
> > > +    * Invoke the user callback if our buffer is drained or below the
> > > +    * low watermark.
> > > +    */
> > > +   if (bufev->writecb != NULL &&
> > > +       EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> > > +           (*bufev->writecb)(bufev, bufev->cbarg);
> > > +
> > > +   return;
> > > +
> > > + error:
> > > +   (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > > +}
> > > +
> > > +static void
> > > +buffertls_handshakecb(int fd, short event, void *arg)
> > > +{
> > > +   struct buffertls *buftls = arg;
> > > +   struct bufferevent *bufev = buftls->bt_bufev;
> > > +   struct tls *ctx = buftls->bt_ctx;
> > > +   int res = 0;
> > > +   short what = EVBUFFER_HANDSHAKE;
> > > +
> > > +   if (event == EV_TIMEOUT) {
> > > +           what |= EVBUFFER_TIMEOUT;
> > > +           goto error;
> > > +   }
> > > +
> > > +   res = tls_handshake(ctx);
> > > +   switch (res) {
> > > +   case TLS_WANT_POLLIN:
> > > +           bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +           return;
> > > +   case TLS_WANT_POLLOUT:
> > > +           bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +           return;
> > > +   case -1:
> > > +           what |= EVBUFFER_ERROR;
> > > +           break;
> > > +   }
> > > +   if (res < 0)
> > > +           goto error;
> > > +
> > > +   /* Handshake was successful, change to read and write callback. */
> > > +   event_del(&bufev->ev_read);
> > > +   event_del(&bufev->ev_write);
> > > +   event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > > +   event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb,
> buftls);
> > > +   if (bufev->enabled & EV_READ)
> > > +           bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +   if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled &
> EV_WRITE)
> > > +           bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +
> > > +   return;
> > > +
> > > + error:
> > > +   (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > > +}
> > > +
> > > +void
> > > +buffertls_set(struct buffertls *buftls, struct bufferevent *bufev,
> > > +    struct tls *ctx, int fd)
> > > +{
> > > +   bufferevent_setfd(bufev, fd);
> > > +   event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls);
> > > +   event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb,
> buftls);
> > > +   buftls->bt_bufev = bufev;
> > > +   buftls->bt_ctx = ctx;
> > > +}
> > > +
> > > +void
> > > +buffertls_accept(struct buffertls *buftls, int fd)
> > > +{
> > > +   struct bufferevent *bufev = buftls->bt_bufev;
> > > +
> > > +   event_del(&bufev->ev_read);
> > > +   event_del(&bufev->ev_write);
> > > +   event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb,
> buftls);
> > > +   event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> > > +       buftls);
> > > +   bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > +}
> > > +
> > > +void
> > > +buffertls_connect(struct buffertls *buftls, int fd)
> > > +{
> > > +   struct bufferevent *bufev = buftls->bt_bufev;
> > > +
> > > +   event_del(&bufev->ev_read);
> > > +   event_del(&bufev->ev_write);
> > > +   event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb,
> buftls);
> > > +   event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> > > +       buftls);
> > > +   bufferevent_add(&bufev->ev_write, bufev->timeout_write);
> > > +}
> > > +
> > > +/*
> > > + * Reads data from a file descriptor into a buffer.
> > > + */
> > > +
> > > +#define EVBUFFER_MAX_READ  4096
> > > +
> > > +int
> > > +evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx)
> > > +{
> > > +   u_char *p;
> > > +   size_t oldoff = buf->off;
> > > +   int n = EVBUFFER_MAX_READ;
> > > +
> > > +   if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
> > > +           n = EVBUFFER_MAX_READ;
> > > +   } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
> > > +           /*
> > > +            * It's possible that a lot of data is available for
> > > +            * reading.  We do not want to exhaust resources
> > > +            * before the reader has a chance to do something
> > > +            * about it.  If the reader does not tell us how much
> > > +            * data we should read, we artifically limit it.
> > > +            */
> > > +           if ((size_t)n > buf->totallen << 2)
> > > +                   n = buf->totallen << 2;
> > > +           if (n < EVBUFFER_MAX_READ)
> > > +                   n = EVBUFFER_MAX_READ;
> > > +   }
> > > +   if (howmuch < 0 || howmuch > n)
> > > +           howmuch = n;
> > > +
> > > +   /* If we don't have FIONREAD, we might waste some space here */
> > > +   if (evbuffer_expand(buf, howmuch) == -1)
> > > +           return (-1);
> > > +
> > > +   /* We can append new data at this point */
> > > +   p = buf->buffer + buf->off;
> > > +
> > > +   n = tls_read(ctx, p, howmuch);
> > > +   if (n <= 0)
> > > +           return (n);
> > > +
> > > +   buf->off += n;
> > > +
> > > +   /* Tell someone about changes in this buffer */
> > > +   if (buf->off != oldoff && buf->cb != NULL)
> > > +           (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
> > > +
> > > +   return (n);
> > > +}
> > > +
> > > +int
> > > +evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx)
> > > +{
> > > +   int n;
> > > +
> > > +   n = tls_write(ctx, buffer->buffer, buffer->off);
> > > +   if (n <= 0)
> > > +           return (n);
> > > +   evbuffer_drain(buffer, n);
> > > +
> > > +   return (n);
> > > +}
> > > Index: evbuffer_tls.h
> > > ===================================================================
> > > RCS file: evbuffer_tls.h
> > > diff -N evbuffer_tls.h
> > > --- /dev/null       1 Jan 1970 00:00:00 -0000
> > > +++ evbuffer_tls.h  10 Apr 2016 06:15:51 -0000
> > > @@ -0,0 +1,37 @@
> > > +/* $OpenBSD: evbuffer_tls.h,v 1.5 2015/10/09 16:58:25 bluhm Exp $ */
> > > +
> > > +/*
> > > + * Copyright (c) 2014-2015 Alexander Bluhm <[hidden email]>
> > > + *
> > > + * Permission to use, copy, modify, and distribute this software for
> any
> > > + * purpose with or without fee is hereby granted, provided that the
> above
> > > + * copyright notice and this permission notice appear in all copies.
> > > + *
> > > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> WARRANTIES
> > > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> LIABLE FOR
> > > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> DAMAGES
> > > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
> AN
> > > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> OUT OF
> > > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > > + */
> > > +
> > > +#ifndef _EVBUFFER_TLS_H_
> > > +#define _EVBUFFER_TLS_H_
> > > +
> > > +#define EVBUFFER_HANDSHAKE 0x04
> > > +
> > > +struct bufferevent;
> > > +struct tls;
> > > +
> > > +struct buffertls {
> > > +   struct bufferevent      *bt_bufev;
> > > +   struct tls              *bt_ctx;
> > > +};
> > > +
> > > +void       buffertls_set(struct buffertls *, struct bufferevent *,
> struct tls *,
> > > +    int);
> > > +void       buffertls_accept(struct buffertls *, int);
> > > +void       buffertls_connect(struct buffertls *, int);
> > > +
> > > +#endif /* _EVBUFFER_TLS_H_ */
> > > Index: ldapd.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/ldapd.c,v
> > > retrieving revision 1.19
> > > diff -u -p -u -p -r1.19 ldapd.c
> > > --- ldapd.c 4 Feb 2016 12:48:06 -0000       1.19
> > > +++ ldapd.c 10 Apr 2016 06:15:51 -0000
> > > @@ -163,7 +163,7 @@ main(int argc, char *argv[])
> > >
> > >     log_verbose(verbose);
> > >     stats.started_at = time(0);
> > > -   ssl_init();
> > > +   tls_init();
> > >
> > >     if (parse_config(conffile) != 0)
> > >             exit(2);
> > > Index: ldapd.h
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/ldapd.h,v
> > > retrieving revision 1.25
> > > diff -u -p -u -p -r1.25 ldapd.h
> > > --- ldapd.h 2 Nov 2015 06:32:51 -0000       1.25
> > > +++ ldapd.h 10 Apr 2016 06:15:51 -0000
> > > @@ -30,11 +30,13 @@
> > >  #include <limits.h>
> > >  #include <pwd.h>
> > >  #include <stdarg.h>
> > > +#include <tls.h>
> > >
> > >  #include "aldap.h"
> > >  #include "schema.h"
> > >  #include "btree.h"
> > >  #include "imsgev.h"
> > > +#include "evbuffer_tls.h"
> > >
> > >  #define CONFFILE            "/etc/ldapd.conf"
> > >  #define LDAPD_USER          "_ldapd"
> > > @@ -203,7 +205,7 @@ struct listener {
> > >     struct event             evt;
> > >     char                     ssl_cert_name[PATH_MAX];
> > >     struct ssl              *ssl;
> > > -   void                    *ssl_ctx;
> > > +   struct tls              *tls;
> > >     TAILQ_ENTRY(listener)    entry;
> > >  };
> > >  TAILQ_HEAD(listenerlist, listener);
> > > @@ -223,12 +225,8 @@ struct conn {
> > >     struct listener         *listener;      /* where it connected from
> */
> > >
> > >     /* SSL support */
> > > -   struct event             s_ev;
> > > -   struct timeval           s_tv;
> > > -   struct listener         *s_l;
> > > -   void                    *s_ssl;
> > > -   unsigned char           *s_buf;
> > > -   int                      s_buflen;
> > > +   struct tls              *tls;
> > > +   struct buffertls         buftls;
> > >     unsigned int             s_flags;
> > >  };
> > >  TAILQ_HEAD(conn_list, conn)         conn_list;
> > > @@ -236,11 +234,12 @@ TAILQ_HEAD(conn_list, conn)    conn_list;
> > >  struct ssl {
> > >     SPLAY_ENTRY(ssl)         ssl_nodes;
> > >     char                     ssl_name[PATH_MAX];
> > > -   char                    *ssl_cert;
> > > -   off_t                    ssl_cert_len;
> > > -   char                    *ssl_key;
> > > -   off_t                    ssl_key_len;
> > > +   uint8_t                 *ssl_cert;
> > > +   size_t                   ssl_cert_len;
> > > +   uint8_t                 *ssl_key;
> > > +   size_t                   ssl_key_len;
> > >     uint8_t                  flags;
> > > +   struct tls_config       *config;
> > >  };
> > >
> > >  struct ldapd_config
> > > @@ -461,6 +460,9 @@ int                      authorized(struct conn
> *conn, str
> > >  /* parse.y */
> > >  int                         parse_config(char *filename);
> > >  int                         cmdline_symset(char *s);
> > > +int                         ssl_cmp(struct ssl *, struct ssl *);
> > > +SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > > +
> > >
> > >  /* log.c */
> > >  void                        log_init(int);
> > > @@ -498,21 +500,6 @@ int                     unindex_entry(struct
> namespace *n
> > >                             struct ber_element *elm);
> > >  int                         index_to_dn(struct namespace *ns, struct
> btval *indx,
> > >                             struct btval *dn);
> > > -
> > > -/* ssl.c */
> > > -void        ssl_init(void);
> > > -void        ssl_transaction(struct conn *);
> > > -
> > > -void        ssl_session_init(struct conn *);
> > > -void        ssl_session_destroy(struct conn *);
> > > -int         ssl_load_certfile(struct ldapd_config *, const char *,
> u_int8_t);
> > > -void        ssl_setup(struct ldapd_config *, struct listener *);
> > > -int         ssl_cmp(struct ssl *, struct ssl *);
> > > -SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > > -
> > > -/* ssl_privsep.c */
> > > -int         ssl_ctx_use_private_key(void *, char *, off_t);
> > > -int         ssl_ctx_use_certificate_chain(void *, char *, off_t);
> > >
> > >  /* validate.c */
> > >  int        validate_entry(const char *dn, struct ber_element *entry,
> int relax);
> > > Index: ldape.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/ldape.c,v
> > > retrieving revision 1.23
> > > diff -u -p -u -p -r1.23 ldape.c
> > > --- ldape.c 24 Dec 2015 17:47:57 -0000      1.23
> > > +++ ldape.c 10 Apr 2016 06:15:51 -0000
> > > @@ -341,6 +341,7 @@ ldape(struct passwd *pw, char *csockpath
> > >     struct event             ev_sigterm;
> > >     struct event             ev_sigchld;
> > >     struct event             ev_sighup;
> > > +   struct ssl               key;
> > >     char                     host[128];
> > >     mode_t                  old_umask = 0;
> > >
> > > @@ -424,7 +425,24 @@ ldape(struct passwd *pw, char *csockpath
> > >             event_add(&l->ev, NULL);
> > >             evtimer_set(&l->evt, conn_accept, l);
> > >
> > > -           ssl_setup(conf, l);
> > > +           if (l->flags & F_SSL) {
> > > +                   if (strlcpy(key.ssl_name, l->ssl_cert_name,
> > > +                       sizeof(key.ssl_name)) >= sizeof(key.ssl_name))
> > > +                           fatal("ldape: certificate name truncated");
> > > +
> > > +                   l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key);
> > > +                   if (l->ssl == NULL)
> > > +                           fatal("ldape: certificate tree corrupted");
> > > +
> > > +                   l->tls = tls_server();
> > > +                   if (l->tls == NULL)
> > > +                           fatal("ldape: couldn't allocate tls
> context");
> > > +
> > > +                   if (tls_configure(l->tls, l->ssl->config)) {
> > > +                           log_warn("ldape: %s", tls_error(l->tls));
> > > +                           fatal("ldape: couldn't configure tls");
> > > +                   }
> > > +           }
> > >     }
> > >
> > >     TAILQ_FOREACH(ns, &conf->namespaces, next) {
> > > Index: parse.y
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/parse.y,v
> > > retrieving revision 1.16
> > > diff -u -p -u -p -r1.16 parse.y
> > > --- parse.y 20 Nov 2014 05:51:20 -0000      1.16
> > > +++ parse.y 10 Apr 2016 06:15:51 -0000
> > > @@ -77,6 +77,7 @@ int                host(const char *, const char *,
> > >                 struct listenerlist *, int, in_port_t, u_int8_t);
> > >  int                 interface(const char *, const char *,
> > >                 struct listenerlist *, int, in_port_t, u_int8_t);
> > > +int                 load_certfile(struct ldapd_config *, const char
> *, u_int8_t);
> > >
> > >  TAILQ_HEAD(symhead, sym)    symhead = TAILQ_HEAD_INITIALIZER(symhead);
> > >  struct sym {
> > > @@ -91,6 +92,8 @@ char              *symget(const char *);
> > >
> > >  struct ldapd_config        *conf;
> > >
> > > +SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > > +
> > >  static struct aci  *mk_aci(int type, int rights, enum scope scope,
> > >                             char *target, char *subject);
> > >
> > > @@ -181,7 +184,7 @@ conf_main       : LISTEN ON STRING port ssl ce
> > >                     cert = ($6 != NULL) ? $6 : $3;
> > >
> > >                     if (($5 == F_STARTTLS || $5 == F_LDAPS) &&
> > > -                       ssl_load_certfile(conf, cert, F_SCERT) < 0) {
> > > +                       load_certfile(conf, cert, F_SCERT) < 0) {
> > >                             yyerror("cannot load certificate: %s",
> cert);
> > >                             free($6);
> > >                             free($3);
> > > @@ -1167,3 +1170,84 @@ namespace_new(const char *suffix)
> > >     return ns;
> > >  }
> > >
> > > +int
> > > +ssl_cmp(struct ssl *s1, struct ssl *s2)
> > > +{
> > > +   return (strcmp(s1->ssl_name, s2->ssl_name));
> > > +}
> > > +
> > > +int
> > > +load_certfile(struct ldapd_config *env, const char *name, u_int8_t
> flags)
> > > +{
> > > +   struct ssl      *s;
> > > +   struct ssl       key;
> > > +   char             certfile[PATH_MAX];
> > > +
> > > +   if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> > > +       >= sizeof(key.ssl_name)) {
> > > +           log_warn("load_certfile: certificate name truncated");
> > > +           return -1;
> > > +   }
> > > +
> > > +   s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> > > +   if (s != NULL) {
> > > +           s->flags |= flags;
> > > +           return 0;
> > > +   }
> > > +
> > > +   if ((s = calloc(1, sizeof(*s))) == NULL)
> > > +           fatal(NULL);
> > > +
> > > +   s->flags = flags;
> > > +   (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> > > +
> > > +   s->config = tls_config_new();
> > > +   if (s->config == NULL)
> > > +           goto err;
> > > +
> > > +   tls_config_set_protocols(s->config, TLS_PROTOCOLS_ALL);
> > > +   if (tls_config_set_ciphers(s->config, "compat"))
> > > +           goto err;
> > > +
> > > +   if ((name[0] == '/' &&
> > > +        !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> > > +       !bsnprintf(certfile, sizeof(certfile),
> "/etc/ldap/certs/%s.crt",
> > > +           name)) {
> > > +           log_warn("load_certfile: path truncated");
> > > +           goto err;
> > > +   }
> > > +
> > > +   log_debug("loading certificate file %s", certfile);
> > > +   s->ssl_cert = tls_load_file(certfile, &s->ssl_cert_len, NULL);
> > > +   if (s->ssl_cert == NULL)
> > > +           goto err;
> > > +
> > > +   if (tls_config_set_cert_mem(s->config, s->ssl_cert,
> s->ssl_cert_len))
> > > +           goto err;
> > > +
> > > +   if ((name[0] == '/' &&
> > > +        !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> > > +       !bsnprintf(certfile, sizeof(certfile),
> "/etc/ldap/certs/%s.key",
> > > +           name)) {
> > > +           log_warn("load_certfile: path truncated");
> > > +           goto err;
> > > +   }
> > > +
> > > +   log_debug("loading key file %s", certfile);
> > > +   s->ssl_key = tls_load_file(certfile, &s->ssl_key_len, NULL);
> > > +   if (s->ssl_key == NULL)
> > > +           goto err;
> > > +
> > > +   if (tls_config_set_key_mem(s->config, s->ssl_key, s->ssl_key_len))
> > > +           goto err;
> > > +
> > > +   SPLAY_INSERT(ssltree, env->sc_ssl, s);
> > > +
> > > +   return (0);
> > > +err:
> > > +   free(s->ssl_cert);
> > > +   free(s->ssl_key);
> > > +   tls_config_free(s->config);
> > > +   free(s);
> > > +   return (-1);
> > > +}
> > > Index: ssl.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/ssl.c,v
> > > retrieving revision 1.10
> > > diff -u -p -u -p -r1.10 ssl.c
> > > --- ssl.c   30 Dec 2015 15:59:55 -0000      1.10
> > > +++ ssl.c   10 Apr 2016 06:15:51 -0000
> > > @@ -1,565 +0,0 @@
> > > -/* $OpenBSD: ssl.c,v 1.10 2015/12/30 15:59:55 benno Exp $  */
> > > -
> > > -/*
> > > - * Copyright (c) 2008 Pierre-Yves Ritschard <[hidden email]>
> > > - * Copyright (c) 2008 Reyk Floeter <[hidden email]>
> > > - *
> > > - * Permission to use, copy, modify, and distribute this software for
> any
> > > - * purpose with or without fee is hereby granted, provided that the
> above
> > > - * copyright notice and this permission notice appear in all copies.
> > > - *
> > > - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> WARRANTIES
> > > - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > > - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> LIABLE FOR
> > > - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> DAMAGES
> > > - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
> AN
> > > - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> OUT OF
> > > - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > > - */
> > > -
> > > -#include <sys/types.h>
> > > -#include <sys/queue.h>
> > > -#include <sys/tree.h>
> > > -#include <sys/socket.h>
> > > -#include <sys/stat.h>
> > > -#include <sys/time.h>
> > > -
> > > -#include <ctype.h>
> > > -#include <event.h>
> > > -#include <fcntl.h>
> > > -#include <pwd.h>
> > > -#include <stdio.h>
> > > -#include <stdlib.h>
> > > -#include <string.h>
> > > -#include <unistd.h>
> > > -
> > > -#include <openssl/ssl.h>
> > > -#include <openssl/engine.h>
> > > -#include <openssl/err.h>
> > > -#include <openssl/dh.h>
> > > -#include <openssl/bn.h>
> > > -
> > > -#define MINIMUM(a, b)      (((a) < (b)) ? (a) : (b))
> > > -
> > > -#include "ldapd.h"
> > > -
> > > -#define SSL_CIPHERS        "HIGH:!aNULL"
> > > -
> > > -void        ssl_error(const char *);
> > > -char       *ssl_load_file(const char *, off_t *);
> > > -SSL_CTX    *ssl_ctx_create(void);
> > > -void        ssl_session_accept(int, short, void *);
> > > -void        ssl_read(int, short, void *);
> > > -void        ssl_write(int, short, void *);
> > > -int         ssl_bufferevent_add(struct event *, int);
> > > -
> > > -DH *get_dh1024(void);
> > > -void        ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *);
> > > -
> > > -extern void        bufferevent_read_pressure_cb(struct evbuffer *,
> size_t,
> > > -               size_t, void *);
> > > -
> > > -void
> > > -ssl_read(int fd, short event, void *p)
> > > -{
> > > -   struct bufferevent      *bufev = p;
> > > -   struct conn             *s = bufev->cbarg;
> > > -   int                      ret;
> > > -   int                      ssl_err;
> > > -   short                    what;
> > > -   size_t                   len;
> > > -   char                     rbuf[IBUF_READ_SIZE];
> > > -   int                      howmuch = IBUF_READ_SIZE;
> > > -
> > > -   what = EVBUFFER_READ;
> > > -
> > > -   if (event == EV_TIMEOUT) {
> > > -           what |= EVBUFFER_TIMEOUT;
> > > -           goto err;
> > > -   }
> > > -
> > > -   if (bufev->wm_read.high != 0)
> > > -           howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
> > > -
> > > -   ret = SSL_read(s->s_ssl, rbuf, howmuch);
> > > -   if (ret <= 0) {
> > > -           ssl_err = SSL_get_error(s->s_ssl, ret);
> > > -
> > > -           switch (ssl_err) {
> > > -           case SSL_ERROR_WANT_READ:
> > > -                   goto retry;
> > > -           case SSL_ERROR_WANT_WRITE:
> > > -                   goto retry;
> > > -           default:
> > > -                   if (ret == 0)
> > > -                           what |= EVBUFFER_EOF;
> > > -                   else {
> > > -                           ssl_error("ssl_read");
> > > -                           what |= EVBUFFER_ERROR;
> > > -                   }
> > > -                   goto err;
> > > -           }
> > > -   }
> > > -
> > > -   if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
> > > -           what |= EVBUFFER_ERROR;
> > > -           goto err;
> > > -   }
> > > -
> > > -   ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > -
> > > -   len = EVBUFFER_LENGTH(bufev->input);
> > > -   if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
> > > -           return;
> > > -   if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
> > > -           struct evbuffer *buf = bufev->input;
> > > -           event_del(&bufev->ev_read);
> > > -           evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
> > > -           return;
> > > -   }
> > > -
> > > -   if (bufev->readcb != NULL)
> > > -           (*bufev->readcb)(bufev, bufev->cbarg);
> > > -   return;
> > > -
> > > -retry:
> > > -   ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> > > -   return;
> > > -
> > > -err:
> > > -   (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > > -}
> > > -
> > > -
> > > -void
> > > -ssl_write(int fd, short event, void *p)
> > > -{
> > > -   struct bufferevent      *bufev = p;
> > > -   struct conn             *s = bufev->cbarg;
> > > -   int                      ret;
> > > -   int                      ssl_err;
> > > -   short                    what;
> > > -
> > > -   what = EVBUFFER_WRITE;
> > > -
> > > -   if (event == EV_TIMEOUT) {
> > > -           what |= EV_TIMEOUT;
> > > -           goto err;
> > > -   }
> > > -
> > > -   if (EVBUFFER_LENGTH(bufev->output)) {
> > > -           if (s->s_buf == NULL) {
> > > -                   s->s_buflen = EVBUFFER_LENGTH(bufev->output);
> > > -                   if ((s->s_buf = malloc(s->s_buflen)) == NULL) {
> > > -                           what |= EVBUFFER_ERROR;
> > > -                           goto err;
> > > -                   }
> > > -                   memcpy(s->s_buf, EVBUFFER_DATA(bufev->output),
> > > -                       s->s_buflen);
> > > -           }
> > > -
> > > -           ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen);
> > > -           if (ret <= 0) {
> > > -                   ssl_err = SSL_get_error(s->s_ssl, ret);
> > > -
> > > -                   switch (ssl_err) {
> > > -                   case SSL_ERROR_WANT_READ:
> > > -                           goto retry;
> > > -                   case SSL_ERROR_WANT_WRITE:
> > > -                           goto retry;
> > > -                   default:
> > > -                           if (ret == 0)
> > > -                                   what |= EVBUFFER_EOF;
> > > -                           else {
> > > -                                   ssl_error("ssl_write");
> > > -                                   what |= EVBUFFER_ERROR;
> > > -                           }
> > > -                           goto err;
> > > -                   }
> > > -           }
> > > -           evbuffer_drain(bufev->output, ret);
> > > -   }
> > > -   if (s->s_buf != NULL) {
> > > -           free(s->s_buf);
> > > -           s->s_buf = NULL;
> > > -           s->s_buflen = 0;
> > > -   }
> > > -   if (EVBUFFER_LENGTH(bufev->output) != 0)
> > > -           ssl_bufferevent_add(&bufev->ev_write,
> bufev->timeout_write);
> > > -
> > > -   if (bufev->writecb != NULL &&
> > > -       EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
> > > -           (*bufev->writecb)(bufev, bufev->cbarg);
> > > -   return;
> > > -
> > > -retry:
> > > -   if (s->s_buflen != 0)
> > > -           ssl_bufferevent_add(&bufev->ev_write,
> bufev->timeout_write);
> > > -   return;
> > > -
> > > -err:
> > > -   if (s->s_buf != NULL) {
> > > -           free(s->s_buf);
> > > -           s->s_buf = NULL;
> > > -           s->s_buflen = 0;
> > > -   }
> > > -   (*bufev->errorcb)(bufev, what, bufev->cbarg);
> > > -}
> > > -
> > > -int
> > > -ssl_bufferevent_add(struct event *ev, int timeout)
> > > -{
> > > -   struct timeval   tv;
> > > -   struct timeval  *ptv = NULL;
> > > -
> > > -   if (timeout) {
> > > -           timerclear(&tv);
> > > -           tv.tv_sec = timeout;
> > > -           ptv = &tv;
> > > -   }
> > > -
> > > -   return (event_add(ev, ptv));
> > > -}
> > > -
> > > -int
> > > -ssl_cmp(struct ssl *s1, struct ssl *s2)
> > > -{
> > > -   return (strcmp(s1->ssl_name, s2->ssl_name));
> > > -}
> > > -
> > > -SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp);
> > > -
> > > -char *
> > > -ssl_load_file(const char *name, off_t *len)
> > > -{
> > > -   struct stat      st;
> > > -   off_t            size;
> > > -   char            *buf = NULL;
> > > -   int              fd;
> > > -
> > > -   if ((fd = open(name, O_RDONLY)) == -1)
> > > -           return (NULL);
> > > -   if (fstat(fd, &st) != 0)
> > > -           goto fail;
> > > -   size = st.st_size;
> > > -   if ((buf = calloc(1, size + 1)) == NULL)
> > > -           goto fail;
> > > -   if (read(fd, buf, size) != size)
> > > -           goto fail;
> > > -   close(fd);
> > > -
> > > -   *len = size + 1;
> > > -   return (buf);
> > > -
> > > -fail:
> > > -   free(buf);
> > > -   close(fd);
> > > -   return (NULL);
> > > -}
> > > -
> > > -SSL_CTX *
> > > -ssl_ctx_create(void)
> > > -{
> > > -   SSL_CTX *ctx;
> > > -
> > > -   ctx = SSL_CTX_new(SSLv23_method());
> > > -   if (ctx == NULL) {
> > > -           ssl_error("ssl_ctx_create");
> > > -           fatal("ssl_ctx_create: could not create SSL context");
> > > -   }
> > > -
> > > -   SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
> > > -   SSL_CTX_set_timeout(ctx, LDAPD_SESSION_TIMEOUT);
> > > -   SSL_CTX_set_options(ctx, SSL_OP_ALL);
> > > -   SSL_CTX_set_options(ctx,
> > > -       SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
> > > -
> > > -   if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) {
> > > -           ssl_error("ssl_ctx_create");
> > > -           fatal("ssl_ctx_create: could not set cipher list");
> > > -   }
> > > -   return (ctx);
> > > -}
> > > -
> > > -int
> > > -ssl_load_certfile(struct ldapd_config *env, const char *name,
> u_int8_t flags)
> > > -{
> > > -   struct ssl      *s;
> > > -   struct ssl       key;
> > > -   char             certfile[PATH_MAX];
> > > -
> > > -   if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name))
> > > -       >= sizeof(key.ssl_name)) {
> > > -           log_warn("ssl_load_certfile: certificate name truncated");
> > > -           return -1;
> > > -   }
> > > -
> > > -   s = SPLAY_FIND(ssltree, env->sc_ssl, &key);
> > > -   if (s != NULL) {
> > > -           s->flags |= flags;
> > > -           return 0;
> > > -   }
> > > -
> > > -   if ((s = calloc(1, sizeof(*s))) == NULL)
> > > -           fatal(NULL);
> > > -
> > > -   s->flags = flags;
> > > -   (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name));
> > > -
> > > -   if ((name[0] == '/' &&
> > > -        !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) ||
> > > -       !bsnprintf(certfile, sizeof(certfile),
> "/etc/ldap/certs/%s.crt",
> > > -           name)) {
> > > -           log_warn("ssl_load_certfile: path truncated");
> > > -           free(s);
> > > -           return -1;
> > > -   }
> > > -
> > > -   log_debug("loading certificate file %s", certfile);
> > > -   if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) ==
> NULL) {
> > > -           free(s);
> > > -           return (-1);
> > > -   }
> > > -
> > > -   if ((name[0] == '/' &&
> > > -        !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) ||
> > > -       !bsnprintf(certfile, sizeof(certfile),
> "/etc/ldap/certs/%s.key",
> > > -           name)) {
> > > -           log_warn("ssl_load_certfile: path truncated");
> > > -           free(s->ssl_cert);
> > > -           free(s);
> > > -           return -1;
> > > -   }
> > > -
> > > -   log_debug("loading key file %s", certfile);
> > > -   if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) ==
> NULL) {
> > > -           free(s->ssl_cert);
> > > -           free(s);
> > > -           return (-1);
> > > -   }
> > > -
> > > -   SPLAY_INSERT(ssltree, env->sc_ssl, s);
> > > -
> > > -   return (0);
> > > -}
> > > -
> > > -void
> > > -ssl_init(void)
> > > -{
> > > -   SSL_library_init();
> > > -   SSL_load_error_strings();
> > > -
> > > -   OpenSSL_add_all_algorithms();
> > > -
> > > -   /* Init hardware crypto engines. */
> > > -   ENGINE_load_builtin_engines();
> > > -   ENGINE_register_all_complete();
> > > -}
> > > -
> > > -void
> > > -ssl_setup(struct ldapd_config *env, struct listener *l)
> > > -{
> > > -   struct ssl      key;
> > > -
> > > -   if (!(l->flags & F_SSL))
> > > -           return;
> > > -
> > > -   if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name))
> > > -       >= sizeof(key.ssl_name))
> > > -           fatal("ssl_setup: certificate name truncated");
> > > -
> > > -   if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL)
> > > -           fatal("ssl_setup: certificate tree corrupted");
> > > -
> > > -   l->ssl_ctx = ssl_ctx_create();
> > > -
> > > -   if (!ssl_ctx_use_certificate_chain(l->ssl_ctx,
> > > -       l->ssl->ssl_cert, l->ssl->ssl_cert_len))
> > > -           goto err;
> > > -   if (!ssl_ctx_use_private_key(l->ssl_ctx,
> > > -       l->ssl->ssl_key, l->ssl->ssl_key_len))
> > > -           goto err;
> > > -
> > > -   if (!SSL_CTX_check_private_key(l->ssl_ctx))
> > > -           goto err;
> > > -   if (!SSL_CTX_set_session_id_context(l->ssl_ctx,
> > > -           (const unsigned char *)l->ssl_cert_name,
> strlen(l->ssl_cert_name) + 1))
> > > -           goto err;
> > > -
> > > -   ssl_set_ephemeral_key_exchange(l->ssl_ctx, get_dh1024());
> > > -
> > > -   log_debug("ssl_setup: ssl setup finished for listener: %p", l);
> > > -   return;
> > > -
> > > -err:
> > > -   SSL_CTX_free(l->ssl_ctx);
> > > -   ssl_error("ssl_setup");
> > > -   fatal("ssl_setup: cannot set SSL up");
> > > -}
> > > -
> > > -void
> > > -ssl_error(const char *where)
> > > -{
> > > -   unsigned long   code;
> > > -   char            errbuf[128];
> > > -   extern int      debug;
> > > -
> > > -   if (!debug)
> > > -           return;
> > > -   for (; (code = ERR_get_error()) != 0 ;) {
> > > -           ERR_error_string_n(code, errbuf, sizeof(errbuf));
> > > -           log_debug("SSL library error: %s: %s", where, errbuf);
> > > -   }
> > > -}
> > > -
> > > -void
> > > -ssl_session_accept(int fd, short event, void *p)
> > > -{
> > > -   struct conn     *s = p;
> > > -   int              ret;
> > > -   int              ssl_err;
> > > -
> > > -   if (event == EV_TIMEOUT) {
> > > -           log_debug("ssl_session_accept: session timed out");
> > > -           conn_close(s);
> > > -           return;
> > > -   }
> > > -
> > > -   log_debug("ssl_session_accept: accepting client");
> > > -   ret = SSL_accept(s->s_ssl);
> > > -   if (ret <= 0) {
> > > -           ssl_err = SSL_get_error(s->s_ssl, ret);
> > > -
> > > -           switch (ssl_err) {
> > > -           case SSL_ERROR_WANT_READ:
> > > -                   goto retry;
> > > -           case SSL_ERROR_WANT_WRITE:
> > > -                   goto retry;
> > > -           case SSL_ERROR_ZERO_RETURN:
> > > -           case SSL_ERROR_SYSCALL:
> > > -                   if (ret == 0) {
> > > -                           conn_close(s);
> > > -                           return;
> > > -                   }
> > > -                   /* FALLTHROUGH */
> > > -           default:
> > > -                   ssl_error("ssl_session_accept");
> > > -                   conn_close(s);
> > > -                   return;
> > > -           }
> > > -   }
> > > -
> > > -   log_debug("ssl_session_accept: accepted ssl client");
> > > -   s->s_flags |= F_SECURE;
> > > -
> > > -   s->bev = bufferevent_new(s->fd, conn_read, conn_write, conn_err,
> s);
> > > -   if (s->bev == NULL) {
> > > -                log_warn("ssl_session_accept: bufferevent_new");
> > > -                conn_close(s);
> > > -                return;
> > > -   }
> > > -   bufferevent_settimeout(s->bev, 0, 60);
> > > -
> > > -   event_set(&s->bev->ev_read, s->fd, EV_READ, ssl_read, s->bev);
> > > -   event_set(&s->bev->ev_write, s->fd, EV_WRITE, ssl_write, s->bev);
> > > -   bufferevent_enable(s->bev, EV_READ);
> > > -
> > > -   return;
> > > -retry:
> > > -   event_add(&s->s_ev, &s->s_tv);
> > > -}
> > > -
> > > -void
> > > -ssl_session_init(struct conn *s)
> > > -{
> > > -   struct listener *l;
> > > -   SSL             *ssl;
> > > -
> > > -   l = s->s_l;
> > > -
> > > -   if (!(l->flags & F_SSL))
> > > -           return;
> > > -
> > > -   log_debug("ssl_session_init: switching to SSL");
> > > -   ssl = SSL_new(l->ssl_ctx);
> > > -   if (ssl == NULL)
> > > -           goto err;
> > > -
> > > -   if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
> > > -           goto err;
> > > -   if (!SSL_set_fd(ssl, s->fd))
> > > -           goto err;
> > > -   SSL_set_accept_state(ssl);
> > > -
> > > -   s->s_ssl = ssl;
> > > -
> > > -   s->s_tv.tv_sec = LDAPD_SESSION_TIMEOUT;
> > > -   s->s_tv.tv_usec = 0;
> > > -   event_set(&s->s_ev, s->fd, EV_READ|EV_TIMEOUT, ssl_session_accept,
> s);
> > > -   event_add(&s->s_ev, &s->s_tv);
> > > -   return;
> > > -
> > > - err:
> > > -   SSL_free(ssl);
> > > -   ssl_error("ssl_session_init");
> > > -}
> > > -
> > > -void
> > > -ssl_session_destroy(struct conn *s)
> > > -{
> > > -   SSL_free(s->s_ssl);
> > > -}
> > > -
> > > -/* From OpenSSL's documentation:
> > > - *
> > > - * If "strong" primes were used to generate the DH parameters, it is
> > > - * not strictly necessary to generate a new key for each handshake
> > > - * but it does improve forward secrecy.
> > > - *
> > > - * -- gilles@
> > > - */
> > > -DH *
> > > -get_dh1024(void)
> > > -{
> > > -   DH *dh;
> > > -   unsigned char dh1024_p[] = {
> > > -           0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75,
> > > -           0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51,
> > > -           0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E,
> > > -           0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D,
> > > -           0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89,
> > > -           0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC,
> > > -           0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02,
> > > -           0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93,
> > > -           0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D,
> > > -           0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65,
> > > -           0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6,
> > > -           0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1,
> > > -           0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9,
> > > -           0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59,
> > > -           0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7,
> > > -           0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B
> > > -   };
> > > -   unsigned char dh1024_g[] = {
> > > -           0x02
> > > -   };
> > > -
> > > -   if ((dh = DH_new()) == NULL)
> > > -           return NULL;
> > > -
> > > -   dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
> > > -   dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
> > > -   if (dh->p == NULL || dh->g == NULL) {
> > > -           DH_free(dh);
> > > -           return NULL;
> > > -   }
> > > -
> > > -   return dh;
> > > -}
> > > -
> > > -void
> > > -ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh)
> > > -{
> > > -   if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh))
> > > -           fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh");
> > > -}
> > > Index: ssl_privsep.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/ldapd/ssl_privsep.c,v
> > > retrieving revision 1.4
> > > diff -u -p -u -p -r1.4 ssl_privsep.c
> > > --- ssl_privsep.c   28 Jan 2015 15:50:30 -0000      1.4
> > > +++ ssl_privsep.c   10 Apr 2016 06:15:51 -0000
> > > @@ -1,172 +0,0 @@
> > > -/*      $OpenBSD: ssl_privsep.c,v 1.4 2015/01/28 15:50:30 reyk Exp $
>   */
> > > -
> > > -/* Copyright (C) 1995-1998 Eric Young ([hidden email])
> > > - * All rights reserved.
> > > - *
> > > - * This package is an SSL implementation written
> > > - * by Eric Young ([hidden email]).
> > > - * The implementation was written so as to conform with Netscapes SSL.
> > > - *
> > > - * This library is free for commercial and non-commercial use as long
> as
> > > - * the following conditions are aheared to.  The following conditions
> > > - * apply to all code found in this distribution, be it the RC4, RSA,
> > > - * lhash, DES, etc., code; not just the SSL code.  The SSL
> documentation
> > > - * included with this distribution is covered by the same copyright
> terms
> > > - * except that the holder is Tim Hudson ([hidden email]).
> > > - *
> > > - * Copyright remains Eric Young's, and as such any Copyright notices
> in
> > > - * the code are not to be removed.
> > > - * If this package is used in a product, Eric Young should be given
> attribution
> > > - * as the author of the parts of the library used.
> > > - * This can be in the form of a textual message at program startup or
> > > - * in documentation (online or textual) provided with the package.
> > > - *
> > > - * Redistribution and use in source and binary forms, with or without
> > > - * modification, are permitted provided that the following conditions
> > > - * are met:
> > > - * 1. Redistributions of source code must retain the copyright
> > > - *    notice, this list of conditions and the following disclaimer.
> > > - * 2. Redistributions in binary form must reproduce the above
> copyright
> > > - *    notice, this list of conditions and the following disclaimer in
> the
> > > - *    documentation and/or other materials provided with the
> distribution.
> > > - * 3. All advertising materials mentioning features or use of this
> software
> > > - *    must display the following acknowledgement:
> > > - *    "This product includes cryptographic software written by
> > > - *     Eric Young ([hidden email])"
> > > - *    The word 'cryptographic' can be left out if the rouines from
> the library
> > > - *    being used are not cryptographic related :-).
> > > - * 4. If you include any Windows specific code (or a derivative
> thereof) from
> > > - *    the apps directory (application code) you must include an
> acknowledgement:
> > > - *    "This product includes software written by Tim Hudson (
> [hidden email])"
> > > - *
> > > - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
> > > - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> > > - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> > > - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
> LIABLE
> > > - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL
> > > - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS
> > > - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> INTERRUPTION)
> > > - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> CONTRACT, STRICT
> > > - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
> ANY WAY
> > > - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> POSSIBILITY OF
> > > - * SUCH DAMAGE.
> > > - *
> > > - * The licence and distribution terms for any publically available
> version or
> > > - * derivative of this code cannot be changed.  i.e. this code cannot
> simply be
> > > - * copied and put under another distribution licence
> > > - * [including the GNU Public Licence.]
> > > - */
> > > -
> > > -/*
> > > - * SSL operations needed when running in a privilege separated
> environment.
> > > - * 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>
> > > -
> > > -#include <openssl/err.h>
> > > -#include <openssl/bio.h>
> > > -#include <openssl/objects.h>
> > > -#include <openssl/evp.h>
> > > -#include <openssl/x509.h>
> > > -#include <openssl/pem.h>
> > > -#include <openssl/ssl.h>
> > > -
> > > -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_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
> > > -{
> > > -   int              ret;
> > > -   BIO             *in;
> > > -   EVP_PKEY        *pkey;
> > > -
> > > -   ret = 0;
> > > -
> > > -   if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> > > -           SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
> > > -           return 0;
> > > -   }
> > > -
> > > -   pkey = PEM_read_bio_PrivateKey(in, NULL,
> > > -       ctx->default_passwd_callback,
> > > -       ctx->default_passwd_callback_userdata);
> > > -
> > > -   if (pkey == NULL) {
> > > -           SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
> > > -           goto end;
> > > -   }
> > > -   ret = SSL_CTX_use_PrivateKey(ctx, pkey);
> > > -   EVP_PKEY_free(pkey);
> > > -end:
> > > -   if (in != NULL)
> > > -           BIO_free(in);
> > > -   return ret;
> > > -}
> > > -
> > > -int
> > > -ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
> > > -{
> > > -   int              ret;
> > > -   BIO             *in;
> > > -   X509            *x;
> > > -   X509            *ca;
> > > -   unsigned long    err;
> > > -
> > > -   ret = 0;
> > > -   x = ca = NULL;
> > > -
> > > -   if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
> > > -           SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,
> ERR_R_BUF_LIB);
> > > -           goto end;
> > > -   }
> > > -
> > > -   if ((x = PEM_read_bio_X509(in, NULL,
> > > -       ctx->default_passwd_callback,
> > > -       ctx->default_passwd_callback_userdata)) == NULL) {
> > > -           SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,
> ERR_R_PEM_LIB);
> > > -           goto end;
> > > -   }
> > > -
> > > -   if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
> > > -           goto end;
> > > -
> > > -   /* If we could set up our certificate, now proceed to
> > > -    * the CA certificates.
> > > -    */
> > > -
> > > -   if (ctx->extra_certs != NULL) {
> > > -           sk_X509_pop_free(ctx->extra_certs, X509_free);
> > > -           ctx->extra_certs = NULL;
> > > -   }
> > > -
> > > -   while ((ca = PEM_read_bio_X509(in, NULL,
> > > -       ctx->default_passwd_callback,
> > > -       ctx->default_passwd_callback_userdata)) != NULL) {
> > > -
> > > -           if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
> > > -                   goto end;
> > > -  --
>
>