forked from Silverfish/proton-bridge
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 60df01eece | |||
| 4e7acd9091 | |||
| 3ca5d0af71 | |||
| 9425e091d8 | |||
| b1ad0ab6dc | |||
| b63b56960e | |||
| 7c232b1331 |
4
go.mod
4
go.mod
@ -5,9 +5,9 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
|
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
|
||||||
github.com/Masterminds/semver/v3 v3.1.1
|
github.com/Masterminds/semver/v3 v3.1.1
|
||||||
github.com/ProtonMail/gluon v0.14.2-0.20230309105237-65db9f3ab739
|
github.com/ProtonMail/gluon v0.14.2-0.20230322121010-763723ee7bbc
|
||||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
||||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230308164916-42e487b4ad74
|
github.com/ProtonMail/go-proton-api v0.3.1-0.20230321105220-39e9131e1a68
|
||||||
github.com/ProtonMail/go-rfc5322 v0.11.0
|
github.com/ProtonMail/go-rfc5322 v0.11.0
|
||||||
github.com/ProtonMail/gopenpgp/v2 v2.4.10
|
github.com/ProtonMail/gopenpgp/v2 v2.4.10
|
||||||
github.com/PuerkitoBio/goquery v1.8.0
|
github.com/PuerkitoBio/goquery v1.8.0
|
||||||
|
|||||||
8
go.sum
8
go.sum
@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs
|
|||||||
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
|
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
|
||||||
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
|
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
|
||||||
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
|
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
|
||||||
github.com/ProtonMail/gluon v0.14.2-0.20230309105237-65db9f3ab739 h1:lnBpIbJj3o1A24M9vTH97MDgSgN2755fCowtijSYo0U=
|
github.com/ProtonMail/gluon v0.14.2-0.20230322121010-763723ee7bbc h1:qLHEYjr7BJaZxeMyqhEBpenuAnduFNZqBA26gT9LXGo=
|
||||||
github.com/ProtonMail/gluon v0.14.2-0.20230309105237-65db9f3ab739/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
|
github.com/ProtonMail/gluon v0.14.2-0.20230322121010-763723ee7bbc/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q=
|
||||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
|
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
|
||||||
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||||
@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB
|
|||||||
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc=
|
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc=
|
||||||
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
|
github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
|
||||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230308164916-42e487b4ad74 h1:gtzxYZcF7rGdsYi0g2+PcLYBCa9H1+CrVKY+5N/yYGE=
|
github.com/ProtonMail/go-proton-api v0.3.1-0.20230321105220-39e9131e1a68 h1:CExt0Vd19dsUtf+IBSa/l96/DTHEmgXi4IbWG99Vs1E=
|
||||||
github.com/ProtonMail/go-proton-api v0.3.1-0.20230308164916-42e487b4ad74/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos=
|
github.com/ProtonMail/go-proton-api v0.3.1-0.20230321105220-39e9131e1a68/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos=
|
||||||
github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY=
|
github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY=
|
||||||
github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw=
|
github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw=
|
||||||
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
|
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
|
||||||
|
|||||||
@ -87,6 +87,11 @@ func migrateOldSettings(v *vault.Vault) error {
|
|||||||
return fmt.Errorf("failed to get user config dir: %w", err)
|
return fmt.Errorf("failed to get user config dir: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return migrateOldSettingsWithDir(configDir, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint:gosec
|
||||||
|
func migrateOldSettingsWithDir(configDir string, v *vault.Vault) error {
|
||||||
b, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "prefs.json"))
|
b, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "prefs.json"))
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
return nil
|
return nil
|
||||||
@ -94,7 +99,27 @@ func migrateOldSettings(v *vault.Vault) error {
|
|||||||
return fmt.Errorf("failed to read old prefs file: %w", err)
|
return fmt.Errorf("failed to read old prefs file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return migratePrefsToVault(v, b)
|
if err := migratePrefsToVault(v, b); err != nil {
|
||||||
|
return fmt.Errorf("failed to migrate prefs to vault: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Info("Migrating TLS certificate")
|
||||||
|
|
||||||
|
certPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "cert.pem"))
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("failed to read old cert file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "key.pem"))
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("failed to read old key file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.SetBridgeTLSCertKey(certPEM, keyPEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateOldAccounts(locations *locations.Locations, v *vault.Vault) error {
|
func migrateOldAccounts(locations *locations.Locations, v *vault.Vault) error {
|
||||||
|
|||||||
@ -38,53 +38,44 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMigratePrefsToVault(t *testing.T) {
|
func TestMigratePrefsToVaultWithKeys(t *testing.T) {
|
||||||
// Create a new vault.
|
// Create a new vault.
|
||||||
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, corrupt)
|
require.False(t, corrupt)
|
||||||
|
|
||||||
// load the old prefs file.
|
// load the old prefs file.
|
||||||
b, err := os.ReadFile(filepath.Join("testdata", "prefs.json"))
|
configDir := filepath.Join("testdata", "with_keys")
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Migrate the old prefs file to the new vault.
|
// Migrate the old prefs file to the new vault.
|
||||||
require.NoError(t, migratePrefsToVault(vault, b))
|
require.NoError(t, migrateOldSettingsWithDir(configDir, vault))
|
||||||
|
|
||||||
// Check that the IMAP and SMTP prefs are migrated.
|
// Check Json Settings
|
||||||
require.Equal(t, 2143, vault.GetIMAPPort())
|
validateJSONPrefs(t, vault)
|
||||||
require.Equal(t, 2025, vault.GetSMTPPort())
|
|
||||||
require.True(t, vault.GetSMTPSSL())
|
|
||||||
|
|
||||||
// Check that the update channel is migrated.
|
// Check the keys were found and collected.
|
||||||
require.True(t, vault.GetAutoUpdate())
|
require.Equal(t, "-----BEGIN CERTIFICATE-----", string(vault.GetBridgeTLSCert()))
|
||||||
require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel())
|
require.Equal(t, "-----BEGIN RSA PRIVATE KEY-----", string(vault.GetBridgeTLSKey()))
|
||||||
require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout())
|
}
|
||||||
|
|
||||||
// Check that the app settings have been migrated.
|
func TestMigratePrefsToVaultWithoutKeys(t *testing.T) {
|
||||||
require.False(t, vault.GetFirstStart())
|
// Create a new vault.
|
||||||
require.Equal(t, "blablabla", vault.GetColorScheme())
|
vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"))
|
||||||
require.Equal(t, "2.3.0+git", vault.GetLastVersion().String())
|
|
||||||
require.True(t, vault.GetAutostart())
|
|
||||||
|
|
||||||
// Check that the other app settings have been migrated.
|
|
||||||
require.Equal(t, 16, vault.SyncWorkers())
|
|
||||||
require.Equal(t, 16, vault.SyncAttPool())
|
|
||||||
require.False(t, vault.GetProxyAllowed())
|
|
||||||
require.False(t, vault.GetShowAllMail())
|
|
||||||
|
|
||||||
// Check that the cookies have been migrated.
|
|
||||||
jar, err := cookiejar.New(nil)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.False(t, corrupt)
|
||||||
|
|
||||||
cookies, err := cookies.NewCookieJar(jar, vault)
|
// load the old prefs file.
|
||||||
require.NoError(t, err)
|
configDir := filepath.Join("testdata", "without_keys")
|
||||||
|
|
||||||
url, err := url.Parse("https://api.protonmail.ch")
|
// Migrate the old prefs file to the new vault.
|
||||||
require.NoError(t, err)
|
require.NoError(t, migrateOldSettingsWithDir(configDir, vault))
|
||||||
|
|
||||||
// There should be a cookie for the API.
|
// Check Json Settings
|
||||||
require.NotEmpty(t, cookies.Cookies(url))
|
validateJSONPrefs(t, vault)
|
||||||
|
|
||||||
|
// Check the keys were found and collected.
|
||||||
|
require.NotEqual(t, []byte("-----BEGIN CERTIFICATE-----"), vault.GetBridgeTLSCert())
|
||||||
|
require.NotEqual(t, []byte("-----BEGIN RSA PRIVATE KEY-----"), vault.GetBridgeTLSKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeychainMigration(t *testing.T) {
|
func TestKeychainMigration(t *testing.T) {
|
||||||
@ -101,7 +92,7 @@ func TestKeychainMigration(t *testing.T) {
|
|||||||
oldCacheDir := filepath.Join(tmpDir, "protonmail", "bridge")
|
oldCacheDir := filepath.Join(tmpDir, "protonmail", "bridge")
|
||||||
require.NoError(t, os.MkdirAll(oldCacheDir, 0o700))
|
require.NoError(t, os.MkdirAll(oldCacheDir, 0o700))
|
||||||
|
|
||||||
oldPrefs, err := os.ReadFile(filepath.Join("testdata", "prefs.json"))
|
oldPrefs, err := os.ReadFile(filepath.Join("testdata", "without_keys", "protonmail", "bridge", "prefs.json"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NoError(t, os.WriteFile(
|
require.NoError(t, os.WriteFile(
|
||||||
@ -196,3 +187,40 @@ func TestUserMigration(t *testing.T) {
|
|||||||
require.Equal(t, vault.CombinedMode, u.AddressMode())
|
require.Equal(t, vault.CombinedMode, u.AddressMode())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateJSONPrefs(t *testing.T, vault *vault.Vault) {
|
||||||
|
// Check that the IMAP and SMTP prefs are migrated.
|
||||||
|
require.Equal(t, 2143, vault.GetIMAPPort())
|
||||||
|
require.Equal(t, 2025, vault.GetSMTPPort())
|
||||||
|
require.True(t, vault.GetSMTPSSL())
|
||||||
|
|
||||||
|
// Check that the update channel is migrated.
|
||||||
|
require.True(t, vault.GetAutoUpdate())
|
||||||
|
require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel())
|
||||||
|
require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout())
|
||||||
|
|
||||||
|
// Check that the app settings have been migrated.
|
||||||
|
require.False(t, vault.GetFirstStart())
|
||||||
|
require.Equal(t, "blablabla", vault.GetColorScheme())
|
||||||
|
require.Equal(t, "2.3.0+git", vault.GetLastVersion().String())
|
||||||
|
require.True(t, vault.GetAutostart())
|
||||||
|
|
||||||
|
// Check that the other app settings have been migrated.
|
||||||
|
require.Equal(t, 16, vault.SyncWorkers())
|
||||||
|
require.Equal(t, 16, vault.SyncAttPool())
|
||||||
|
require.False(t, vault.GetProxyAllowed())
|
||||||
|
require.False(t, vault.GetShowAllMail())
|
||||||
|
|
||||||
|
// Check that the cookies have been migrated.
|
||||||
|
jar, err := cookiejar.New(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cookies, err := cookies.NewCookieJar(jar, vault)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
url, err := url.Parse("https://api.protonmail.ch")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// There should be a cookie for the API.
|
||||||
|
require.NotEmpty(t, cookies.Cookies(url))
|
||||||
|
}
|
||||||
|
|||||||
1
internal/app/testdata/with_keys/protonmail/bridge/cert.pem
vendored
Normal file
1
internal/app/testdata/with_keys/protonmail/bridge/cert.pem
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
1
internal/app/testdata/with_keys/protonmail/bridge/key.pem
vendored
Normal file
1
internal/app/testdata/with_keys/protonmail/bridge/key.pem
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
31
internal/app/testdata/without_keys/protonmail/bridge/prefs.json
vendored
Normal file
31
internal/app/testdata/without_keys/protonmail/bridge/prefs.json
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"allow_proxy": "false",
|
||||||
|
"attachment_workers": "16",
|
||||||
|
"autostart": "true",
|
||||||
|
"autoupdate": "true",
|
||||||
|
"cache_compression": "true",
|
||||||
|
"cache_concurrent_read": "16",
|
||||||
|
"cache_concurrent_write": "16",
|
||||||
|
"cache_enabled": "true",
|
||||||
|
"cache_location": "/home/user/.config/protonmail/bridge/cache/c11/messages",
|
||||||
|
"cache_min_free_abs": "250000000",
|
||||||
|
"cache_min_free_rat": "",
|
||||||
|
"color_scheme": "blablabla",
|
||||||
|
"cookies": "{\"https://api.protonmail.ch\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.ch\",\"Expires\":\"2023-02-19T00:20:40.269424437+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=blablablablablablablablabla; Domain=protonmail.ch; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"default\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:40.269428627+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=default; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}],\"https://protonmail.com\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.com\",\"Expires\":\"2023-02-19T00:20:18.315084712+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=Y3q2Mh-ClvqL6LWeYdfyPgAAABI; Domain=protonmail.com; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"redirect\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:18.315087646+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=redirect; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}]}",
|
||||||
|
"fetch_workers": "16",
|
||||||
|
"first_time_start": "false",
|
||||||
|
"first_time_start_gui": "true",
|
||||||
|
"imap_workers": "16",
|
||||||
|
"is_all_mail_visible": "false",
|
||||||
|
"last_heartbeat": "325",
|
||||||
|
"last_used_version": "2.3.0+git",
|
||||||
|
"preferred_keychain": "secret-service",
|
||||||
|
"rebranding_migrated": "true",
|
||||||
|
"report_outgoing_email_without_encryption": "false",
|
||||||
|
"rollout": "0.4849529004202015",
|
||||||
|
"user_port_api": "1042",
|
||||||
|
"update_channel": "early",
|
||||||
|
"user_port_imap": "2143",
|
||||||
|
"user_port_smtp": "2025",
|
||||||
|
"user_ssl_smtp": "true"
|
||||||
|
}
|
||||||
@ -81,6 +81,7 @@ func newVault(locations *locations.Locations) (*vault.Vault, bool, bool, error)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if key, err := getVaultKey(vaultDir); err != nil {
|
if key, err := getVaultKey(vaultDir); err != nil {
|
||||||
|
logrus.WithError(err).Error("Could not load/create vault key")
|
||||||
insecure = true
|
insecure = true
|
||||||
|
|
||||||
// We store the insecure vault in a separate directory
|
// We store the insecure vault in a separate directory
|
||||||
|
|||||||
@ -374,6 +374,47 @@ func TestBridge_User_Network_NoBadEvents(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBridge503DuringEventDoesNotCauseBadEvent(t *testing.T) {
|
||||||
|
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) {
|
||||||
|
// Create a user.
|
||||||
|
userID, addrID, err := s.CreateUser("user", password)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
labelID, err := s.CreateLabel(userID, "folder", "", proton.LabelTypeFolder)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Create 10 messages for the user.
|
||||||
|
withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) {
|
||||||
|
createNumMessages(ctx, t, c, addrID, labelID, 10)
|
||||||
|
})
|
||||||
|
|
||||||
|
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
|
||||||
|
userLoginAndSync(ctx, t, bridge, "user", password)
|
||||||
|
|
||||||
|
var messageIDs []string
|
||||||
|
|
||||||
|
// Create 10 more messages for the user, generating events.
|
||||||
|
withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) {
|
||||||
|
messageIDs = createNumMessages(ctx, t, c, addrID, labelID, 10)
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.Reporter.EXPECT().ReportMessageWithContext(gomock.Any(), gomock.Any()).MinTimes(1)
|
||||||
|
|
||||||
|
s.AddStatusHook(func(req *http.Request) (int, bool) {
|
||||||
|
if xslices.Index(xslices.Map(messageIDs[0:5], func(messageID string) string {
|
||||||
|
return "/mail/v4/messages/" + messageID
|
||||||
|
}), req.URL.Path) < 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.StatusServiceUnavailable, true
|
||||||
|
})
|
||||||
|
|
||||||
|
userContinueEventProcess(ctx, t, s, bridge)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// userLoginAndSync logs in user and waits until user is fully synced.
|
// userLoginAndSync logs in user and waits until user is fully synced.
|
||||||
func userLoginAndSync(
|
func userLoginAndSync(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|||||||
@ -92,7 +92,7 @@ git submodule update --init --recursive $vcpkgRoot
|
|||||||
. $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" `
|
. $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" `
|
||||||
-DBRIDGE_APP_FULL_NAME="$bridgeFullName" `
|
-DBRIDGE_APP_FULL_NAME="$bridgeFullName" `
|
||||||
-DBRIDGE_VENDOR="$bridgeVendor" `
|
-DBRIDGE_VENDOR="$bridgeVendor" `
|
||||||
-DBRIDGE_REVISION=$REVISION_HASH `
|
-DBRIDGE_REVISION="$REVISION_HASH" `
|
||||||
-DBRIDGE_APP_VERSION="$bridgeVersion" `
|
-DBRIDGE_APP_VERSION="$bridgeVersion" `
|
||||||
-DBRIDGE_BUILD_TIME="$bridgeBuidTime" `
|
-DBRIDGE_BUILD_TIME="$bridgeBuidTime" `
|
||||||
-DBRIDGE_DSN_SENTRY="$bridgeDsnSentry" `
|
-DBRIDGE_DSN_SENTRY="$bridgeDsnSentry" `
|
||||||
|
|||||||
@ -25,6 +25,14 @@ func (vault *Vault) GetBridgeTLSKey() []byte {
|
|||||||
return vault.get().Certs.Bridge.Key
|
return vault.get().Certs.Bridge.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBridgeTLSCertKey sets the path to PEM-encoded certificates for the bridge.
|
||||||
|
func (vault *Vault) SetBridgeTLSCertKey(cert, key []byte) error {
|
||||||
|
return vault.mod(func(data *Data) {
|
||||||
|
data.Certs.Bridge.Cert = cert
|
||||||
|
data.Certs.Bridge.Key = key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (vault *Vault) GetCertsInstalled() bool {
|
func (vault *Vault) GetCertsInstalled() bool {
|
||||||
return vault.get().Certs.Installed
|
return vault.get().Certs.Installed
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,8 @@ package keychain
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
|
||||||
|
"github.com/bradenaw/juniper/xslices"
|
||||||
"github.com/docker/docker-credential-helpers/credentials"
|
"github.com/docker/docker-credential-helpers/credentials"
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus"
|
||||||
"github.com/keybase/go-keychain/secretservice"
|
"github.com/keybase/go-keychain/secretservice"
|
||||||
@ -30,10 +32,13 @@ const (
|
|||||||
labelAtt = "label"
|
labelAtt = "label"
|
||||||
usernameAtt = "username"
|
usernameAtt = "username"
|
||||||
|
|
||||||
defaulDomain = "protonmail/bridge/users/"
|
defaultLabel = "Proton Mail Bridge Credentials"
|
||||||
defaultLabel = "Docker Credentials"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getDomain() string {
|
||||||
|
return hostURL(constants.KeyChainName)
|
||||||
|
}
|
||||||
|
|
||||||
func getSession() (*secretservice.SecretService, *secretservice.Session, error) {
|
func getSession() (*secretservice.SecretService, *secretservice.Session, error) {
|
||||||
service, err := secretservice.NewService()
|
service, err := secretservice.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -73,8 +78,9 @@ func getItems(service *secretservice.SecretService, attributes map[string]string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return xslices.Filter(items, func(t dbus.ObjectPath) bool {
|
||||||
return items, err
|
return strings.HasPrefix(string(t), "/org/freedesktop/secrets")
|
||||||
|
}), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func unlock(service *secretservice.SecretService) error {
|
func unlock(service *secretservice.SecretService) error {
|
||||||
@ -105,11 +111,9 @@ func (s *SecretServiceDBusHelper) Add(creds *credentials.Credentials) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attributes := map[string]string{
|
attributes := map[string]string{
|
||||||
usernameAtt: creds.Username,
|
usernameAtt: creds.Username,
|
||||||
serverAtt: creds.ServerURL,
|
serverAtt: creds.ServerURL,
|
||||||
labelAtt: defaultLabel,
|
labelAtt: defaultLabel,
|
||||||
"xdg:schema": "io.docker.Credentials",
|
|
||||||
"docker_cli": "1",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleTimeout(func() error {
|
return handleTimeout(func() error {
|
||||||
@ -203,13 +207,15 @@ func (s *SecretServiceDBusHelper) List() (map[string]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultDomain := getDomain()
|
||||||
|
|
||||||
for _, it := range items {
|
for _, it := range items {
|
||||||
attributes, err := service.GetAttributes(it)
|
attributes, err := service.GetAttributes(it)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(attributes[serverAtt], defaulDomain) {
|
if !strings.HasPrefix(attributes[serverAtt], defaultDomain) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user