GODT-1609: use byte array for password

This commit is contained in:
Romain LE JEUNE
2022-10-03 21:12:00 +02:00
committed by James Houlahan
parent 3b5f931f06
commit b536b8707e
20 changed files with 64 additions and 73 deletions

2
go.mod
View File

@ -5,7 +5,7 @@ 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.11.1-0.20221003131446-151fe7c114e2 github.com/ProtonMail/gluon v0.11.1-0.20221003134135-990f7daba502
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
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

2
go.sum
View File

@ -31,6 +31,8 @@ github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkF
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.11.1-0.20221003131446-151fe7c114e2 h1:4AVKhOmX5n0xa7fEbq6DUFj0yO9PTK5V/k7633oyBwg= github.com/ProtonMail/gluon v0.11.1-0.20221003131446-151fe7c114e2 h1:4AVKhOmX5n0xa7fEbq6DUFj0yO9PTK5V/k7633oyBwg=
github.com/ProtonMail/gluon v0.11.1-0.20221003131446-151fe7c114e2/go.mod h1:9k3URQEASX9XSA+JEcukjIiK3S6aR9GzhLhwccy8AnI= github.com/ProtonMail/gluon v0.11.1-0.20221003131446-151fe7c114e2/go.mod h1:9k3URQEASX9XSA+JEcukjIiK3S6aR9GzhLhwccy8AnI=
github.com/ProtonMail/gluon v0.11.1-0.20221003134135-990f7daba502 h1:J3xJzMsepbP22bYJI8szJEwu3DNAdMyGIMyGCJ3CSFc=
github.com/ProtonMail/gluon v0.11.1-0.20221003134135-990f7daba502/go.mod h1:9k3URQEASX9XSA+JEcukjIiK3S6aR9GzhLhwccy8AnI=
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=

View File

@ -26,9 +26,10 @@ import (
const ( const (
username = "username" username = "username"
password = "password"
) )
var password = []byte("password")
var ( var (
v2_3_0 = semver.MustParse("2.3.0") v2_3_0 = semver.MustParse("2.3.0")
v2_4_0 = semver.MustParse("2.4.0") v2_4_0 = semver.MustParse("2.4.0")
@ -339,7 +340,7 @@ func withEnv(t *testing.T, tests func(ctx context.Context, server *server.Server
defer server.Close() defer server.Close()
// Add test user. // Add test user.
_, _, err := server.AddUser(username, password, username+"@pm.me") _, _, err := server.AddUser(username, string(password), username+"@pm.me")
require.NoError(t, err) require.NoError(t, err)
// Generate a random vault key. // Generate a random vault key.

View File

@ -23,7 +23,7 @@ func (backend *smtpBackend) Login(state *smtp.ConnectionState, username string,
defer backend.usersLock.RUnlock() defer backend.usersLock.RUnlock()
for _, user := range backend.users { for _, user := range backend.users {
if slices.Contains(user.Emails(), username) && user.BridgePass() == password { if slices.Contains(user.Emails(), username) && string(user.BridgePass()) == password {
return user.NewSMTPSession(username), nil return user.NewSMTPSession(username), nil
} }
} }

View File

@ -32,7 +32,7 @@ type UserInfo struct {
AddressMode vault.AddressMode AddressMode vault.AddressMode
// BridgePass is the user's bridge password. // BridgePass is the user's bridge password.
BridgePass string BridgePass []byte
// UsedSpace is the amount of space used by the user. // UsedSpace is the amount of space used by the user.
UsedSpace int UsedSpace int
@ -76,11 +76,11 @@ func (bridge *Bridge) QueryUserInfo(query string) (UserInfo, error) {
// If necessary, a TOTP and mailbox password are requested via the callbacks. // If necessary, a TOTP and mailbox password are requested via the callbacks.
func (bridge *Bridge) LoginUser( func (bridge *Bridge) LoginUser(
ctx context.Context, ctx context.Context,
username, password string, username string, password []byte,
getTOTP func() (string, error), getTOTP func() (string, error),
getKeyPass func() ([]byte, error), getKeyPass func() ([]byte, error),
) (string, error) { ) (string, error) {
client, auth, err := bridge.api.NewClientWithLogin(ctx, username, password) client, auth, err := bridge.api.NewClientWithLogin(ctx, username, string(password))
if err != nil { if err != nil {
return "", err return "", err
} }
@ -106,7 +106,7 @@ func (bridge *Bridge) LoginUser(
keyPass = pass keyPass = pass
} else { } else {
keyPass = []byte(password) keyPass = password
} }
apiUser, apiAddrs, userKR, addrKRs, saltedKeyPass, err := client.Unlock(ctx, keyPass) apiUser, apiAddrs, userKR, addrKRs, saltedKeyPass, err := client.Unlock(ctx, keyPass)

View File

@ -255,7 +255,8 @@ func TestBridge_LoginDeleteRestart(t *testing.T) {
func TestBridge_BridgePass(t *testing.T) { func TestBridge_BridgePass(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, dialer *bridge.TestDialer, locator bridge.Locator, storeKey []byte) { withEnv(t, func(ctx context.Context, s *server.Server, dialer *bridge.TestDialer, locator bridge.Locator, storeKey []byte) {
var userID, pass string var userID string
var pass []byte
withBridge(t, ctx, s.GetHostURL(), dialer, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { withBridge(t, ctx, s.GetHostURL(), dialer, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
// Login the user. // Login the user.

View File

@ -39,7 +39,8 @@ func (c *AppleMail) Configure(
hostname string, hostname string,
imapPort, smtpPort int, imapPort, smtpPort int,
imapSSL, smtpSSL bool, imapSSL, smtpSSL bool,
username, addresses, password string, username, addresses string,
password []byte,
) error { ) error {
mc := prepareMobileConfig(hostname, imapPort, smtpPort, imapSSL, smtpSSL, username, addresses, password) mc := prepareMobileConfig(hostname, imapPort, smtpPort, imapSSL, smtpSSL, username, addresses, password)
@ -65,7 +66,8 @@ func prepareMobileConfig(
hostname string, hostname string,
imapPort, smtpPort int, imapPort, smtpPort int,
imapSSL, smtpSSL bool, imapSSL, smtpSSL bool,
username, addresses, password string, username, addresses string,
password []byte,
) *mobileconfig.Config { ) *mobileconfig.Config {
return &mobileconfig.Config{ return &mobileconfig.Config{
DisplayName: username, DisplayName: username,

View File

@ -17,18 +17,17 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.28.1 // protoc-gen-go v1.28.0
// protoc v3.21.6 // protoc v3.21.3
// source: focus.proto // source: focus.proto
package proto package proto
import ( import (
reflect "reflect"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb" emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
) )
const ( const (

View File

@ -1,14 +1,13 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.2.0 // - protoc-gen-go-grpc v1.2.0
// - protoc v3.21.6 // - protoc v3.21.3
// source: focus.proto // source: focus.proto
package proto package proto
import ( import (
context "context" context "context"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"

View File

@ -1336,7 +1336,7 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE(
"\001 \001(\t\022\021\n\tosVersion\030\002 \001(\t\022\023\n\013description\030" "\001 \001(\t\022\021\n\tosVersion\030\002 \001(\t\022\023\n\013description\030"
"\003 \001(\t\022\017\n\007address\030\004 \001(\t\022\023\n\013emailClient\030\005 " "\003 \001(\t\022\017\n\007address\030\004 \001(\t\022\023\n\013emailClient\030\005 "
"\001(\t\022\023\n\013includeLogs\030\006 \001(\010\"2\n\014LoginRequest" "\001(\t\022\023\n\013includeLogs\030\006 \001(\010\"2\n\014LoginRequest"
"\022\020\n\010username\030\001 \001(\t\022\020\n\010password\030\002 \001(\t\"%\n\021" "\022\020\n\010username\030\001 \001(\t\022\020\n\010password\030\002 \001(\014\"%\n\021"
"LoginAbortRequest\022\020\n\010username\030\001 \001(\t\"0\n\027C" "LoginAbortRequest\022\020\n\010username\030\001 \001(\t\"0\n\027C"
"hangeLocalCacheRequest\022\025\n\rdiskCachePath\030" "hangeLocalCacheRequest\022\025\n\rdiskCachePath\030"
"\002 \001(\t\"8\n\022ChangePortsRequest\022\020\n\010imapPort\030" "\002 \001(\t\"8\n\022ChangePortsRequest\022\020\n\010imapPort\030"
@ -1346,7 +1346,7 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE(
"rText\030\003 \001(\t\022\020\n\010loggedIn\030\004 \001(\010\022\021\n\tsplitMo" "rText\030\003 \001(\t\022\020\n\010loggedIn\030\004 \001(\010\022\021\n\tsplitMo"
"de\030\005 \001(\010\022\026\n\016setupGuideSeen\030\006 \001(\010\022\021\n\tused" "de\030\005 \001(\010\022\026\n\016setupGuideSeen\030\006 \001(\010\022\021\n\tused"
"Bytes\030\007 \001(\003\022\022\n\ntotalBytes\030\010 \001(\003\022\020\n\010passw" "Bytes\030\007 \001(\003\022\022\n\ntotalBytes\030\010 \001(\003\022\020\n\010passw"
"ord\030\t \001(\t\022\021\n\taddresses\030\n \003(\t\"6\n\024UserSpli" "ord\030\t \001(\014\022\021\n\taddresses\030\n \003(\t\"6\n\024UserSpli"
"tModeRequest\022\016\n\006userID\030\001 \001(\t\022\016\n\006active\030\002" "tModeRequest\022\016\n\006userID\030\001 \001(\t\022\016\n\006active\030\002"
" \001(\010\"-\n\020UserListResponse\022\031\n\005users\030\001 \003(\0132" " \001(\010\"-\n\020UserListResponse\022\031\n\005users\030\001 \003(\0132"
"\n.grpc.User\"<\n\031ConfigureAppleMailRequest" "\n.grpc.User\"<\n\031ConfigureAppleMailRequest"
@ -2488,13 +2488,12 @@ const char* LoginRequest::_InternalParse(const char* ptr, ::_pbi::ParseContext*
} else } else
goto handle_unusual; goto handle_unusual;
continue; continue;
// string password = 2; // bytes password = 2;
case 2: case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
auto str = _internal_mutable_password(); auto str = _internal_mutable_password();
ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
CHK_(ptr); CHK_(ptr);
CHK_(::_pbi::VerifyUTF8(str, "grpc.LoginRequest.password"));
} else } else
goto handle_unusual; goto handle_unusual;
continue; continue;
@ -2537,13 +2536,9 @@ uint8_t* LoginRequest::_InternalSerialize(
1, this->_internal_username(), target); 1, this->_internal_username(), target);
} }
// string password = 2; // bytes password = 2;
if (!this->_internal_password().empty()) { if (!this->_internal_password().empty()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( target = stream->WriteBytesMaybeAliased(
this->_internal_password().data(), static_cast<int>(this->_internal_password().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"grpc.LoginRequest.password");
target = stream->WriteStringMaybeAliased(
2, this->_internal_password(), target); 2, this->_internal_password(), target);
} }
@ -2570,10 +2565,10 @@ size_t LoginRequest::ByteSizeLong() const {
this->_internal_username()); this->_internal_username());
} }
// string password = 2; // bytes password = 2;
if (!this->_internal_password().empty()) { if (!this->_internal_password().empty()) {
total_size += 1 + total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
this->_internal_password()); this->_internal_password());
} }
@ -3660,13 +3655,12 @@ const char* User::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
} else } else
goto handle_unusual; goto handle_unusual;
continue; continue;
// string password = 9; // bytes password = 9;
case 9: case 9:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) { if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
auto str = _internal_mutable_password(); auto str = _internal_mutable_password();
ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
CHK_(ptr); CHK_(ptr);
CHK_(::_pbi::VerifyUTF8(str, "grpc.User.password"));
} else } else
goto handle_unusual; goto handle_unusual;
continue; continue;
@ -3774,13 +3768,9 @@ uint8_t* User::_InternalSerialize(
target = ::_pbi::WireFormatLite::WriteInt64ToArray(8, this->_internal_totalbytes(), target); target = ::_pbi::WireFormatLite::WriteInt64ToArray(8, this->_internal_totalbytes(), target);
} }
// string password = 9; // bytes password = 9;
if (!this->_internal_password().empty()) { if (!this->_internal_password().empty()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( target = stream->WriteBytesMaybeAliased(
this->_internal_password().data(), static_cast<int>(this->_internal_password().length()),
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
"grpc.User.password");
target = stream->WriteStringMaybeAliased(
9, this->_internal_password(), target); 9, this->_internal_password(), target);
} }
@ -3839,10 +3829,10 @@ size_t User::ByteSizeLong() const {
this->_internal_avatartext()); this->_internal_avatartext());
} }
// string password = 9; // bytes password = 9;
if (!this->_internal_password().empty()) { if (!this->_internal_password().empty()) {
total_size += 1 + total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize(
this->_internal_password()); this->_internal_password());
} }

View File

@ -967,7 +967,7 @@ class LoginRequest final :
std::string* _internal_mutable_username(); std::string* _internal_mutable_username();
public: public:
// string password = 2; // bytes password = 2;
void clear_password(); void clear_password();
const std::string& password() const; const std::string& password() const;
template <typename ArgT0 = const std::string&, typename... ArgT> template <typename ArgT0 = const std::string&, typename... ArgT>
@ -1824,7 +1824,7 @@ class User final :
std::string* _internal_mutable_avatartext(); std::string* _internal_mutable_avatartext();
public: public:
// string password = 9; // bytes password = 9;
void clear_password(); void clear_password();
const std::string& password() const; const std::string& password() const;
template <typename ArgT0 = const std::string&, typename... ArgT> template <typename ArgT0 = const std::string&, typename... ArgT>
@ -10195,7 +10195,7 @@ inline void LoginRequest::set_allocated_username(std::string* username) {
// @@protoc_insertion_point(field_set_allocated:grpc.LoginRequest.username) // @@protoc_insertion_point(field_set_allocated:grpc.LoginRequest.username)
} }
// string password = 2; // bytes password = 2;
inline void LoginRequest::clear_password() { inline void LoginRequest::clear_password() {
_impl_.password_.ClearToEmpty(); _impl_.password_.ClearToEmpty();
} }
@ -10207,7 +10207,7 @@ template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE inline PROTOBUF_ALWAYS_INLINE
void LoginRequest::set_password(ArgT0&& arg0, ArgT... args) { void LoginRequest::set_password(ArgT0&& arg0, ArgT... args) {
_impl_.password_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); _impl_.password_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
// @@protoc_insertion_point(field_set:grpc.LoginRequest.password) // @@protoc_insertion_point(field_set:grpc.LoginRequest.password)
} }
inline std::string* LoginRequest::mutable_password() { inline std::string* LoginRequest::mutable_password() {
@ -10730,7 +10730,7 @@ inline void User::set_totalbytes(int64_t value) {
// @@protoc_insertion_point(field_set:grpc.User.totalBytes) // @@protoc_insertion_point(field_set:grpc.User.totalBytes)
} }
// string password = 9; // bytes password = 9;
inline void User::clear_password() { inline void User::clear_password() {
_impl_.password_.ClearToEmpty(); _impl_.password_.ClearToEmpty();
} }
@ -10742,7 +10742,7 @@ template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE inline PROTOBUF_ALWAYS_INLINE
void User::set_password(ArgT0&& arg0, ArgT... args) { void User::set_password(ArgT0&& arg0, ArgT... args) {
_impl_.password_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); _impl_.password_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
// @@protoc_insertion_point(field_set:grpc.User.password) // @@protoc_insertion_point(field_set:grpc.User.password)
} }
inline std::string* User::mutable_password() { inline std::string* User::mutable_password() {

View File

@ -129,7 +129,7 @@ func (f *frontendCLI) loginAccount(c *ishell.Context) { //nolint:funlen
userID, err := f.bridge.LoginUser( userID, err := f.bridge.LoginUser(
context.Background(), context.Background(),
loginName, loginName,
password, []byte(password),
func() (string, error) { func() (string, error) {
return f.readStringInAttempts("Two factor code", c.ReadLine, isNotEmpty), nil return f.readStringInAttempts("Two factor code", c.ReadLine, isNotEmpty), nil
}, },

View File

@ -468,7 +468,7 @@ type LoginRequest struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` Password []byte `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
} }
func (x *LoginRequest) Reset() { func (x *LoginRequest) Reset() {
@ -510,11 +510,11 @@ func (x *LoginRequest) GetUsername() string {
return "" return ""
} }
func (x *LoginRequest) GetPassword() string { func (x *LoginRequest) GetPassword() []byte {
if x != nil { if x != nil {
return x.Password return x.Password
} }
return "" return nil
} }
type LoginAbortRequest struct { type LoginAbortRequest struct {
@ -738,7 +738,7 @@ type User struct {
SetupGuideSeen bool `protobuf:"varint,6,opt,name=setupGuideSeen,proto3" json:"setupGuideSeen,omitempty"` SetupGuideSeen bool `protobuf:"varint,6,opt,name=setupGuideSeen,proto3" json:"setupGuideSeen,omitempty"`
UsedBytes int64 `protobuf:"varint,7,opt,name=usedBytes,proto3" json:"usedBytes,omitempty"` UsedBytes int64 `protobuf:"varint,7,opt,name=usedBytes,proto3" json:"usedBytes,omitempty"`
TotalBytes int64 `protobuf:"varint,8,opt,name=totalBytes,proto3" json:"totalBytes,omitempty"` TotalBytes int64 `protobuf:"varint,8,opt,name=totalBytes,proto3" json:"totalBytes,omitempty"`
Password string `protobuf:"bytes,9,opt,name=password,proto3" json:"password,omitempty"` Password []byte `protobuf:"bytes,9,opt,name=password,proto3" json:"password,omitempty"`
Addresses []string `protobuf:"bytes,10,rep,name=addresses,proto3" json:"addresses,omitempty"` Addresses []string `protobuf:"bytes,10,rep,name=addresses,proto3" json:"addresses,omitempty"`
} }
@ -830,11 +830,11 @@ func (x *User) GetTotalBytes() int64 {
return 0 return 0
} }
func (x *User) GetPassword() string { func (x *User) GetPassword() []byte {
if x != nil { if x != nil {
return x.Password return x.Password
} }
return "" return nil
} }
func (x *User) GetAddresses() []string { func (x *User) GetAddresses() []string {
@ -3727,7 +3727,7 @@ var file_bridge_proto_rawDesc = []byte{
0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x22, 0x2f, 0x0a, 0x11, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x2f, 0x0a, 0x11, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f,
0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65,
@ -3760,7 +3760,7 @@ var file_bridge_proto_rawDesc = []byte{
0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79,
0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c,
0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0a, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0a,
0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22,
0x46, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65,

View File

@ -148,7 +148,7 @@ message ReportBugRequest {
message LoginRequest { message LoginRequest {
string username = 1; string username = 1;
string password = 2; bytes password = 2;
} }
message LoginAbortRequest { message LoginAbortRequest {
@ -189,7 +189,7 @@ message User {
bool setupGuideSeen = 6; bool setupGuideSeen = 6;
int64 usedBytes = 7; int64 usedBytes = 7;
int64 totalBytes = 8; int64 totalBytes = 8;
string password = 9; bytes password = 9;
repeated string addresses = 10; repeated string addresses = 10;
} }

View File

@ -356,8 +356,8 @@ func (s *Service) Login(ctx context.Context, login *LoginRequest) (*emptypb.Empt
go func() { go func() {
defer s.panicHandler.HandlePanic() defer s.panicHandler.HandlePanic()
var password []byte
password, err := base64.StdEncoding.DecodeString(login.Password) _, err := base64.StdEncoding.Decode(password, login.Password)
if err != nil { if err != nil {
s.log.WithError(err).Error("Cannot decode password") s.log.WithError(err).Error("Cannot decode password")
_ = s.SendEvent(NewLoginError(LoginErrorType_USERNAME_PASSWORD_ERROR, "Cannot decode password")) _ = s.SendEvent(NewLoginError(LoginErrorType_USERNAME_PASSWORD_ERROR, "Cannot decode password"))
@ -368,7 +368,7 @@ func (s *Service) Login(ctx context.Context, login *LoginRequest) (*emptypb.Empt
// - bad credentials // - bad credentials
// - bad proton plan // - bad proton plan
// - user already exists // - user already exists
userID, err := s.bridge.LoginUser(context.Background(), login.Username, string(password), nil, nil) userID, err := s.bridge.LoginUser(context.Background(), login.Username, password, nil, nil)
if err != nil { if err != nil {
s.log.WithError(err).Error("Cannot login user") s.log.WithError(err).Error("Cannot login user")
_ = s.SendEvent(NewLoginError(LoginErrorType_USERNAME_PASSWORD_ERROR, "Cannot login user")) _ = s.SendEvent(NewLoginError(LoginErrorType_USERNAME_PASSWORD_ERROR, "Cannot login user"))

View File

@ -30,7 +30,7 @@ type imapConnector struct {
updateCh <-chan imap.Update updateCh <-chan imap.Update
emails []string emails []string
password string password []byte
flags, permFlags, attrs imap.FlagSet flags, permFlags, attrs imap.FlagSet
} }
@ -38,7 +38,7 @@ type imapConnector struct {
func newIMAPConnector( func newIMAPConnector(
client *liteapi.Client, client *liteapi.Client,
updateCh <-chan imap.Update, updateCh <-chan imap.Update,
password string, password []byte,
emails ...string, emails ...string,
) *imapConnector { ) *imapConnector {
return &imapConnector{ return &imapConnector{
@ -55,8 +55,8 @@ func newIMAPConnector(
} }
// Authorize returns whether the given username/password combination are valid for this connector. // Authorize returns whether the given username/password combination are valid for this connector.
func (conn *imapConnector) Authorize(username string, password string) bool { func (conn *imapConnector) Authorize(username string, password []byte) bool {
if subtle.ConstantTimeCompare([]byte(conn.password), []byte(password)) != 1 { if subtle.ConstantTimeCompare(conn.password, password) != 1 {
return false return false
} }

View File

@ -205,8 +205,8 @@ func (user *User) GluonKey() []byte {
} }
// BridgePass returns the user's bridge password, used for authentication over SMTP and IMAP. // BridgePass returns the user's bridge password, used for authentication over SMTP and IMAP.
func (user *User) BridgePass() string { func (user *User) BridgePass() []byte {
return user.vault.BridgePass() return []byte(user.vault.BridgePass())
} }
// UsedSpace returns the total space used by the user on the API. // UsedSpace returns the total space used by the user on the API.

View File

@ -1,8 +1,6 @@
package vault package vault
import ( import (
"encoding/hex"
"github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/imap"
) )
@ -52,8 +50,8 @@ func (user *User) AddressMode() AddressMode {
return user.vault.getUser(user.userID).AddressMode return user.vault.getUser(user.userID).AddressMode
} }
func (user *User) BridgePass() string { func (user *User) BridgePass() []byte {
return hex.EncodeToString(user.vault.getUser(user.userID).BridgePass) return user.vault.getUser(user.userID).BridgePass
} }
func (user *User) AuthUID() string { func (user *User) AuthUID() string {

View File

@ -1,7 +1,6 @@
package vault_test package vault_test
import ( import (
"encoding/hex"
"testing" "testing"
"github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/imap"
@ -53,7 +52,7 @@ func TestUser(t *testing.T) {
// Get auth information for user 1. // Get auth information for user 1.
require.Equal(t, "userID1", user1.UserID()) require.Equal(t, "userID1", user1.UserID())
require.Equal(t, "user1", user1.Username()) require.Equal(t, "user1", user1.Username())
require.Equal(t, hex.EncodeToString([]byte("token")), user1.BridgePass()) require.Equal(t, []byte("token"), user1.BridgePass())
require.Equal(t, vault.CombinedMode, user1.AddressMode()) require.Equal(t, vault.CombinedMode, user1.AddressMode())
require.Equal(t, "authUID1", user1.AuthUID()) require.Equal(t, "authUID1", user1.AuthUID())
require.Equal(t, "authRef1", user1.AuthRef()) require.Equal(t, "authRef1", user1.AuthRef())
@ -73,7 +72,7 @@ func TestUser(t *testing.T) {
// Get auth information for user 2. // Get auth information for user 2.
require.Equal(t, "userID2", user2.UserID()) require.Equal(t, "userID2", user2.UserID())
require.Equal(t, "user2", user2.Username()) require.Equal(t, "user2", user2.Username())
require.Equal(t, hex.EncodeToString([]byte("token")), user2.BridgePass()) require.Equal(t, []byte("token"), user2.BridgePass())
require.Equal(t, vault.CombinedMode, user2.AddressMode()) require.Equal(t, vault.CombinedMode, user2.AddressMode())
require.Equal(t, "authUID2", user2.AuthUID()) require.Equal(t, "authUID2", user2.AuthUID())
require.Equal(t, "authRef2", user2.AuthRef()) require.Equal(t, "authRef2", user2.AuthRef())

View File

@ -46,7 +46,7 @@ type IMAP struct {
TLS bool TLS bool
Username string Username string
Password string Password []byte
} }
type SMTP struct { type SMTP struct {