You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.2 KiB
135 lines
4.2 KiB
// 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 pmapi |
|
|
|
import ( |
|
"net/http" |
|
"net/http/httptest" |
|
"testing" |
|
) |
|
|
|
const liveAPI = "api.protonmail.ch" |
|
|
|
var testLiveConfig = &ClientConfig{ |
|
AppVersion: "Bridge_1.2.4-test", |
|
ClientID: "Bridge", |
|
} |
|
|
|
func setTestDialerWithPinning(cm *ClientManager) (*int, *DialerWithPinning) { |
|
called := 0 |
|
p := NewDialerWithPinning(cm, testLiveConfig.AppVersion) |
|
p.ReportCertIssueLocal = func() { called++ } |
|
cm.SetRoundTripper(p.TransportWithPinning()) |
|
return &called, p |
|
} |
|
|
|
func TestTLSPinValid(t *testing.T) { |
|
cm := NewClientManager(testLiveConfig) |
|
cm.host = liveAPI |
|
RootScheme = "https" |
|
called, _ := setTestDialerWithPinning(cm) |
|
client := cm.GetClient("pmapi" + t.Name()) |
|
|
|
_, err := client.AuthInfo("this.address.is.disabled") |
|
Ok(t, err) |
|
|
|
Equals(t, 0, *called) |
|
} |
|
|
|
func TestTLSPinBackup(t *testing.T) { |
|
cm := NewClientManager(testLiveConfig) |
|
cm.host = liveAPI |
|
called, p := setTestDialerWithPinning(cm) |
|
p.report.KnownPins[1] = p.report.KnownPins[0] |
|
p.report.KnownPins[0] = "" |
|
|
|
client := cm.GetClient("pmapi" + t.Name()) |
|
|
|
_, err := client.AuthInfo("this.address.is.disabled") |
|
Ok(t, err) |
|
|
|
Equals(t, 0, *called) |
|
} |
|
|
|
func _TestTLSPinNoMatch(t *testing.T) { // nolint[unused] |
|
cm := NewClientManager(testLiveConfig) |
|
cm.host = liveAPI |
|
|
|
called, p := setTestDialerWithPinning(cm) |
|
for i := 0; i < len(p.report.KnownPins); i++ { |
|
p.report.KnownPins[i] = "testing" |
|
} |
|
|
|
client := cm.GetClient("pmapi" + t.Name()) |
|
|
|
_, err := client.AuthInfo("this.address.is.disabled") |
|
Ok(t, err) |
|
|
|
// check that it will be called only once per session |
|
client = cm.GetClient("pmapi" + t.Name()) |
|
_, err = client.AuthInfo("this.address.is.disabled") |
|
Ok(t, err) |
|
|
|
Equals(t, 1, *called) |
|
} |
|
|
|
func _TestTLSPinInvalid(t *testing.T) { // nolint[unused] |
|
cm := NewClientManager(testLiveConfig) |
|
|
|
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
writeJSONResponsefromFile(t, w, "/auth/info/post_response.json", 0) |
|
})) |
|
defer ts.Close() |
|
|
|
called, _ := setTestDialerWithPinning(cm) |
|
|
|
client := cm.GetClient("pmapi" + t.Name()) |
|
|
|
cm.host = liveAPI |
|
_, err := client.AuthInfo("this.address.is.disabled") |
|
Ok(t, err) |
|
|
|
cm.host = ts.URL |
|
_, err = client.AuthInfo("this.address.is.disabled") |
|
Assert(t, err != nil, "error is expected but have %v", err) |
|
|
|
Equals(t, 1, *called) |
|
} |
|
|
|
func _TestTLSSignedCertWrongPublicKey(t *testing.T) { // nolint[unused] |
|
cm := NewClientManager(testLiveConfig) |
|
_, dialer := setTestDialerWithPinning(cm) |
|
_, err := dialer.dialAndCheckFingerprints("tcp", "rsa4096.badssl.com:443") |
|
Assert(t, err != nil, "expected dial to fail because of wrong public key: ", err.Error()) |
|
} |
|
|
|
func _TestTLSSignedCertTrustedPublicKey(t *testing.T) { // nolint[unused] |
|
cm := NewClientManager(testLiveConfig) |
|
_, dialer := setTestDialerWithPinning(cm) |
|
dialer.report.KnownPins = append(dialer.report.KnownPins, `pin-sha256="W8/42Z0ffufwnHIOSndT+eVzBJSC0E8uTIC8O6mEliQ="`) |
|
_, err := dialer.dialAndCheckFingerprints("tcp", "rsa4096.badssl.com:443") |
|
Assert(t, err == nil, "expected dial to succeed because public key is known and cert is signed by CA: ", err.Error()) |
|
} |
|
|
|
func _TestTLSSelfSignedCertTrustedPublicKey(t *testing.T) { // nolint[unused] |
|
cm := NewClientManager(testLiveConfig) |
|
_, dialer := setTestDialerWithPinning(cm) |
|
dialer.report.KnownPins = append(dialer.report.KnownPins, `pin-sha256="9SLklscvzMYj8f+52lp5ze/hY0CFHyLSPQzSpYYIBm8="`) |
|
_, err := dialer.dialAndCheckFingerprints("tcp", "self-signed.badssl.com:443") |
|
Assert(t, err == nil, "expected dial to succeed because public key is known despite cert being self-signed: ", err.Error()) |
|
}
|
|
|