2023-01-30 16:27:06 +03:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
2024-02-08 16:49:01 +03:00
|
|
|
"log/slog"
|
2023-02-25 13:28:15 +03:00
|
|
|
"net"
|
2023-01-30 16:27:06 +03:00
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/mjl-/mox/dns"
|
|
|
|
"github.com/mjl-/mox/mlog"
|
|
|
|
"github.com/mjl-/mox/mox-"
|
|
|
|
"github.com/mjl-/mox/mtasts"
|
|
|
|
)
|
|
|
|
|
|
|
|
func mtastsPolicyHandle(w http.ResponseWriter, r *http.Request) {
|
2023-12-05 15:35:58 +03:00
|
|
|
log := func() mlog.Log {
|
|
|
|
return pkglog.WithContext(r.Context())
|
2023-03-01 00:12:27 +03:00
|
|
|
}
|
2023-01-30 16:27:06 +03:00
|
|
|
|
2023-02-28 22:40:52 +03:00
|
|
|
host := strings.ToLower(r.Host)
|
|
|
|
if !strings.HasPrefix(host, "mta-sts.") {
|
2023-01-30 16:27:06 +03:00
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
|
|
|
}
|
2023-02-28 22:40:52 +03:00
|
|
|
host = strings.TrimPrefix(host, "mta-sts.")
|
|
|
|
nhost, _, err := net.SplitHostPort(host)
|
|
|
|
if err == nil {
|
|
|
|
// Only relevant for when host has a port.
|
|
|
|
host = nhost
|
2023-02-25 13:28:15 +03:00
|
|
|
}
|
|
|
|
domain, err := dns.ParseDomain(host)
|
|
|
|
if err != nil {
|
2023-12-05 15:35:58 +03:00
|
|
|
log().Errorx("mtasts policy request: bad domain", err, slog.String("host", host))
|
2023-01-30 16:27:06 +03:00
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
conf, _ := mox.Conf.Domain(domain)
|
|
|
|
sts := conf.MTASTS
|
|
|
|
if sts == nil {
|
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-19 11:51:24 +03:00
|
|
|
var mxs []mtasts.MX
|
2023-01-30 16:27:06 +03:00
|
|
|
for _, s := range sts.MX {
|
2024-04-19 11:51:24 +03:00
|
|
|
var mx mtasts.MX
|
2023-01-30 16:27:06 +03:00
|
|
|
if strings.HasPrefix(s, "*.") {
|
|
|
|
mx.Wildcard = true
|
|
|
|
s = s[2:]
|
|
|
|
}
|
|
|
|
d, err := dns.ParseDomain(s)
|
|
|
|
if err != nil {
|
2023-12-05 15:35:58 +03:00
|
|
|
log().Errorx("bad domain in mtasts config", err, slog.String("domain", s))
|
2023-01-30 16:27:06 +03:00
|
|
|
http.Error(w, "500 - internal server error - invalid domain in configuration", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
mx.Domain = d
|
|
|
|
mxs = append(mxs, mx)
|
|
|
|
}
|
|
|
|
if len(mxs) == 0 {
|
2024-04-19 11:51:24 +03:00
|
|
|
mxs = []mtasts.MX{{Domain: mox.Conf.Static.HostnameDomain}}
|
2023-01-30 16:27:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
policy := mtasts.Policy{
|
|
|
|
Version: "STSv1",
|
|
|
|
Mode: sts.Mode,
|
|
|
|
MaxAgeSeconds: int(sts.MaxAge / time.Second),
|
|
|
|
MX: mxs,
|
|
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
w.Header().Set("Cache-Control", "no-cache, max-age=0")
|
2023-02-16 15:22:00 +03:00
|
|
|
_, _ = w.Write([]byte(policy.String()))
|
2023-01-30 16:27:06 +03:00
|
|
|
}
|