Commit f283e253 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

gnutls: simplify certificate verification

parent c00886df
...@@ -333,22 +333,6 @@ static int gnutls_CertSearch (vlc_tls_t *obj, const char *host, ...@@ -333,22 +333,6 @@ static int gnutls_CertSearch (vlc_tls_t *obj, const char *host,
} }
static struct
{
unsigned flag;
const char msg[29];
} cert_errs[] =
{
{ GNUTLS_CERT_INVALID, "Certificate not verified" },
{ GNUTLS_CERT_REVOKED, "Certificate revoked" },
{ GNUTLS_CERT_SIGNER_NOT_FOUND, "Signer not found" },
{ GNUTLS_CERT_SIGNER_NOT_CA, "Signer not a CA" },
{ GNUTLS_CERT_INSECURE_ALGORITHM, "Signature algorithm insecure" },
{ GNUTLS_CERT_NOT_ACTIVATED, "Certificate not activated" },
{ GNUTLS_CERT_EXPIRED, "Certificate expired" },
};
static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host, static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
const char *service) const char *service)
{ {
...@@ -361,29 +345,37 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host, ...@@ -361,29 +345,37 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
/* certificates chain verification */ /* certificates chain verification */
unsigned status; unsigned status;
val = gnutls_certificate_verify_peers2 (sys->session, &status); val = gnutls_certificate_verify_peers3 (sys->session, host, &status);
if (val) if (val)
{ {
msg_Err (session, "Certificate verification error: %s", msg_Err (session, "Certificate verification error: %s",
gnutls_strerror (val)); gnutls_strerror (val));
return -1; return -1;
} }
if (status)
if (status == 0)
return 0; /* good certificate */
gnutls_datum_t datum;
if (gnutls_certificate_verification_status_print(status,
gnutls_certificate_type_get (sys->session), &datum, 0) == 0)
{ {
msg_Err (session, "Certificate verification failure (0x%04X)", status); msg_Err (session, "Certificate verification failure: %s", datum.data);
for (size_t i = 0; i < sizeof (cert_errs) / sizeof (cert_errs[0]); i++) gnutls_free (datum.data);
if (status & cert_errs[i].flag)
msg_Err (session, " * %s", cert_errs[i].msg);
if (status & ~(GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
return -1;
} }
if (host == NULL) status &= ~GNUTLS_CERT_INVALID; /* always set / catch-all error */
return status ? -1 : 0; status &= ~GNUTLS_CERT_SIGNER_NOT_FOUND; /* unknown CA */
status &= ~GNUTLS_CERT_UNEXPECTED_OWNER; /* mismatched hostname */
if (status != 0 || host == NULL)
return -1; /* really bad certificate */
/* certificate (host)name verification */ /* manual verification */
const gnutls_datum_t *data; const gnutls_datum_t *data;
unsigned count; unsigned count;
data = gnutls_certificate_get_peers (sys->session, &count); data = gnutls_certificate_get_peers (sys->session, &count);
if (data == NULL || count == 0) if (data == NULL || count == 0)
{ {
...@@ -392,34 +384,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host, ...@@ -392,34 +384,7 @@ static int gnutls_HandshakeAndValidate (vlc_tls_t *session, const char *host,
} }
msg_Dbg (session, "%u certificate(s) in the list", count); msg_Dbg (session, "%u certificate(s) in the list", count);
if (status && gnutls_CertSearch (session, host, service, data)) return gnutls_CertSearch (session, host, service, data);
return -1;
gnutls_x509_crt_t cert;
val = gnutls_x509_crt_init (&cert);
if (val)
{
msg_Err (session, "X.509 fatal error: %s", gnutls_strerror (val));
return -1;
}
val = gnutls_x509_crt_import (cert, data, GNUTLS_X509_FMT_DER);
if (val)
{
msg_Err (session, "Certificate import error: %s",
gnutls_strerror (val));
goto error;
}
val = !gnutls_x509_crt_check_hostname (cert, host);
if (val)
{
msg_Err (session, "Certificate does not match \"%s\"", host);
val = gnutls_CertSearch (session, host, service, data);
}
error:
gnutls_x509_crt_deinit (cert);
return val;
} }
static int static int
......
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