diff options
author | Lance Richardson <lrichard@redhat.com> | 2017-05-01 10:13:02 -0400 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-05-04 15:18:51 -0700 |
commit | c19ae4ccf9e8e08df31f0eb1dae8ea84aef5afbc (patch) | |
tree | 760b1a99211c73d6cbc8e7ddf789cb8dc43c29dd | |
parent | e5fb78af9a3cd14d96947ed11a5a918ba73ceba2 (diff) | |
download | openvswitch-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.h | 1 | ||||
-rw-r--r-- | lib/stream-ssl.c | 41 | ||||
-rw-r--r-- | lib/stream.c | 15 | ||||
-rw-r--r-- | lib/stream.h | 2 |
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); |