[ovs-dev,RFC,v3,1/6] stream: store stream peer id with stream state

Submitted by Lance Richardson on April 19, 2017, 7:06 p.m.

Details

Message ID 20170419190647.4148-1-lrichard@redhat.com
State Superseded
Headers show

Commit Message

Lance Richardson April 19, 2017, 7:06 p.m.
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>
---
v2:
  - Accomodate OpenSSL 1.1 deprecation of ASN1_STRING_data().
  - Added comment explaining source of "id:<uuid>" in CN field.

v3:
  - Eliminated code for stripping "id:<uuid>" from CN field.

 lib/stream-provider.h |  1 +
 lib/stream-ssl.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
 lib/stream.c          | 16 ++++++++++++++++
 lib/stream.h          |  3 +++
 4 files changed, 64 insertions(+)

Patch hide | download patch | download mbox

diff --git a/lib/stream-provider.h b/lib/stream-provider.h
index 2226a80..ce88785 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 5d88b52..b083da6 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -420,6 +420,44 @@  do_ca_cert_bootstrap(struct stream *stream)
     return EPROTO;
 }
 
+static char *
+get_peer_common_name(const struct ssl_stream *sslv)
+{
+    X509_NAME_ENTRY *cn_entry;
+    ASN1_STRING *cn_data;
+    X509 *peer_cert;
+    int cn_index;
+    const char *cn;
+
+    peer_cert = SSL_get_peer_certificate(sslv->ssl);
+    if (!peer_cert) {
+        return NULL;
+    }
+    cn_index = X509_NAME_get_index_by_NID(X509_get_subject_name(peer_cert),
+                                          NID_commonName, -1);
+    if (cn_index < 0) {
+        return NULL;
+    }
+
+    cn_entry = X509_NAME_get_entry(X509_get_subject_name(peer_cert), cn_index);
+    if (!cn_entry) {
+        return NULL;
+    }
+
+    cn_data = X509_NAME_ENTRY_get_data(cn_entry);
+    if (!cn_data) {
+        return NULL;
+    }
+
+#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 +515,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 f6ea849..f183a4d 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,20 @@  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 f8e1891..f9bfdc8 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -53,6 +53,9 @@  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);