mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-23 02:26:42 +00:00
feat: migrate to gopenpgp v2
This commit is contained in:
@ -15,8 +15,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// Code generated by ./credits.sh at Thu 07 May 2020 08:24:48 PM CEST. DO NOT EDIT.
|
||||
// Code generated by ./credits.sh at Fri 05 Jun 2020 09:09:44 AM CEST. DO NOT EDIT.
|
||||
|
||||
package bridge
|
||||
|
||||
const Credits = "github.com/0xAX/notificator;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/andybalholm/cascadia;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/danieljoos/wincred;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/golang/mock;github.com/google/go-cmp;github.com/gopherjs/gopherjs;github.com/go-resty/resty/v2;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/jhillyerd/enmime;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/pkg/errors;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/gopenpgp;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
||||
const Credits = "github.com/0xAX/notificator;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/andybalholm/cascadia;github.com/certifi/gocertifi;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/raven-go;github.com/golang/mock;github.com/google/go-cmp;github.com/gopherjs/gopherjs;github.com/go-resty/resty/v2;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/jhillyerd/enmime;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/pkg/errors;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/gopenpgp/v2;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// Code generated by ./release-notes.sh at Thu 07 May 2020 08:46:50 PM CEST. DO NOT EDIT.
|
||||
// Code generated by ./release-notes.sh at Tue 09 Jun 2020 10:21:50 AM CEST. DO NOT EDIT.
|
||||
|
||||
package bridge
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/cache"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/uidplus"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/message"
|
||||
@ -82,7 +82,11 @@ func (im *imapMailbox) CreateMessage(flags []string, date time.Time, body imap.L
|
||||
return errors.New("no available address for encryption")
|
||||
}
|
||||
m.AddressID = addr.ID
|
||||
kr := addr.KeyRing()
|
||||
|
||||
kr, err := im.user.client().KeyRingForAddressID(addr.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle imported messages which have no "Sender" address.
|
||||
// This sometimes occurs with outlook which reports errors as imported emails or for drafts.
|
||||
@ -184,7 +188,7 @@ func (im *imapMailbox) CreateMessage(flags []string, date time.Time, body imap.L
|
||||
return uidplus.AppendResponse(im.storeMailbox.UIDValidity(), targetSeq)
|
||||
}
|
||||
|
||||
func (im *imapMailbox) importMessage(m *pmapi.Message, readers []io.Reader, kr *pmcrypto.KeyRing) (err error) { // nolint[funlen]
|
||||
func (im *imapMailbox) importMessage(m *pmapi.Message, readers []io.Reader, kr *crypto.KeyRing) (err error) { // nolint[funlen]
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
// Overwrite content for main header for import.
|
||||
@ -240,7 +244,7 @@ func (im *imapMailbox) importMessage(m *pmapi.Message, readers []io.Reader, kr *
|
||||
}
|
||||
|
||||
// Create encrypted writer.
|
||||
pgpMessage, err := kr.Encrypt(pmcrypto.NewPlainMessage(data), nil)
|
||||
pgpMessage, err := kr.Encrypt(crypto.NewPlainMessage(data), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -722,7 +726,7 @@ func (im *imapMailbox) buildMessage(m *pmapi.Message) (structure *message.BodySt
|
||||
return structure, msgBody, err
|
||||
}
|
||||
|
||||
func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *pmcrypto.KeyRing) (structure *message.BodyStructure, msgBody []byte, err error) { // nolint[funlen]
|
||||
func (im *imapMailbox) buildMessageInner(m *pmapi.Message, kr *crypto.KeyRing) (structure *message.BodyStructure, msgBody []byte, err error) { // nolint[funlen]
|
||||
multipartType, err := im.setMessageContentType(m)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@ -21,7 +21,7 @@ import (
|
||||
"io"
|
||||
"net/mail"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/uidplus"
|
||||
"github.com/ProtonMail/proton-bridge/internal/store"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
@ -35,7 +35,7 @@ type storeUserProvider interface {
|
||||
GetAddress(addressID string) (storeAddressProvider, error)
|
||||
|
||||
CreateDraft(
|
||||
kr *pmcrypto.KeyRing,
|
||||
kr *crypto.KeyRing,
|
||||
message *pmapi.Message,
|
||||
attachmentReaders []io.Reader,
|
||||
attachedPublicKey,
|
||||
|
||||
76
internal/smtp/repro_test.go
Normal file
76
internal/smtp/repro_test.go
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestThing(t *testing.T) {
|
||||
// Load the key.
|
||||
key, err := crypto.NewKeyFromArmored(testPublicKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Put it in a keyring.
|
||||
keyRing, err := crypto.NewKeyRing(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Filter out expired ones.
|
||||
validKeyRings, err := crypto.FilterExpiredKeys([]*crypto.KeyRing{keyRing})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Filtering shouldn't make them unequal.
|
||||
assert.True(t, isEqual(keyRing, validKeyRings[0]))
|
||||
}
|
||||
|
||||
func isEqual(a, b *crypto.KeyRing) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if a == nil && b != nil || a != nil && b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
aKeys, bKeys := a.GetKeys(), b.GetKeys()
|
||||
|
||||
if len(aKeys) != len(bKeys) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range aKeys {
|
||||
aFPs := aKeys[i].GetSHA256Fingerprints()
|
||||
bFPs := bKeys[i].GetSHA256Fingerprints()
|
||||
|
||||
if !cmp.Equal(aFPs, bFPs) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@ -20,7 +20,7 @@ package smtp
|
||||
import (
|
||||
"errors"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/algo"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
@ -37,7 +37,7 @@ type SendingInfo struct {
|
||||
Sign bool
|
||||
Scheme int
|
||||
MIMEType string
|
||||
PublicKey *pmcrypto.KeyRing
|
||||
PublicKey *crypto.KeyRing
|
||||
}
|
||||
|
||||
func generateSendingInfo(
|
||||
@ -46,10 +46,10 @@ func generateSendingInfo(
|
||||
isInternal bool,
|
||||
composeMode string,
|
||||
apiKeys,
|
||||
contactKeys []*pmcrypto.KeyRing,
|
||||
contactKeys []*crypto.KeyRing,
|
||||
settingsSign bool,
|
||||
settingsPgpScheme int) (sendingInfo SendingInfo, err error) {
|
||||
contactKeys, err = pmcrypto.FilterExpiredKeys(contactKeys)
|
||||
contactKeys, err = crypto.FilterExpiredKeys(contactKeys)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -72,7 +72,7 @@ func generateInternalSendingInfo(
|
||||
contactMeta *ContactMetadata,
|
||||
composeMode string,
|
||||
apiKeys,
|
||||
contactKeys []*pmcrypto.KeyRing,
|
||||
contactKeys []*crypto.KeyRing,
|
||||
settingsSign bool, //nolint[unparam]
|
||||
settingsPgpScheme int) (sendingInfo SendingInfo, err error) { //nolint[unparam]
|
||||
// If sending internally, there should always be a public key; if not, there's an error.
|
||||
@ -125,7 +125,7 @@ func generateExternalSendingInfo(
|
||||
contactMeta *ContactMetadata,
|
||||
composeMode string,
|
||||
apiKeys,
|
||||
contactKeys []*pmcrypto.KeyRing,
|
||||
contactKeys []*crypto.KeyRing,
|
||||
settingsSign bool,
|
||||
settingsPgpScheme int) (sendingInfo SendingInfo, err error) {
|
||||
// The default settings, unless overridden by presence of a saved contact.
|
||||
@ -230,14 +230,27 @@ func schemeAndMIME(contact *ContactMetadata, settingsScheme int, settingsMIMETyp
|
||||
|
||||
// checkContactKeysAgainstAPI keeps only those contact keys which are up to date and have
|
||||
// an ID that matches an API key's ID.
|
||||
func checkContactKeysAgainstAPI(contactKeys, apiKeys []*pmcrypto.KeyRing) (filteredKeys []*pmcrypto.KeyRing, err error) { //nolint[unparam]
|
||||
func checkContactKeysAgainstAPI(contactKeys, apiKeys []*crypto.KeyRing) (filteredKeys []*crypto.KeyRing, err error) { //nolint[unparam]
|
||||
keyIDsAreEqual := func(a, b interface{}) bool {
|
||||
aKey, bKey := a.(*pmcrypto.KeyRing), b.(*pmcrypto.KeyRing)
|
||||
return aKey.GetEntities()[0].PrimaryKey.KeyId == bKey.GetEntities()[0].PrimaryKey.KeyId
|
||||
aKey, bKey := a.(*crypto.KeyRing), b.(*crypto.KeyRing)
|
||||
|
||||
aFirst, getKeyErr := aKey.GetKey(0)
|
||||
if getKeyErr != nil {
|
||||
err = errors.New("missing primary key")
|
||||
return false
|
||||
}
|
||||
|
||||
bFirst, getKeyErr := bKey.GetKey(0)
|
||||
if getKeyErr != nil {
|
||||
err = errors.New("missing primary key")
|
||||
return false
|
||||
}
|
||||
|
||||
return aFirst.GetKeyID() == bFirst.GetKeyID()
|
||||
}
|
||||
|
||||
for _, v := range algo.SetIntersection(contactKeys, apiKeys, keyIDsAreEqual) {
|
||||
filteredKeys = append(filteredKeys, v.(*pmcrypto.KeyRing))
|
||||
filteredKeys = append(filteredKeys, v.(*crypto.KeyRing))
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@ -18,15 +18,15 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/internal/users"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -46,8 +46,8 @@ func initMocks(t *testing.T) mocks {
|
||||
type args struct {
|
||||
eventListener listener.Listener
|
||||
contactMeta *ContactMetadata
|
||||
apiKeys []*pmcrypto.KeyRing
|
||||
contactKeys []*pmcrypto.KeyRing
|
||||
apiKeys []*crypto.KeyRing
|
||||
contactKeys []*crypto.KeyRing
|
||||
composeMode string
|
||||
settingsPgpScheme int
|
||||
settingsSign bool
|
||||
@ -68,18 +68,61 @@ func (tt *testData) runTest(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gotSendingInfo, tt.wantSendingInfo)
|
||||
|
||||
assert.Equal(t, gotSendingInfo.Encrypt, tt.wantSendingInfo.Encrypt)
|
||||
assert.Equal(t, gotSendingInfo.Sign, tt.wantSendingInfo.Sign)
|
||||
assert.Equal(t, gotSendingInfo.Scheme, tt.wantSendingInfo.Scheme)
|
||||
assert.Equal(t, gotSendingInfo.MIMEType, tt.wantSendingInfo.MIMEType)
|
||||
assert.True(t, keyRingsAreEqual(gotSendingInfo.PublicKey, tt.wantSendingInfo.PublicKey))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func keyRingFromKey(publicKey string) *crypto.KeyRing {
|
||||
key, err := crypto.NewKeyFromArmored(publicKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
kr, err := crypto.NewKeyRing(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return kr
|
||||
}
|
||||
|
||||
func keyRingsAreEqual(a, b *crypto.KeyRing) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if a == nil && b != nil || a != nil && b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
aKeys, bKeys := a.GetKeys(), b.GetKeys()
|
||||
|
||||
if len(aKeys) != len(bKeys) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range aKeys {
|
||||
aFPs := aKeys[i].GetSHA256Fingerprints()
|
||||
bFPs := bKeys[i].GetSHA256Fingerprints()
|
||||
|
||||
if !cmp.Equal(aFPs, bFPs) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
m := initMocks(t)
|
||||
|
||||
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubKey := keyRingFromKey(testPublicKey)
|
||||
|
||||
tests := []testData{
|
||||
{
|
||||
@ -88,8 +131,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -107,8 +150,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
@ -126,8 +169,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -145,8 +188,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
@ -164,8 +207,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: false,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
@ -183,8 +226,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
eventListener: m.eventListener,
|
||||
contactMeta: nil,
|
||||
isInternal: true,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
},
|
||||
wantSendingInfo: SendingInfo{},
|
||||
wantErr: true,
|
||||
@ -195,8 +238,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
contactMeta: nil,
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -217,20 +260,11 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
|
||||
func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
m := initMocks(t)
|
||||
|
||||
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubKey := keyRingFromKey(testPublicKey)
|
||||
|
||||
preferredPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
preferredPubKey := keyRingFromKey(testPublicKey)
|
||||
|
||||
differentPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testDifferentPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
differentPubKey := keyRingFromKey(testDifferentPublicKey)
|
||||
|
||||
m.eventListener.EXPECT().Emit(events.NoActiveKeyForRecipientEvent, "badkey@email.com")
|
||||
|
||||
@ -241,8 +275,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -260,8 +294,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -279,8 +313,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{preferredPubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{preferredPubKey},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -299,8 +333,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Email: "badkey@email.com", Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: true,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{differentPubKey},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{differentPubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -313,8 +347,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -332,8 +366,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
contactKeys: []*pmcrypto.KeyRing{differentPubKey},
|
||||
apiKeys: []*crypto.KeyRing{pubKey},
|
||||
contactKeys: []*crypto.KeyRing{differentPubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -352,15 +386,9 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubKey := keyRingFromKey(testPublicKey)
|
||||
|
||||
expiredPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testExpiredPublicKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
expiredPubKey := keyRingFromKey(testExpiredPublicKey)
|
||||
|
||||
tests := []testData{
|
||||
{
|
||||
@ -369,8 +397,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -388,8 +416,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{expiredPubKey},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{expiredPubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -407,8 +435,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -426,8 +454,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-inline"},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -445,8 +473,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{Encrypt: true},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{pubKey},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{pubKey},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPMIMEPackage,
|
||||
},
|
||||
@ -464,8 +492,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
@ -483,8 +511,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{MIMEType: pmapi.ContentTypePlainText},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
@ -502,8 +530,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
|
||||
contactMeta: &ContactMetadata{SignMissing: true},
|
||||
isInternal: false,
|
||||
composeMode: pmapi.ContentTypeHTML,
|
||||
apiKeys: []*pmcrypto.KeyRing{},
|
||||
contactKeys: []*pmcrypto.KeyRing{},
|
||||
apiKeys: []*crypto.KeyRing{},
|
||||
contactKeys: []*crypto.KeyRing{},
|
||||
settingsSign: true,
|
||||
settingsPgpScheme: pmapi.PGPInlinePackage,
|
||||
},
|
||||
|
||||
@ -20,13 +20,13 @@ package smtp
|
||||
import (
|
||||
"io"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
)
|
||||
|
||||
type storeUserProvider interface {
|
||||
CreateDraft(
|
||||
kr *pmcrypto.KeyRing,
|
||||
kr *crypto.KeyRing,
|
||||
message *pmapi.Message,
|
||||
attachmentReaders []io.Reader,
|
||||
attachedPublicKey,
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -32,7 +31,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/message"
|
||||
@ -93,16 +92,26 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
err = errors.New("backend: invalid email address: not owned by user")
|
||||
return
|
||||
}
|
||||
kr := addr.KeyRing()
|
||||
|
||||
kr, err := su.client().KeyRingForAddressID(addr.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var attachedPublicKey string
|
||||
var attachedPublicKeyName string
|
||||
if mailSettings.AttachPublicKey > 0 {
|
||||
attachedPublicKey, err = kr.GetArmoredPublicKey()
|
||||
firstKey, err := kr.GetKey(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attachedPublicKeyName = "publickey - " + kr.Identities()[0].Name
|
||||
|
||||
attachedPublicKey, err = firstKey.GetArmoredPublicKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachedPublicKeyName = "publickey - " + kr.GetIdentities()[0].Name
|
||||
}
|
||||
|
||||
message, mimeBody, plainBody, attReaders, err := message.Parse(messageReader, attachedPublicKey, attachedPublicKeyName)
|
||||
@ -171,7 +180,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
|
||||
atts = append(atts, message.Attachments...)
|
||||
// Decrypt attachment keys, because we will need to re-encrypt them with the recipients' public keys.
|
||||
attkeys := make(map[string]*pmcrypto.SymmetricKey)
|
||||
attkeys := make(map[string]*crypto.SessionKey)
|
||||
attkeysEncoded := make(map[string]pmapi.AlgoKey)
|
||||
|
||||
for _, att := range atts {
|
||||
@ -203,7 +212,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
// PMEL 3.
|
||||
composeMode := message.MIMEType
|
||||
|
||||
var plainKey, htmlKey, mimeKey *pmcrypto.SymmetricKey
|
||||
var plainKey, htmlKey, mimeKey *crypto.SessionKey
|
||||
var plainData, htmlData, mimeData []byte
|
||||
|
||||
containsUnencryptedRecipients := false
|
||||
@ -219,7 +228,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
return err
|
||||
}
|
||||
var contactMeta *ContactMetadata
|
||||
var contactKeys []*pmcrypto.KeyRing
|
||||
var contactKeyRings []*crypto.KeyRing
|
||||
for _, contactEmail := range contactEmails {
|
||||
if contactEmail.Defaults == 1 { // WARNING: in doc it says _ignore for now, future feature_
|
||||
continue
|
||||
@ -236,12 +245,19 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contactKeyRing, err := crypto.NewKeyRing(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, contactRawKey := range contactMeta.Keys {
|
||||
contactKey, err := pmcrypto.ReadKeyRing(bytes.NewBufferString(contactRawKey))
|
||||
contactKey, err := crypto.NewKeyFromArmored(contactRawKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contactKeys = append(contactKeys, contactKey)
|
||||
if err := contactKeyRing.AddKey(contactKey); err != nil {
|
||||
return err
|
||||
}
|
||||
contactKeyRings = append(contactKeyRings, contactKeyRing)
|
||||
}
|
||||
|
||||
break // We take the first hit where Defaults == 0, see "How to find the right contact" of PMEL
|
||||
@ -254,16 +270,22 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
return err
|
||||
}
|
||||
|
||||
var apiKeys []*pmcrypto.KeyRing
|
||||
var apiKeyRings []*crypto.KeyRing
|
||||
for _, apiRawKey := range apiRawKeyList {
|
||||
var kr *pmcrypto.KeyRing
|
||||
if kr, err = pmcrypto.ReadArmoredKeyRing(strings.NewReader(apiRawKey.PublicKey)); err != nil {
|
||||
key, err := crypto.NewKeyFromArmored(apiRawKey.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiKeys = append(apiKeys, kr)
|
||||
|
||||
kr, err := crypto.NewKeyRing(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiKeyRings = append(apiKeyRings, kr)
|
||||
}
|
||||
|
||||
sendingInfo, err := generateSendingInfo(su.eventListener, contactMeta, isInternal, composeMode, apiKeys, contactKeys, settingsSign, settingsPgpScheme)
|
||||
sendingInfo, err := generateSendingInfo(su.eventListener, contactMeta, isInternal, composeMode, apiKeyRings, contactKeyRings, settingsSign, settingsPgpScheme)
|
||||
if !sendingInfo.Encrypt {
|
||||
containsUnencryptedRecipients = true
|
||||
}
|
||||
@ -284,7 +306,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
|
||||
}
|
||||
}
|
||||
if sendingInfo.Scheme == pmapi.PGPMIMEPackage {
|
||||
mimeBodyPacket, _, err := createPackets(sendingInfo.PublicKey, mimeKey, map[string]*pmcrypto.SymmetricKey{})
|
||||
mimeBodyPacket, _, err := createPackets(sendingInfo.PublicKey, mimeKey, map[string]*crypto.SessionKey{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import (
|
||||
"encoding/base64"
|
||||
"regexp"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
)
|
||||
|
||||
@ -37,9 +37,9 @@ func looksLikeEmail(e string) bool {
|
||||
}
|
||||
|
||||
func createPackets(
|
||||
pubkey *pmcrypto.KeyRing,
|
||||
bodyKey *pmcrypto.SymmetricKey,
|
||||
attkeys map[string]*pmcrypto.SymmetricKey,
|
||||
pubkey *crypto.KeyRing,
|
||||
bodyKey *crypto.SessionKey,
|
||||
attkeys map[string]*crypto.SessionKey,
|
||||
) (bodyPacket string, attachmentPackets map[string]string, err error) {
|
||||
// Encrypt message body keys.
|
||||
packetBytes, err := pubkey.EncryptSessionKey(bodyKey)
|
||||
@ -61,24 +61,33 @@ func createPackets(
|
||||
}
|
||||
|
||||
func encryptSymmetric(
|
||||
kr *pmcrypto.KeyRing,
|
||||
kr *crypto.KeyRing,
|
||||
textToEncrypt string,
|
||||
canonicalizeText bool, // nolint[unparam]
|
||||
) (key *pmcrypto.SymmetricKey, symEncryptedData []byte, err error) {
|
||||
) (key *crypto.SessionKey, symEncryptedData []byte, err error) {
|
||||
// We use only primary key to encrypt the message. Our keyring contains all keys (primary, old and deacivated ones).
|
||||
pgpMessage, err := kr.FirstKey().Encrypt(pmcrypto.NewPlainMessageFromString(textToEncrypt), kr)
|
||||
firstKey, err := kr.FirstKey()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pgpMessage, err := firstKey.Encrypt(crypto.NewPlainMessageFromString(textToEncrypt), kr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pgpSplitMessage, err := pgpMessage.SeparateKeyAndData(len(textToEncrypt), 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
key, err = kr.DecryptSessionKey(pgpSplitMessage.GetBinaryKeyPacket())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
symEncryptedData = pgpSplitMessage.GetBinaryDataPacket()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -87,7 +96,7 @@ func buildPackage(
|
||||
sharedScheme int,
|
||||
mimeType string,
|
||||
bodyData []byte,
|
||||
bodyKey *pmcrypto.SymmetricKey,
|
||||
bodyKey *crypto.SessionKey,
|
||||
attKeys map[string]pmapi.AlgoKey,
|
||||
) (pkg *pmapi.MessagePackage) {
|
||||
if len(addressMap) == 0 {
|
||||
|
||||
@ -26,7 +26,7 @@ import (
|
||||
"net/textproto"
|
||||
"strings"
|
||||
|
||||
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -37,7 +37,7 @@ import (
|
||||
// If `attachedPublicKey` is passed, it's added to attachments.
|
||||
// Both draft and attachments are encrypted with passed `kr` key.
|
||||
func (store *Store) CreateDraft(
|
||||
kr *pmcrypto.KeyRing,
|
||||
kr *crypto.KeyRing,
|
||||
message *pmapi.Message,
|
||||
attachmentReaders []io.Reader,
|
||||
attachedPublicKey,
|
||||
@ -92,7 +92,7 @@ func (store *Store) getDraftAction(message *pmapi.Message) int {
|
||||
return pmapi.DraftActionReply
|
||||
}
|
||||
|
||||
func (store *Store) createAttachment(kr *pmcrypto.KeyRing, attachment *pmapi.Attachment, attachmentBody []byte) (*pmapi.Attachment, error) {
|
||||
func (store *Store) createAttachment(kr *crypto.KeyRing, attachment *pmapi.Attachment, attachmentBody []byte) (*pmapi.Attachment, error) {
|
||||
r := bytes.NewReader(attachmentBody)
|
||||
sigReader, err := attachment.DetachedSign(kr, r)
|
||||
if err != nil {
|
||||
|
||||
@ -53,9 +53,6 @@ type User struct {
|
||||
|
||||
lock sync.RWMutex
|
||||
isAuthorized bool
|
||||
|
||||
unlockingKeyringLock sync.Mutex
|
||||
wasKeyringUnlocked bool
|
||||
}
|
||||
|
||||
// newUser creates a new user.
|
||||
@ -99,10 +96,6 @@ func (u *User) client() pmapi.Client {
|
||||
// if necessary), and setting the imap idle updates channel (used to send imap idle updates to the imap backend if
|
||||
// something in the store changed).
|
||||
func (u *User) init(idleUpdates chan imapBackend.Update) (err error) {
|
||||
u.unlockingKeyringLock.Lock()
|
||||
u.wasKeyringUnlocked = false
|
||||
u.unlockingKeyringLock.Unlock()
|
||||
|
||||
u.log.Info("Initialising user")
|
||||
|
||||
// Reload the user's credentials (if they log out and back in we need the new
|
||||
@ -197,22 +190,14 @@ func (u *User) authorizeIfNecessary(emitEvent bool) (err error) {
|
||||
|
||||
// unlockIfNecessary will not trigger keyring unlocking if it was already successfully unlocked.
|
||||
func (u *User) unlockIfNecessary() error {
|
||||
u.unlockingKeyringLock.Lock()
|
||||
defer u.unlockingKeyringLock.Unlock()
|
||||
|
||||
if u.wasKeyringUnlocked {
|
||||
if u.client().IsUnlocked() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := u.client().Unlock(u.creds.MailboxPassword); err != nil {
|
||||
if err := u.client().Unlock([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user")
|
||||
}
|
||||
|
||||
if err := u.client().UnlockAddresses([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user addresses")
|
||||
}
|
||||
|
||||
u.wasKeyringUnlocked = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -228,14 +213,10 @@ func (u *User) authorizeAndUnlock() (err error) {
|
||||
return errors.Wrap(err, "failed to refresh API auth")
|
||||
}
|
||||
|
||||
if _, err = u.client().Unlock(u.creds.MailboxPassword); err != nil {
|
||||
if err := u.client().Unlock([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user")
|
||||
}
|
||||
|
||||
if err = u.client().UnlockAddresses([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user addresses")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -432,12 +413,8 @@ func (u *User) UpdateUser() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = u.client().Unlock(u.creds.MailboxPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := u.client().UnlockAddresses([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return err
|
||||
if err = u.client().Unlock([]byte(u.creds.MailboxPassword)); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user")
|
||||
}
|
||||
|
||||
emails := u.client().Addresses().ActiveEmails()
|
||||
@ -514,10 +491,6 @@ func (u *User) Logout() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
u.unlockingKeyringLock.Lock()
|
||||
u.wasKeyringUnlocked = false
|
||||
u.unlockingKeyringLock.Unlock()
|
||||
|
||||
u.client().Logout()
|
||||
|
||||
if err = u.credStorer.Logout(u.userID); err != nil {
|
||||
|
||||
@ -35,12 +35,11 @@ func TestUpdateUser(t *testing.T) {
|
||||
defer cleanUpUserData(user)
|
||||
|
||||
gomock.InOrder(
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().IsUnlocked().Return(false),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
|
||||
m.pmapiClient.EXPECT().UpdateUser().Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}),
|
||||
|
||||
m.credentialsStore.EXPECT().UpdateEmails("user", []string{testPMAPIAddress.Email}),
|
||||
@ -155,8 +154,8 @@ func TestCheckBridgeLoginOK(t *testing.T) {
|
||||
defer cleanUpUserData(user)
|
||||
|
||||
gomock.InOrder(
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().IsUnlocked().Return(false),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
)
|
||||
|
||||
err := user.CheckBridgeLogin(testCredentials.BridgePassword)
|
||||
@ -166,6 +165,28 @@ func TestCheckBridgeLoginOK(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestCheckBridgeLoginTwiceOK(t *testing.T) {
|
||||
m := initMocks(t)
|
||||
defer m.ctrl.Finish()
|
||||
|
||||
user := testNewUser(m)
|
||||
defer cleanUpUserData(user)
|
||||
|
||||
gomock.InOrder(
|
||||
m.pmapiClient.EXPECT().IsUnlocked().Return(false),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().IsUnlocked().Return(true),
|
||||
)
|
||||
|
||||
err := user.CheckBridgeLogin(testCredentials.BridgePassword)
|
||||
waitForEvents()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = user.CheckBridgeLogin(testCredentials.BridgePassword)
|
||||
waitForEvents()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestCheckBridgeLoginUpgradeApplication(t *testing.T) {
|
||||
m := initMocks(t)
|
||||
defer m.ctrl.Finish()
|
||||
@ -220,8 +241,8 @@ func TestCheckBridgeLoginBadPassword(t *testing.T) {
|
||||
defer cleanUpUserData(user)
|
||||
|
||||
gomock.InOrder(
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().IsUnlocked().Return(false),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
)
|
||||
|
||||
err := user.CheckBridgeLogin("wrong!")
|
||||
|
||||
@ -114,33 +114,7 @@ func TestNewUserUnlockFails(t *testing.T) {
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, errors.New("bad password")),
|
||||
m.credentialsStore.EXPECT().Logout("user").Return(nil),
|
||||
m.pmapiClient.EXPECT().Logout(),
|
||||
m.credentialsStore.EXPECT().Logout("user").Return(nil),
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentialsDisconnected, nil),
|
||||
)
|
||||
|
||||
checkNewUserHasCredentials(testCredentialsDisconnected, m)
|
||||
}
|
||||
|
||||
func TestNewUserUnlockAddressesFails(t *testing.T) {
|
||||
m := initMocks(t)
|
||||
defer m.ctrl.Finish()
|
||||
|
||||
m.clientManager.EXPECT().GetClient("user").Return(m.pmapiClient).MinTimes(1)
|
||||
|
||||
m.eventListener.EXPECT().Emit(events.LogoutEvent, "user")
|
||||
m.eventListener.EXPECT().Emit(events.UserRefreshEvent, "user")
|
||||
m.eventListener.EXPECT().Emit(events.CloseConnectionEvent, "user@pm.me")
|
||||
|
||||
gomock.InOrder(
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(errors.New("bad password")),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(errors.New("bad password")),
|
||||
m.credentialsStore.EXPECT().Logout("user").Return(nil),
|
||||
m.pmapiClient.EXPECT().Logout(),
|
||||
m.credentialsStore.EXPECT().Logout("user").Return(nil),
|
||||
|
||||
@ -182,17 +182,8 @@ func (u *Users) closeAllConnections() {
|
||||
}
|
||||
}
|
||||
|
||||
// Login authenticates a user.
|
||||
// The login flow:
|
||||
// * Authenticate user:
|
||||
// client, auth, err := users.Authenticate(username, password)
|
||||
//
|
||||
// * In case user `auth.HasTwoFactor()`, ask for it and fully authenticate the user.
|
||||
// auth2FA, err := client.Auth2FA(twoFactorCode)
|
||||
//
|
||||
// * In case user `auth.HasMailboxPassword()`, ask for it, otherwise use `password`
|
||||
// and then finish the login procedure.
|
||||
// user, err := users.FinishLogin(client, auth, mailboxPassword)
|
||||
// Login authenticates a user by username/password, returning an authorised client and an auth object.
|
||||
// The authorisation scope may not yet be full if the user has 2FA enabled.
|
||||
func (u *Users) Login(username, password string) (authClient pmapi.Client, auth *pmapi.Auth, err error) {
|
||||
u.crashBandicoot(username)
|
||||
|
||||
@ -214,7 +205,6 @@ func (u *Users) Login(username, password string) (authClient pmapi.Client, auth
|
||||
}
|
||||
|
||||
// FinishLogin finishes the login procedure and adds the user into the credentials store.
|
||||
// See `Login` for more details of the login flow.
|
||||
func (u *Users) FinishLogin(authClient pmapi.Client, auth *pmapi.Auth, mbPassword string) (user *User, err error) { //nolint[funlen]
|
||||
defer func() {
|
||||
if err == pmapi.ErrUpgradeApplication {
|
||||
@ -230,20 +220,22 @@ func (u *Users) FinishLogin(authClient pmapi.Client, auth *pmapi.Auth, mbPasswor
|
||||
authClient.Logout()
|
||||
}()
|
||||
|
||||
apiUser, hashedPassword, err := getAPIUser(authClient, auth, mbPassword)
|
||||
apiUser, passphrase, err := getAPIUser(authClient, mbPassword)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get API user")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Got API user")
|
||||
|
||||
var ok bool
|
||||
if user, ok = u.hasUser(apiUser.ID); ok {
|
||||
if err = u.connectExistingUser(user, auth, hashedPassword); err != nil {
|
||||
if err = u.connectExistingUser(user, auth, passphrase); err != nil {
|
||||
log.WithError(err).Error("Failed to connect existing user")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err = u.addNewUser(apiUser, auth, hashedPassword); err != nil {
|
||||
if err = u.addNewUser(apiUser, auth, passphrase); err != nil {
|
||||
log.WithError(err).Error("Failed to add new user")
|
||||
return
|
||||
}
|
||||
@ -255,13 +247,15 @@ func (u *Users) FinishLogin(authClient pmapi.Client, auth *pmapi.Auth, mbPasswor
|
||||
}
|
||||
|
||||
// connectExistingUser connects an existing user.
|
||||
func (u *Users) connectExistingUser(user *User, auth *pmapi.Auth, hashedPassword string) (err error) {
|
||||
func (u *Users) connectExistingUser(user *User, auth *pmapi.Auth, passphrase string) (err error) {
|
||||
if user.IsConnected() {
|
||||
return errors.New("user is already connected")
|
||||
}
|
||||
|
||||
log.Info("Connecting existing user")
|
||||
|
||||
// Update the user's password in the cred store in case they changed it.
|
||||
if err = u.credStorer.UpdatePassword(user.ID(), hashedPassword); err != nil {
|
||||
if err = u.credStorer.UpdatePassword(user.ID(), passphrase); err != nil {
|
||||
return errors.Wrap(err, "failed to update password of user in credentials store")
|
||||
}
|
||||
|
||||
@ -283,7 +277,7 @@ func (u *Users) connectExistingUser(user *User, auth *pmapi.Auth, hashedPassword
|
||||
}
|
||||
|
||||
// addNewUser adds a new user.
|
||||
func (u *Users) addNewUser(apiUser *pmapi.User, auth *pmapi.Auth, hashedPassword string) (err error) {
|
||||
func (u *Users) addNewUser(apiUser *pmapi.User, auth *pmapi.Auth, passphrase string) (err error) {
|
||||
u.lock.Lock()
|
||||
defer u.lock.Unlock()
|
||||
|
||||
@ -299,7 +293,7 @@ func (u *Users) addNewUser(apiUser *pmapi.User, auth *pmapi.Auth, hashedPassword
|
||||
|
||||
activeEmails := client.Addresses().ActiveEmails()
|
||||
|
||||
if _, err = u.credStorer.Add(apiUser.ID, apiUser.Name, auth.GenToken(), hashedPassword, activeEmails); err != nil {
|
||||
if _, err = u.credStorer.Add(apiUser.ID, apiUser.Name, auth.GenToken(), passphrase, activeEmails); err != nil {
|
||||
return errors.Wrap(err, "failed to add user to credentials store")
|
||||
}
|
||||
|
||||
@ -321,21 +315,27 @@ func (u *Users) addNewUser(apiUser *pmapi.User, auth *pmapi.Auth, hashedPassword
|
||||
return err
|
||||
}
|
||||
|
||||
func getAPIUser(client pmapi.Client, auth *pmapi.Auth, mbPassword string) (user *pmapi.User, hashedPassword string, err error) {
|
||||
hashedPassword, err = pmapi.HashMailboxPassword(mbPassword, auth.KeySalt)
|
||||
func getAPIUser(client pmapi.Client, mbPassword string) (user *pmapi.User, passphrase string, err error) {
|
||||
salt, err := client.AuthSalt()
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get salt")
|
||||
return
|
||||
}
|
||||
|
||||
passphrase, err = pmapi.HashMailboxPassword(mbPassword, salt)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not hash mailbox password")
|
||||
return
|
||||
}
|
||||
|
||||
// We unlock the user's PGP key here to detect if the user's mailbox password is wrong.
|
||||
if _, err = client.Unlock(hashedPassword); err != nil {
|
||||
if err = client.Unlock([]byte(passphrase)); err != nil {
|
||||
log.WithError(err).Error("Wrong mailbox password")
|
||||
return
|
||||
}
|
||||
|
||||
if user, err = client.CurrentUser(); err != nil {
|
||||
log.WithError(err).Error("Could not load API user")
|
||||
log.WithError(err).Error("Could not load user data")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,8 @@ func TestUsersFinishLoginBadMailboxPassword(t *testing.T) {
|
||||
m.credentialsStore.EXPECT().List().Return([]string{}, nil),
|
||||
|
||||
// Set up mocks for FinishLogin.
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, err),
|
||||
m.pmapiClient.EXPECT().AuthSalt().Return("", nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(err),
|
||||
m.pmapiClient.EXPECT().DeleteAuth(),
|
||||
m.pmapiClient.EXPECT().Logout(),
|
||||
)
|
||||
@ -57,7 +58,8 @@ func TestUsersFinishLoginUpgradeApplication(t *testing.T) {
|
||||
m.credentialsStore.EXPECT().List().Return([]string{}, nil),
|
||||
|
||||
// Set up mocks for FinishLogin.
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, pmapi.ErrUpgradeApplication),
|
||||
m.pmapiClient.EXPECT().AuthSalt().Return("", nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(pmapi.ErrUpgradeApplication),
|
||||
|
||||
m.eventListener.EXPECT().Emit(events.UpgradeApplicationEvent, ""),
|
||||
m.pmapiClient.EXPECT().DeleteAuth().Return(err),
|
||||
@ -70,7 +72,6 @@ func TestUsersFinishLoginUpgradeApplication(t *testing.T) {
|
||||
func refreshWithToken(token string) *pmapi.Auth {
|
||||
return &pmapi.Auth{
|
||||
RefreshToken: token,
|
||||
KeySalt: "", // No salting in tests.
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +94,8 @@ func TestUsersFinishLoginNewUser(t *testing.T) {
|
||||
m.credentialsStore.EXPECT().List().Return([]string{}, nil),
|
||||
|
||||
// getAPIUser() loads user info from API (e.g. userID).
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().AuthSalt().Return("", nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().CurrentUser().Return(testPMAPIUser, nil),
|
||||
|
||||
// addNewUser()
|
||||
@ -106,8 +108,7 @@ func TestUsersFinishLoginNewUser(t *testing.T) {
|
||||
// user.init() in addNewUser
|
||||
m.credentialsStore.EXPECT().Get("user").Return(credentialsWithToken(":afterLogin"), nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh(":afterLogin").Return(refreshWithToken("afterCredentials"), nil),
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
|
||||
// store.New() in user.init
|
||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||
@ -158,7 +159,8 @@ func TestUsersFinishLoginExistingDisconnectedUser(t *testing.T) {
|
||||
m.pmapiClient.EXPECT().Addresses().Return(nil),
|
||||
|
||||
// getAPIUser() loads user info from API (e.g. userID).
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().AuthSalt().Return("", nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().CurrentUser().Return(testPMAPIUser, nil),
|
||||
|
||||
// connectExistingUser()
|
||||
@ -169,8 +171,7 @@ func TestUsersFinishLoginExistingDisconnectedUser(t *testing.T) {
|
||||
// user.init() in connectExistingUser
|
||||
m.credentialsStore.EXPECT().Get("user").Return(credentialsWithToken(":afterLogin"), nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh(":afterLogin").Return(refreshWithToken("afterCredentials"), nil),
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
|
||||
// store.New() in user.init
|
||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||
@ -206,7 +207,8 @@ func TestUsersFinishLoginConnectedUser(t *testing.T) {
|
||||
|
||||
// Then, try to log in again...
|
||||
gomock.InOrder(
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().AuthSalt().Return("", nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().CurrentUser().Return(testPMAPIUser, nil),
|
||||
m.pmapiClient.EXPECT().DeleteAuth(),
|
||||
m.pmapiClient.EXPECT().Logout(),
|
||||
|
||||
@ -93,8 +93,7 @@ func mockConnectedUser(m mocks) {
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||
|
||||
m.pmapiClient.EXPECT().Unlock(testCredentials.MailboxPassword).Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||
|
||||
// Set up mocks for store initialisation for the authorized user.
|
||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||
|
||||
@ -49,11 +49,9 @@ func TestMain(m *testing.M) {
|
||||
var (
|
||||
testAuth = &pmapi.Auth{ //nolint[gochecknoglobals]
|
||||
RefreshToken: "tok",
|
||||
KeySalt: "", // No salting in tests.
|
||||
}
|
||||
testAuthRefresh = &pmapi.Auth{ //nolint[gochecknoglobals]
|
||||
RefreshToken: "reftok",
|
||||
KeySalt: "", // No salting in tests.
|
||||
}
|
||||
|
||||
testCredentials = &credentials.Credentials{ //nolint[gochecknoglobals]
|
||||
@ -209,8 +207,7 @@ func testNewUsersWithUsers(t *testing.T, m mocks) *Users {
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||
m.pmapiClient.EXPECT().CountMessages("").Return([]*pmapi.MessagesCount{}, nil),
|
||||
m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}),
|
||||
@ -219,8 +216,7 @@ func testNewUsersWithUsers(t *testing.T, m mocks) *Users {
|
||||
m.credentialsStore.EXPECT().Get("users").Return(testCredentialsSplit, nil),
|
||||
m.credentialsStore.EXPECT().Get("users").Return(testCredentialsSplit, nil),
|
||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||
m.pmapiClient.EXPECT().Unlock("pass").Return(nil, nil),
|
||||
m.pmapiClient.EXPECT().UnlockAddresses([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().Unlock([]byte("pass")).Return(nil),
|
||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||
m.pmapiClient.EXPECT().CountMessages("").Return([]*pmapi.MessagesCount{}, nil),
|
||||
m.pmapiClient.EXPECT().Addresses().Return(testPMAPIAddresses),
|
||||
|
||||
Reference in New Issue
Block a user