#include "fetchmail.h"
#include "getaddrinfo.h"
#include "i18n.h"
+#include "sdump.h"
/* Defines to allow BeOS and Cygwin to play nice... */
#ifdef __BEOS__
memset(&req, 0, sizeof(struct addrinfo));
req.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+ req.ai_flags = AI_ADDRCONFIG;
+#endif
i = fm_getaddrinfo(host, service, &req, ai0);
if (i) {
const EVP_MD *digest_tp;
unsigned int dsz, esz;
X509_NAME *subj, *issuer;
+ char *tt;
x509_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
if (depth == 0 && !_depth0ck) {
_depth0ck = 1;
-
+
if (outlevel >= O_VERBOSE) {
if ((i = X509_NAME_get_text_by_NID(issuer, NID_organizationName, buf, sizeof(buf))) != -1) {
- report(stdout, GT_("Issuer Organization: %s\n"), buf);
+ report(stdout, GT_("Issuer Organization: %s\n"), (tt = sdump(buf, i)));
+ xfree(tt);
if ((size_t)i >= sizeof(buf) - 1)
report(stdout, GT_("Warning: Issuer Organization Name too long (possibly truncated).\n"));
} else
report(stdout, GT_("Unknown Organization\n"));
if ((i = X509_NAME_get_text_by_NID(issuer, NID_commonName, buf, sizeof(buf))) != -1) {
- report(stdout, GT_("Issuer CommonName: %s\n"), buf);
+ report(stdout, GT_("Issuer CommonName: %s\n"), (tt = sdump(buf, i)));
+ xfree(tt);
if ((size_t)i >= sizeof(buf) - 1)
report(stdout, GT_("Warning: Issuer CommonName too long (possibly truncated).\n"));
} else
report(stdout, GT_("Unknown Issuer CommonName\n"));
}
if ((i = X509_NAME_get_text_by_NID(subj, NID_commonName, buf, sizeof(buf))) != -1) {
- if (outlevel >= O_VERBOSE)
- report(stdout, GT_("Server CommonName: %s\n"), buf);
+ if (outlevel >= O_VERBOSE) {
+ report(stdout, GT_("Server CommonName: %s\n"), (tt = sdump(buf, i)));
+ xfree(tt);
+ }
if ((size_t)i >= sizeof(buf) - 1) {
/* Possible truncation. In this case, this is a DNS name, so this
* is really bad. We do not tolerate this even in the non-strict case. */
report(stderr, GT_("Bad certificate: Subject CommonName too long!\n"));
return (0);
}
+ if ((size_t)i > strlen(buf)) {
+ /* Name contains embedded NUL characters, so we complain. This is likely
+ * a certificate spoofing attack. */
+ report(stderr, GT_("Bad certificate: Subject CommonName contains NUL, aborting!\n"));
+ return 0;
+ }
if (_ssl_server_cname != NULL) {
char *p1 = buf;
char *p2 = _ssl_server_cname;
* first find a match among alternative names */
gens = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
if (gens) {
- int i, r;
- for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) {
- const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+ int j, r;
+ for (j = 0, r = sk_GENERAL_NAME_num(gens); j < r; ++j) {
+ const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, j);
if (gn->type == GEN_DNS) {
char *p1 = (char *)gn->d.ia5->data;
char *p2 = _ssl_server_cname;
- if (outlevel >= O_VERBOSE)
- report(stderr, "Subject Alternative Name: %s\n", p1);
+ if (outlevel >= O_VERBOSE) {
+ report(stdout, GT_("Subject Alternative Name: %s\n"), (tt = sdump(p1, (size_t)gn->d.ia5->length)));
+ xfree(tt);
+ }
+ /* Name contains embedded NUL characters, so we complain. This
+ * is likely a certificate spoofing attack. */
+ if ((size_t)gn->d.ia5->length != strlen(p1)) {
+ report(stderr, GT_("Bad certificate: Subject Alternative Name contains NUL, aborting!\n"));
+ sk_GENERAL_NAME_free(gens);
+ return 0;
+ }
if (*p1 == '*') {
++p1;
n = strlen(p2) - strlen(p1);
n = strlen(p2) - strlen(p1);
if (n >= 0)
p2 += n;
- }
+ }
if (0 == strcasecmp(p1, p2)) {
- matched = 1;
+ matched = 1;
}
if (!matched) {
report(stderr,
GT_("Server CommonName mismatch: %s != %s\n"),
- buf, _ssl_server_cname );
+ (tt = sdump(buf, i)), _ssl_server_cname );
+ xfree(tt);
if (ok_return && strict)
return (0);
}
if (outlevel > O_NORMAL)
report(stdout, GT_("%s key fingerprint: %s\n"), _server_label, text);
if (_check_digest != NULL) {
- if (strcmp(text, _check_digest) == 0) {
+ if (strcasecmp(text, _check_digest) == 0) {
if (outlevel > O_NORMAL)
report(stdout, GT_("%s fingerprints match.\n"), _server_label);
} else {