1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
diff --git a/build-tree/sendmail-8.13.8/cf/README b/build-tree/sendmail-8.13.8/cf/README
index fce316e..0384c4b 100644
--- sendmail-8.13.8/cf/README
+++ sendmail-8.13.8/cf/README
@@ -3051,7 +3051,7 @@ starts with '+' and the items are separated by '++'. Allowed
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 --git a/build-tree/sendmail-8.13.8/doc/op/op.me b/build-tree/sendmail-8.13.8/doc/op/op.me
index 3f4f0a5..db595db 100644
--- sendmail-8.13.8/doc/op/op.me
+++ sendmail-8.13.8/doc/op/op.me
@@ -4929,9 +4929,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 --git a/build-tree/sendmail-8.13.8/sendmail/tls.c b/build-tree/sendmail-8.13.8/sendmail/tls.c
index 71fcdc3..8499c65 100644
--- sendmail-8.13.8/sendmail/tls.c
+++ sendmail-8.13.8/sendmail/tls.c
@@ -1194,23 +1194,63 @@ tls_get_info(ssl, srv, host, mac, certreq)
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;
|