|
|
4be148 |
Adapt to headers being included in a different order in sendto_kdc.c.
|
|
|
4be148 |
Drop portions which drop checkhost.c and checkhost.h.
|
|
|
4be148 |
|
|
|
4be148 |
commit 472349d2a47fbc7db82e46ba46411b95c312fc1f
|
|
|
4be148 |
Author: Greg Hudson <ghudson@mit.edu>
|
|
|
4be148 |
Date: Sun Jun 22 10:42:14 2014 -0400
|
|
|
4be148 |
|
|
|
4be148 |
Move KKDCP OpenSSL code to an internal plugin
|
|
|
4be148 |
|
|
|
4be148 |
Create an internal pluggable interface "tls" with one in-tree dynamic
|
|
|
4be148 |
plugin module named "k5tls". Move all of the OpenSSL calls to the
|
|
|
4be148 |
plugin module, and make the libkrb5 code load and invoke the plugin.
|
|
|
4be148 |
This way we do not load or initialize libssl unless an HTTP proxy is
|
|
|
4be148 |
used.
|
|
|
4be148 |
|
|
|
4be148 |
ticket: 7929
|
|
|
4be148 |
|
|
|
4be148 |
diff --git a/src/Makefile.in b/src/Makefile.in
|
|
|
4be148 |
index 5e2cf4e..92bb60a 100644
|
|
|
4be148 |
--- a/src/Makefile.in
|
|
|
4be148 |
+++ b/src/Makefile.in
|
|
|
4be148 |
@@ -20,6 +20,7 @@ SUBDIRS=util include lib \
|
|
|
4be148 |
@ldap_plugin_dir@ \
|
|
|
4be148 |
plugins/preauth/otp \
|
|
|
4be148 |
plugins/preauth/pkinit \
|
|
|
4be148 |
+ plugins/tls/k5tls \
|
|
|
4be148 |
kdc kadmin slave clients appl tests \
|
|
|
4be148 |
config-files build-tools man doc @po@
|
|
|
4be148 |
WINSUBDIRS=include util lib ccapi windows clients appl
|
|
|
4be148 |
@@ -62,7 +63,7 @@ INSTALLMKDIRS = $(KRB5ROOT) $(KRB5MANROOT) $(KRB5OTHERMKDIRS) \
|
|
|
4be148 |
$(KRB5_LIBDIR) $(KRB5_INCDIR) \
|
|
|
4be148 |
$(KRB5_DB_MODULE_DIR) $(KRB5_PA_MODULE_DIR) \
|
|
|
4be148 |
$(KRB5_AD_MODULE_DIR) \
|
|
|
4be148 |
- $(KRB5_LIBKRB5_MODULE_DIR) \
|
|
|
4be148 |
+ $(KRB5_LIBKRB5_MODULE_DIR) $(KRB5_TLS_MODULE_DIR) \
|
|
|
4be148 |
@localstatedir@ @localstatedir@/krb5kdc \
|
|
|
4be148 |
$(KRB5_INCSUBDIRS) $(datadir) $(EXAMPLEDIR) \
|
|
|
4be148 |
$(PKGCONFIG_DIR)
|
|
|
4be148 |
diff --git a/src/config/pre.in b/src/config/pre.in
|
|
|
4be148 |
index e1d7e4b..fd8ee56 100644
|
|
|
4be148 |
--- a/src/config/pre.in
|
|
|
4be148 |
+++ b/src/config/pre.in
|
|
|
4be148 |
@@ -213,6 +213,7 @@ KRB5_DB_MODULE_DIR = $(MODULE_DIR)/kdb
|
|
|
4be148 |
KRB5_PA_MODULE_DIR = $(MODULE_DIR)/preauth
|
|
|
4be148 |
KRB5_AD_MODULE_DIR = $(MODULE_DIR)/authdata
|
|
|
4be148 |
KRB5_LIBKRB5_MODULE_DIR = $(MODULE_DIR)/libkrb5
|
|
|
4be148 |
+KRB5_TLS_MODULE_DIR = $(MODULE_DIR)/tls
|
|
|
4be148 |
KRB5_LOCALEDIR = @localedir@
|
|
|
4be148 |
GSS_MODULE_DIR = @libdir@/gss
|
|
|
4be148 |
KRB5_INCSUBDIRS = \
|
|
|
4be148 |
diff --git a/src/configure.in b/src/configure.in
|
|
|
4be148 |
index 8aa513e..43509ab 100644
|
|
|
4be148 |
--- a/src/configure.in
|
|
|
4be148 |
+++ b/src/configure.in
|
|
|
4be148 |
@@ -308,6 +308,11 @@ no)
|
|
|
4be148 |
;;
|
|
|
4be148 |
esac
|
|
|
4be148 |
|
|
|
4be148 |
+if test "$PROXY_TLS_IMPL" = no; then
|
|
|
4be148 |
+ AC_DEFINE(PROXY_TLS_IMPL_NONE,1,
|
|
|
4be148 |
+ [Define if no HTTP TLS implementation is selected])
|
|
|
4be148 |
+fi
|
|
|
4be148 |
+
|
|
|
4be148 |
AC_SUBST(PROXY_TLS_IMPL)
|
|
|
4be148 |
AC_SUBST(PROXY_TLS_IMPL_CFLAGS)
|
|
|
4be148 |
AC_SUBST(PROXY_TLS_IMPL_LIBS)
|
|
|
4be148 |
@@ -1386,6 +1391,7 @@ dnl ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
|
|
|
4be148 |
plugins/authdata/greet
|
|
|
4be148 |
plugins/authdata/greet_client
|
|
|
4be148 |
plugins/authdata/greet_server
|
|
|
4be148 |
+ plugins/tls/k5tls
|
|
|
4be148 |
|
|
|
4be148 |
clients clients/klist clients/kinit clients/kvno
|
|
|
4be148 |
clients/kdestroy clients/kpasswd clients/ksu clients/kswitch
|
|
|
4be148 |
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
|
|
4be148 |
index 9f14ee0..38846eb 100644
|
|
|
4be148 |
--- a/src/include/k5-int.h
|
|
|
4be148 |
+++ b/src/include/k5-int.h
|
|
|
4be148 |
@@ -1083,7 +1083,8 @@ struct plugin_interface {
|
|
|
4be148 |
#define PLUGIN_INTERFACE_LOCALAUTH 5
|
|
|
4be148 |
#define PLUGIN_INTERFACE_HOSTREALM 6
|
|
|
4be148 |
#define PLUGIN_INTERFACE_AUDIT 7
|
|
|
4be148 |
-#define PLUGIN_NUM_INTERFACES 8
|
|
|
4be148 |
+#define PLUGIN_INTERFACE_TLS 8
|
|
|
4be148 |
+#define PLUGIN_NUM_INTERFACES 9
|
|
|
4be148 |
|
|
|
4be148 |
/* Retrieve the plugin module of type interface_id and name modname,
|
|
|
4be148 |
* storing the result into module. */
|
|
|
4be148 |
@@ -1126,6 +1127,7 @@ typedef struct krb5_preauth_context_st krb5_preauth_context;
|
|
|
4be148 |
struct ccselect_module_handle;
|
|
|
4be148 |
struct localauth_module_handle;
|
|
|
4be148 |
struct hostrealm_module_handle;
|
|
|
4be148 |
+struct k5_tls_vtable_st;
|
|
|
4be148 |
struct _krb5_context {
|
|
|
4be148 |
krb5_magic magic;
|
|
|
4be148 |
krb5_enctype *in_tkt_etypes;
|
|
|
4be148 |
@@ -1169,6 +1171,9 @@ struct _krb5_context {
|
|
|
4be148 |
/* hostrealm module stuff */
|
|
|
4be148 |
struct hostrealm_module_handle **hostrealm_handles;
|
|
|
4be148 |
|
|
|
4be148 |
+ /* TLS module vtable (if loaded) */
|
|
|
4be148 |
+ struct k5_tls_vtable_st *tls;
|
|
|
4be148 |
+
|
|
|
4be148 |
/* error detail info */
|
|
|
4be148 |
struct errinfo err;
|
|
|
4be148 |
|
|
|
4be148 |
diff --git a/src/include/k5-tls.h b/src/include/k5-tls.h
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..0661c05
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/include/k5-tls.h
|
|
|
4be148 |
@@ -0,0 +1,104 @@
|
|
|
4be148 |
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
4be148 |
+/* include/k5-tls.h - internal pluggable interface for TLS */
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
|
|
|
4be148 |
+ * All rights reserved.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * Redistribution and use in source and binary forms, with or without
|
|
|
4be148 |
+ * modification, are permitted provided that the following conditions
|
|
|
4be148 |
+ * are met:
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * * Redistributions of source code must retain the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * * Redistributions in binary form must reproduce the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer in
|
|
|
4be148 |
+ * the documentation and/or other materials provided with the
|
|
|
4be148 |
+ * distribution.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
4be148 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
4be148 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
4be148 |
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
4be148 |
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
4be148 |
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
4be148 |
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
4be148 |
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
4be148 |
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
4be148 |
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
4be148 |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
4be148 |
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * This internal pluggable interface allows libkrb5 to load an in-tree module
|
|
|
4be148 |
+ * providing TLS support at runtime. It is currently tailored for the needs of
|
|
|
4be148 |
+ * the OpenSSL module as used for HTTP proxy support. As an internal
|
|
|
4be148 |
+ * interface, it can be changed to fit different implementations and consumers
|
|
|
4be148 |
+ * without regard for backward compatibility.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+
|
|
|
4be148 |
+#ifndef K5_TLS_H
|
|
|
4be148 |
+#define K5_TLS_H
|
|
|
4be148 |
+
|
|
|
4be148 |
+#include "k5-int.h"
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* An abstract type for localauth module data. */
|
|
|
4be148 |
+typedef struct k5_tls_handle_st *k5_tls_handle;
|
|
|
4be148 |
+
|
|
|
4be148 |
+typedef enum {
|
|
|
4be148 |
+ DATA_READ, DONE, WANT_READ, WANT_WRITE, ERROR_TLS
|
|
|
4be148 |
+} k5_tls_status;
|
|
|
4be148 |
+
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Create a handle for fd, where the server certificate must match servername
|
|
|
4be148 |
+ * and be trusted according to anchors. anchors is a null-terminated list
|
|
|
4be148 |
+ * using the DIR:/FILE:/ENV: syntax borrowed from PKINIT. If anchors is null,
|
|
|
4be148 |
+ * use the system default trust anchors.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+typedef krb5_error_code
|
|
|
4be148 |
+(*k5_tls_setup_fn)(krb5_context context, SOCKET fd, const char *servername,
|
|
|
4be148 |
+ char **anchors, k5_tls_handle *handle_out);
|
|
|
4be148 |
+
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Write len bytes of data using TLS. Return DONE if writing is complete,
|
|
|
4be148 |
+ * WANT_READ or WANT_WRITE if the underlying socket must be readable or
|
|
|
4be148 |
+ * writable to continue, and ERROR_TLS if the TLS channel or underlying socket
|
|
|
4be148 |
+ * experienced an error. After WANT_READ or WANT_WRITE, the operation will be
|
|
|
4be148 |
+ * retried with the same arguments even if some data has already been written.
|
|
|
4be148 |
+ * (OpenSSL makes this contract easy to fulfill. For other implementations we
|
|
|
4be148 |
+ * might want to change it.)
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+typedef k5_tls_status
|
|
|
4be148 |
+(*k5_tls_write_fn)(krb5_context context, k5_tls_handle handle,
|
|
|
4be148 |
+ const void *data, size_t len);
|
|
|
4be148 |
+
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Read up to data_size bytes of data using TLS. Return DATA_READ and set
|
|
|
4be148 |
+ * *len_out if any data is read. Return DONE if there is no more data to be
|
|
|
4be148 |
+ * read on the connection, WANT_READ or WANT_WRITE if the underlying socket
|
|
|
4be148 |
+ * must be readable or writable to continue, and ERROR_TLS if the TLS channel
|
|
|
4be148 |
+ * or underlying socket experienced an error.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * After DATA_READ, there may still be pending buffered data to read. The
|
|
|
4be148 |
+ * caller must call this method again with additional buffer space before
|
|
|
4be148 |
+ * selecting for reading on the underlying socket.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+typedef k5_tls_status
|
|
|
4be148 |
+(*k5_tls_read_fn)(krb5_context context, k5_tls_handle handle, void *data,
|
|
|
4be148 |
+ size_t data_size, size_t *len_out);
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Release a handle. Do not pass a null pointer. */
|
|
|
4be148 |
+typedef void
|
|
|
4be148 |
+(*k5_tls_free_handle_fn)(krb5_context context, k5_tls_handle handle);
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* All functions are mandatory unless they are all null, in which case the
|
|
|
4be148 |
+ * caller should assume that TLS is unsupported. */
|
|
|
4be148 |
+typedef struct k5_tls_vtable_st {
|
|
|
4be148 |
+ k5_tls_setup_fn setup;
|
|
|
4be148 |
+ k5_tls_write_fn write;
|
|
|
4be148 |
+ k5_tls_read_fn read;
|
|
|
4be148 |
+ k5_tls_free_handle_fn free_handle;
|
|
|
4be148 |
+} *k5_tls_vtable;
|
|
|
4be148 |
+
|
|
|
4be148 |
+#endif /* K5_TLS_H */
|
|
|
4be148 |
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
|
|
|
4be148 |
index 9e75b29..a0aa85a 100644
|
|
|
4be148 |
--- a/src/include/k5-trace.h
|
|
|
4be148 |
+++ b/src/include/k5-trace.h
|
|
|
4be148 |
@@ -324,23 +324,11 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
|
|
|
4be148 |
TRACE(c, "Resolving hostname {str}", hostname)
|
|
|
4be148 |
#define TRACE_SENDTO_KDC_RESPONSE(c, len, raddr) \
|
|
|
4be148 |
TRACE(c, "Received answer ({int} bytes) from {raddr}", len, raddr)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_SERVER_NAME_MISMATCH(c, hostname) \
|
|
|
4be148 |
- TRACE(c, "HTTPS certificate name mismatch: server certificate is " \
|
|
|
4be148 |
- "not for \"{str}\"", hostname)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_SERVER_NAME_MATCH(c, hostname) \
|
|
|
4be148 |
- TRACE(c, "HTTPS certificate name matched \"{str}\"", hostname)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_NO_REMOTE_CERTIFICATE(c) \
|
|
|
4be148 |
- TRACE(c, "HTTPS server certificate not received")
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_PROXY_CERTIFICATE_ERROR(c, depth, \
|
|
|
4be148 |
- namelen, name, \
|
|
|
4be148 |
- err, errs) \
|
|
|
4be148 |
- TRACE(c, "HTTPS certificate error at {int} ({lenstr}): " \
|
|
|
4be148 |
- "{int} ({str})", depth, namelen, name, err, errs)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(c, raddr) \
|
|
|
4be148 |
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(c, raddr) \
|
|
|
4be148 |
TRACE(c, "HTTPS error connecting to {raddr}", raddr)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(c, raddr, err) \
|
|
|
4be148 |
- TRACE(c, "HTTPS error receiving from {raddr}: {errno}", raddr, err)
|
|
|
4be148 |
-#define TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(c, raddr) \
|
|
|
4be148 |
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(c, raddr) \
|
|
|
4be148 |
+ TRACE(c, "HTTPS error receiving from {raddr}", raddr)
|
|
|
4be148 |
+#define TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(c, raddr) \
|
|
|
4be148 |
TRACE(c, "HTTPS error sending to {raddr}", raddr)
|
|
|
4be148 |
#define TRACE_SENDTO_KDC_HTTPS_SEND(c, raddr) \
|
|
|
4be148 |
TRACE(c, "Sending HTTPS request to {raddr}", raddr)
|
|
|
4be148 |
@@ -383,6 +371,19 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
|
|
|
4be148 |
TRACE(c, "TGS reply didn't decode with subkey; trying session key " \
|
|
|
4be148 |
"({keyblock)}", keyblock)
|
|
|
4be148 |
|
|
|
4be148 |
+#define TRACE_TLS_ERROR(c, errs) \
|
|
|
4be148 |
+ TRACE(c, "TLS error: {str}", errs)
|
|
|
4be148 |
+#define TRACE_TLS_NO_REMOTE_CERTIFICATE(c) \
|
|
|
4be148 |
+ TRACE(c, "TLS server certificate not received")
|
|
|
4be148 |
+#define TRACE_TLS_CERT_ERROR(c, depth, namelen, name, err, errs) \
|
|
|
4be148 |
+ TRACE(c, "TLS certificate error at {int} ({lenstr}): {int} ({str})", \
|
|
|
4be148 |
+ depth, namelen, name, err, errs)
|
|
|
4be148 |
+#define TRACE_TLS_SERVER_NAME_MISMATCH(c, hostname) \
|
|
|
4be148 |
+ TRACE(c, "TLS certificate name mismatch: server certificate is " \
|
|
|
4be148 |
+ "not for \"{str}\"", hostname)
|
|
|
4be148 |
+#define TRACE_TLS_SERVER_NAME_MATCH(c, hostname) \
|
|
|
4be148 |
+ TRACE(c, "TLS certificate name matched \"{str}\"", hostname)
|
|
|
4be148 |
+
|
|
|
4be148 |
#define TRACE_TKT_CREDS(c, creds, cache) \
|
|
|
4be148 |
TRACE(c, "Getting credentials {creds} using ccache {ccache}", \
|
|
|
4be148 |
creds, cache)
|
|
|
4be148 |
diff --git a/src/lib/krb5/Makefile.in b/src/lib/krb5/Makefile.in
|
|
|
4be148 |
index 472c008..d9cddc1 100644
|
|
|
4be148 |
--- a/src/lib/krb5/Makefile.in
|
|
|
4be148 |
+++ b/src/lib/krb5/Makefile.in
|
|
|
4be148 |
@@ -56,8 +56,7 @@ RELDIR=krb5
|
|
|
4be148 |
SHLIB_EXPDEPS = \
|
|
|
4be148 |
$(TOPLIBD)/libk5crypto$(SHLIBEXT) \
|
|
|
4be148 |
$(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB)
|
|
|
4be148 |
-SHLIB_EXPLIBS=-lk5crypto -lcom_err $(PROXY_TLS_IMPL_LIBS) $(SUPPORT_LIB) \
|
|
|
4be148 |
- @GEN_LIB@ $(LIBS)
|
|
|
4be148 |
+SHLIB_EXPLIBS=-lk5crypto -lcom_err $(SUPPORT_LIB) @GEN_LIB@ $(LIBS)
|
|
|
4be148 |
|
|
|
4be148 |
all-unix:: all-liblinks
|
|
|
4be148 |
|
|
|
4be148 |
diff --git a/src/lib/krb5/krb/copy_ctx.c b/src/lib/krb5/krb/copy_ctx.c
|
|
|
4be148 |
index 4237023..322c288 100644
|
|
|
4be148 |
--- a/src/lib/krb5/krb/copy_ctx.c
|
|
|
4be148 |
+++ b/src/lib/krb5/krb/copy_ctx.c
|
|
|
4be148 |
@@ -81,6 +81,7 @@ krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
|
|
|
4be148 |
nctx->ccselect_handles = NULL;
|
|
|
4be148 |
nctx->localauth_handles = NULL;
|
|
|
4be148 |
nctx->hostrealm_handles = NULL;
|
|
|
4be148 |
+ nctx->tls = NULL;
|
|
|
4be148 |
nctx->kdblog_context = NULL;
|
|
|
4be148 |
nctx->trace_callback = NULL;
|
|
|
4be148 |
nctx->trace_callback_data = NULL;
|
|
|
4be148 |
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
|
|
4be148 |
index 6801bb1..6548f36 100644
|
|
|
4be148 |
--- a/src/lib/krb5/krb/init_ctx.c
|
|
|
4be148 |
+++ b/src/lib/krb5/krb/init_ctx.c
|
|
|
4be148 |
@@ -319,6 +319,7 @@ krb5_free_context(krb5_context ctx)
|
|
|
4be148 |
k5_localauth_free_context(ctx);
|
|
|
4be148 |
k5_plugin_free_context(ctx);
|
|
|
4be148 |
free(ctx->plugin_base_dir);
|
|
|
4be148 |
+ free(ctx->tls);
|
|
|
4be148 |
|
|
|
4be148 |
ctx->magic = 0;
|
|
|
4be148 |
free(ctx);
|
|
|
4be148 |
diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
|
|
|
4be148 |
index 8b62c7b..7375f51 100644
|
|
|
4be148 |
--- a/src/lib/krb5/krb/plugin.c
|
|
|
4be148 |
+++ b/src/lib/krb5/krb/plugin.c
|
|
|
4be148 |
@@ -55,7 +55,8 @@ const char *interface_names[] = {
|
|
|
4be148 |
"ccselect",
|
|
|
4be148 |
"localauth",
|
|
|
4be148 |
"hostrealm",
|
|
|
4be148 |
- "audit"
|
|
|
4be148 |
+ "audit",
|
|
|
4be148 |
+ "tls"
|
|
|
4be148 |
};
|
|
|
4be148 |
|
|
|
4be148 |
/* Return the context's interface structure for id, or NULL if invalid. */
|
|
|
4be148 |
diff --git a/src/lib/krb5/krb5_libinit.c b/src/lib/krb5/krb5_libinit.c
|
|
|
4be148 |
index b72bc58..eb40124 100644
|
|
|
4be148 |
--- a/src/lib/krb5/krb5_libinit.c
|
|
|
4be148 |
+++ b/src/lib/krb5/krb5_libinit.c
|
|
|
4be148 |
@@ -55,8 +55,6 @@ int krb5int_lib_init(void)
|
|
|
4be148 |
if (err)
|
|
|
4be148 |
return err;
|
|
|
4be148 |
|
|
|
4be148 |
- k5_sendto_kdc_initialize();
|
|
|
4be148 |
-
|
|
|
4be148 |
return 0;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in
|
|
|
4be148 |
index fa8a093..ea68990 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/Makefile.in
|
|
|
4be148 |
+++ b/src/lib/krb5/os/Makefile.in
|
|
|
4be148 |
@@ -2,7 +2,7 @@ mydir=lib$(S)krb5$(S)os
|
|
|
4be148 |
BUILDTOP=$(REL)..$(S)..$(S)..
|
|
|
4be148 |
DEFINES=-DLIBDIR=\"$(KRB5_LIBDIR)\" -DBINDIR=\"$(CLIENT_BINDIR)\" \
|
|
|
4be148 |
-DSBINDIR=\"$(ADMIN_BINDIR)\"
|
|
|
4be148 |
-LOCALINCLUDES= $(PROXY_TLS_IMPL_CFLAGS) -I$(top_srcdir)/util/profile
|
|
|
4be148 |
+LOCALINCLUDES= -I$(top_srcdir)/util/profile
|
|
|
4be148 |
|
|
|
4be148 |
##DOS##BUILDTOP = ..\..\..
|
|
|
4be148 |
##DOS##PREFIXDIR=os
|
|
|
4be148 |
@@ -13,7 +13,6 @@ STLIBOBJS= \
|
|
|
4be148 |
c_ustime.o \
|
|
|
4be148 |
ccdefname.o \
|
|
|
4be148 |
changepw.o \
|
|
|
4be148 |
- checkhost.o \
|
|
|
4be148 |
dnsglue.o \
|
|
|
4be148 |
dnssrv.o \
|
|
|
4be148 |
expand_path.o \
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/deps b/src/lib/krb5/os/deps
|
|
|
4be148 |
index d56ff30..211354c 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/deps
|
|
|
4be148 |
+++ b/src/lib/krb5/os/deps
|
|
|
4be148 |
@@ -49,17 +49,6 @@ changepw.so changepw.po $(OUTPRE)changepw.$(OBJEXT): \
|
|
|
4be148 |
$(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \
|
|
|
4be148 |
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
|
|
|
4be148 |
changepw.c os-proto.h
|
|
|
4be148 |
-checkhost.so checkhost.po $(OUTPRE)checkhost.$(OBJEXT): \
|
|
|
4be148 |
- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
|
|
|
4be148 |
- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
|
|
|
4be148 |
- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
|
|
|
4be148 |
- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
|
|
|
4be148 |
- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
|
|
|
4be148 |
- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
|
|
|
4be148 |
- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \
|
|
|
4be148 |
- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
|
|
|
4be148 |
- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
|
|
|
4be148 |
- $(top_srcdir)/include/socket-utils.h checkhost.c checkhost.h
|
|
|
4be148 |
dnsglue.so dnsglue.po $(OUTPRE)dnsglue.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
|
|
|
4be148 |
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
|
|
|
4be148 |
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
|
|
|
4be148 |
@@ -429,7 +418,7 @@ sendto_kdc.so sendto_kdc.po $(OUTPRE)sendto_kdc.$(OBJEXT): \
|
|
|
4be148 |
$(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
|
|
|
4be148 |
$(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
|
|
|
4be148 |
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
|
|
|
4be148 |
- $(top_srcdir)/include/socket-utils.h checkhost.h os-proto.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/socket-utils.h os-proto.h \
|
|
|
4be148 |
sendto_kdc.c
|
|
|
4be148 |
sn2princ.so sn2princ.po $(OUTPRE)sn2princ.$(OBJEXT): \
|
|
|
4be148 |
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
|
|
|
4be148 |
index 1f2039c..160a2d0 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/locate_kdc.c
|
|
|
4be148 |
+++ b/src/lib/krb5/os/locate_kdc.c
|
|
|
4be148 |
@@ -177,7 +177,6 @@ oom:
|
|
|
4be148 |
return ENOMEM;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
static void
|
|
|
4be148 |
parse_uri_if_https(char *host_or_uri, k5_transport *transport, char **host,
|
|
|
4be148 |
char **uri_path)
|
|
|
4be148 |
@@ -195,13 +194,6 @@ parse_uri_if_https(char *host_or_uri, k5_transport *transport, char **host,
|
|
|
4be148 |
}
|
|
|
4be148 |
}
|
|
|
4be148 |
}
|
|
|
4be148 |
-#else
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-parse_uri_if_https(char *host_or_uri, k5_transport *transport, char **host,
|
|
|
4be148 |
- char **uri)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-}
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
|
|
|
4be148 |
/* Return true if server is identical to an entry in list. */
|
|
|
4be148 |
static krb5_boolean
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
|
|
|
4be148 |
index 34bf028..69ee376 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/os-proto.h
|
|
|
4be148 |
+++ b/src/lib/krb5/os/os-proto.h
|
|
|
4be148 |
@@ -187,6 +187,5 @@ krb5_error_code localauth_k5login_initvt(krb5_context context, int maj_ver,
|
|
|
4be148 |
krb5_plugin_vtable vtable);
|
|
|
4be148 |
krb5_error_code localauth_an2ln_initvt(krb5_context context, int maj_ver,
|
|
|
4be148 |
int min_ver, krb5_plugin_vtable vtable);
|
|
|
4be148 |
-void k5_sendto_kdc_initialize(void);
|
|
|
4be148 |
|
|
|
4be148 |
#endif /* KRB5_LIBOS_INT_PROTO__ */
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
index a572831..2242240 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
+++ b/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
@@ -54,6 +54,7 @@
|
|
|
4be148 |
* as necessary. */
|
|
|
4be148 |
|
|
|
4be148 |
#include "fake-addrinfo.h"
|
|
|
4be148 |
+#include "k5-tls.h"
|
|
|
4be148 |
#include "k5-int.h"
|
|
|
4be148 |
|
|
|
4be148 |
#include "os-proto.h"
|
|
|
4be148 |
@@ -74,15 +75,6 @@
|
|
|
4be148 |
#endif
|
|
|
4be148 |
#endif
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
-#include <openssl/err.h>
|
|
|
4be148 |
-#include <openssl/ssl.h>
|
|
|
4be148 |
-#include <openssl/x509.h>
|
|
|
4be148 |
-#include <openssl/x509v3.h>
|
|
|
4be148 |
-#include <dirent.h>
|
|
|
4be148 |
-#include "checkhost.h"
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
-
|
|
|
4be148 |
#define MAX_PASS 3
|
|
|
4be148 |
#define DEFAULT_UDP_PREF_LIMIT 1465
|
|
|
4be148 |
#define HARD_UDP_LIMIT 32700 /* could probably do 64K-epsilon ? */
|
|
|
4be148 |
@@ -147,29 +139,30 @@ struct conn_state {
|
|
|
4be148 |
const char *uri_path;
|
|
|
4be148 |
const char *servername;
|
|
|
4be148 |
char *https_request;
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
- SSL *ssl;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
+ k5_tls_handle tls;
|
|
|
4be148 |
} http;
|
|
|
4be148 |
};
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
-/* Extra-data identifier, used to pass context into the verify callback. */
|
|
|
4be148 |
-static int ssl_ex_context_id = -1;
|
|
|
4be148 |
-static int ssl_ex_conn_id = -1;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
-
|
|
|
4be148 |
-void
|
|
|
4be148 |
-k5_sendto_kdc_initialize(void)
|
|
|
4be148 |
+/* Set up context->tls. On allocation failure, return ENOMEM. On plugin load
|
|
|
4be148 |
+ * failure, set context->tls to point to a nulled vtable and return 0. */
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+init_tls_vtable(krb5_context context)
|
|
|
4be148 |
{
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
- SSL_library_init();
|
|
|
4be148 |
- SSL_load_error_strings();
|
|
|
4be148 |
- OpenSSL_add_all_algorithms();
|
|
|
4be148 |
+ krb5_plugin_initvt_fn initfn;
|
|
|
4be148 |
|
|
|
4be148 |
- ssl_ex_context_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
|
|
4be148 |
- ssl_ex_conn_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
+ if (context->tls != NULL)
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ context->tls = calloc(1, sizeof(*context->tls));
|
|
|
4be148 |
+ if (context->tls == NULL)
|
|
|
4be148 |
+ return ENOMEM;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Attempt to load the module; just let it stay nulled out on failure. */
|
|
|
4be148 |
+ k5_plugin_register_dyn(context, PLUGIN_INTERFACE_TLS, "k5tls", "tls");
|
|
|
4be148 |
+ if (k5_plugin_load(context, PLUGIN_INTERFACE_TLS, "k5tls", &initfn) == 0)
|
|
|
4be148 |
+ (*initfn)(context, 0, 0, (krb5_plugin_vtable)context->tls);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
/* Get current time in milliseconds. */
|
|
|
4be148 |
@@ -184,21 +177,15 @@ get_curtime_ms(time_ms *time_out)
|
|
|
4be148 |
return 0;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
static void
|
|
|
4be148 |
-free_http_ssl_data(struct conn_state *state)
|
|
|
4be148 |
+free_http_tls_data(krb5_context context, struct conn_state *state)
|
|
|
4be148 |
{
|
|
|
4be148 |
- SSL_free(state->http.ssl);
|
|
|
4be148 |
- state->http.ssl = NULL;
|
|
|
4be148 |
+ if (state->http.tls != NULL)
|
|
|
4be148 |
+ context->tls->free_handle(context, state->http.tls);
|
|
|
4be148 |
+ state->http.tls = NULL;
|
|
|
4be148 |
free(state->http.https_request);
|
|
|
4be148 |
state->http.https_request = NULL;
|
|
|
4be148 |
}
|
|
|
4be148 |
-#else
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-free_http_ssl_data(struct conn_state *state)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-}
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
|
|
|
4be148 |
#ifdef USE_POLL
|
|
|
4be148 |
|
|
|
4be148 |
@@ -532,7 +519,6 @@ static fd_handler_fn service_udp_read;
|
|
|
4be148 |
static fd_handler_fn service_https_write;
|
|
|
4be148 |
static fd_handler_fn service_https_read;
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
static krb5_error_code
|
|
|
4be148 |
make_proxy_request(struct conn_state *state, const krb5_data *realm,
|
|
|
4be148 |
const krb5_data *message, char **req_out, size_t *len_out)
|
|
|
4be148 |
@@ -585,14 +571,6 @@ cleanup:
|
|
|
4be148 |
krb5_free_data(NULL, encoded_pm);
|
|
|
4be148 |
return ret;
|
|
|
4be148 |
}
|
|
|
4be148 |
-#else
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-make_proxy_request(struct conn_state *state, const krb5_data *realm,
|
|
|
4be148 |
- const krb5_data *message, char **req_out, size_t *len_out)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- abort();
|
|
|
4be148 |
-}
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
|
|
|
4be148 |
/* Set up the actual message we will send across the underlying transport to
|
|
|
4be148 |
* communicate the payload message, using one or both of state->out.sgbuf. */
|
|
|
4be148 |
@@ -963,7 +941,7 @@ static void
|
|
|
4be148 |
kill_conn(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
struct select_state *selstate)
|
|
|
4be148 |
{
|
|
|
4be148 |
- free_http_ssl_data(conn);
|
|
|
4be148 |
+ free_http_tls_data(context, conn);
|
|
|
4be148 |
|
|
|
4be148 |
if (socktype_for_transport(conn->addr.transport) == SOCK_STREAM)
|
|
|
4be148 |
TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &conn->addr);
|
|
|
4be148 |
@@ -1145,249 +1123,44 @@ service_udp_read(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
return TRUE;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
-#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
-/* Output any error strings that OpenSSL's accumulated as tracing messages. */
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-flush_ssl_errors(krb5_context context)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- unsigned long err;
|
|
|
4be148 |
- char buf[128];
|
|
|
4be148 |
-
|
|
|
4be148 |
- while ((err = ERR_get_error()) != 0) {
|
|
|
4be148 |
- ERR_error_string_n(err, buf, sizeof(buf));
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_ERROR(context, buf);
|
|
|
4be148 |
- }
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-load_http_anchor_file(X509_STORE *store, const char *path)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- FILE *fp;
|
|
|
4be148 |
- STACK_OF(X509_INFO) *sk = NULL;
|
|
|
4be148 |
- X509_INFO *xi;
|
|
|
4be148 |
- int i;
|
|
|
4be148 |
-
|
|
|
4be148 |
- fp = fopen(path, "r");
|
|
|
4be148 |
- if (fp == NULL)
|
|
|
4be148 |
- return errno;
|
|
|
4be148 |
- sk = PEM_X509_INFO_read(fp, NULL, NULL, NULL);
|
|
|
4be148 |
- fclose(fp);
|
|
|
4be148 |
- if (sk == NULL)
|
|
|
4be148 |
- return ENOENT;
|
|
|
4be148 |
- for (i = 0; i < sk_X509_INFO_num(sk); i++) {
|
|
|
4be148 |
- xi = sk_X509_INFO_value(sk, i);
|
|
|
4be148 |
- if (xi->x509 != NULL)
|
|
|
4be148 |
- X509_STORE_add_cert(store, xi->x509);
|
|
|
4be148 |
- }
|
|
|
4be148 |
- sk_X509_INFO_pop_free(sk, X509_INFO_free);
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-load_http_anchor_dir(X509_STORE *store, const char *path)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- DIR *d = NULL;
|
|
|
4be148 |
- struct dirent *dentry = NULL;
|
|
|
4be148 |
- char filename[1024];
|
|
|
4be148 |
- krb5_boolean found_any = FALSE;
|
|
|
4be148 |
-
|
|
|
4be148 |
- d = opendir(path);
|
|
|
4be148 |
- if (d == NULL)
|
|
|
4be148 |
- return ENOENT;
|
|
|
4be148 |
- while ((dentry = readdir(d)) != NULL) {
|
|
|
4be148 |
- if (dentry->d_name[0] != '.') {
|
|
|
4be148 |
- snprintf(filename, sizeof(filename), "%s/%s",
|
|
|
4be148 |
- path, dentry->d_name);
|
|
|
4be148 |
- if (load_http_anchor_file(store, filename) == 0)
|
|
|
4be148 |
- found_any = TRUE;
|
|
|
4be148 |
- }
|
|
|
4be148 |
- }
|
|
|
4be148 |
- closedir(d);
|
|
|
4be148 |
- return found_any ? 0 : ENOENT;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-load_http_anchor(SSL_CTX *ctx, const char *location)
|
|
|
4be148 |
+/* Set up conn->http.tls. Return true on success. */
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+setup_tls(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
+ struct conn_state *conn, struct select_state *selstate)
|
|
|
4be148 |
{
|
|
|
4be148 |
- X509_STORE *store;
|
|
|
4be148 |
- const char *envloc;
|
|
|
4be148 |
-
|
|
|
4be148 |
- store = SSL_CTX_get_cert_store(ctx);
|
|
|
4be148 |
- if (strncmp(location, "FILE:", 5) == 0) {
|
|
|
4be148 |
- return load_http_anchor_file(store, location + 5);
|
|
|
4be148 |
- } else if (strncmp(location, "DIR:", 4) == 0) {
|
|
|
4be148 |
- return load_http_anchor_dir(store, location + 4);
|
|
|
4be148 |
- } else if (strncmp(location, "ENV:", 4) == 0) {
|
|
|
4be148 |
- envloc = getenv(location + 4);
|
|
|
4be148 |
- if (envloc == NULL)
|
|
|
4be148 |
- return ENOENT;
|
|
|
4be148 |
- return load_http_anchor(ctx, envloc);
|
|
|
4be148 |
- }
|
|
|
4be148 |
- return EINVAL;
|
|
|
4be148 |
-}
|
|
|
4be148 |
+ krb5_error_code ret;
|
|
|
4be148 |
+ krb5_boolean ok = FALSE;
|
|
|
4be148 |
+ char **anchors = NULL, *realmstr = NULL;
|
|
|
4be148 |
+ const char *names[4];
|
|
|
4be148 |
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-load_http_verify_anchors(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
- SSL_CTX *sctx)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- const char *anchors[4];
|
|
|
4be148 |
- char **values = NULL, *realmz;
|
|
|
4be148 |
- unsigned int i;
|
|
|
4be148 |
- krb5_error_code err;
|
|
|
4be148 |
+ if (init_tls_vtable(context) != 0 || context->tls->setup == NULL)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
|
|
|
4be148 |
- realmz = k5memdup0(realm->data, realm->length, &err;;
|
|
|
4be148 |
- if (realmz == NULL)
|
|
|
4be148 |
+ realmstr = k5memdup0(realm->data, realm->length, &ret;;
|
|
|
4be148 |
+ if (realmstr == NULL)
|
|
|
4be148 |
goto cleanup;
|
|
|
4be148 |
|
|
|
4be148 |
/* Load the configured anchors. */
|
|
|
4be148 |
- anchors[0] = KRB5_CONF_REALMS;
|
|
|
4be148 |
- anchors[1] = realmz;
|
|
|
4be148 |
- anchors[2] = KRB5_CONF_HTTP_ANCHORS;
|
|
|
4be148 |
- anchors[3] = NULL;
|
|
|
4be148 |
- if (profile_get_values(context->profile, anchors, &values) == 0) {
|
|
|
4be148 |
- for (i = 0; values[i] != NULL; i++) {
|
|
|
4be148 |
- err = load_http_anchor(sctx, values[i]);
|
|
|
4be148 |
- if (err != 0)
|
|
|
4be148 |
- break;
|
|
|
4be148 |
- }
|
|
|
4be148 |
- profile_free_list(values);
|
|
|
4be148 |
- } else {
|
|
|
4be148 |
- /* Use the library defaults. */
|
|
|
4be148 |
- if (SSL_CTX_set_default_verify_paths(sctx) != 1)
|
|
|
4be148 |
- err = ENOENT;
|
|
|
4be148 |
- }
|
|
|
4be148 |
-
|
|
|
4be148 |
-cleanup:
|
|
|
4be148 |
- free(realmz);
|
|
|
4be148 |
- return err;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_boolean
|
|
|
4be148 |
-ssl_check_name_or_ip(X509 *x, const char *expected_name)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- struct in_addr in;
|
|
|
4be148 |
- struct in6_addr in6;
|
|
|
4be148 |
-
|
|
|
4be148 |
- if (inet_aton(expected_name, &in) != 0 ||
|
|
|
4be148 |
- inet_pton(AF_INET6, expected_name, &in6) != 0) {
|
|
|
4be148 |
- return k5_check_cert_address(x, expected_name);
|
|
|
4be148 |
- } else {
|
|
|
4be148 |
- return k5_check_cert_servername(x, expected_name);
|
|
|
4be148 |
- }
|
|
|
4be148 |
-}
|
|
|
4be148 |
+ names[0] = KRB5_CONF_REALMS;
|
|
|
4be148 |
+ names[1] = realmstr;
|
|
|
4be148 |
+ names[2] = KRB5_CONF_HTTP_ANCHORS;
|
|
|
4be148 |
+ names[3] = NULL;
|
|
|
4be148 |
+ ret = profile_get_values(context->profile, names, &anchors);
|
|
|
4be148 |
+ if (ret != 0 && ret != PROF_NO_RELATION)
|
|
|
4be148 |
+ goto cleanup;
|
|
|
4be148 |
|
|
|
4be148 |
-static int
|
|
|
4be148 |
-ssl_verify_callback(int preverify_ok, X509_STORE_CTX *store_ctx)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- X509 *x;
|
|
|
4be148 |
- SSL *ssl;
|
|
|
4be148 |
- BIO *bio;
|
|
|
4be148 |
- krb5_context context;
|
|
|
4be148 |
- int err, depth;
|
|
|
4be148 |
- struct conn_state *conn = NULL;
|
|
|
4be148 |
- const char *cert = NULL, *errstr, *expected_name;
|
|
|
4be148 |
- size_t count;
|
|
|
4be148 |
-
|
|
|
4be148 |
- ssl = X509_STORE_CTX_get_ex_data(store_ctx,
|
|
|
4be148 |
- SSL_get_ex_data_X509_STORE_CTX_idx());
|
|
|
4be148 |
- context = SSL_get_ex_data(ssl, ssl_ex_context_id);
|
|
|
4be148 |
- conn = SSL_get_ex_data(ssl, ssl_ex_conn_id);
|
|
|
4be148 |
- /* We do have the peer's cert, right? */
|
|
|
4be148 |
- x = X509_STORE_CTX_get_current_cert(store_ctx);
|
|
|
4be148 |
- if (x == NULL) {
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_NO_REMOTE_CERTIFICATE(context);
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
- }
|
|
|
4be148 |
- /* Figure out where we are. */
|
|
|
4be148 |
- depth = X509_STORE_CTX_get_error_depth(store_ctx);
|
|
|
4be148 |
- if (depth < 0)
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
- /* If there's an error at this level that we're not ignoring, fail. */
|
|
|
4be148 |
- err = X509_STORE_CTX_get_error(store_ctx);
|
|
|
4be148 |
- if (err != X509_V_OK) {
|
|
|
4be148 |
- bio = BIO_new(BIO_s_mem());
|
|
|
4be148 |
- if (bio != NULL) {
|
|
|
4be148 |
- X509_NAME_print_ex(bio, x->cert_info->subject, 0, 0);
|
|
|
4be148 |
- count = BIO_get_mem_data(bio, &cert);
|
|
|
4be148 |
- errstr = X509_verify_cert_error_string(err);
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_PROXY_CERTIFICATE_ERROR(context, depth,
|
|
|
4be148 |
- count, cert, err,
|
|
|
4be148 |
- errstr);
|
|
|
4be148 |
- BIO_free(bio);
|
|
|
4be148 |
- }
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
- }
|
|
|
4be148 |
- /* If we're not looking at the peer, we're done and everything's ok. */
|
|
|
4be148 |
- if (depth != 0)
|
|
|
4be148 |
- return 1;
|
|
|
4be148 |
- /* Check if the name we expect to find is in the certificate. */
|
|
|
4be148 |
- expected_name = conn->http.servername;
|
|
|
4be148 |
- if (ssl_check_name_or_ip(x, expected_name)) {
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_SERVER_NAME_MATCH(context, expected_name);
|
|
|
4be148 |
- return 1;
|
|
|
4be148 |
- } else {
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_SERVER_NAME_MISMATCH(context, expected_name);
|
|
|
4be148 |
+ if (context->tls->setup(context, conn->fd, conn->http.servername, anchors,
|
|
|
4be148 |
+ &conn->http.tls) != 0) {
|
|
|
4be148 |
+ TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(context, &conn->addr);
|
|
|
4be148 |
+ goto cleanup;
|
|
|
4be148 |
}
|
|
|
4be148 |
- /* The name didn't match. */
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
-}
|
|
|
4be148 |
|
|
|
4be148 |
-/*
|
|
|
4be148 |
- * Set up structures that we use to manage the SSL handling for this connection
|
|
|
4be148 |
- * and apply any non-default settings. Kill the connection and return false if
|
|
|
4be148 |
- * anything goes wrong while we're doing that; return true otherwise.
|
|
|
4be148 |
- */
|
|
|
4be148 |
-static krb5_boolean
|
|
|
4be148 |
-setup_ssl(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
- struct conn_state *conn, struct select_state *selstate)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- int e;
|
|
|
4be148 |
- long options;
|
|
|
4be148 |
- SSL_CTX *ctx = NULL;
|
|
|
4be148 |
- SSL *ssl = NULL;
|
|
|
4be148 |
+ ok = TRUE;
|
|
|
4be148 |
|
|
|
4be148 |
- if (ssl_ex_context_id == -1 || ssl_ex_conn_id == -1)
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
-
|
|
|
4be148 |
- /* Do general SSL library setup. */
|
|
|
4be148 |
- ctx = SSL_CTX_new(SSLv23_client_method());
|
|
|
4be148 |
- if (ctx == NULL)
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
- options = SSL_CTX_get_options(ctx);
|
|
|
4be148 |
- SSL_CTX_set_options(ctx, options | SSL_OP_NO_SSLv2);
|
|
|
4be148 |
-
|
|
|
4be148 |
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, ssl_verify_callback);
|
|
|
4be148 |
- X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), 0);
|
|
|
4be148 |
- e = load_http_verify_anchors(context, realm, ctx);
|
|
|
4be148 |
- if (e != 0)
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
-
|
|
|
4be148 |
- ssl = SSL_new(ctx);
|
|
|
4be148 |
- if (ssl == NULL)
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
-
|
|
|
4be148 |
- if (!SSL_set_ex_data(ssl, ssl_ex_context_id, context))
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
- if (!SSL_set_ex_data(ssl, ssl_ex_conn_id, conn))
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
-
|
|
|
4be148 |
- /* Tell the SSL library about the socket. */
|
|
|
4be148 |
- if (!SSL_set_fd(ssl, conn->fd))
|
|
|
4be148 |
- goto kill_conn;
|
|
|
4be148 |
- SSL_set_connect_state(ssl);
|
|
|
4be148 |
-
|
|
|
4be148 |
- SSL_CTX_free(ctx);
|
|
|
4be148 |
- conn->http.ssl = ssl;
|
|
|
4be148 |
-
|
|
|
4be148 |
- return TRUE;
|
|
|
4be148 |
-
|
|
|
4be148 |
-kill_conn:
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(context, &conn->addr);
|
|
|
4be148 |
- flush_ssl_errors(context);
|
|
|
4be148 |
- SSL_free(ssl);
|
|
|
4be148 |
- SSL_CTX_free(ctx);
|
|
|
4be148 |
- kill_conn(context, conn, selstate);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
+cleanup:
|
|
|
4be148 |
+ free(realmstr);
|
|
|
4be148 |
+ profile_free_list(anchors);
|
|
|
4be148 |
+ return ok;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
/* Set conn->state to READING when done; otherwise, call a cm_set_. */
|
|
|
4be148 |
@@ -1395,50 +1168,41 @@ static krb5_boolean
|
|
|
4be148 |
service_https_write(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
struct conn_state *conn, struct select_state *selstate)
|
|
|
4be148 |
{
|
|
|
4be148 |
- ssize_t nwritten;
|
|
|
4be148 |
- int e;
|
|
|
4be148 |
+ k5_tls_status st;
|
|
|
4be148 |
|
|
|
4be148 |
/* If this is our first time in here, set up the SSL context. */
|
|
|
4be148 |
- if (conn->http.ssl == NULL && !setup_ssl(context, realm, conn, selstate))
|
|
|
4be148 |
+ if (conn->http.tls == NULL && !setup_tls(context, realm, conn, selstate)) {
|
|
|
4be148 |
+ kill_conn(context, conn, selstate);
|
|
|
4be148 |
return FALSE;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
|
|
|
4be148 |
/* Try to transmit our request to the server. */
|
|
|
4be148 |
- nwritten = SSL_write(conn->http.ssl, SG_BUF(conn->out.sgp),
|
|
|
4be148 |
- SG_LEN(conn->out.sgbuf));
|
|
|
4be148 |
- if (nwritten <= 0) {
|
|
|
4be148 |
- e = SSL_get_error(conn->http.ssl, nwritten);
|
|
|
4be148 |
- if (e == SSL_ERROR_WANT_READ) {
|
|
|
4be148 |
- cm_read(selstate, conn->fd);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
- } else if (e == SSL_ERROR_WANT_WRITE) {
|
|
|
4be148 |
- cm_write(selstate, conn->fd);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
- }
|
|
|
4be148 |
+ st = context->tls->write(context, conn->http.tls, SG_BUF(conn->out.sgp),
|
|
|
4be148 |
+ SG_LEN(conn->out.sgbuf));
|
|
|
4be148 |
+ if (st == DONE) {
|
|
|
4be148 |
+ TRACE_SENDTO_KDC_HTTPS_SEND(context, &conn->addr);
|
|
|
4be148 |
+ cm_read(selstate, conn->fd);
|
|
|
4be148 |
+ conn->state = READING;
|
|
|
4be148 |
+ } else if (st == WANT_READ) {
|
|
|
4be148 |
+ cm_read(selstate, conn->fd);
|
|
|
4be148 |
+ } else if (st == WANT_WRITE) {
|
|
|
4be148 |
+ cm_write(selstate, conn->fd);
|
|
|
4be148 |
+ } else if (st == ERROR_TLS) {
|
|
|
4be148 |
TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(context, &conn->addr);
|
|
|
4be148 |
- flush_ssl_errors(context);
|
|
|
4be148 |
kill_conn(context, conn, selstate);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
- /* Done writing, switch to reading. */
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_SEND(context, &conn->addr);
|
|
|
4be148 |
- cm_read(selstate, conn->fd);
|
|
|
4be148 |
- conn->state = READING;
|
|
|
4be148 |
return FALSE;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
-/*
|
|
|
4be148 |
- * Return true on readable data, call a cm_read/write function and return
|
|
|
4be148 |
- * false if the SSL layer needs it, kill the connection otherwise.
|
|
|
4be148 |
- */
|
|
|
4be148 |
+/* Return true on finished data. Call a cm_read/write function and return
|
|
|
4be148 |
+ * false if the TLS layer needs it. Kill the connection on error. */
|
|
|
4be148 |
static krb5_boolean
|
|
|
4be148 |
https_read_bytes(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
struct select_state *selstate)
|
|
|
4be148 |
{
|
|
|
4be148 |
- size_t bufsize;
|
|
|
4be148 |
- ssize_t nread;
|
|
|
4be148 |
- krb5_boolean readbytes = FALSE;
|
|
|
4be148 |
- int e = 0;
|
|
|
4be148 |
+ size_t bufsize, nread;
|
|
|
4be148 |
+ k5_tls_status st;
|
|
|
4be148 |
char *tmp;
|
|
|
4be148 |
struct incoming_message *in = &conn->in;
|
|
|
4be148 |
|
|
|
4be148 |
@@ -1458,31 +1222,26 @@ https_read_bytes(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
in->bufsize = bufsize;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
- nread = SSL_read(conn->http.ssl, &in->buf[in->pos],
|
|
|
4be148 |
- in->bufsize - in->pos - 1);
|
|
|
4be148 |
- if (nread <= 0)
|
|
|
4be148 |
+ st = context->tls->read(context, conn->http.tls, &in->buf[in->pos],
|
|
|
4be148 |
+ in->bufsize - in->pos - 1, &nread);
|
|
|
4be148 |
+ if (st != DATA_READ)
|
|
|
4be148 |
break;
|
|
|
4be148 |
+
|
|
|
4be148 |
in->pos += nread;
|
|
|
4be148 |
in->buf[in->pos] = '\0';
|
|
|
4be148 |
- readbytes = TRUE;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
- e = SSL_get_error(conn->http.ssl, nread);
|
|
|
4be148 |
- if (e == SSL_ERROR_WANT_READ) {
|
|
|
4be148 |
+ if (st == DONE)
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (st == WANT_READ) {
|
|
|
4be148 |
cm_read(selstate, conn->fd);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
- } else if (e == SSL_ERROR_WANT_WRITE) {
|
|
|
4be148 |
+ } else if (st == WANT_WRITE) {
|
|
|
4be148 |
cm_write(selstate, conn->fd);
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
- } else if ((e == SSL_ERROR_ZERO_RETURN) ||
|
|
|
4be148 |
- (e == SSL_ERROR_SYSCALL && nread == 0 && readbytes)) {
|
|
|
4be148 |
- return TRUE;
|
|
|
4be148 |
+ } else if (st == ERROR_TLS) {
|
|
|
4be148 |
+ TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(context, &conn->addr);
|
|
|
4be148 |
+ kill_conn(context, conn, selstate);
|
|
|
4be148 |
}
|
|
|
4be148 |
-
|
|
|
4be148 |
- e = readbytes ? SOCKET_ERRNO : ECONNRESET;
|
|
|
4be148 |
- TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(context, &conn->addr, e);
|
|
|
4be148 |
- flush_ssl_errors(context);
|
|
|
4be148 |
- kill_conn(context, conn, selstate);
|
|
|
4be148 |
return FALSE;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
@@ -1531,20 +1290,6 @@ kill_conn:
|
|
|
4be148 |
kill_conn(context, conn, selstate);
|
|
|
4be148 |
return FALSE;
|
|
|
4be148 |
}
|
|
|
4be148 |
-#else
|
|
|
4be148 |
-static krb5_boolean
|
|
|
4be148 |
-service_https_write(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
- struct conn_state *conn, struct select_state *selstate)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- abort();
|
|
|
4be148 |
-}
|
|
|
4be148 |
-static krb5_boolean
|
|
|
4be148 |
-service_https_read(krb5_context context, const krb5_data *realm,
|
|
|
4be148 |
- struct conn_state *conn, struct select_state *selstate)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- abort();
|
|
|
4be148 |
-}
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
|
|
|
4be148 |
/* Return the maximum of endtime and the endtime fields of all currently active
|
|
|
4be148 |
* TCP connections. */
|
|
|
4be148 |
@@ -1765,7 +1510,7 @@ cleanup:
|
|
|
4be148 |
if (socktype_for_transport(state->addr.transport) == SOCK_STREAM)
|
|
|
4be148 |
TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &state->addr);
|
|
|
4be148 |
closesocket(state->fd);
|
|
|
4be148 |
- free_http_ssl_data(state);
|
|
|
4be148 |
+ free_http_tls_data(context, state);
|
|
|
4be148 |
}
|
|
|
4be148 |
if (state->state == READING && state->in.buf != udpbuf)
|
|
|
4be148 |
free(state->in.buf);
|
|
|
4be148 |
diff --git a/src/plugins/tls/k5tls/Makefile.in b/src/plugins/tls/k5tls/Makefile.in
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..4d58df0
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/plugins/tls/k5tls/Makefile.in
|
|
|
4be148 |
@@ -0,0 +1,22 @@
|
|
|
4be148 |
+mydir=plugins$(S)tls$(S)k5tls
|
|
|
4be148 |
+BUILDTOP=$(REL)..$(S)..$(S)..
|
|
|
4be148 |
+MODULE_INSTALL_DIR = $(KRB5_TLS_MODULE_DIR)
|
|
|
4be148 |
+LOCALINCLUDES= $(PROXY_TLS_IMPL_CFLAGS)
|
|
|
4be148 |
+
|
|
|
4be148 |
+LIBBASE=k5tls
|
|
|
4be148 |
+LIBMAJOR=0
|
|
|
4be148 |
+LIBMINOR=0
|
|
|
4be148 |
+RELDIR=../plugins/tls/k5tls
|
|
|
4be148 |
+SHLIB_EXPDEPS= $(KRB5_DEPLIB) $(SUPPORT_DEPLIB)
|
|
|
4be148 |
+SHLIB_EXPLIBS= $(KRB5_LIB) $(SUPPORT_LIB) $(PROXY_TLS_IMPL_LIBS)
|
|
|
4be148 |
+
|
|
|
4be148 |
+STLIBOBJS=openssl.o notls.o
|
|
|
4be148 |
+
|
|
|
4be148 |
+SRCS=$(srcdir)/openssl.c $(srcdir)/notls.c
|
|
|
4be148 |
+
|
|
|
4be148 |
+all-unix:: all-liblinks
|
|
|
4be148 |
+install-unix:: install-libs
|
|
|
4be148 |
+clean-unix:: clean-libs clean-libobjs
|
|
|
4be148 |
+
|
|
|
4be148 |
+@libnover_frag@
|
|
|
4be148 |
+@libobj_frag@
|
|
|
4be148 |
diff --git a/src/plugins/tls/k5tls/deps b/src/plugins/tls/k5tls/deps
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..a6088a7
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/plugins/tls/k5tls/deps
|
|
|
4be148 |
@@ -0,0 +1,25 @@
|
|
|
4be148 |
+#
|
|
|
4be148 |
+# Generated makefile dependencies follow.
|
|
|
4be148 |
+#
|
|
|
4be148 |
+openssl.so openssl.po $(OUTPRE)openssl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
|
|
|
4be148 |
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
|
|
|
4be148 |
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-tls.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/socket-utils.h openssl.c
|
|
|
4be148 |
+notls.so notls.po $(OUTPRE)notls.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
|
|
|
4be148 |
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
|
|
|
4be148 |
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-tls.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
|
|
|
4be148 |
+ $(top_srcdir)/include/socket-utils.h notls.c
|
|
|
4be148 |
diff --git a/src/plugins/tls/k5tls/k5tls.exports b/src/plugins/tls/k5tls/k5tls.exports
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..d67d928
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/plugins/tls/k5tls/k5tls.exports
|
|
|
4be148 |
@@ -0,0 +1 @@
|
|
|
4be148 |
+tls_k5tls_initvt
|
|
|
4be148 |
diff --git a/src/plugins/tls/k5tls/notls.c b/src/plugins/tls/k5tls/notls.c
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..7be0a4a
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/plugins/tls/k5tls/notls.c
|
|
|
4be148 |
@@ -0,0 +1,53 @@
|
|
|
4be148 |
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
4be148 |
+/* plus/tls/k5tls/none.c - Stub TLS module implementation */
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Copyright (C) 2014 by the Massachusetts Institute of Technology.
|
|
|
4be148 |
+ * All rights reserved.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * Redistribution and use in source and binary forms, with or without
|
|
|
4be148 |
+ * modification, are permitted provided that the following conditions
|
|
|
4be148 |
+ * are met:
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * * Redistributions of source code must retain the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * * Redistributions in binary form must reproduce the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer in
|
|
|
4be148 |
+ * the documentation and/or other materials provided with the
|
|
|
4be148 |
+ * distribution.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
4be148 |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
4be148 |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
4be148 |
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
4be148 |
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
4be148 |
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
4be148 |
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
4be148 |
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
4be148 |
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
4be148 |
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
4be148 |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
4be148 |
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* This dummy module is used if no TLS implemented is selected. */
|
|
|
4be148 |
+
|
|
|
4be148 |
+#include "k5-int.h"
|
|
|
4be148 |
+#include "k5-utf8.h"
|
|
|
4be148 |
+#include "k5-tls.h"
|
|
|
4be148 |
+
|
|
|
4be148 |
+#ifdef PROXY_TLS_IMPL_NONE
|
|
|
4be148 |
+
|
|
|
4be148 |
+krb5_error_code
|
|
|
4be148 |
+tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver,
|
|
|
4be148 |
+ krb5_plugin_vtable vtable);
|
|
|
4be148 |
+
|
|
|
4be148 |
+krb5_error_code
|
|
|
4be148 |
+tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver,
|
|
|
4be148 |
+ krb5_plugin_vtable vtable)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ /* Leave all vtable functions nulled. */
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+#endif /* PROXY_TLS_IMPL_NONE */
|
|
|
4be148 |
diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
|
|
|
4be148 |
new file mode 100644
|
|
|
4be148 |
index 0000000..0691a34
|
|
|
4be148 |
--- /dev/null
|
|
|
4be148 |
+++ b/src/plugins/tls/k5tls/openssl.c
|
|
|
4be148 |
@@ -0,0 +1,570 @@
|
|
|
4be148 |
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
4be148 |
+/* plugins/tls/k5tls/openssl.c - OpenSSL TLS module implementation */
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Copyright 2013,2014 Red Hat, Inc.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * Redistribution and use in source and binary forms, with or without
|
|
|
4be148 |
+ * modification, are permitted provided that the following conditions are met:
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * 1. Redistributions of source code must retain the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * 2. Redistributions in binary form must reproduce the above copyright
|
|
|
4be148 |
+ * notice, this list of conditions and the following disclaimer in
|
|
|
4be148 |
+ * the documentation and/or other materials provided with the
|
|
|
4be148 |
+ * distribution.
|
|
|
4be148 |
+ *
|
|
|
4be148 |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
|
4be148 |
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
4be148 |
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
4be148 |
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
|
4be148 |
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
4be148 |
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
4be148 |
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
4be148 |
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
4be148 |
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
4be148 |
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
4be148 |
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+
|
|
|
4be148 |
+#include "k5-int.h"
|
|
|
4be148 |
+#include "k5-utf8.h"
|
|
|
4be148 |
+#include "k5-tls.h"
|
|
|
4be148 |
+
|
|
|
4be148 |
+#ifdef PROXY_TLS_IMPL_OPENSSL
|
|
|
4be148 |
+#include <openssl/err.h>
|
|
|
4be148 |
+#include <openssl/ssl.h>
|
|
|
4be148 |
+#include <openssl/x509.h>
|
|
|
4be148 |
+#include <openssl/x509v3.h>
|
|
|
4be148 |
+#include <dirent.h>
|
|
|
4be148 |
+
|
|
|
4be148 |
+struct k5_tls_handle_st {
|
|
|
4be148 |
+ SSL *ssl;
|
|
|
4be148 |
+ char *servername;
|
|
|
4be148 |
+};
|
|
|
4be148 |
+
|
|
|
4be148 |
+static int ex_context_id = -1;
|
|
|
4be148 |
+static int ex_handle_id = -1;
|
|
|
4be148 |
+
|
|
|
4be148 |
+MAKE_INIT_FUNCTION(init_openssl);
|
|
|
4be148 |
+
|
|
|
4be148 |
+int
|
|
|
4be148 |
+init_openssl()
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ SSL_library_init();
|
|
|
4be148 |
+ SSL_load_error_strings();
|
|
|
4be148 |
+ OpenSSL_add_all_algorithms();
|
|
|
4be148 |
+ ex_context_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
|
|
4be148 |
+ ex_handle_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+flush_errors(krb5_context context)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ unsigned long err;
|
|
|
4be148 |
+ char buf[128];
|
|
|
4be148 |
+
|
|
|
4be148 |
+ while ((err = ERR_get_error()) != 0) {
|
|
|
4be148 |
+ ERR_error_string_n(err, buf, sizeof(buf));
|
|
|
4be148 |
+ TRACE_TLS_ERROR(context, buf);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Return the passed-in character, lower-cased if it's an ASCII character. */
|
|
|
4be148 |
+static inline char
|
|
|
4be148 |
+ascii_tolower(char p)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ if (KRB5_UPPER(p))
|
|
|
4be148 |
+ return p + ('a' - 'A');
|
|
|
4be148 |
+ return p;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/*
|
|
|
4be148 |
+ * Check a single label. If allow_wildcard is true, and the presented name
|
|
|
4be148 |
+ * includes a wildcard, return true and note that we matched a wildcard.
|
|
|
4be148 |
+ * Otherwise, for both the presented and expected values, do a case-insensitive
|
|
|
4be148 |
+ * comparison of ASCII characters, and a case-sensitive comparison of
|
|
|
4be148 |
+ * everything else.
|
|
|
4be148 |
+ */
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+label_match(const char *presented, size_t plen, const char *expected,
|
|
|
4be148 |
+ size_t elen, krb5_boolean allow_wildcard, krb5_boolean *wildcard)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ unsigned int i;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (allow_wildcard && plen == 1 && presented[0] == '*') {
|
|
|
4be148 |
+ *wildcard = TRUE;
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (plen != elen)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ for (i = 0; i < elen; i++) {
|
|
|
4be148 |
+ if (ascii_tolower(presented[i]) != ascii_tolower(expected[i]))
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Break up the two names and check them, label by label. */
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+domain_match(const char *presented, size_t plen, const char *expected)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ const char *p, *q, *r, *s;
|
|
|
4be148 |
+ int n_label;
|
|
|
4be148 |
+ krb5_boolean used_wildcard = FALSE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ n_label = 0;
|
|
|
4be148 |
+ p = presented;
|
|
|
4be148 |
+ r = expected;
|
|
|
4be148 |
+ while (p < presented + plen && *r != '\0') {
|
|
|
4be148 |
+ q = memchr(p, '.', plen - (p - presented));
|
|
|
4be148 |
+ if (q == NULL)
|
|
|
4be148 |
+ q = presented + plen;
|
|
|
4be148 |
+ s = r + strcspn(r, ".");
|
|
|
4be148 |
+ if (!label_match(p, q - p, r, s - r, n_label == 0, &used_wildcard))
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ p = q < presented + plen ? q + 1 : q;
|
|
|
4be148 |
+ r = *s ? s + 1 : s;
|
|
|
4be148 |
+ n_label++;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ if (used_wildcard && n_label <= 2)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ if (p == presented + plen && *r == '\0')
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Fetch the list of subjectAltNames from a certificate. */
|
|
|
4be148 |
+static GENERAL_NAMES *
|
|
|
4be148 |
+get_cert_sans(X509 *x)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ int ext;
|
|
|
4be148 |
+ X509_EXTENSION *san_ext;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ ext = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
|
|
|
4be148 |
+ if (ext < 0)
|
|
|
4be148 |
+ return NULL;
|
|
|
4be148 |
+ san_ext = X509_get_ext(x, ext);
|
|
|
4be148 |
+ if (san_ext == NULL)
|
|
|
4be148 |
+ return NULL;
|
|
|
4be148 |
+ return X509V3_EXT_d2i(san_ext);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Fetch a CN value from the subjct name field, returning its length, or -1 if
|
|
|
4be148 |
+ * there is no subject name or it contains no CN value. */
|
|
|
4be148 |
+static int
|
|
|
4be148 |
+get_cert_cn(X509 *x, char *buf, size_t bufsize)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ X509_NAME *name;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ name = X509_get_subject_name(x);
|
|
|
4be148 |
+ if (name == NULL)
|
|
|
4be148 |
+ return -1;
|
|
|
4be148 |
+ return X509_NAME_get_text_by_NID(name, NID_commonName, buf, bufsize);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Return true if text matches any of the addresses we can recover from x. */
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+check_cert_address(X509 *x, const char *text)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ char buf[1024];
|
|
|
4be148 |
+ GENERAL_NAMES *sans;
|
|
|
4be148 |
+ GENERAL_NAME *san = NULL;
|
|
|
4be148 |
+ ASN1_OCTET_STRING *ip;
|
|
|
4be148 |
+ krb5_boolean found_ip_san = FALSE, matched = FALSE;
|
|
|
4be148 |
+ int n_sans, i;
|
|
|
4be148 |
+ int name_length;
|
|
|
4be148 |
+ struct in_addr sin;
|
|
|
4be148 |
+ struct in6_addr sin6;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Parse the IP address into an octet string. */
|
|
|
4be148 |
+ ip = M_ASN1_OCTET_STRING_new();
|
|
|
4be148 |
+ if (ip == NULL)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ if (inet_pton(AF_INET, text, &sin)) {
|
|
|
4be148 |
+ M_ASN1_OCTET_STRING_set(ip, &sin, sizeof(sin));
|
|
|
4be148 |
+ } else if (inet_pton(AF_INET6, text, &sin6)) {
|
|
|
4be148 |
+ M_ASN1_OCTET_STRING_set(ip, &sin6, sizeof(sin6));
|
|
|
4be148 |
+ } else {
|
|
|
4be148 |
+ ASN1_OCTET_STRING_free(ip);
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Check for matches in ipaddress subjectAltName values. */
|
|
|
4be148 |
+ sans = get_cert_sans(x);
|
|
|
4be148 |
+ if (sans != NULL) {
|
|
|
4be148 |
+ n_sans = sk_GENERAL_NAME_num(sans);
|
|
|
4be148 |
+ for (i = 0; i < n_sans; i++) {
|
|
|
4be148 |
+ san = sk_GENERAL_NAME_value(sans, i);
|
|
|
4be148 |
+ if (san->type != GEN_IPADD)
|
|
|
4be148 |
+ continue;
|
|
|
4be148 |
+ found_ip_san = TRUE;
|
|
|
4be148 |
+ matched = (ASN1_OCTET_STRING_cmp(ip, san->d.iPAddress) == 0);
|
|
|
4be148 |
+ if (matched)
|
|
|
4be148 |
+ break;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ ASN1_OCTET_STRING_free(ip);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (found_ip_san)
|
|
|
4be148 |
+ return matched;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Check for a match against the CN value in the peer's subject name. */
|
|
|
4be148 |
+ name_length = get_cert_cn(x, buf, sizeof(buf));
|
|
|
4be148 |
+ if (name_length >= 0) {
|
|
|
4be148 |
+ /* Do a string compare to check if it's an acceptable value. */
|
|
|
4be148 |
+ return strlen(text) == (size_t)name_length &&
|
|
|
4be148 |
+ strncmp(text, buf, name_length) == 0;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* We didn't find a match. */
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Return true if expected matches any of the names we can recover from x. */
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+check_cert_servername(X509 *x, const char *expected)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ char buf[1024];
|
|
|
4be148 |
+ GENERAL_NAMES *sans;
|
|
|
4be148 |
+ GENERAL_NAME *san = NULL;
|
|
|
4be148 |
+ unsigned char *dnsname;
|
|
|
4be148 |
+ krb5_boolean found_dns_san = FALSE, matched = FALSE;
|
|
|
4be148 |
+ int name_length, n_sans, i;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Check for matches in dnsname subjectAltName values. */
|
|
|
4be148 |
+ sans = get_cert_sans(x);
|
|
|
4be148 |
+ if (sans != NULL) {
|
|
|
4be148 |
+ n_sans = sk_GENERAL_NAME_num(sans);
|
|
|
4be148 |
+ for (i = 0; i < n_sans; i++) {
|
|
|
4be148 |
+ san = sk_GENERAL_NAME_value(sans, i);
|
|
|
4be148 |
+ if (san->type != GEN_DNS)
|
|
|
4be148 |
+ continue;
|
|
|
4be148 |
+ found_dns_san = TRUE;
|
|
|
4be148 |
+ dnsname = NULL;
|
|
|
4be148 |
+ name_length = ASN1_STRING_to_UTF8(&dnsname, san->d.dNSName);
|
|
|
4be148 |
+ if (dnsname == NULL)
|
|
|
4be148 |
+ continue;
|
|
|
4be148 |
+ matched = domain_match((char *)dnsname, name_length, expected);
|
|
|
4be148 |
+ OPENSSL_free(dnsname);
|
|
|
4be148 |
+ if (matched)
|
|
|
4be148 |
+ break;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (matched)
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+ if (found_dns_san)
|
|
|
4be148 |
+ return matched;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Check for a match against the CN value in the peer's subject name. */
|
|
|
4be148 |
+ name_length = get_cert_cn(x, buf, sizeof(buf));
|
|
|
4be148 |
+ if (name_length >= 0)
|
|
|
4be148 |
+ return domain_match(buf, name_length, expected);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* We didn't find a match. */
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+check_cert_name_or_ip(X509 *x, const char *expected_name)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ struct in_addr in;
|
|
|
4be148 |
+ struct in6_addr in6;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (inet_pton(AF_INET, expected_name, &in) != 0 ||
|
|
|
4be148 |
+ inet_pton(AF_INET6, expected_name, &in6) != 0) {
|
|
|
4be148 |
+ return check_cert_address(x, expected_name);
|
|
|
4be148 |
+ } else {
|
|
|
4be148 |
+ return check_cert_servername(x, expected_name);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static int
|
|
|
4be148 |
+verify_callback(int preverify_ok, X509_STORE_CTX *store_ctx)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ X509 *x;
|
|
|
4be148 |
+ SSL *ssl;
|
|
|
4be148 |
+ BIO *bio;
|
|
|
4be148 |
+ krb5_context context;
|
|
|
4be148 |
+ int err, depth;
|
|
|
4be148 |
+ k5_tls_handle handle;
|
|
|
4be148 |
+ const char *cert = NULL, *errstr, *expected_name;
|
|
|
4be148 |
+ size_t count;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ ssl = X509_STORE_CTX_get_ex_data(store_ctx,
|
|
|
4be148 |
+ SSL_get_ex_data_X509_STORE_CTX_idx());
|
|
|
4be148 |
+ context = SSL_get_ex_data(ssl, ex_context_id);
|
|
|
4be148 |
+ handle = SSL_get_ex_data(ssl, ex_handle_id);
|
|
|
4be148 |
+ assert(context != NULL && handle != NULL);
|
|
|
4be148 |
+ /* We do have the peer's cert, right? */
|
|
|
4be148 |
+ x = X509_STORE_CTX_get_current_cert(store_ctx);
|
|
|
4be148 |
+ if (x == NULL) {
|
|
|
4be148 |
+ TRACE_TLS_NO_REMOTE_CERTIFICATE(context);
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ /* Figure out where we are. */
|
|
|
4be148 |
+ depth = X509_STORE_CTX_get_error_depth(store_ctx);
|
|
|
4be148 |
+ if (depth < 0)
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+ /* If there's an error at this level that we're not ignoring, fail. */
|
|
|
4be148 |
+ err = X509_STORE_CTX_get_error(store_ctx);
|
|
|
4be148 |
+ if (err != X509_V_OK) {
|
|
|
4be148 |
+ bio = BIO_new(BIO_s_mem());
|
|
|
4be148 |
+ if (bio != NULL) {
|
|
|
4be148 |
+ X509_NAME_print_ex(bio, x->cert_info->subject, 0, 0);
|
|
|
4be148 |
+ count = BIO_get_mem_data(bio, &cert);
|
|
|
4be148 |
+ errstr = X509_verify_cert_error_string(err);
|
|
|
4be148 |
+ TRACE_TLS_CERT_ERROR(context, depth, count, cert, err, errstr);
|
|
|
4be148 |
+ BIO_free(bio);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ /* If we're not looking at the peer, we're done and everything's ok. */
|
|
|
4be148 |
+ if (depth != 0)
|
|
|
4be148 |
+ return 1;
|
|
|
4be148 |
+ /* Check if the name we expect to find is in the certificate. */
|
|
|
4be148 |
+ expected_name = handle->servername;
|
|
|
4be148 |
+ if (check_cert_name_or_ip(x, expected_name)) {
|
|
|
4be148 |
+ TRACE_TLS_SERVER_NAME_MATCH(context, expected_name);
|
|
|
4be148 |
+ return 1;
|
|
|
4be148 |
+ } else {
|
|
|
4be148 |
+ TRACE_TLS_SERVER_NAME_MISMATCH(context, expected_name);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ /* The name didn't match. */
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+load_anchor_file(X509_STORE *store, const char *path)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ FILE *fp;
|
|
|
4be148 |
+ STACK_OF(X509_INFO) *sk = NULL;
|
|
|
4be148 |
+ X509_INFO *xi;
|
|
|
4be148 |
+ int i;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ fp = fopen(path, "r");
|
|
|
4be148 |
+ if (fp == NULL)
|
|
|
4be148 |
+ return errno;
|
|
|
4be148 |
+ sk = PEM_X509_INFO_read(fp, NULL, NULL, NULL);
|
|
|
4be148 |
+ fclose(fp);
|
|
|
4be148 |
+ if (sk == NULL)
|
|
|
4be148 |
+ return ENOENT;
|
|
|
4be148 |
+ for (i = 0; i < sk_X509_INFO_num(sk); i++) {
|
|
|
4be148 |
+ xi = sk_X509_INFO_value(sk, i);
|
|
|
4be148 |
+ if (xi->x509 != NULL)
|
|
|
4be148 |
+ X509_STORE_add_cert(store, xi->x509);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ sk_X509_INFO_pop_free(sk, X509_INFO_free);
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+load_anchor_dir(X509_STORE *store, const char *path)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ DIR *d = NULL;
|
|
|
4be148 |
+ struct dirent *dentry = NULL;
|
|
|
4be148 |
+ char filename[1024];
|
|
|
4be148 |
+ krb5_boolean found_any = FALSE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ d = opendir(path);
|
|
|
4be148 |
+ if (d == NULL)
|
|
|
4be148 |
+ return ENOENT;
|
|
|
4be148 |
+ while ((dentry = readdir(d)) != NULL) {
|
|
|
4be148 |
+ if (dentry->d_name[0] != '.') {
|
|
|
4be148 |
+ snprintf(filename, sizeof(filename), "%s/%s",
|
|
|
4be148 |
+ path, dentry->d_name);
|
|
|
4be148 |
+ if (load_anchor_file(store, filename) == 0)
|
|
|
4be148 |
+ found_any = TRUE;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ closedir(d);
|
|
|
4be148 |
+ return found_any ? 0 : ENOENT;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+load_anchor(SSL_CTX *ctx, const char *location)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ X509_STORE *store;
|
|
|
4be148 |
+ const char *envloc;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ store = SSL_CTX_get_cert_store(ctx);
|
|
|
4be148 |
+ if (strncmp(location, "FILE:", 5) == 0) {
|
|
|
4be148 |
+ return load_anchor_file(store, location + 5);
|
|
|
4be148 |
+ } else if (strncmp(location, "DIR:", 4) == 0) {
|
|
|
4be148 |
+ return load_anchor_dir(store, location + 4);
|
|
|
4be148 |
+ } else if (strncmp(location, "ENV:", 4) == 0) {
|
|
|
4be148 |
+ envloc = getenv(location + 4);
|
|
|
4be148 |
+ if (envloc == NULL)
|
|
|
4be148 |
+ return ENOENT;
|
|
|
4be148 |
+ return load_anchor(ctx, envloc);
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ return EINVAL;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+load_anchors(krb5_context context, char **anchors, SSL_CTX *sctx)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ unsigned int i;
|
|
|
4be148 |
+ krb5_error_code ret;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (anchors != NULL) {
|
|
|
4be148 |
+ for (i = 0; anchors[i] != NULL; i++) {
|
|
|
4be148 |
+ ret = load_anchor(sctx, anchors[i]);
|
|
|
4be148 |
+ if (ret)
|
|
|
4be148 |
+ return ret;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ } else {
|
|
|
4be148 |
+ /* Use the library defaults. */
|
|
|
4be148 |
+ if (SSL_CTX_set_default_verify_paths(sctx) != 1)
|
|
|
4be148 |
+ return ENOENT;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+setup(krb5_context context, SOCKET fd, const char *servername,
|
|
|
4be148 |
+ char **anchors, k5_tls_handle *handle_out)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ int e;
|
|
|
4be148 |
+ long options;
|
|
|
4be148 |
+ SSL_CTX *ctx = NULL;
|
|
|
4be148 |
+ SSL *ssl = NULL;
|
|
|
4be148 |
+ k5_tls_handle handle = NULL;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ *handle_out = NULL;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ (void)CALL_INIT_FUNCTION(init_openssl);
|
|
|
4be148 |
+ if (ex_context_id == -1 || ex_handle_id == -1)
|
|
|
4be148 |
+ return KRB5_PLUGIN_OP_NOTSUPP;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Do general SSL library setup. */
|
|
|
4be148 |
+ ctx = SSL_CTX_new(SSLv23_client_method());
|
|
|
4be148 |
+ if (ctx == NULL)
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+ options = SSL_CTX_get_options(ctx);
|
|
|
4be148 |
+ SSL_CTX_set_options(ctx, options | SSL_OP_NO_SSLv2);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
|
|
|
4be148 |
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), 0);
|
|
|
4be148 |
+ e = load_anchors(context, anchors, ctx);
|
|
|
4be148 |
+ if (e != 0)
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ ssl = SSL_new(ctx);
|
|
|
4be148 |
+ if (ssl == NULL)
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (!SSL_set_fd(ssl, fd))
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+ SSL_set_connect_state(ssl);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Create a handle and allow verify_callback to access it. */
|
|
|
4be148 |
+ handle = malloc(sizeof(*handle));
|
|
|
4be148 |
+ if (handle == NULL || !SSL_set_ex_data(ssl, ex_handle_id, handle))
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ handle->ssl = ssl;
|
|
|
4be148 |
+ handle->servername = strdup(servername);
|
|
|
4be148 |
+ if (handle->servername == NULL)
|
|
|
4be148 |
+ goto error;
|
|
|
4be148 |
+ *handle_out = handle;
|
|
|
4be148 |
+ SSL_CTX_free(ctx);
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+
|
|
|
4be148 |
+error:
|
|
|
4be148 |
+ flush_errors(context);
|
|
|
4be148 |
+ free(handle);
|
|
|
4be148 |
+ SSL_free(ssl);
|
|
|
4be148 |
+ SSL_CTX_free(ctx);
|
|
|
4be148 |
+ return KRB5_PLUGIN_OP_NOTSUPP;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static k5_tls_status
|
|
|
4be148 |
+write_tls(krb5_context context, k5_tls_handle handle, const void *data,
|
|
|
4be148 |
+ size_t len)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ int nwritten, e;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Try to transmit our request; allow verify_callback to access context. */
|
|
|
4be148 |
+ if (!SSL_set_ex_data(handle->ssl, ex_context_id, context))
|
|
|
4be148 |
+ return ERROR_TLS;
|
|
|
4be148 |
+ nwritten = SSL_write(handle->ssl, data, len);
|
|
|
4be148 |
+ (void)SSL_set_ex_data(handle->ssl, ex_context_id, NULL);
|
|
|
4be148 |
+ if (nwritten > 0)
|
|
|
4be148 |
+ return DONE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ e = SSL_get_error(handle->ssl, nwritten);
|
|
|
4be148 |
+ if (e == SSL_ERROR_WANT_READ)
|
|
|
4be148 |
+ return WANT_READ;
|
|
|
4be148 |
+ else if (e == SSL_ERROR_WANT_WRITE)
|
|
|
4be148 |
+ return WANT_WRITE;
|
|
|
4be148 |
+ flush_errors(context);
|
|
|
4be148 |
+ return ERROR_TLS;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static k5_tls_status
|
|
|
4be148 |
+read_tls(krb5_context context, k5_tls_handle handle, void *data,
|
|
|
4be148 |
+ size_t data_size, size_t *len_out)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ ssize_t nread;
|
|
|
4be148 |
+ int e;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ *len_out = 0;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* Try to read response data; allow verify_callback to access context. */
|
|
|
4be148 |
+ if (!SSL_set_ex_data(handle->ssl, ex_context_id, context))
|
|
|
4be148 |
+ return ERROR_TLS;
|
|
|
4be148 |
+ nread = SSL_read(handle->ssl, data, data_size);
|
|
|
4be148 |
+ (void)SSL_set_ex_data(handle->ssl, ex_context_id, NULL);
|
|
|
4be148 |
+ if (nread > 0) {
|
|
|
4be148 |
+ *len_out = nread;
|
|
|
4be148 |
+ return DATA_READ;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+
|
|
|
4be148 |
+ e = SSL_get_error(handle->ssl, nread);
|
|
|
4be148 |
+ if (e == SSL_ERROR_WANT_READ)
|
|
|
4be148 |
+ return WANT_READ;
|
|
|
4be148 |
+ else if (e == SSL_ERROR_WANT_WRITE)
|
|
|
4be148 |
+ return WANT_WRITE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (e == SSL_ERROR_ZERO_RETURN || (e == SSL_ERROR_SYSCALL && nread == 0))
|
|
|
4be148 |
+ return DONE;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ flush_errors(context);
|
|
|
4be148 |
+ return ERROR_TLS;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+free_handle(krb5_context context, k5_tls_handle handle)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ SSL_free(handle->ssl);
|
|
|
4be148 |
+ free(handle->servername);
|
|
|
4be148 |
+ free(handle);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+krb5_error_code
|
|
|
4be148 |
+tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver,
|
|
|
4be148 |
+ krb5_plugin_vtable vtable);
|
|
|
4be148 |
+
|
|
|
4be148 |
+krb5_error_code
|
|
|
4be148 |
+tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver,
|
|
|
4be148 |
+ krb5_plugin_vtable vtable)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ k5_tls_vtable vt;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ vt = (k5_tls_vtable)vtable;
|
|
|
4be148 |
+ vt->setup = setup;
|
|
|
4be148 |
+ vt->write = write_tls;
|
|
|
4be148 |
+ vt->read = read_tls;
|
|
|
4be148 |
+ vt->free_handle = free_handle;
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+#endif /* PROXY_TLS_IMPL_OPENSSL */
|