7.4 Lynx
Lynx is a text-based browser, included in our study because it is
often used programmatically by other software. It relies on GnuTLS
to validate SSL certificates:
ret = gnutls_certificate_verify_peers2(handle->gnutls_
state, &tls_status);
if (ret < 0) {
int flag_continue = 1;
char *msg2;
if (tls_status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
msg2 = gettext("no issuer was found");
} else if (tls_status & GNUTLS_CERT_SIGNER_NOT_CA) {
msg2 = gettext("issuer is not a CA");
} else if (tls_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
{
msg2 = gettext("the certificate has no known issuer"
);
} else if (tls_status & GNUTLS_CERT_REVOKED) {
msg2 = gettext("the certificate has been revoked");
} else {
msg2 = gettext("the certificate is not trusted"); }
... }
This code misinterprets the semantics of gnutls_certificate_
verify_peers2. As explained in Section 4.1, this function indeed
sets the tls_status code if certificate validation fails, but for certain errors—including self-signed certificates!—it returns 0. Even
though the above code includes two identical checks for GNUTLS_
CERT_SIGNER_NOT_FOUND, neither check is ever executed when GNUTLS_CERT_SIGNER_NOT_FOUND is actually true! In this case hostname
verification is correct, but chain-of-trust verification is broken.