aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/man/nng_tls.7.adoc2
-rw-r--r--docs/man/nng_tls_options.5.adoc24
-rw-r--r--docs/man/nng_ws.7.adoc9
-rw-r--r--include/nng/nng.h13
-rw-r--r--include/nng/supplemental/tls/engine.h8
-rw-r--r--src/supplemental/tls/mbedtls/tls.c86
-rw-r--r--src/supplemental/tls/tls_common.c42
7 files changed, 169 insertions, 15 deletions
diff --git a/docs/man/nng_tls.7.adoc b/docs/man/nng_tls.7.adoc
index 24fbc5f9..017af4fc 100644
--- a/docs/man/nng_tls.7.adoc
+++ b/docs/man/nng_tls.7.adoc
@@ -127,6 +127,8 @@ Note that setting these must be done before the transport is started.
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CERT_KEY_FILE[`NNG_OPT_TLS_CERT_KEY_FILE`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CONFIG[`NNG_OPT_TLS_CONFIG`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_VERIFIED[`NNG_OPT_TLS_VERIFIED_`]
+* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_PEER_CN[`NNG_OPT_TLS_PEER_CN`]
+* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_PEER_ALT_NAMES[`NNG_OPT_TLS_PEER_ALT_NAMES`]
* xref:nng_options.5.adoc#NNG_OPT_URL[`NNG_OPT_URL`]
== SEE ALSO
diff --git a/docs/man/nng_tls_options.5.adoc b/docs/man/nng_tls_options.5.adoc
index e2db237f..a06a600f 100644
--- a/docs/man/nng_tls_options.5.adoc
+++ b/docs/man/nng_tls_options.5.adoc
@@ -20,12 +20,14 @@ nng_tls_options - TLS-specific options
----
#include <nng/nng.h>
-#define NNG_OPT_TLS_AUTH_MODE "tls-authmode"
-#define NNG_OPT_TLS_CA_FILE "tls-ca-file"
-#define NNG_OPT_TLS_CERT_KEY_FILE "tls-cert-key-file"
-#define NNG_OPT_TLS_CONFIG "tls-config"
-#define NNG_OPT_TLS_SERVER_NAME "tls-server-name"
-#define NNG_OPT_TLS_VERIFIED "tls-verified"
+#define NNG_OPT_TLS_AUTH_MODE "tls-authmode"
+#define NNG_OPT_TLS_CA_FILE "tls-ca-file"
+#define NNG_OPT_TLS_CERT_KEY_FILE "tls-cert-key-file"
+#define NNG_OPT_TLS_CONFIG "tls-config"
+#define NNG_OPT_TLS_SERVER_NAME "tls-server-name"
+#define NNG_OPT_TLS_VERIFIED "tls-verified"
+#define NNG_OPT_TLS_PEER_CN "tls-peer-cn"
+#define NNG_OPT_TLS_PEER_ALT_NAMES "tls-peer-alt-names"
----
== DESCRIPTION
@@ -91,6 +93,16 @@ This read-only option indicates whether the remote peer has been properly verifi
authentication.
May return incorrect results if peer authentication is disabled.
+[[NNG_OPT_TLS_PEER_CN]]((`NNG_OPT_TLS_PEER_CN`))::
+(string)
+This read-only option returns the common name of the peer certificate.
+May return incorrect results if peer authentication is disabled.
+
+[[NNG_OPT_TLS_PEER_ALT_NAMES]]((`NNG_OPT_TLS_PEER_ALT_NAMES`))::
+(string)
+This read-only option returns string list with the subject alternative names of the
+peer certificate. May return incorrect results if peer authentication is disabled.
+
=== Inherited Options
Generally, the following option values are also available for TLS objects,
diff --git a/docs/man/nng_ws.7.adoc b/docs/man/nng_ws.7.adoc
index 349955b1..171ec934 100644
--- a/docs/man/nng_ws.7.adoc
+++ b/docs/man/nng_ws.7.adoc
@@ -199,6 +199,15 @@ more details.
authentication.
May return incorrect results if peer authentication is disabled.
+`NNG_OPT_TLS_PEER_CN`::
+(string) This read-only option returns the common name of the peer certificate.
+May return incorrect results if peer authentication is disabled.
+
+`NNG_OPT_TLS_PEER_ALT_NAMES`::
+(string list) returns string list with the subject alternative names of the
+peer certificate. May return incorrect results if peer authentication
+is disabled.
+
// We should also look at a hook mechanism for listeners. Probably this could
// look like NNG_OPT_WS_LISTEN_HOOK_FUNC which would take a function pointer
// along the lines of int hook(void *, char *req_headers, char **res_headers),
diff --git a/include/nng/nng.h b/include/nng/nng.h
index 811cb456..5bb320b6 100644
--- a/include/nng/nng.h
+++ b/include/nng/nng.h
@@ -755,6 +755,19 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`.
#define NNG_OPT_TLS_VERIFIED "tls-verified"
+// NNG_OPT_TLS_PEER_CN returns the string with the common name
+// of the peer certificate. Typically this is read-only and
+// only available for pipes. This option may return incorrect results if
+// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`.
+#define NNG_OPT_TLS_PEER_CN "tls-peer-cn"
+
+// NNG_OPT_TLS_PEER_ALT_NAMES returns string list with the
+// subject alternative names of the peer certificate. Typically this is
+// read-only and only available for pipes. This option may return
+// incorrect results if peer authentication is disabled with
+// `NNG_TLS_AUTH_MODE_NONE`.
+#define NNG_OPT_TLS_PEER_ALT_NAMES "tls-peer-alt-names"
+
// TCP options. These may be supported on various transports that use
// TCP underneath such as TLS, or not.
diff --git a/include/nng/supplemental/tls/engine.h b/include/nng/supplemental/tls/engine.h
index 81385fbc..309d83c5 100644
--- a/include/nng/supplemental/tls/engine.h
+++ b/include/nng/supplemental/tls/engine.h
@@ -80,6 +80,14 @@ typedef struct nng_tls_engine_conn_ops_s {
// verified returns true if the connection is fully
// TLS verified, false otherwise.
bool (*verified)(nng_tls_engine_conn *);
+
+ // peer_cn returns the common name of the peer
+ // The return string needs to be freed.
+ char *(*peer_cn)(nng_tls_engine_conn *);
+
+ // peer_alt_names returns the subject alternative names.
+ // The return string list and its strings need to be freed.
+ char **(*peer_alt_names)(nng_tls_engine_conn *);
} nng_tls_engine_conn_ops;
typedef struct nng_tls_engine_config_ops_s {
diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c
index a216b3a6..79f3ffd4 100644
--- a/src/supplemental/tls/mbedtls/tls.c
+++ b/src/supplemental/tls/mbedtls/tls.c
@@ -276,6 +276,74 @@ conn_verified(nng_tls_engine_conn *ec)
return (mbedtls_ssl_get_verify_result(&ec->ctx) == 0);
}
+static char *
+conn_peer_cn(nng_tls_engine_conn *ec)
+{
+ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&ec->ctx);
+ if (!crt) {
+ return (NULL);
+ }
+
+ char buf[0x400];
+ int len = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject);
+ if (len <= 0) {
+ return (NULL);
+ }
+
+ const char *pos = strstr(buf, "CN=");
+ if (!pos) {
+ return (NULL);
+ }
+
+ pos += 3;
+ len -= pos - buf - 1;
+ if (len <= 1) {
+ return (NULL);
+ }
+
+ char *rv = malloc(len);
+ memcpy(rv, pos, len);
+ return (rv);
+}
+
+static char **
+conn_peer_alt_names(nng_tls_engine_conn *ec)
+{
+ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&ec->ctx);
+ if (!crt) {
+ return (NULL);
+ }
+
+ const mbedtls_asn1_sequence * seq = &crt->subject_alt_names;
+
+ // get count
+ int count = 0;
+ do {
+ if (seq->buf.len > 0) ++count;
+ seq = seq->next;
+ } while (seq);
+ if (count == 0) return NULL;
+
+ seq = &crt->subject_alt_names;
+
+ // copy strings
+ char ** rv = malloc((count + 1) * sizeof(char *));
+ int i = 0;
+ do {
+ if (seq->buf.len == 0) continue;
+
+ rv[i] = malloc(seq->buf.len + 1);
+ memcpy(rv[i], seq->buf.p, seq->buf.len);
+ rv[i][seq->buf.len] = 0;
+ ++i;
+
+ seq = seq->next;
+ } while (seq);
+ rv[i] = NULL;
+
+ return rv;
+}
+
static void
config_fini(nng_tls_engine_config *cfg)
{
@@ -526,14 +594,16 @@ static nng_tls_engine_config_ops config_ops = {
};
static nng_tls_engine_conn_ops conn_ops = {
- .size = sizeof(nng_tls_engine_conn),
- .init = conn_init,
- .fini = conn_fini,
- .close = conn_close,
- .recv = conn_recv,
- .send = conn_send,
- .handshake = conn_handshake,
- .verified = conn_verified,
+ .size = sizeof(nng_tls_engine_conn),
+ .init = conn_init,
+ .fini = conn_fini,
+ .close = conn_close,
+ .recv = conn_recv,
+ .send = conn_send,
+ .handshake = conn_handshake,
+ .verified = conn_verified,
+ .peer_cn = conn_peer_cn,
+ .peer_alt_names = conn_peer_alt_names,
};
static nng_tls_engine tls_engine_mbed = {
diff --git a/src/supplemental/tls/tls_common.c b/src/supplemental/tls/tls_common.c
index 357c8411..d05a289d 100644
--- a/src/supplemental/tls/tls_common.c
+++ b/src/supplemental/tls/tls_common.c
@@ -756,12 +756,52 @@ tls_get_verified(void *arg, void *buf, size_t *szp, nni_type t)
return (nni_copyout_bool(v, buf, szp, t));
}
+static int
+tls_get_peer_cn(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ NNI_ARG_UNUSED(szp);
+
+ if (t != NNI_TYPE_STRING) {
+ return (NNG_EBADTYPE);
+ }
+
+ tls_conn *conn = arg;
+ nni_mtx_lock(&conn->lock);
+ *(char **) buf = conn->ops.peer_cn((void *) (conn + 1));
+ nni_mtx_unlock(&conn->lock);
+ return (0);
+}
+
+static int
+tls_get_peer_alt_names(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ NNI_ARG_UNUSED(szp);
+
+ if (t != NNI_TYPE_POINTER) {
+ return (NNG_EBADTYPE);
+ }
+
+ tls_conn *conn = arg;
+ nni_mtx_lock(&conn->lock);
+ *(char ***) buf = conn->ops.peer_alt_names((void *) (conn + 1));
+ nni_mtx_unlock(&conn->lock);
+ return (0);
+}
+
static const nni_option tls_options[] = {
{
.o_name = NNG_OPT_TLS_VERIFIED,
.o_get = tls_get_verified,
},
{
+ .o_name = NNG_OPT_TLS_PEER_CN,
+ .o_get = tls_get_peer_cn,
+ },
+ {
+ .o_name = NNG_OPT_TLS_PEER_ALT_NAMES,
+ .o_get = tls_get_peer_alt_names,
+ },
+ {
.o_name = NULL,
},
};
@@ -1680,4 +1720,4 @@ nni_tls_sys_fini(void)
{
}
-#endif // !NNG_SUPP_TLS \ No newline at end of file
+#endif // !NNG_SUPP_TLS