xmpp-certwatch
created pr with
xmpp-certwatch/deadline-patch.1
added xmpp-certwatch/deadline-patch.2
1: 7f16f12 < -: ------- Point to fork of dane
-: ------- > 1: 89cbec1 Point to fork of dane
commented
Patch applied to dane:From e2cd4b16559a4e6d42ceaf4db9123de61a59612a Mon Sep 17 00:00:00 2001
From: Eric Roberts <ericroberts@gmail.com>
Date: Mon, 26 Oct 2026 14:40:49 -0400
Subject: [PATCH] Add deadline in DialStartTLS STARTTLS negotiation
getSTARTTLSconn now applies TimeoutTCP as a connection deadline covering
the whole STARTTLS exchange and TLS handshake, and startTLSHandshake
clears it on success so the returned conn is not left with an absolute
deadline, since previously only the TCP connect was bounded and a
stalled server could hang DialStartTLS indefinitely.
---
starttls.go | 27 +++++++++++++++++++--------
utils.go | 12 ++++++++++++
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/starttls.go b/starttls.go
index e3205b9..0b85021 100644
--- a/starttls.go
+++ b/starttls.go
@@ -4,9 +4,11 @@ import (
bufio
crypto/tls
fmt
+ net
os
strconv
strings
+ time
)
const bufsize = 2048
@@ -23,7 +25,7 @@ func DoXMPP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
buf := make([]byte, bufsize)
server := daneconfig.Server
- conn, err := getTCPconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
+ conn, err := getSTARTTLSconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
if err != nil {
return nil, err
}
@@ -87,7 +89,7 @@ func DoXMPP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
}
daneconfig.Transcript = transcript
- return TLShandshake(conn, tlsconfig)
+ return startTLSHandshake(conn, tlsconfig)
}
//
@@ -99,7 +101,7 @@ func DoPOP3(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
var line, transcript string
server := daneconfig.Server
- conn, err := getTCPconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
+ conn, err := getSTARTTLSconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
if err != nil {
return nil, err
}
@@ -132,7 +134,7 @@ func DoPOP3(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
}
daneconfig.Transcript = transcript
- return TLShandshake(conn, tlsconfig)
+ return startTLSHandshake(conn, tlsconfig)
}
//
@@ -145,7 +147,7 @@ func DoIMAP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
var line, transcript string
server := daneconfig.Server
- conn, err := getTCPconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
+ conn, err := getSTARTTLSconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
if err != nil {
return nil, err
}
@@ -202,7 +204,7 @@ func DoIMAP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
}
daneconfig.Transcript = transcript
- return TLShandshake(conn, tlsconfig)
+ return startTLSHandshake(conn, tlsconfig)
}
//
@@ -236,7 +238,7 @@ func DoSMTP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
var responseDone, gotSTARTTLS bool
server := daneconfig.Server
- conn, err := getTCPconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
+ conn, err := getSTARTTLSconn(server.Ipaddr, server.Port, daneconfig.TimeoutTCP)
if err != nil {
return nil, err
}
@@ -320,7 +322,16 @@ func DoSMTP(tlsconfig *tls.Config, daneconfig *Config) (*tls.Conn, error) {
}
daneconfig.Transcript = transcript
- return TLShandshake(conn, tlsconfig)
+ return startTLSHandshake(conn, tlsconfig)
+}
+
+func startTLSHandshake(conn net.Conn, tlsconfig *tls.Config) (*tls.Conn, error) {
+
+ tlsconn, err := TLShandshake(conn, tlsconfig)
+ if err == nil {
+ _ = conn.SetDeadline(time.Time{})
+ }
+ return tlsconn, err
}
//
diff --git a/utils.go b/utils.go
index 0fa4f20..ce4ef72 100644
--- a/utils.go
+++ b/utils.go
@@ -45,6 +45,18 @@ func getTCPconn(address net.IP, port int, timeout int) (net.Conn, error) {
return conn, err
}
+func getSTARTTLSconn(address net.IP, port int, timeout int) (net.Conn, error) {
+
+ conn, err := getTCPconn(address, port, timeout)
+ if err != nil {
+ return nil, err
+ }
+ if timeout > 0 {
+ _ = conn.SetDeadline(time.Now().Add(time.Second * time.Duration(timeout)))
+ }
+ return conn, nil
+}
+
//
// CertToPEMBytes returns PEM encoded bytes corresponding to the given
// x.509 certificate.
--
2.55.0
cmds
checkout latest patchset:
ssh pr.pico.sh pull xmpp-certwatch:deadline-patch | git am -3checkout specific patchset revision:
ssh pr.pico.sh pull xmpp-certwatch:deadline-patch [rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh xmpp-certwatch:deadline-patchadd comment to patch request:
ssh pr.pico.sh comment xmpp-certwatch:deadline-patch "lgtm!"
Patchset
xmpp-certwatch/deadline-patch.1
Point to fork of dane
Eric Roberts
2026-10-26T18:48:44ZWhich adds deadline for dialStartTLS and should hopefully fix our issue.
Semantic diff summary
0 added,
0 modified,
0 signature changed,
0 removed
across 0 analyzed files
(2 files skipped: unsupported file type)
+7
-5
go.mod
#
| ... | ... | @@ -3,15 +3,18 @@ module xmpp-certwatch | |
| 3 | 3 | go 1.18 | |
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | + | github.com/google/uuid v1.3.1 | |
| 6 | 7 | github.com/miekg/dns v1.1.56 | |
| 8 | + | github.com/redis/go-redis/v9 v9.2.1 | |
| 7 | 9 | github.com/shuque/dane v0.2.3 | |
| 10 | + | mellium.im/sasl v0.3.1 | |
| 11 | + | mellium.im/xmlstream v0.15.4 | |
| 12 | + | mellium.im/xmpp v0.21.4 | |
| 8 | 13 | ) | |
| 9 | 14 | ||
| 10 | 15 | require ( | |
| 11 | 16 | github.com/cespare/xxhash/v2 v2.2.0 // indirect | |
| 12 | 17 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | |
| 13 | - | github.com/google/uuid v1.3.1 // indirect | |
| 14 | - | github.com/redis/go-redis/v9 v9.2.1 // indirect | |
| 15 | 18 | golang.org/x/crypto v0.14.0 // indirect | |
| 16 | 19 | golang.org/x/mod v0.13.0 // indirect | |
| 17 | 20 | golang.org/x/net v0.17.0 // indirect |
| ... | ... | @@ -19,7 +22,6 @@ require ( | |
| 19 | 22 | golang.org/x/text v0.13.0 // indirect | |
| 20 | 23 | golang.org/x/tools v0.14.0 // indirect | |
| 21 | 24 | mellium.im/reader v0.1.0 // indirect | |
| 22 | - | mellium.im/sasl v0.3.1 // indirect | |
| 23 | - | mellium.im/xmlstream v0.15.4 // indirect | |
| 24 | - | mellium.im/xmpp v0.21.4 // indirect | |
| 25 | 25 | ) | |
| 26 | + | ||
| 27 | + | replace github.com/shuque/dane => tangled.org/mrry.band/dane v0.0.0-20261026184049-e2cd4b16559a |
+5
-22
go.sum
#
| ... | ... | @@ -1,45 +1,26 @@ | |
| 1 | + | github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= | |
| 2 | + | github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= | |
| 1 | 3 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= | |
| 2 | 4 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |
| 3 | 5 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | |
| 4 | 6 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | |
| 5 | 7 | github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= | |
| 6 | 8 | github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |
| 7 | - | github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= | |
| 8 | - | github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= | |
| 9 | 9 | github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= | |
| 10 | 10 | github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= | |
| 11 | 11 | github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= | |
| 12 | 12 | github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= | |
| 13 | - | github.com/shuque/dane v0.2.3 h1:t6773cDgw+UJzRFJCbsdqtxfYouWsUlNUNvBGUGNUY8= | |
| 14 | - | github.com/shuque/dane v0.2.3/go.mod h1:073qaSQS+yVGykJJezTRYcA+leXW1MH7uvvq5ZCeosw= | |
| 15 | 13 | golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= | |
| 16 | 14 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= | |
| 17 | - | golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= | |
| 18 | - | golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= | |
| 19 | - | golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= | |
| 20 | - | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | |
| 21 | 15 | golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= | |
| 22 | 16 | golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= | |
| 23 | - | golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= | |
| 24 | - | golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= | |
| 25 | - | golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= | |
| 26 | - | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= | |
| 27 | - | golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= | |
| 28 | - | golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= | |
| 29 | 17 | golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= | |
| 30 | 18 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= | |
| 31 | - | golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= | |
| 32 | - | golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
| 33 | - | golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= | |
| 34 | - | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
| 19 | + | golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= | |
| 35 | 20 | golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= | |
| 36 | 21 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
| 37 | 22 | golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= | |
| 38 | 23 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | |
| 39 | - | golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= | |
| 40 | - | golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= | |
| 41 | - | golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= | |
| 42 | - | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= | |
| 43 | 24 | golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= | |
| 44 | 25 | golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= | |
| 45 | 26 | mellium.im/reader v0.1.0 h1:UUEMev16gdvaxxZC7fC08j7IzuDKh310nB6BlwnxTww= |
| ... | ... | @@ -50,3 +31,5 @@ mellium.im/xmlstream v0.15.4 h1:gLKxcWl4rLMUpKgtzrTBvr4OexPeO/edYus+uK3F6ZI= | |
| 50 | 31 | mellium.im/xmlstream v0.15.4/go.mod h1:yXaCW2++fmVO4L9piKVkyLDqnCmictVYF7FDQW8prb4= | |
| 51 | 32 | mellium.im/xmpp v0.21.4 h1:hhAGFC/mGt2Bbmx46vPn+kQT0pJec7uaq+9xckkr9uI= | |
| 52 | 33 | mellium.im/xmpp v0.21.4/go.mod h1:Emo7bXXyEEgH2hdTO9zp9eGJoc9yK5dAlG0/YVJlh+U= | |
| 34 | + | tangled.org/mrry.band/dane v0.0.0-20261026184049-e2cd4b16559a h1:q6Talb03OQYFjSrfuzfxKILRqq4HI6ZnleLONA0eQYk= | |
| 35 | + | tangled.org/mrry.band/dane v0.0.0-20261026184049-e2cd4b16559a/go.mod h1:073qaSQS+yVGykJJezTRYcA+leXW1MH7uvvq5ZCeosw= |