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 <[email protected]>
> + * Copyright (c) 2014-2015 Alexander Bluhm <[email protected]>
> + * 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 <[email protected]>
> + *
> + * 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 <[email protected]>
> - * Copyright (c) 2008 Reyk Floeter <[email protected]>
> - *
> - * 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 ([email protected])
> - * All rights reserved.
> - *
> - * This package is an SSL implementation written
> - * by Eric Young ([email protected]).
> - * 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 ([email protected]).
> - *
> - * 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 ([email protected])"
> - *    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 
> ([email protected])"
> - *
> - * 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 via email to