14 Commits

6 changed files with 74 additions and 20 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
Rspamd helper for CommuniGate Pro 5.x, 6.x Rspamd helper for CommuniGate Pro 5.x, 6.x
Copyright (C) 2017-2023 Andrey Igoshin <ai@vsu.ru> Copyright (C) 2017-2024 Andrey Igoshin <ai@vsu.ru>
Version 1.5.0 Version 1.5.7
https://git.vsu.ru/ai/rspamd-cgp https://git.vsu.ru/ai/rspamd-cgp
+7 -3
View File
@@ -2,17 +2,21 @@
export GOPATH="${HOME}/src/rspamd-cgp" export GOPATH="${HOME}/src/rspamd-cgp"
# если на целевой ОС не совпадает glibc, то собираем без зависимостей # если на целевой ОС не совпадает glibc, то собираем без зависимостей.
# результирующий файл, скорее всего, получится медленнее и большего размера # результирующий файл, возможно, получится медленнее и большего размера.
export CGO_ENABLED=0 export CGO_ENABLED=0
if [ "$1" == "fmt" ]; then if [ "$1" == "fmt" ]; then
go fmt $* go fmt $*
elif [ "$1" == "tidy" ]; then elif [ "$1" == "tidy" ]; then
go mod tidy go mod tidy
elif [ "$1" == "update" ]; then
echo "update..."
go get -u ./...
go mod tidy
elif [ "$1" == "vet" ]; then elif [ "$1" == "vet" ]; then
echo "vet..." echo "vet..."
go vet go vet ./...
else else
go build go build
fi fi
+58 -9
View File
@@ -28,7 +28,7 @@ var protocol int
func init() { func init() {
reMD = regexp.MustCompile(`^\s+DomainName\s+=\s+([^;]+);`) reMD = regexp.MustCompile(`^\s+DomainName\s+=\s+([^;]+);`)
reSELF = regexp.MustCompile(`^S (?:<([^>]+)> )?(?:DSN|GROUP|LIST|PBX|PIPE|RULE) \[0\.0\.0\.0\]`) reSELF = regexp.MustCompile(`^S (?:<([^>]+)> )?(?:DSN|GROUP|LIST|PBX|PIPE|RULE) \[0\.0\.0\.0\]`)
reSMTP = regexp.MustCompile(`^S (?:<([^>]+)> )?(?:SMTP|HTTPU?|AIRSYNC|XIMSS) \[([0-9a-f.:]+)\]`) reSMTP = regexp.MustCompile(`^S (?:<([^>]+)> )?(?:SMTP|HTTPU?|AIRSYNC|XIMSS|IMAP) \[([0-9a-f.:]+)\]`)
err := setMainDomain() err := setMainDomain()
if err != nil { if err != nil {
@@ -47,7 +47,8 @@ func AddHeader(seq int, headers []string) {
} }
} }
func Discard(seq int) { func Discard(seq int, qid int, from string, rcpts []string) {
Putline("* %d [%d]: Action: discard; from %s, rcpts %s\n", seq, qid, from, strings.Join(rcpts, ","))
Putline("%d DISCARD\n", seq) Putline("%d DISCARD\n", seq)
} }
@@ -146,30 +147,39 @@ func Message(filename string) (from string, rcpts []string, auth string, ip stri
return return
} }
func MirrorTo(seq int, to []string, headers []string, mirrorDiscard bool) { func MirrorTo(seq int, qid int, to []string, headers []string, body []byte, mirrorDiscard bool) {
hdrs := replaceSpecChars(strings.Join(headers, "\n"))
if protocol >= 4 { if protocol >= 4 {
if len(to) > 0 { if len(to) > 0 {
seenHdr, err := makeSeen(body)
if err != nil {
Failure(seq, qid, err)
return
}
headers = append(headers, seenHdr)
hdrs := replaceSpecChars(strings.Join(headers, "\n"))
mirrorTo := []string{} mirrorTo := []string{}
for _, m := range to { for _, m := range to {
mirrorTo = append(mirrorTo, fmt.Sprintf("MIRRORTO \"%s\"", m)) mirrorTo = append(mirrorTo, fmt.Sprintf("MIRRORTO \"%s\"", m))
} }
if mirrorDiscard { if mirrorDiscard {
Putline("%d %s DISCARD\n", seq, strings.Join(mirrorTo, " ")) Putline("%d ADDHEADER \"%s\" %s DISCARD\n", seq, hdrs, strings.Join(mirrorTo, " "))
} else { } else {
Putline("%d %s ADDHEADER \"%s\" OK\n", seq, strings.Join(mirrorTo, " "), hdrs) Putline("%d ADDHEADER \"%s\" %s OK\n", seq, hdrs, strings.Join(mirrorTo, " "))
} }
} else { } else {
hdrs := replaceSpecChars(strings.Join(headers, "\n"))
Putline("%d ADDHEADER \"%s\" OK\n", seq, hdrs) Putline("%d ADDHEADER \"%s\" OK\n", seq, hdrs)
} }
} else { } else {
hdrs := replaceSpecChars(strings.Join(headers, "\n"))
Putline("%d ADDHEADER \"%s\"\n", seq, hdrs) Putline("%d ADDHEADER \"%s\"\n", seq, hdrs)
} }
} }
@@ -221,6 +231,13 @@ func RewriteSubject(seq int, headers []string, subject string, qid int, from str
} }
} }
for _, hdr = range headers {
_, err = fh.WriteString(hdr)
if err != nil {
goto fin
}
}
m = bufio.NewReader(bytes.NewReader(body)) m = bufio.NewReader(bytes.NewReader(body))
for { for {
@@ -305,7 +322,7 @@ fin:
if err != nil { if err != nil {
Failure(seq, qid, err) Failure(seq, qid, err)
} else { } else {
Discard(seq) Discard(seq, qid, from, rcpts)
} }
} }
@@ -411,7 +428,7 @@ func isSeen(m *bufio.Reader) (seen bool, err error) {
} }
if hdr == "\n" { if hdr == "\n" {
// конец заголовка // конец RFC5322 заголовка
break break
} }
@@ -435,6 +452,38 @@ func isSeen(m *bufio.Reader) (seen bool, err error) {
return return
} }
func makeSeen(body []byte) (seenhdr string, err error) {
var hdr string
m := bufio.NewReader(bytes.NewReader(body))
for {
hdr, err = getHeader(m)
if err == io.EOF {
err = nil
if len(hdr) == 0 {
break
}
}
if err != nil {
return
}
if hdr == "\n" {
break
}
if strings.HasPrefix(hdr, recvHdr) {
seenhdr = fmt.Sprintf("%s %x", seenHdr, sha256.Sum224([]byte(nospace(hdr))))
break
}
}
return
}
func nospace(s string) string { func nospace(s string) string {
var b strings.Builder var b strings.Builder
+2 -2
View File
@@ -1,10 +1,10 @@
module git.vsu.ru/ai/rspamd-cgp module git.vsu.ru/ai/rspamd-cgp
go 1.18 go 1.23
require github.com/json-iterator/go v1.1.12 require github.com/json-iterator/go v1.1.12
require ( require (
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
) )
+2 -1
View File
@@ -4,8 +4,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+3 -3
View File
@@ -16,7 +16,7 @@ import (
"git.vsu.ru/ai/rspamd-cgp/config" "git.vsu.ru/ai/rspamd-cgp/config"
) )
var ( const (
headerJunkG string = "X-Junk-Score: [XX]" headerJunkG string = "X-Junk-Score: [XX]"
headerJunkA string = "X-Junk-Score: [XXXX]" headerJunkA string = "X-Junk-Score: [XXXX]"
headerJunkR string = "X-Junk-Score: [XXXXXXXXXX]" headerJunkR string = "X-Junk-Score: [XXXXXXXXXX]"
@@ -149,10 +149,10 @@ func Scan(seq int, filename string) {
} }
case "discard": case "discard":
cgp.Discard(seq) cgp.Discard(seq, qid, from, rcpts)
case "quarantine": case "quarantine":
cgp.MirrorTo(seq, mirrorTo, append(headers, headerJunkR), mirrorDiscard) cgp.MirrorTo(seq, qid, mirrorTo, append(headers, headerJunkR), body, mirrorDiscard)
case "reject": case "reject":
cgp.AddHeader(seq, append(headers, headerJunkR)) cgp.AddHeader(seq, append(headers, headerJunkR))