diff --git a/Changelog.md b/Changelog.md index f998c6af..95ecf0c3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,8 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) ## Unreleased +## [v1.3.x] Emma (beta since 2020-08-05) + ### Added * GODT-633 Persistent anonymous API cookies for better load balancing and abuse detection. @@ -41,6 +43,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) ## [v1.3.x] Emma (beta 2020-07-XXX) ### Added +* GODT-554 Detect and notify about "bad certificate" IMAP TLS error. * IMAP mailbox info update when new mailbox is created. * GODT-72 Use ISO-8859-1 encoding if charset is not specified and it isn't UTF-8. @@ -103,6 +106,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) * GODT-321 Changing address ordering would cause all messages to disappear in combined mode. * GODT-129 Fix custom message PGP by using template. * GODT-280 Don't assume contact keys are stored armored. +* GODT-427 Fix race condition in auth refresh that could cause user to be logged out. ## [v1.2.8] Donghai-fix-append (beta 2020-06-XXX) diff --git a/Makefile b/Makefile index 98f23366..c7e43342 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ TARGET_OS?=${GOOS} ## Build .PHONY: build build-nogui check-has-go -BRIDGE_VERSION?=1.2.7-git +BRIDGE_VERSION?=$(shell git describe --abbrev=0 --tags)-git REVISION:=$(shell git rev-parse --short=10 HEAD) BUILD_TIME:=$(shell date +%FT%T%z) diff --git a/go.mod b/go.mod index ad73dc6b..d0e4bfed 100644 --- a/go.mod +++ b/go.mod @@ -71,6 +71,7 @@ require ( replace ( github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0 + github.com/emersion/go-imap => github.com/jameshoulahan/go-imap v0.0.0-20200728140727-d57327f48843 github.com/emersion/go-smtp => github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309 github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20170924085257-7509ea014998 golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200416114516-1fa7f403fb9c diff --git a/go.sum b/go.sum index 27ca5581..c4bd7bcc 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,6 @@ github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7h github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emersion/go-imap v1.0.6-0.20200708083111-011063d6c9df h1:Vlwnsd5P5s+ek+wzEXbZ/g9tUBndVQAb3E1/+/ya3UQ= -github.com/emersion/go-imap v1.0.6-0.20200708083111-011063d6c9df/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU= github.com/emersion/go-imap-appendlimit v0.0.0-20190308131241-25671c986a6a h1:bMdSPm6sssuOFpIaveu3XGAijMS3Tq2S3EqFZmZxidc= github.com/emersion/go-imap-appendlimit v0.0.0-20190308131241-25671c986a6a/go.mod h1:ikgISoP7pRAolqsVP64yMteJa2FIpS6ju88eBT6K1yQ= github.com/emersion/go-imap-idle v0.0.0-20200601154248-f05f54664cc4 h1:/JIALzmCduf5o8TWJSiOBzTb9+R0SChwElUrJLlp2po= @@ -98,6 +96,8 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/jameshoulahan/go-imap v0.0.0-20200728140727-d57327f48843 h1:suxlO4AC4E4bjueAsL0m+qp8kmkxRWMGj+5bBU/KJ8g= +github.com/jameshoulahan/go-imap v0.0.0-20200728140727-d57327f48843/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU= github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:g0fAGBisHaEQ0TRq1iBvemFRf+8AEWEmBESSiWB3Vsc= github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= diff --git a/internal/bridge/release_notes.go b/internal/bridge/release_notes.go index a5f4e263..c3f9a024 100644 --- a/internal/bridge/release_notes.go +++ b/internal/bridge/release_notes.go @@ -15,12 +15,17 @@ // You should have received a copy of the GNU General Public License // along with ProtonMail Bridge. If not, see . -// Code generated by ./release-notes.sh at Wed 12 Aug 2020 12:25:26 PM CEST. DO NOT EDIT. +// Code generated by ./release-notes.sh at Wed 29 Jul 2020 07:07:28 AM CEST. DO NOT EDIT. package bridge -const ReleaseNotes = ` +const ReleaseNotes = `• Improvements to Alternative Routing: Version two of this feature is now more resilient to unstable internet connections, which results in a smoother experience using this feature. Also includes fixes to previous implementation of Alternative Routing when first starting the application or when turning it off. +• Email parsing improvements: Improved detection of email encodings embedded in html/xml in addition to message header; add a fallback option if encoding is not specified and decoding as UTF8 fails (ISO-8859-1) ; tweaked logic of parsing "References" header. +• User interaction improvements: Some smaller improvements in specific cases to make the interaction with Proton Bridge clearer for the user +• Code updates & maintenance: Migrated to GopenPGP v2, updates to GoIMAPv1, increased bbolt version to 1.3.5 and various improvements regarding extensibility and maintainability for upcoming work. +• General stability improvements: Improvements to the behavior of the application under various unstable internet conditions. ` -const ReleaseFixedBugs = `• Fixed ignored import to Sent folder +const ReleaseFixedBugs = `• Fixed a slew of smaller bugs and some conditions which could cause the application to crash. +• The full changelog can be found at https://github.com/ProtonMail/proton-bridge/blob/master/Changelog.md ` diff --git a/internal/events/events.go b/internal/events/events.go index 773b61a6..f4c8411c 100644 --- a/internal/events/events.go +++ b/internal/events/events.go @@ -40,6 +40,7 @@ const ( NoActiveKeyForRecipientEvent = "noActiveKeyForRecipient" UpgradeApplicationEvent = "upgradeApplication" TLSCertIssue = "tlsCertPinningIssue" + IMAPTLSBadCert = "imapTLSBadCert" // LogoutEventTimeout is the minimum time to permit between logout events being sent. LogoutEventTimeout = 3 * time.Minute diff --git a/internal/frontend/qml/Gui.qml b/internal/frontend/qml/Gui.qml index 6e387ad3..82b2743e 100644 --- a/internal/frontend/qml/Gui.qml +++ b/internal/frontend/qml/Gui.qml @@ -237,6 +237,14 @@ Item { winMain.tlsBarState="notOK" } + onShowIMAPCertTroubleshoot : { + go.notifyBubble(1, qsTr( + "Bridge was unable to establish a connection with your Email client.
Learn more
", + "notification message" + )) + } + + } Timer { diff --git a/internal/frontend/qml/tst_Gui.qml b/internal/frontend/qml/tst_Gui.qml index 5b790aaf..464cad92 100644 --- a/internal/frontend/qml/tst_Gui.qml +++ b/internal/frontend/qml/tst_Gui.qml @@ -110,7 +110,7 @@ Window { ListElement { title: "Internet off" } ListElement { title: "NeedUpdate" } ListElement { title: "UpToDate" } - ListElement { title: "ForceUpdate" } + ListElement { title: "ForceUpdate" } ListElement { title: "Linux" } ListElement { title: "Windows" } ListElement { title: "Macos" } @@ -122,6 +122,7 @@ Window { ListElement { title: "Minimize this" } ListElement { title: "SendAlertPopup" } ListElement { title: "TLSCertError" } + ListElement { title: "IMAPCertError" } } ListView { @@ -208,6 +209,9 @@ Window { case "TLSCertError" : go.showCertIssue() break; + case "IMAPCertError" : + go.showIMAPCertTroubleshoot() + break; default : console.log("Not implemented " + data) } @@ -310,6 +314,7 @@ Window { signal failedAutostartCode(string code) signal showCertIssue() + signal showIMAPCertTroubleshoot() signal updateFinished(bool hasError) diff --git a/internal/frontend/qt/frontend.go b/internal/frontend/qt/frontend.go index bcf8d439..f4d84d91 100644 --- a/internal/frontend/qt/frontend.go +++ b/internal/frontend/qt/frontend.go @@ -188,6 +188,7 @@ func (s *FrontendQt) watchEvents() { updateApplicationCh := s.getEventChannel(events.UpgradeApplicationEvent) newUserCh := s.getEventChannel(events.UserRefreshEvent) certIssue := s.getEventChannel(events.TLSCertIssue) + imapCertIssue := s.getEventChannel(events.IMAPTLSBadCert) for { select { case errorDetails := <-errorCh: @@ -227,6 +228,8 @@ func (s *FrontendQt) watchEvents() { s.Qml.LoadAccounts() case <-certIssue: s.Qml.ShowCertIssue() + case <-imapCertIssue: + s.Qml.ShowIMAPCertTroubleshoot() } } } diff --git a/internal/frontend/qt/ui.go b/internal/frontend/qt/ui.go index 124c1e9a..bd8a0b4e 100644 --- a/internal/frontend/qt/ui.go +++ b/internal/frontend/qt/ui.go @@ -135,6 +135,7 @@ type GoQMLInterface struct { _ func(x, y float32) `slot:"saveOutgoingNoEncPopupCoord"` _ func(recipient string) `signal:"showNoActiveKeyForRecipient"` _ func() `signal:"showCertIssue"` + _ func() `signal:"ShowIMAPCertTroubleshoot"` _ func() `slot:"startUpdate"` _ func(hasError bool) `signal:"updateFinished"` diff --git a/internal/imap/backend.go b/internal/imap/backend.go index 3652199a..0e300fdb 100644 --- a/internal/imap/backend.go +++ b/internal/imap/backend.go @@ -29,6 +29,7 @@ import ( "github.com/ProtonMail/proton-bridge/pkg/listener" "github.com/emersion/go-imap" goIMAPBackend "github.com/emersion/go-imap/backend" + "github.com/sirupsen/logrus" ) type panicHandler interface { @@ -219,3 +220,11 @@ func (ib *imapBackend) monitorDisconnectedUsers() { ib.deleteUser(address) } } + +func (ib *imapBackend) upgradeError(err error) { + logrus.WithError(err).Error("IMAP connection couldn't be upgraded to TLS during STARTTLS") + + if strings.Contains(err.Error(), "remote error: tls: bad certificate") { + ib.eventListener.Emit(events.IMAPTLSBadCert, err.Error()) + } +} diff --git a/internal/imap/server.go b/internal/imap/server.go index 34a45fc0..3aac8ada 100644 --- a/internal/imap/server.go +++ b/internal/imap/server.go @@ -57,6 +57,7 @@ func NewIMAPServer(debugClient, debugServer bool, port int, tls *tls.Config, ima s.AllowInsecureAuth = true s.ErrorLog = newServerErrorLogger("server-imap") s.AutoLogout = 30 * time.Minute + s.UpgradeError = imapBackend.upgradeError serverID := imapid.ID{ imapid.FieldName: "ProtonMail", diff --git a/pkg/pmapi/auth.go b/pkg/pmapi/auth.go index 29fef42b..6232c6d9 100644 --- a/pkg/pmapi/auth.go +++ b/pkg/pmapi/auth.go @@ -357,6 +357,9 @@ func (c *client) Auth2FA(twoFactorCode string, auth *Auth) (*Auth2FA, error) { // AuthRefresh will refresh an expired access token. func (c *client) AuthRefresh(uidAndRefreshToken string) (auth *Auth, err error) { + c.refreshLocker.Lock() + defer c.refreshLocker.Unlock() + // If we don't yet have a saved access token, save this one in case the refresh fails! // That way we can try again later (see handleUnauthorizedStatus). c.cm.setTokenIfUnset(c.userID, uidAndRefreshToken) diff --git a/pkg/pmapi/client.go b/pkg/pmapi/client.go index 8c76658e..42f5e862 100644 --- a/pkg/pmapi/client.go +++ b/pkg/pmapi/client.go @@ -113,6 +113,7 @@ type client struct { accessToken string userID string requestLocker sync.Locker + refreshLocker sync.Locker user *User addresses AddressList @@ -130,6 +131,7 @@ func newClient(cm *ClientManager, userID string) *client { hc: getHTTPClient(cm.config, cm.roundTripper, cm.cookieJar), userID: userID, requestLocker: &sync.Mutex{}, + refreshLocker: &sync.Mutex{}, keyRingLock: &sync.Mutex{}, addrKeyRing: make(map[string]*crypto.KeyRing), log: logrus.WithField("pkg", "pmapi").WithField("userID", userID), diff --git a/release-notes/bugs.txt b/release-notes/bugs.txt index 3387c026..57c2f374 100644 --- a/release-notes/bugs.txt +++ b/release-notes/bugs.txt @@ -1 +1,2 @@ -• Fixed ignored import to Sent folder +• Fixed a slew of smaller bugs and some conditions which could cause the application to crash. +• The full changelog can be found at https://github.com/ProtonMail/proton-bridge/blob/master/Changelog.md diff --git a/release-notes/notes.txt b/release-notes/notes.txt index e69de29b..ebe7beea 100644 --- a/release-notes/notes.txt +++ b/release-notes/notes.txt @@ -0,0 +1,5 @@ +• Improvements to Alternative Routing: Version two of this feature is now more resilient to unstable internet connections, which results in a smoother experience using this feature. Also includes fixes to previous implementation of Alternative Routing when first starting the application or when turning it off. +• Email parsing improvements: Improved detection of email encodings embedded in html/xml in addition to message header; add a fallback option if encoding is not specified and decoding as UTF8 fails (ISO-8859-1) ; tweaked logic of parsing "References" header. +• User interaction improvements: Some smaller improvements in specific cases to make the interaction with Proton Bridge clearer for the user +• Code updates & maintenance: Migrated to GopenPGP v2, updates to GoIMAPv1, increased bbolt version to 1.3.5 and various improvements regarding extensibility and maintainability for upcoming work. +• General stability improvements: Improvements to the behavior of the application under various unstable internet conditions. diff --git a/test/Makefile b/test/Makefile index 82758c9e..be965951 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ .PHONY: check-has-go install-godog test test-live test-debug test-live-debug export GO111MODULE=on -export BRIDGE_VERSION:=1.2.7-integrationtests +export BRIDGE_VERSION:=1.3.0-integrationtests export VERBOSITY?=fatal export TEST_DATA=testdata