diff --git a/internal/clientconfig/applemail.go b/internal/clientconfig/applemail.go index eba6f0f7..6b598818 100644 --- a/internal/clientconfig/applemail.go +++ b/internal/clientconfig/applemail.go @@ -21,6 +21,7 @@ import ( "os" "path/filepath" "strconv" + "strings" "time" "github.com/ProtonMail/proton-bridge/v3/internal/useragent" @@ -70,24 +71,24 @@ func prepareMobileConfig( password []byte, ) *mobileconfig.Config { return &mobileconfig.Config{ - DisplayName: username, - EmailAddress: addresses, - AccountName: displayName, - AccountDescription: username, - Identifier: "protonmail " + username + strconv.FormatInt(time.Now().Unix(), 10), + DisplayName: escapeXMLString(username), + EmailAddress: escapeXMLString(addresses), + AccountName: escapeXMLString(displayName), + AccountDescription: escapeXMLString(username), + Identifier: escapeXMLString("protonmail " + username + strconv.FormatInt(time.Now().Unix(), 10)), IMAP: &mobileconfig.IMAP{ - Hostname: hostname, + Hostname: escapeXMLString(hostname), Port: imapPort, TLS: imapSSL, - Username: username, - Password: string(password), + Username: escapeXMLString(username), + Password: escapeXMLString(string(password)), }, SMTP: &mobileconfig.SMTP{ - Hostname: hostname, + Hostname: escapeXMLString(hostname), Port: smtpPort, TLS: smtpSSL, - Username: username, - Password: string(password), + Username: escapeXMLString(username), + Password: escapeXMLString(string(password)), }, } } @@ -121,3 +122,13 @@ func saveConfigTemporarily(mc *mobileconfig.Config) (fname string, err error) { return } + +// escapeXMLString replace all occurrences of the 5 characters `&`, `<`, `>`, `"` and `'` by their respective escaped version as per the XML spec. +// https://www.w3.org/TR/xml/#syntax +func escapeXMLString(input string) string { + result := strings.ReplaceAll(input, `&`, `&`) + result = strings.ReplaceAll(result, `<`, `<`) + result = strings.ReplaceAll(result, `>`, `>`) + result = strings.ReplaceAll(result, `"`, `"`) + return strings.ReplaceAll(result, `'`, `'`) +} diff --git a/internal/clientconfig/applemail_test.go b/internal/clientconfig/applemail_test.go new file mode 100644 index 00000000..68036d03 --- /dev/null +++ b/internal/clientconfig/applemail_test.go @@ -0,0 +1,38 @@ +// Copyright (c) 2024 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail 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. +// +// Proton Mail 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 Proton Mail Bridge. If not, see . + +//go:build darwin + +package clientconfig + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEscapeXMLString(t *testing.T) { + require.Equal(t, escapeXMLString(`abc&&''""<<>>def`), `abc&&''""<<>>def`) +} + +// This test requires human interaction (user configuration profile installation prompt). It is for debugging purpose and is disabled by default. +func _TestInstallCert(t *testing.T) { //nolint:unused + require.NoError( + t, + (&AppleMail{}).Configure(`127.0.0.1`, 1143, 1025, true, false, `user&>>`, `<>`, `user&a`, []byte(`ir8R9vhdNXyB7isWzhyEkQ`)), + ) +}