Skip to content

Commit fdd0ebf

Browse files
authored
TASK-5830: TLSRPT (#791)
1 parent 16dea7b commit fdd0ebf

File tree

2 files changed

+125
-1
lines changed

2 files changed

+125
-1
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
lastUpdated: "05/10/2025"
3+
title: "smtp_tls_reporting"
4+
description: "hook invoked after every TLS events for reporting purpose rfc8460 TLSRPT"
5+
---
6+
7+
<a name="hooks.core.smtp_tls_reporting"></a>
8+
## Name
9+
10+
smtp_tls_reporting - This hook is added in 5.1 and allows you inspect a SMTP TLS reporting data
11+
point in JSON format.
12+
13+
## Synopsis
14+
15+
`#include "hooks/core/smtp_tls_reporting.h"`
16+
17+
`int core_smtp_tls_reporting(void closure, struct json_object *json)`
18+
19+
20+
## Description
21+
22+
This hook is called upon:
23+
- any TLSRPT (rfc8460) defined failures, before a TLS connection is attempted,
24+
normally during TLS policy (including MTA-STS, TLSA/DANE) fetching stage.
25+
- TLS negotiation failures or successes during outbound delivery when MTA-STS or TLSA/DANE is enabled.
26+
**Currently, only enabled on domains with successfully fetched MTA-STS policies or DANE TLSA records **.
27+
28+
The JSON fields and values are defined in `tlsrpt.h`, with most of the field names the same as
29+
defined in the RFC: https://datatracker.ietf.org/doc/html/rfc8460.
30+
31+
The following JSON fields are not defined in the RFC:
32+
* `epoch` - epoch time of when the hook is invoked
33+
* `type` - whether the data is for a successful TLS connection or a failure.
34+
`0` - failure; `1` - success
35+
36+
**An example JSON for a success**:
37+
38+
```
39+
{
40+
"epoch": 1746712864,
41+
"type": 1,
42+
"policy": {
43+
"policy-type": "sts",
44+
"policy-domain": "test.bird.com",
45+
"policy-string": [
46+
"version: STSv1",
47+
"mode: enforce",
48+
"mx: mx.bird.com",
49+
"mx: server.ectest.OMNITI.com",
50+
"max_age: 604800"
51+
]
52+
},
53+
"sending-mta-ip": "127.0.0.1",
54+
"receiving-mx-hostname": "server.ectest.OMNITI.com",
55+
"receiving-ip": "127.0.0.1"
56+
}
57+
```
58+
59+
**An example JSON for a failure**:
60+
61+
```
62+
{
63+
"epoch": 1746629177,
64+
"type": 0,
65+
"policy": {
66+
"policy-type": "sts",
67+
"policy-domain": "mismatch.cert.com",
68+
"policy-string": [
69+
"version: STSv1",
70+
"mode: enforce",
71+
"mx: test.bird.com",
72+
"max_age: 86400"
73+
]
74+
},
75+
"result-type": "certificate-host-mismatch",
76+
"failure-reason-code": "4.7.5 [internal] SSL certificate subject does not match host",
77+
"sending-mta-ip": "127.0.0.1",
78+
"receiving-mx-hostname": "test.BIRD.com",
79+
"receiving-ip": "127.0.0.1"
80+
}
81+
```
82+
83+
84+
**Return Values**
85+
86+
This hook returns `int`, but for now the return value has no significance.
87+
88+
89+
**Threading**
90+
91+
This hook could be called in any thread. Please avoid doing time consuming tasks in the hook's
92+
implementation.
93+
94+
95+
### Example: a Lua implementation of the hook to log the JSON into the `paniclog`
96+
97+
```
98+
require("msys.core");
99+
require("json")
100+
101+
local mod = {}
102+
103+
function mod:core_smtp_tls_reporting(js)
104+
print("tls report: ", js) -- log the whole JSON
105+
if js.type == 0 then -- failure
106+
print(string.format("TLSRPT: %s@%s@%s", js.policy["policy-domain"],
107+
js.policy["policy-type"], js["result-type"]))
108+
else -- success
109+
print(string.format("TLSRPT: %s@%s@%s", js.policy["policy-domain"],
110+
js.policy["policy-type"], "OK"))
111+
end
112+
end
113+
114+
msys.registerModule("tlsrpt", mod);
115+
```
116+
117+
**Example of the paniclog output from the above Lua hook**:
118+
```
119+
1746712864:scriptlet: tls report: { "epoch": 1746712864, "type": 1, "policy": { "policy-type": "sts", "policy-domain": "test.bird.com", "policy-string": [ "version: STSv1", "mode: enforce", "mx: mx.bird.com", "mx: server.ectest.OMNITI.com", "max_age: 604800" ] }, "sending-mta-ip": "127.0.0.1", "receiving-mx-hostname": "server.ectest.OMNITI.com", "receiving-ip": "127.0.0.1" }
120+
1746712864:scriptlet: TLSRPT: test.bird.com@sts@OK
121+
1746719856:scriptlet: tls report: { "epoch": 1746719856, "type": 0, "policy": { "policy-type": "sts", "policy-domain": "mismatch.cert.com", "policy-string": [ "version: STSv1", "mode: enforce", "mx: test.bird.com", "max_age: 86400" ] }, "result-type": "certificate-host-mismatch", "failure-reason-code": "4.7.5 [internal] SSL certificate subject does not match host", "sending-mta-ip": "127.0.0.1", "receiving-mx-hostname": "test.BIRD.com", "receiving-ip": "127.0.0.1" }
122+
1746719856:scriptlet: TLSRPT: mismatch.cert.com@sts@certificate-host-mismatch
123+
```

content/momentum/4/hooks/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ description: "This chapter includes hook point and C function reference material
1616
| [ec_httpsrv_register_auth](/momentum/4/apis-ec-httpsrv-register-auth) | Register an HTTP handler for authenticating a URI |
1717
| [ec_httpsrv_request_local_address](/momentum/4/apis-ec-httpsrv-request-local-address) | Returns the local IP address from the current session |
1818
| [ec_httpsrv_request_peer_address](/momentum/4/apis-ec-httpsrv-request-peer-address) | Returns the remote peer address from the current session |
19-
| [inbound_smtp_tls_post_accept](/momentum/4/hooks/inbound-smtp-tls-post-accept) | Modify the message state after the tls handshake in esmtp_tls_accept (available in 4.4.0 or higher) |
19+
| [inbound_smtp_tls_post_accept](/momentum/4/hooks/inbound-smtp-tls-post-accept) | Modify the message state after the tls handshake in esmtp_tls_accept (available in 4.4.0 or higher) |
20+
| [core_smtp_tls_reporting](/momentum/4/hooks/core-smtp-tls-reporting) | Report TLS events for TLSRPT (TLS reporting) |
2021

2122
This chapter includes hook point and C function reference material that is specific to Momentum 4.
2223

0 commit comments

Comments
 (0)