diff -Naurp sendmail-8.14.3/cf/README sendmail-8.14.3.oden/cf/README --- sendmail-8.14.3/cf/README 2008-02-15 18:05:32.000000000 -0500 +++ sendmail-8.14.3.oden/cf/README 2010-01-12 07:38:00.000000000 -0500 @@ -3142,7 +3142,7 @@ starts with '+' and the items are separa extensions are: CN:name name must match ${cn_subject} -CN ${server_name} must match ${cn_subject} +CN ${client_name}/${server_name} must match ${cn_subject} CS:name name must match ${cert_subject} CI:name name must match ${cert_issuer} diff -Naurp sendmail-8.14.3/doc/op/op.me sendmail-8.14.3.oden/doc/op/op.me --- sendmail-8.14.3/doc/op/op.me 2007-06-22 19:08:59.000000000 -0400 +++ sendmail-8.14.3.oden/doc/op/op.me 2010-01-12 07:38:00.000000000 -0500 @@ -4952,9 +4952,21 @@ as "(may be forged)". .ip ${cn_issuer} The CN (common name) of the CA that signed the presented certificate (STARTTLS only). +Note: if the CN cannot be extracted properly it will be replaced by +one of these strings based on the encountered error: +.(b +.ta 25n +BadCertificateContainsNUL CN contains a NUL character +BadCertificateTooLong CN is too long +BadCertificateUnknown CN could not be extracted +.)b +In the last case, some other (unspecific) error occurred. .ip ${cn_subject} The CN (common name) of the presented certificate (STARTTLS only). +See +.b ${cn_issuer} +for possible replacements. .ip ${currHeader} Header value as quoted string (possibly truncated to diff -Naurp sendmail-8.14.3/sendmail/tls.c sendmail-8.14.3.oden/sendmail/tls.c --- sendmail-8.14.3/sendmail/tls.c 2006-10-12 17:35:11.000000000 -0400 +++ sendmail-8.14.3.oden/sendmail/tls.c 2010-01-12 07:38:00.000000000 -0500 @@ -1196,23 +1196,62 @@ tls_get_info(ssl, srv, host, mac, certre if (cert != NULL) { unsigned int n; + X509_NAME *subj, *issuer; unsigned char md[EVP_MAX_MD_SIZE]; char buf[MAXNAME]; - X509_NAME_oneline(X509_get_subject_name(cert), - buf, sizeof(buf)); + subj = X509_get_subject_name(cert); + issuer = X509_get_issuer_name(cert); + X509_NAME_oneline(subj, buf, sizeof(buf)); macdefine(mac, A_TEMP, macid("{cert_subject}"), xtextify(buf, "<>\")")); - X509_NAME_oneline(X509_get_issuer_name(cert), - buf, sizeof(buf)); + X509_NAME_oneline(issuer, buf, sizeof(buf)); macdefine(mac, A_TEMP, macid("{cert_issuer}"), xtextify(buf, "<>\")")); - X509_NAME_get_text_by_NID(X509_get_subject_name(cert), - NID_commonName, buf, sizeof(buf)); + +#define CHECK_X509_NAME(which) \ + do { \ + if (r == -1) \ + { \ + sm_strlcpy(buf, "BadCertificateUnknown", sizeof(buf)); \ + if (LogLevel > 7) \ + sm_syslog(LOG_INFO, NOQID, \ + "STARTTLS=%s, relay=%.100s, field=%s, status=failed to extract CN", \ + who, \ + host == NULL ? "local" : host, \ + which); \ + } \ + else if ((size_t)r >= sizeof(buf) - 1) \ + { \ + sm_strlcpy(buf, "BadCertificateTooLong", sizeof(buf)); \ + if (LogLevel > 7) \ + sm_syslog(LOG_INFO, NOQID, \ + "STARTTLS=%s, relay=%.100s, field=%s, status=CN too long", \ + who, \ + host == NULL ? "local" : host, \ + which); \ + } \ + else if ((size_t)r > strlen(buf)) \ + { \ + sm_strlcpy(buf, "BadCertificateContainsNUL", \ + sizeof(buf)); \ + if (LogLevel > 7) \ + sm_syslog(LOG_INFO, NOQID, \ + "STARTTLS=%s, relay=%.100s, field=%s, status=CN contains NUL", \ + who, \ + host == NULL ? "local" : host, \ + which); \ + } \ + } while (0) + + r = X509_NAME_get_text_by_NID(subj, NID_commonName, buf, + sizeof buf); + CHECK_X509_NAME("cn_subject"); macdefine(mac, A_TEMP, macid("{cn_subject}"), xtextify(buf, "<>\")")); - X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), - NID_commonName, buf, sizeof(buf)); + r = X509_NAME_get_text_by_NID(issuer, NID_commonName, buf, + sizeof buf); + CHECK_X509_NAME("cn_issuer"); macdefine(mac, A_TEMP, macid("{cn_issuer}"), xtextify(buf, "<>\")")); n = 0;