feat(GODT-2673): Use NoClient as UserAgent without any client connected and...

This commit is contained in:
Romain Le Jeune
2023-06-01 15:15:37 +00:00
parent c4dc829e6d
commit 802f7dbc67
9 changed files with 122 additions and 10 deletions

View File

@ -50,6 +50,8 @@ import (
"github.com/ProtonMail/proton-bridge/v3/tests"
"github.com/bradenaw/juniper/xslices"
imapid "github.com/emersion/go-imap-id"
"github.com/emersion/go-sasl"
"github.com/emersion/go-smtp"
"github.com/stretchr/testify/require"
)
@ -184,14 +186,14 @@ func TestBridge_UserAgent_Persistence(t *testing.T) {
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, useragent.DefaultUserAgent)
require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil)))
imapWaiter.Wait()
smtpWaiter.Wait()
currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, vault.DefaultUserAgent)
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
defer func() { _ = imapClient.Logout() }()
@ -221,6 +223,89 @@ func TestBridge_UserAgent_Persistence(t *testing.T) {
})
}
func TestBridge_UserAgentFromUnknownClient(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
otherPassword := []byte("bar")
otherUser := "foo"
_, _, err := s.CreateUser(otherUser, otherPassword)
require.NoError(t, err)
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(b *bridge.Bridge, mocks *bridge.Mocks) {
imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, useragent.DefaultUserAgent)
userID, err := b.LoginFull(context.Background(), username, password, nil, nil)
require.NoError(t, err)
imapWaiter.Wait()
smtpWaiter.Wait()
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
defer func() { _ = imapClient.Logout() }()
info, err := b.GetUserInfo(userID)
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
require.NoError(t, imapClient.Login(info.Addresses[0], string(info.BridgePass)))
currentUserAgent = b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, "UnknownClient/0.0.1")
})
})
}
func TestBridge_UserAgentFromSMTPClient(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
otherPassword := []byte("bar")
otherUser := "foo"
_, _, err := s.CreateUser(otherUser, otherPassword)
require.NoError(t, err)
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(b *bridge.Bridge, mocks *bridge.Mocks) {
imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, useragent.DefaultUserAgent)
userID, err := b.LoginFull(context.Background(), username, password, nil, nil)
require.NoError(t, err)
imapWaiter.Wait()
smtpWaiter.Wait()
client, err := smtp.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(b.GetSMTPPort())))
require.NoError(t, err)
defer client.Close() //nolint:errcheck
info, err := b.GetUserInfo(userID)
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
// Upgrade to TLS.
require.NoError(t, client.StartTLS(&tls.Config{InsecureSkipVerify: true}))
require.NoError(t, client.Auth(sasl.NewLoginClient(
info.Addresses[0],
string(info.BridgePass)),
))
currentUserAgent = b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, "UnknownClient/0.0.1")
})
})
}
func TestBridge_UserAgentFromIMAPID(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
var (

View File

@ -23,6 +23,7 @@ import (
"io"
"os"
"path/filepath"
"strings"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon"
@ -36,6 +37,7 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/ProtonMail/proton-bridge/v3/internal/logging"
"github.com/ProtonMail/proton-bridge/v3/internal/user"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/sirupsen/logrus"
)
@ -82,6 +84,11 @@ func (bridge *Bridge) handleIMAPEvent(event imapEvents.Event) {
"pkg": "imap",
}).Error("Incorrect login credentials.")
bridge.publish(events.IMAPLoginFailed{Username: event.Username})
case imapEvents.Login:
if strings.Contains(bridge.GetCurrentUserAgent(), useragent.DefaultUserAgent) {
bridge.setUserAgent(useragent.UnknownClient, useragent.DefaultVersion)
}
}
}

View File

@ -20,8 +20,10 @@ package bridge
import (
"fmt"
"io"
"strings"
"github.com/ProtonMail/proton-bridge/v3/internal/safe"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/emersion/go-smtp"
"github.com/sirupsen/logrus"
)
@ -55,6 +57,9 @@ func (s *smtpSession) AuthPlain(username, password string) error {
s.userID = user.ID()
s.authID = addrID
if strings.Contains(s.Bridge.GetCurrentUserAgent(), useragent.DefaultUserAgent) {
s.Bridge.setUserAgent(useragent.UnknownClient, useragent.DefaultVersion)
}
return nil
}

View File

@ -24,6 +24,10 @@ import (
"sync"
)
const DefaultUserAgent = "NoClient/0.0.1"
const DefaultVersion = "0.0.1"
const UnknownClient = "UnknownClient"
type UserAgent struct {
client, platform string
@ -81,7 +85,7 @@ func (ua *UserAgent) GetUserAgent() string {
if ua.client != "" {
client = ua.client
} else {
client = "NoClient/0.0.1"
client = DefaultUserAgent
}
return fmt.Sprintf("%v (%v)", client, ua.platform)

View File

@ -24,6 +24,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/sirupsen/logrus"
)
@ -245,7 +246,7 @@ func (vault *Vault) GetLastUserAgent() string {
// Handle case where there may be no value.
if len(v) == 0 {
v = DefaultUserAgent
v = useragent.DefaultUserAgent
}
return v

View File

@ -24,6 +24,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/ProtonMail/proton-bridge/v3/internal/vault"
"github.com/stretchr/testify/require"
)
@ -236,7 +237,7 @@ func TestVault_Settings_LastUserAgent(t *testing.T) {
s := newVault(t)
// Check the default first start value.
require.Equal(t, vault.DefaultUserAgent, s.GetLastUserAgent())
require.Equal(t, useragent.DefaultUserAgent, s.GetLastUserAgent())
}
func Test_Settings_PasswordArchive(t *testing.T) {

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/ProtonMail/proton-bridge/v3/pkg/ports"
)
@ -61,7 +62,6 @@ type Settings struct {
}
const DefaultMaxSyncMemory = 2 * 1024 * uint64(1024*1024)
const DefaultUserAgent = "UnknownClient/0.0.1"
func GetDefaultSyncWorkerCount() int {
const minSyncWorkers = 16
@ -105,7 +105,7 @@ func newDefaultSettings(gluonDir string) Settings {
SyncWorkers: syncWorkers,
SyncAttPool: syncWorkers,
LastUserAgent: DefaultUserAgent,
LastUserAgent: useragent.DefaultUserAgent,
LastHeartbeatSent: time.Time{},
PasswordArchive: PasswordArchive{},

View File

@ -6,8 +6,11 @@ Feature: The IMAP ID is propagated to bridge
And the user logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Initial user agent before an IMAP client announces its ID
When user "[user:user]" connects IMAP client "1"
Scenario: Initial user agent before an IMAP client connects
Then the user agent is "NoClient/0.0.1 ([GOOS])"
Scenario: User agent before an IMAP client announces its ID
When user "[user:user]" connects and authenticates IMAP client "1"
Then the user agent is "UnknownClient/0.0.1 ([GOOS])"
Scenario: User agent after an IMAP client announces its ID

View File

@ -17,6 +17,12 @@ Feature: A user can authenticate an SMTP client
When user "[user:user]" connects SMTP client "1"
Then SMTP client "1" can authenticate
Scenario: User agent with only SMTP client connected
Then the user agent is "NoClient/0.0.1 ([GOOS])"
When user "[user:user]" connects SMTP client "1"
Then SMTP client "1" can authenticate
Then the user agent is "UnknownClient/0.0.1 ([GOOS])"
Scenario: SMTP client cannot authenticate with wrong username
When user "[user:user]" connects SMTP client "1"
Then SMTP client "1" cannot authenticate with incorrect username