diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2011-09-26 16:04:51 +0200 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2011-11-09 20:10:16 +0100 |
commit | d55bc3b41b6dd5e23a1c0c5c20d2a507864d5367 (patch) | |
tree | dca98d5ecb32e84fd059bd6ebb4a55b2a001d75c /src | |
parent | 50a5cac2445bc0c199958ac04d5127e4be09fb1e (diff) | |
download | pianobar-d55bc3b41b6dd5e23a1c0c5c20d2a507864d5367.tar.gz pianobar-d55bc3b41b6dd5e23a1c0c5c20d2a507864d5367.tar.bz2 pianobar-d55bc3b41b6dd5e23a1c0c5c20d2a507864d5367.zip |
waitress: Server certificate verification
Diffstat (limited to 'src')
-rw-r--r-- | src/libwaitress/waitress.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c index c7ae583..aff023b 100644 --- a/src/libwaitress/waitress.c +++ b/src/libwaitress/waitress.c @@ -40,6 +40,10 @@ THE SOFTWARE. #include <errno.h> #include <assert.h> +#ifdef ENABLE_TLS +#include <gnutls/x509.h> +#endif + #include "config.h" #include "waitress.h" @@ -687,6 +691,58 @@ static int WaitressParseStatusline (const char * const line) { return -1; } +#ifdef ENABLE_TLS +/* verify server certificate + */ +static int WaitressTlsVerify (gnutls_session_t session) { + unsigned int status, certListSize; + const gnutls_datum_t *certList; + gnutls_x509_crt_t cert; + const WaitressHandle_t *waith; + + waith = gnutls_session_get_ptr (session); + assert (waith != NULL); + + if (gnutls_certificate_verify_peers2 (session, &status) != GNUTLS_E_SUCCESS) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + /* don't accept invalid certs */ + if (status & (GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND | + GNUTLS_CERT_REVOKED | GNUTLS_CERT_EXPIRED | + GNUTLS_CERT_NOT_ACTIVATED)) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + /* check hostname */ + if ((certList = gnutls_certificate_get_peers (session, + &certListSize)) == NULL) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + if (gnutls_x509_crt_import (cert, &certList[0], + GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + if (gnutls_x509_crt_check_hostname (cert, waith->url.host) == 0) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + gnutls_x509_crt_deinit (cert); + + return 0; +} +#endif + /* Connect to server */ static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) { @@ -987,6 +1043,12 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) { WaitressPollRead); gnutls_transport_set_push_function (waith->request.tlsSession, WaitressPollWrite); + + /* certificate verification function */ + gnutls_session_set_ptr (waith->request.tlsSession, + (gnutls_transport_ptr_t) waith); + gnutls_certificate_set_verify_function (waith->request.tlsCred, + WaitressTlsVerify); } #else if (waith->url.tls) { |