forked from External/ergo
Compare commits
3 commits
master
...
implicittl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71871ca1ef | ||
|
|
ca03a42dff | ||
|
|
9589d019cb |
7 changed files with 52 additions and 30 deletions
|
|
@ -1,6 +1,15 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to Ergo will be documented in this file.
|
All notable changes to Ergo will be documented in this file.
|
||||||
|
|
||||||
|
## [2.11.1] - 2022-01-22
|
||||||
|
|
||||||
|
Ergo 2.11.1 is a bugfix release, fixing a denial-of-service issue in our websocket implementation. We regret the oversight.
|
||||||
|
|
||||||
|
This release includes no changes to the config file format or database file format.
|
||||||
|
|
||||||
|
### Security
|
||||||
|
* Fixed a denial-of-service issue affecting websocket clients (#2039)
|
||||||
|
|
||||||
## [2.11.0] - 2022-12-25
|
## [2.11.0] - 2022-12-25
|
||||||
|
|
||||||
We're pleased to be publishing v2.11.0, a new stable release. This is another bugfix release aimed at improving client compatibility and keeping up with the IRCv3 specification process.
|
We're pleased to be publishing v2.11.0, a new stable release. This is another bugfix release aimed at improving client compatibility and keeping up with the IRCv3 specification process.
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,7 @@ accounts:
|
||||||
# port: 25
|
# port: 25
|
||||||
# username: "admin"
|
# username: "admin"
|
||||||
# password: "hunter2"
|
# password: "hunter2"
|
||||||
|
# implicit-tls: false # TLS from the first byte, typically on port 465
|
||||||
blacklist-regexes:
|
blacklist-regexes:
|
||||||
# - ".*@mailinator.com"
|
# - ".*@mailinator.com"
|
||||||
timeout: 60s
|
timeout: 60s
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MTAConfig struct {
|
type MTAConfig struct {
|
||||||
Server string
|
Server string
|
||||||
Port int
|
Port int
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
|
ImplicitTLS bool `yaml:"implicit-tls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MailtoConfig struct {
|
type MailtoConfig struct {
|
||||||
|
|
@ -132,11 +133,13 @@ func SendMail(config MailtoConfig, recipient string, msg []byte) (err error) {
|
||||||
|
|
||||||
var addr string
|
var addr string
|
||||||
var auth smtp.Auth
|
var auth smtp.Auth
|
||||||
|
var implicitTLS bool
|
||||||
if !config.DirectSendingEnabled() {
|
if !config.DirectSendingEnabled() {
|
||||||
addr = fmt.Sprintf("%s:%d", config.MTAReal.Server, config.MTAReal.Port)
|
addr = fmt.Sprintf("%s:%d", config.MTAReal.Server, config.MTAReal.Port)
|
||||||
if config.MTAReal.Username != "" && config.MTAReal.Password != "" {
|
if config.MTAReal.Username != "" && config.MTAReal.Password != "" {
|
||||||
auth = smtp.PlainAuth("", config.MTAReal.Username, config.MTAReal.Password, config.MTAReal.Server)
|
auth = smtp.PlainAuth("", config.MTAReal.Username, config.MTAReal.Password, config.MTAReal.Server)
|
||||||
}
|
}
|
||||||
|
implicitTLS = config.MTAReal.ImplicitTLS
|
||||||
} else {
|
} else {
|
||||||
idx := strings.IndexByte(recipient, '@')
|
idx := strings.IndexByte(recipient, '@')
|
||||||
if idx == -1 {
|
if idx == -1 {
|
||||||
|
|
@ -149,5 +152,8 @@ func SendMail(config MailtoConfig, recipient string, msg []byte) (err error) {
|
||||||
addr = fmt.Sprintf("%s:smtp", mx)
|
addr = fmt.Sprintf("%s:smtp", mx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return smtp.SendMail(addr, auth, config.HeloDomain, config.Sender, []string{recipient}, msg, config.RequireTLS, config.Timeout)
|
return smtp.SendMail(
|
||||||
|
addr, auth, config.HeloDomain, config.Sender, []string{recipient}, msg,
|
||||||
|
config.RequireTLS, implicitTLS, config.Timeout,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,9 +128,9 @@ func (wc IRCWSConn) WriteLines(buffers [][]byte) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc IRCWSConn) ReadLine() (line []byte, err error) {
|
func (wc IRCWSConn) ReadLine() (line []byte, err error) {
|
||||||
messageType, line, err := wc.conn.ReadMessage()
|
_, line, err = wc.conn.ReadMessage()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if messageType == websocket.BinaryMessage && !utf8.Valid(line) {
|
if !utf8.Valid(line) {
|
||||||
return line, errInvalidUtf8
|
return line, errInvalidUtf8
|
||||||
}
|
}
|
||||||
return line, nil
|
return line, nil
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,17 @@ type Client struct {
|
||||||
|
|
||||||
// Dial returns a new Client connected to an SMTP server at addr.
|
// Dial returns a new Client connected to an SMTP server at addr.
|
||||||
// The addr must include a port, as in "mail.example.com:smtp".
|
// The addr must include a port, as in "mail.example.com:smtp".
|
||||||
func Dial(addr string, timeout time.Duration) (*Client, error) {
|
func Dial(addr string, timeout time.Duration, implicitTLS bool) (*Client, error) {
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
var err error
|
var err error
|
||||||
|
dialer := net.Dialer{
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if timeout == 0 {
|
if !implicitTLS {
|
||||||
conn, err = net.Dial("tcp", addr)
|
conn, err = dialer.Dial("tcp", addr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = net.DialTimeout("tcp", addr, timeout)
|
conn, err = tls.DialWithDialer(&dialer, "tcp", addr, nil)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -338,7 +341,7 @@ var testHookStartTLS func(*tls.Config) // nil, except for tests
|
||||||
// functionality. Higher-level packages exist outside of the standard
|
// functionality. Higher-level packages exist outside of the standard
|
||||||
// library.
|
// library.
|
||||||
// XXX: modified in Ergo to add `requireTLS`, `heloDomain`, and `timeout` arguments
|
// XXX: modified in Ergo to add `requireTLS`, `heloDomain`, and `timeout` arguments
|
||||||
func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS bool, timeout time.Duration) error {
|
func SendMail(addr string, a Auth, heloDomain string, from string, to []string, msg []byte, requireTLS, implicitTLS bool, timeout time.Duration) error {
|
||||||
if err := validateLine(from); err != nil {
|
if err := validateLine(from); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -347,7 +350,7 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := Dial(addr, timeout)
|
c, err := Dial(addr, timeout, implicitTLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -355,23 +358,25 @@ func SendMail(addr string, a Auth, heloDomain string, from string, to []string,
|
||||||
if err = c.Hello(heloDomain); err != nil {
|
if err = c.Hello(heloDomain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ok, _ := c.Extension("STARTTLS"); ok {
|
if !implicitTLS {
|
||||||
var config *tls.Config
|
if ok, _ := c.Extension("STARTTLS"); ok {
|
||||||
if requireTLS {
|
var config *tls.Config
|
||||||
config = &tls.Config{ServerName: c.serverName}
|
if requireTLS {
|
||||||
} else {
|
config = &tls.Config{ServerName: c.serverName}
|
||||||
// if TLS isn't a hard requirement, don't verify the certificate either,
|
} else {
|
||||||
// since a MITM attacker could just remove the STARTTLS advertisement
|
// if TLS isn't a hard requirement, don't verify the certificate either,
|
||||||
config = &tls.Config{InsecureSkipVerify: true}
|
// since a MITM attacker could just remove the STARTTLS advertisement
|
||||||
|
config = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
}
|
||||||
|
if testHookStartTLS != nil {
|
||||||
|
testHookStartTLS(config)
|
||||||
|
}
|
||||||
|
if err = c.StartTLS(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if requireTLS {
|
||||||
|
return errors.New("TLS required, but not negotiated")
|
||||||
}
|
}
|
||||||
if testHookStartTLS != nil {
|
|
||||||
testHookStartTLS(config)
|
|
||||||
}
|
|
||||||
if err = c.StartTLS(config); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if requireTLS {
|
|
||||||
return errors.New("TLS required, but not negotiated")
|
|
||||||
}
|
}
|
||||||
if a != nil && c.ext != nil {
|
if a != nil && c.ext != nil {
|
||||||
if _, ok := c.ext["AUTH"]; !ok {
|
if _, ok := c.ext["AUTH"]; !ok {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import "fmt"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// SemVer is the semantic version of Ergo.
|
// SemVer is the semantic version of Ergo.
|
||||||
SemVer = "2.11.0"
|
SemVer = "2.11.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,7 @@ accounts:
|
||||||
# port: 25
|
# port: 25
|
||||||
# username: "admin"
|
# username: "admin"
|
||||||
# password: "hunter2"
|
# password: "hunter2"
|
||||||
|
# implicit-tls: false # TLS from the first byte, typically on port 465
|
||||||
blacklist-regexes:
|
blacklist-regexes:
|
||||||
# - ".*@mailinator.com"
|
# - ".*@mailinator.com"
|
||||||
timeout: 60s
|
timeout: 60s
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue