reject wrong email in SMTP MAIL(), reject impersonation attempts
This commit is contained in:
@@ -125,7 +125,7 @@ func (b *Bot) Ban(addr net.Addr) {
|
||||
}
|
||||
|
||||
// AllowAuth check if SMTP login (email) and password are valid
|
||||
func (b *Bot) AllowAuth(email, password string) bool {
|
||||
func (b *Bot) AllowAuth(email, password string) (id.RoomID, bool) {
|
||||
var suffix bool
|
||||
for _, domain := range b.domains {
|
||||
if strings.HasSuffix(email, "@"+domain) {
|
||||
@@ -134,22 +134,27 @@ func (b *Bot) AllowAuth(email, password string) bool {
|
||||
}
|
||||
}
|
||||
if !suffix {
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
|
||||
roomID, ok := b.getMapping(utils.Mailbox(email))
|
||||
if !ok {
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
cfg, err := b.getRoomSettings(roomID)
|
||||
if err != nil {
|
||||
b.log.Error("failed to retrieve settings: %v", err)
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
|
||||
if cfg.NoSend() {
|
||||
b.log.Warn("trying to send email from %q (%q), but it's receive-only", email, roomID)
|
||||
return "", false
|
||||
}
|
||||
|
||||
allow, err := argon2pw.CompareHashWithPassword(cfg.Password(), password)
|
||||
if err != nil {
|
||||
b.log.Warn("Password for %s is not valid: %v", email, err)
|
||||
}
|
||||
return allow
|
||||
return roomID, allow
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ type Manager struct {
|
||||
}
|
||||
|
||||
type matrixbot interface {
|
||||
AllowAuth(string, string) bool
|
||||
AllowAuth(string, string) (id.RoomID, bool)
|
||||
IsGreylisted(net.Addr) bool
|
||||
IsBanned(net.Addr) bool
|
||||
Ban(net.Addr)
|
||||
|
||||
@@ -47,7 +47,8 @@ func (m *mailServer) Login(state *smtp.ConnectionState, username, password strin
|
||||
return nil, ErrBanned
|
||||
}
|
||||
|
||||
if !m.bot.AllowAuth(username, password) {
|
||||
roomID, allow := m.bot.AllowAuth(username, password)
|
||||
if !allow {
|
||||
m.log.Debug("username=%s or password=<redacted> is invalid", username)
|
||||
m.bot.Ban(state.RemoteAddr)
|
||||
return nil, ErrBanned
|
||||
@@ -60,6 +61,8 @@ func (m *mailServer) Login(state *smtp.ConnectionState, username, password strin
|
||||
from: username,
|
||||
log: m.log,
|
||||
domains: m.domains,
|
||||
getRoomID: m.bot.GetMapping,
|
||||
fromRoom: roomID,
|
||||
tos: []string{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -48,9 +48,10 @@ func (s *incomingSession) Mail(from string, opts smtp.MailOptions) error {
|
||||
func (s *incomingSession) Rcpt(to string) error {
|
||||
sentry.GetHubFromContext(s.ctx).Scope().SetTag("to", to)
|
||||
s.tos = append(s.tos, to)
|
||||
hostname := utils.Hostname(to)
|
||||
var domainok bool
|
||||
for _, domain := range s.domains {
|
||||
if utils.Hostname(to) == domain {
|
||||
if hostname == domain {
|
||||
domainok = true
|
||||
break
|
||||
}
|
||||
@@ -109,10 +110,12 @@ type outgoingSession struct {
|
||||
sendmail func(string, string, string) error
|
||||
privkey string
|
||||
domains []string
|
||||
getRoomID func(string) (id.RoomID, bool)
|
||||
|
||||
ctx context.Context
|
||||
tos []string
|
||||
from string
|
||||
fromRoom id.RoomID
|
||||
}
|
||||
|
||||
func (s *outgoingSession) Mail(from string, opts smtp.MailOptions) error {
|
||||
@@ -120,6 +123,28 @@ func (s *outgoingSession) Mail(from string, opts smtp.MailOptions) error {
|
||||
if !email.AddressValid(from) {
|
||||
return errors.New("please, provide email address")
|
||||
}
|
||||
hostname := utils.Hostname(from)
|
||||
var domainok bool
|
||||
for _, domain := range s.domains {
|
||||
if hostname == domain {
|
||||
domainok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !domainok {
|
||||
s.log.Debug("wrong domain of %s", from)
|
||||
return ErrNoUser
|
||||
}
|
||||
|
||||
roomID, ok := s.getRoomID(utils.Mailbox(from))
|
||||
if !ok {
|
||||
s.log.Debug("mapping for %s not found", from)
|
||||
return ErrNoUser
|
||||
}
|
||||
if s.fromRoom != roomID {
|
||||
s.log.Warn("sender from %q tries to impersonate %q", s.fromRoom, roomID)
|
||||
return ErrNoUser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user