@@ -267,6 +267,10 @@ static void ustream_ssl_verify_cert(struct ustream_ssl *us)
void *ssl = us->ssl;
X509 *cert;
int res;
+ BIO *bio;
+ char *ptr;
+ int len;
+ unsigned char md[32];
res = SSL_get_verify_result(ssl);
if (res != X509_V_OK) {
@@ -282,6 +286,24 @@ static void ustream_ssl_verify_cert(struct ustream_ssl *us)
us->valid_cert = true;
us->valid_cn = ustream_ssl_verify_cn(us, cert);
+ bio = BIO_new(BIO_s_mem());
+ PEM_write_bio_X509(bio, cert);
+ len = BIO_get_mem_data(bio, &ptr);
+ us->peer_cert = calloc(1, len + 1);
+ memcpy(us->peer_cert, ptr, len);
+ BIO_free(bio);
+
+ X509_digest(cert, EVP_sha256(), md, NULL);
+ for (int n = 0; n < 32; n++)
+ sprintf(&us->peer_cert_sha256[2*n], "%02X", md[n]);
+
+ bio = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, 0);
+ len = BIO_get_mem_data(bio, &ptr);
+ us->peer_cert_sn = calloc(1, len + 1);
+ memcpy(us->peer_cert_sn, ptr, len);
+ BIO_free(bio);
+
X509_free(cert);
}
@@ -156,6 +156,8 @@ static void ustream_ssl_free(struct ustream *s)
uloop_timeout_cancel(&us->error_timer);
__ustream_ssl_session_free(us->ssl);
free(us->peer_cn);
+ free(us->peer_cert);
+ free(us->peer_cert_sn);
us->ctx = NULL;
us->ssl = NULL;
@@ -199,6 +201,9 @@ static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struc
us->conn = conn;
us->ctx = ctx;
+ us->peer_cert = NULL;
+ us->peer_cert_sn = NULL;
+
us->ssl = __ustream_ssl_session_new(us->ctx);
if (!us->ssl)
return -ENOMEM;
@@ -43,6 +43,10 @@ struct ustream_ssl {
bool valid_cert;
bool valid_cn;
bool require_validation;
+
+ char *peer_cert;
+ char peer_cert_sha256[65];
+ char *peer_cert_sn;
};
struct ustream_ssl_ctx;
Store peer certificate, it's sha256 hash and subject name in ustream_ssl struct, so the upper layer can access and use this data. This data can then be used, for example, in client authentication. Signed-off-by: Luka Logar <luka.logar@cifra.si> --- ustream-openssl.c | 22 ++++++++++++++++++++++ ustream-ssl.c | 5 +++++ ustream-ssl.h | 4 ++++ 3 files changed, 31 insertions(+)