On Thursday 14 May 2015, Michal Lesniewski wrote:
> On 14.05.2015 15:02, Joel Sing wrote:
> > On Thursday 14 May 2015, Michal Lesniewski wrote:
> >> Hello,
> >>
> >> I'm trying to configure OpenBSD 5.7 httpd with tls with
> >> intermediate/chain certificate without no success.
> >>
> >> my httpd.conf:
> >>
> >> server "default" {
> >>           listen on 10.11.0.200 tls port 443
> >>
> >>           tls {
> >>                   certificate "/etc/ssl/server-unified.pem"
> >>                   key "/etc/ssl/private/server.key"
> >>           }
> >>
> >>           root "/htdocs/default"
> >> }
> >>
> >> types {
> >>           include "/usr/share/misc/mime.types"
> >> }
> >>
> >>
> >>
> >> My certificate is intermediate/chain certificate. That mean I need to
> >> supply "next level" certificate that is between my certificate and CA.
> >>
> >> I made that chain certificate concatenating PEM format files with
> >> corresponding certs (all certs Signature Algorithm:
> >> sha256WithRSAEncryption)
> >>
> >> cat server.pem sub.class2.server.ca.pem ca-sha2.pem >
> >> /etc/ssl/server-unified.pem
> >>
> >> server-unified.pem looks like:
> >>
> >> -----BEGIN CERTIFICATE-----
> >> (Primary SSL certificate: server.pem)
> >> -----END CERTIFICATE-----
> >> -----BEGIN CERTIFICATE-----
> >> (Intermediate certificate: sub.class2.server.ca.pem)
> >> -----END CERTIFICATE-----
> >> -----BEGIN CERTIFICATE-----
> >> (Root certificate: ca-sha2.pem)
> >> -----END CERTIFICATE-----
> >>
> >> Certificate and key installed in default locations:
> >>
> >> # ls -alh /etc/ssl/private/server.key
> >> -r--------  1 root  wheel   6.2K May 13 19:40
> >> /etc/ssl/private/server.key # ls -alh /etc/ssl/server.pem
> >> -rw-r--r--  1 root  wheel   3.3K May 13 19:41 /etc/ssl/server.pem
> >> # ls -alh /etc/ssl/server-unified.pem
> >> -rw-r--r--  1 root  wheel   8.0K May 14 13:53
> >> /etc/ssl/server-unified.pem
> >>
> >>
> >> I try to test using openssl s_client:
> >>
> >> michal@michal-MSQ87TN:~$ openssl s_client -connect 10.11.0.200:443
> >> CONNECTED(00000003)
> >> GET / HTTP/1.0
> >>
> >>
> >>
> >> httpd log:
> >>
> >>
> >> # httpd -dvvvvvvvvvv
> >> startup
> >> server_tls_load_keypair: using certificate /etc/ssl/server-unified.pem
> >> server_tls_load_keypair: using private key /etc/ssl/private/server.key
> >> socket_rlimit: max open files 1024
> >> socket_rlimit: max open files 1024
> >> server_privinit: adding server default
> >> server_privinit: adding server default
> >> socket_rlimit: max open files 1024
> >> server_launch: running server default
> >> server_launch: running server default
> >> server_launch: running server default
> >>
> >>> there is no "server_tls_init"
> >>> nothing apears when started openssl s_client command
> >
> > This smells very much like the same problem that has been mentioned on
> > the list earlier - with a 6KB private key and a 8KB bundle, you're almost
> > certainly hitting the 16K limit for a single imsg. Unfortunately there
> > were missing return value checks which means that this fails silently. If
> > you can try httpd from -current you will likely see an error instead of a
> > silent failure. Otherwise you can try removing one of the certificates
> > from the bundle in order to reduce the size and see if it then
> > reports "server_tls_init" and starts working.
>
> tested on -current:
>
> # httpd -dvvvvvvvvvvvvv
> startup
> server_tls_load_keypair: using certificate /etc/ssl/server-unified.pem
> server_tls_load_keypair: using private key /etc/ssl/private/server.key
> socket_rlimit: max open files 1024
> server_privinit: adding server default
> server_privinit: adding server default
> config_setserver: failed to compose IMSG_CFG_SERVER imsg for `default':
> Result too large
> fatal: send server: Result too large
> socket_rlimit: max open files 1024
> logger exiting, pid 4965
> socket_rlimit: max open files 1024
> server exiting, pid 10727
> server exiting, pid 32594
> server exiting, pid 5337
>
> Above situation occurs when I have server cert + intermediate + ca and
> only server cert + intermediate in server-chain.pem.
> httpd starts only when I supply only my server cert to it.
> Is there any solution to run httpd with such big private key?

Try this (albeit only tested a little beyond compilation...)

Index: config.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.37
diff -u -p -r1.37 config.c
--- config.c    11 Apr 2015 14:52:49 -0000      1.37
+++ config.c    14 May 2015 13:58:57 -0000
@@ -193,14 +193,6 @@ config_setserver(struct httpd *env, stru
                        iov[c].iov_base = srv->srv_conf.return_uri;
                        iov[c++].iov_len = srv->srv_conf.return_uri_len;
                }
-               if (srv->srv_conf.tls_cert_len != 0) {
-                       iov[c].iov_base = srv->srv_conf.tls_cert;
-                       iov[c++].iov_len = srv->srv_conf.tls_cert_len;
-               }
-               if (srv->srv_conf.tls_key_len != 0) {
-                       iov[c].iov_base = srv->srv_conf.tls_key;
-                       iov[c++].iov_len = srv->srv_conf.tls_key_len;
-               }
 
                if (id == PROC_SERVER &&
                    (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) {
@@ -220,6 +212,9 @@ config_setserver(struct httpd *env, stru
                                        return (-1);
                                }
                        }
+
+                       /* Configure TLS if necessary. */
+                       config_settls(env, srv);
                } else {
                        if (proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1,
                            iov, c) != 0) {
@@ -235,6 +230,72 @@ config_setserver(struct httpd *env, stru
 }
 
 int
+config_settls(struct httpd *env, struct server *srv)
+{
+       struct privsep          *ps = env->sc_ps;
+       struct tls_config        tls;
+       struct iovec             iov[2];
+       size_t                   c;
+
+       if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0)
+               return (0);
+
+       log_debug("%s: configuring TLS for %s", __func__, srv->srv_conf.name);
+
+       if (srv->srv_conf.tls_cert_len != 0) {
+               DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__,
+                   srv->srv_conf.name, srv->srv_conf.id,
+                   ps->ps_title[PROC_SERVER], srv->srv_s);
+
+               memset(&tls, 0, sizeof(tls));
+               tls.id = srv->srv_conf.id;
+               tls.port = srv->srv_conf.port;
+               memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss));
+               tls.tls_cert_len = srv->srv_conf.tls_cert_len;
+
+               c = 0;
+               iov[c].iov_base = &tls;
+               iov[c++].iov_len = sizeof(tls);
+               iov[c].iov_base = srv->srv_conf.tls_cert;
+               iov[c++].iov_len = srv->srv_conf.tls_cert_len;
+
+               if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1,
+                   iov, c) != 0) {
+                       log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+                           "`%s'", __func__, srv->srv_conf.name);
+                       return (-1);
+               }
+       }
+
+       if (srv->srv_conf.tls_key_len != 0) {
+               DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__,
+                   srv->srv_conf.name, srv->srv_conf.id,
+                   ps->ps_title[PROC_SERVER], srv->srv_s);
+
+               memset(&tls, 0, sizeof(tls));
+               tls.id = srv->srv_conf.id;
+               tls.port = srv->srv_conf.port;
+               memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss));
+               tls.tls_key_len = srv->srv_conf.tls_key_len;
+
+               c = 0;
+               iov[c].iov_base = &tls;
+               iov[c++].iov_len = sizeof(tls);
+               iov[c].iov_base = srv->srv_conf.tls_key;
+               iov[c++].iov_len = srv->srv_conf.tls_key_len;
+
+               if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1,
+                   iov, c) != 0) {
+                       log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+                           "`%s'", __func__, srv->srv_conf.name);
+                       return (-1);
+               }
+       }
+
+       return (0);
+}
+
+int
 config_getserver_auth(struct httpd *env, struct server_config *srv_conf)
 {
        struct privsep          *ps = env->sc_ps;
@@ -422,9 +483,7 @@ config_getserver(struct httpd *env, stru
        /* Reset these variables to avoid free'ing invalid pointers */
        serverconfig_reset(&srv_conf);
 
-       if ((IMSG_DATA_SIZE(imsg) - s) <
-           (srv_conf.tls_cert_len + srv_conf.tls_key_len +
-           srv_conf.return_uri_len)) {
+       if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) {
                log_debug("%s: invalid message length", __func__);
                goto fail;
        }
@@ -475,17 +534,64 @@ config_getserver(struct httpd *env, stru
                        goto fail;
                s += srv->srv_conf.return_uri_len;
        }
-       if (srv->srv_conf.tls_cert_len != 0) {
+
+       return (0);
+
+ fail:
+       if (imsg->fd != -1)
+               close(imsg->fd);
+       if (srv != NULL)
+               free(srv->srv_conf.return_uri);
+       free(srv);
+
+       return (-1);
+}
+
+int
+config_gettls(struct httpd *env, struct imsg *imsg)
+{
+#ifdef DEBUG
+       struct privsep          *ps = env->sc_ps;
+#endif
+       struct server           *srv = NULL;
+       struct tls_config        tls_conf;
+       u_int8_t                *p = imsg->data;
+       size_t                   s;
+
+       IMSG_SIZE_CHECK(imsg, &tls_conf);
+       memcpy(&tls_conf, p, sizeof(tls_conf));
+       s = sizeof(tls_conf);
+
+       if ((IMSG_DATA_SIZE(imsg) - s) <
+           (tls_conf.tls_cert_len + tls_conf.tls_key_len)) {
+               log_debug("%s: invalid message length", __func__);
+               goto fail;
+       }
+
+       /* Find server with matching listening socket. */
+       if ((srv = server_byaddr((struct sockaddr *)
+           &tls_conf.ss, tls_conf.port)) == NULL) {
+               log_debug("%s: server not found", __func__);
+               goto fail;
+       }
+
+       DPRINTF("%s: %s %d TLS configuration \"%s[%u]\"", __func__,
+           ps->ps_title[privsep_process], ps->ps_instance,
+           srv->srv_conf.name, srv->srv_conf.id);
+
+       if (tls_conf.tls_cert_len != 0) {
+               srv->srv_conf.tls_cert_len = tls_conf.tls_cert_len;
                if ((srv->srv_conf.tls_cert = get_data(p + s,
-                   srv->srv_conf.tls_cert_len)) == NULL)
+                   tls_conf.tls_cert_len)) == NULL)
                        goto fail;
-               s += srv->srv_conf.tls_cert_len;
+               s += tls_conf.tls_cert_len;
        }
-       if (srv->srv_conf.tls_key_len != 0) {
+       if (tls_conf.tls_key_len != 0) {
+               srv->srv_conf.tls_key_len = tls_conf.tls_key_len;
                if ((srv->srv_conf.tls_key = get_data(p + s,
-                   srv->srv_conf.tls_key_len)) == NULL)
+                   tls_conf.tls_key_len)) == NULL)
                        goto fail;
-               s += srv->srv_conf.tls_key_len;
+               s += tls_conf.tls_key_len;
        }
 
        return (0);
@@ -493,11 +599,6 @@ config_getserver(struct httpd *env, stru
  fail:
        if (imsg->fd != -1)
                close(imsg->fd);
-       if (srv != NULL) {
-               free(srv->srv_conf.tls_cert);
-               free(srv->srv_conf.tls_key);
-       }
-       free(srv);
 
        return (-1);
 }
Index: httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.82
diff -u -p -r1.82 httpd.h
--- httpd.h     15 Mar 2015 22:08:45 -0000      1.82
+++ httpd.h     14 May 2015 13:58:57 -0000
@@ -199,6 +199,7 @@ enum imsg_type {
        IMSG_CTL_START,
        IMSG_CTL_REOPEN,
        IMSG_CFG_SERVER,
+       IMSG_CFG_TLS,
        IMSG_CFG_MEDIA,
        IMSG_CFG_AUTH,
        IMSG_CFG_DONE,
@@ -436,6 +437,18 @@ struct server_config {
 };
 TAILQ_HEAD(serverhosts, server_config);
 
+struct tls_config {
+       u_int32_t                id;
+
+       in_port_t                port;
+       struct sockaddr_storage  ss;
+
+       u_int8_t                *tls_cert;
+       size_t                   tls_cert_len;
+       u_int8_t                *tls_key;
+       size_t                   tls_key_len;
+};
+
 struct server {
        TAILQ_ENTRY(server)      srv_entry;
        struct server_config     srv_conf;
@@ -674,7 +687,9 @@ int  config_setreset(struct httpd *, u_i
 int     config_getreset(struct httpd *, struct imsg *);
 int     config_getcfg(struct httpd *, struct imsg *);
 int     config_setserver(struct httpd *, struct server *);
+int     config_settls(struct httpd *, struct server *);
 int     config_getserver(struct httpd *, struct imsg *);
+int     config_gettls(struct httpd *, struct imsg *);
 int     config_setmedia(struct httpd *, struct media_type *);
 int     config_getmedia(struct httpd *, struct imsg *);
 int     config_setauth(struct httpd *, struct auth *);
Index: server.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server.c,v
retrieving revision 1.63
diff -u -p -r1.63 server.c
--- server.c    23 Apr 2015 16:59:28 -0000      1.63
+++ server.c    14 May 2015 13:58:57 -0000
@@ -1118,6 +1118,9 @@ server_dispatch_parent(int fd, struct pr
        case IMSG_CFG_SERVER:
                config_getserver(env, imsg);
                break;
+       case IMSG_CFG_TLS:
+               config_gettls(env, imsg);
+               break;
        case IMSG_CFG_DONE:
                config_getcfg(env, imsg);
                break;

-- 

    "Action without study is fatal. Study without action is futile."
        -- Mary Ritter Beard

Reply via email to