summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLance Richardson <lrichard@redhat.com>2017-05-01 10:13:02 -0400
committerBen Pfaff <blp@ovn.org>2017-05-04 15:18:51 -0700
commitc19ae4ccf9e8e08df31f0eb1dae8ea84aef5afbc (patch)
tree760b1a99211c73d6cbc8e7ddf789cb8dc43c29dd
parente5fb78af9a3cd14d96947ed11a5a918ba73ceba2 (diff)
downloadopenvswitch-c19ae4ccf9e8e08df31f0eb1dae8ea84aef5afbc.tar.gz
stream: store stream peer id with stream state
Track authenticated stream peer ID. For SSL connections, the authenticated ID is the CN (Common Name) field extracted from the peer's SSL certificate. Signed-off-by: Lance Richardson <lrichard@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--lib/stream-provider.h1
-rw-r--r--lib/stream-ssl.c41
-rw-r--r--lib/stream.c15
-rw-r--r--lib/stream.h2
4 files changed, 59 insertions, 0 deletions
diff --git a/lib/stream-provider.h b/lib/stream-provider.h
index 2226a806c..ce88785ca 100644
--- a/lib/stream-provider.h
+++ b/lib/stream-provider.h
@@ -30,6 +30,7 @@ struct stream {
int state;
int error;
char *name;
+ char *peer_id;
};
void stream_init(struct stream *, const struct stream_class *,
diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c
index 5d88b52a2..97d6e7464 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -420,6 +420,41 @@ do_ca_cert_bootstrap(struct stream *stream)
return EPROTO;
}
+static char *
+get_peer_common_name(const struct ssl_stream *sslv)
+{
+ X509 *peer_cert = SSL_get_peer_certificate(sslv->ssl);
+ if (!peer_cert) {
+ return NULL;
+ }
+
+ int cn_index = X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert),
+ NID_commonName, -1);
+ if (cn_index < 0) {
+ return NULL;
+ }
+
+ X509_NAME_ENTRY *cn_entry = X509_NAME_get_entry(
+ X509_get_subject_name(peer_cert), cn_index);
+ if (!cn_entry) {
+ return NULL;
+ }
+
+ ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(cn_entry);
+ if (!cn_data) {
+ return NULL;
+ }
+
+ const char *cn;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ /* ASN1_STRING_data() is deprecated as of OpenSSL version 1.1 */
+ cn = (const char *)ASN1_STRING_data(cn_data);
+#else
+ cn = (const char *)ASN1_STRING_get0_data(cn_data);
+ #endif
+ return xstrdup(cn);
+}
+
static int
ssl_connect(struct stream *stream)
{
@@ -477,6 +512,12 @@ ssl_connect(struct stream *stream)
VLOG_INFO("rejecting SSL connection during bootstrap race window");
return EPROTO;
} else {
+ char *cn = get_peer_common_name(sslv);
+
+ if (cn) {
+ stream_set_peer_id(stream, cn);
+ free(cn);
+ }
return 0;
}
}
diff --git a/lib/stream.c b/lib/stream.c
index f6ea8496f..5959309c6 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -278,8 +278,10 @@ stream_close(struct stream *stream)
{
if (stream != NULL) {
char *name = stream->name;
+ char *peer_id = stream->peer_id;
(stream->class->close)(stream);
free(name);
+ free(peer_id);
}
}
@@ -430,6 +432,19 @@ stream_send_wait(struct stream *stream)
stream_wait(stream, STREAM_SEND);
}
+void
+stream_set_peer_id(struct stream *stream, const char *peer_id)
+{
+ free(stream->peer_id);
+ stream->peer_id = xstrdup(peer_id);
+}
+
+const char *
+stream_get_peer_id(const struct stream *stream)
+{
+ return stream->peer_id;
+}
+
/* Given 'name', a pstream name in the form "TYPE:ARGS", stores the class
* named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores
* a null pointer into '*classp' if 'name' is in the wrong form or if no such
diff --git a/lib/stream.h b/lib/stream.h
index f8e189103..7d35fa646 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -53,6 +53,8 @@ void stream_wait(struct stream *, enum stream_wait_type);
void stream_connect_wait(struct stream *);
void stream_recv_wait(struct stream *);
void stream_send_wait(struct stream *);
+void stream_set_peer_id(struct stream *, const char *);
+const char *stream_get_peer_id(const struct stream *);
/* Passive streams: listeners for incoming stream connections. */
int pstream_verify_name(const char *name);