Commit c2a97aa7 authored by Philipp Schafft's avatar Philipp Schafft 🦁
Browse files

Feature: Allow accessing all of the certificate chain

This is based on a patch by Stephan Jauernick <info@stephan-jauernick.de>
parent 8c40ba7c
......@@ -86,6 +86,7 @@ extern "C" {
typedef enum {
SHOUT_CONTROL__MIN = 0,
SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM,
SHOUT_CONTROL_GET_SERVER_CERTIFICATE_CHAIN_AS_PEM,
SHOUT_CONTROL__MAX = 32767
} shout_control_t;
......
......@@ -700,12 +700,17 @@ int shout_connection_control(shout_connection_t *con, shout_cont
switch (control) {
#ifdef HAVE_OPENSSL
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM:
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_CHAIN_AS_PEM:
if (con->tls) {
void **vpp = va_arg(ap, void **);
char *buf;
if (vpp) {
ret = shout_tls_get_peer_certificate(con->tls, &buf);
if (control == SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM) {
ret = shout_tls_get_peer_certificate(con->tls, &buf);
} else {
ret = shout_tls_get_peer_certificate_chain(con->tls, &buf);
}
if (ret == SHOUTERR_SUCCESS) {
*vpp = buf;
}
......@@ -718,6 +723,7 @@ int shout_connection_control(shout_connection_t *con, shout_cont
break;
#else
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM:
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_CHAIN_AS_PEM:
ret = SHOUTERR_UNSUPPORTED;
break;
#endif
......
......@@ -1083,10 +1083,11 @@ int shout_control(shout_t *self, shout_control_t control, ...)
switch (control) {
#ifdef HAVE_OPENSSL
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM:
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_CHAIN_AS_PEM:
if (self->connection->tls) {
void **vpp = va_arg(ap, void **);
if (vpp) {
ret = shout_connection_control(self->connection, SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM, vpp);
ret = shout_connection_control(self->connection, control, vpp);
} else {
ret = SHOUTERR_INSANE;
}
......@@ -1096,6 +1097,7 @@ int shout_control(shout_t *self, shout_control_t control, ...)
break;
#else
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_AS_PEM:
case SHOUT_CONTROL_GET_SERVER_CERTIFICATE_CHAIN_AS_PEM:
ret = SHOUTERR_UNSUPPORTED;
break;
#endif
......
......@@ -306,6 +306,7 @@ ssize_t shout_tls_read(shout_tls_t *tls, void *buf, size_t len);
ssize_t shout_tls_write(shout_tls_t *tls, const void *buf, size_t len);
int shout_tls_recoverable(shout_tls_t *tls);
int shout_tls_get_peer_certificate(shout_tls_t *tls, char **buf);
int shout_tls_get_peer_certificate_chain(shout_tls_t *tls, char **buf);
int shout_tls_set_callback(shout_tls_t *tls, shout_tls_callback_t callback, void *userdata);
#endif
......
......@@ -337,6 +337,49 @@ int shout_tls_get_peer_certificate(shout_tls_t *tls, char **buf)
return SHOUTERR_SUCCESS;
}
int shout_tls_get_peer_certificate_chain(shout_tls_t *tls, char **buf)
{
BIO *bio;
unsigned char *data;
unsigned int len;
int j, certs;
STACK_OF(X509) * chain;
if (!tls || !buf)
return SHOUTERR_INSANE;
chain = SSL_get_peer_cert_chain(tls->ssl);
certs = sk_X509_num(chain);
if (!certs)
return SHOUTERR_TLSBADCERT;
bio = BIO_new(BIO_s_mem());
if (!bio)
return SHOUTERR_MALLOC;
for(j = 0; j < certs; ++j) {
X509 *cert = sk_X509_value(chain, j);
PEM_write_bio_X509(bio, cert);
}
len = BIO_get_mem_data(bio, &data);
if (len) {
*buf = malloc(len + 1);
memcpy(*buf, data, len);
(*buf)[len] = 0;
}
BIO_free(bio);
return SHOUTERR_SUCCESS;
}
int shout_tls_set_callback(shout_tls_t *tls, shout_tls_callback_t callback, void *userdata)
{
if (!tls)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment