than examining the error stack after a failed SSL_connect. */
SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);
+ /* Use the private key from the cert file unless otherwise specified. */
+ if (opt.cert_file && !opt.private_key)
+ {
+ opt.private_key = opt.cert_file;
+ opt.private_key_type = opt.cert_type;
+ }
+
if (opt.cert_file)
if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file,
key_type_to_ssl_type (opt.cert_type))
if (!cert)
{
logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
- severity, escnonprint (host));
+ severity, quotearg_style (escape_quoting_style, host));
success = false;
goto no_cert; /* must bail out since CERT is NULL */
}
char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);
char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
DEBUGP (("certificate:\n subject: %s\n issuer: %s\n",
- escnonprint (subject), escnonprint (issuer)));
+ quotearg_style (escape_quoting_style, subject),
+ quotearg_style (escape_quoting_style, issuer)));
OPENSSL_free (subject);
OPENSSL_free (issuer);
}
{
char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
logprintf (LOG_NOTQUIET,
- _("%s: cannot verify %s's certificate, issued by `%s':\n"),
- severity, escnonprint (host), escnonprint (issuer));
+ _("%s: cannot verify %s's certificate, issued by %s:\n"),
+ severity, quotearg_style (escape_quoting_style, host),
+ quote (issuer));
/* Try to print more user-friendly (and translated) messages for
the frequent verification errors. */
switch (vresult)
- Ensure that ASN1 strings from the certificate are encoded as
UTF-8 which can be meaningfully compared to HOST. */
+ X509_NAME *xname = X509_get_subject_name(cert);
common_name[0] = '\0';
- X509_NAME_get_text_by_NID (X509_get_subject_name (cert),
- NID_commonName, common_name, sizeof (common_name));
+ X509_NAME_get_text_by_NID (xname, NID_commonName, common_name,
+ sizeof (common_name));
+
if (!pattern_match (common_name, host))
{
logprintf (LOG_NOTQUIET, _("\
-%s: certificate common name `%s' doesn't match requested host name `%s'.\n"),
- severity, escnonprint (common_name), escnonprint (host));
+%s: certificate common name %s doesn't match requested host name %s.\n"),
+ severity, quote (common_name), quote (host));
success = false;
}
+ else
+ {
+ /* We now determine the length of the ASN1 string. If it differs from
+ * common_name's length, then there is a \0 before the string terminates.
+ * This can be an instance of a null-prefix attack.
+ *
+ * https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike
+ * */
+
+ int i = -1, j;
+ X509_NAME_ENTRY *xentry;
+ ASN1_STRING *sdata;
+
+ if (xname) {
+ for (;;)
+ {
+ j = X509_NAME_get_index_by_NID (xname, NID_commonName, i);
+ if (j == -1) break;
+ i = j;
+ }
+ }
+
+ xentry = X509_NAME_get_entry(xname,i);
+ sdata = X509_NAME_ENTRY_get_data(xentry);
+ if (strlen (common_name) != ASN1_STRING_length (sdata))
+ {
+ logprintf (LOG_NOTQUIET, _("\
+%s: certificate common name is invalid (contains a NUL character).\n\
+This may be an indication that the host is not who it claims to be\n\
+(that is, it is not the real %s).\n"),
+ severity, quote (host));
+ success = false;
+ }
+ }
+
if (success)
DEBUGP (("X509 certificate successfully verified and matches host %s\n",
- escnonprint (host)));
+ quotearg_style (escape_quoting_style, host)));
X509_free (cert);
no_cert:
if (opt.check_cert && !success)
logprintf (LOG_NOTQUIET, _("\
To connect to %s insecurely, use `--no-check-certificate'.\n"),
- escnonprint (host));
+ quotearg_style (escape_quoting_style, host));
/* Allow --no-check-cert to disable certificate checking. */
return opt.check_cert ? success : true;