mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-17 23:56:56 +00:00
User Agent do not contain bridge version, only client in format
This commit is contained in:
committed by
James Houlahan
parent
1d49a484a8
commit
984b28e8f9
@ -79,6 +79,13 @@ type ClientConfig struct {
|
||||
// The client application name and version.
|
||||
AppVersion string
|
||||
|
||||
// The client application user agent in format `client name/client version (os)`, e.g.:
|
||||
// (Intel Mac OS X 10_15_3)
|
||||
// Mac OS X Mail/13.0 (3608.60.0.2.5) (Intel Mac OS X 10_15_3)
|
||||
// Thunderbird/1.5.0 (Ubuntu 18.04.4 LTS)
|
||||
// MSOffice 12 (Windows 10 (10.0))
|
||||
UserAgent string
|
||||
|
||||
// The client ID.
|
||||
ClientID string
|
||||
|
||||
@ -213,6 +220,7 @@ func (c *client) Do(req *http.Request, retryUnauthorized bool) (res *http.Respon
|
||||
func (c *client) doBuffered(req *http.Request, bodyBuffer []byte, retryUnauthorized bool) (res *http.Response, err error) { // nolint[funlen]
|
||||
isAuthReq := strings.Contains(req.URL.Path, "/auth")
|
||||
|
||||
req.Header.Set("User-Agent", c.cm.config.UserAgent)
|
||||
req.Header.Set("x-pm-appversion", c.cm.config.AppVersion)
|
||||
req.Header.Set("x-pm-apiversion", strconv.Itoa(Version))
|
||||
|
||||
|
||||
@ -1,3 +1,20 @@
|
||||
// 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 (
|
||||
@ -96,6 +113,7 @@ func NewClientManager(config *ClientConfig) (cm *ClientManager) {
|
||||
cm.newClient = func(userID string) Client {
|
||||
return newClient(cm, userID)
|
||||
}
|
||||
cm.SetUserAgent("", "", "") // Set default user agent.
|
||||
|
||||
go cm.watchTokenExpirations()
|
||||
|
||||
@ -113,6 +131,10 @@ func (cm *ClientManager) SetRoundTripper(rt http.RoundTripper) {
|
||||
cm.roundTripper = rt
|
||||
}
|
||||
|
||||
func (cm *ClientManager) SetUserAgent(clientName, clientVersion, os string) {
|
||||
cm.config.UserAgent = formatUserAgent(clientName, clientVersion, os)
|
||||
}
|
||||
|
||||
// GetClient returns a client for the given userID.
|
||||
// If the client does not exist already, it is created.
|
||||
func (cm *ClientManager) GetClient(userID string) Client {
|
||||
|
||||
@ -19,7 +19,6 @@ package pmapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// rootURL is the API root URL.
|
||||
@ -31,11 +30,6 @@ import (
|
||||
var rootURL = "api.protonmail.ch" //nolint[gochecknoglobals]
|
||||
var rootScheme = "https" //nolint[gochecknoglobals]
|
||||
|
||||
// CurrentUserAgent is the default User-Agent for go-pmapi lib. This can be changed to program
|
||||
// version and email client.
|
||||
// e.g. Bridge/1.0.4 (Windows) MicrosoftOutlook/16.0.9330.2087
|
||||
var CurrentUserAgent = "GoPMAPI/1.0.14 (" + runtime.GOOS + "; no client)" //nolint[gochecknoglobals]
|
||||
|
||||
// The HTTP transport to use by default.
|
||||
var defaultTransport = &http.Transport{ //nolint[gochecknoglobals]
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
|
||||
@ -39,6 +39,9 @@ type PinningTLSDialer struct {
|
||||
// appVersion is needed to report TLS mismatches.
|
||||
appVersion string
|
||||
|
||||
// userAgent is needed to report TLS mismatches.
|
||||
userAgent string
|
||||
|
||||
// enableRemoteReporting instructs the dialer to report TLS mismatches.
|
||||
enableRemoteReporting bool
|
||||
|
||||
@ -61,9 +64,10 @@ func (p *PinningTLSDialer) SetTLSIssueNotifier(notifier func()) {
|
||||
p.tlsIssueNotifier = notifier
|
||||
}
|
||||
|
||||
func (p *PinningTLSDialer) EnableRemoteTLSIssueReporting(appVersion string) {
|
||||
func (p *PinningTLSDialer) EnableRemoteTLSIssueReporting(appVersion, userAgent string) {
|
||||
p.enableRemoteReporting = true
|
||||
p.appVersion = appVersion
|
||||
p.userAgent = userAgent
|
||||
}
|
||||
|
||||
// DialTLS dials the given network/address, returning an error if the certificates don't match the trusted pins.
|
||||
@ -89,6 +93,7 @@ func (p *PinningTLSDialer) DialTLS(network, address string) (conn net.Conn, err
|
||||
time.Now().Format(time.RFC3339),
|
||||
tlsConn.ConnectionState(),
|
||||
p.appVersion,
|
||||
p.userAgent,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -5,12 +5,11 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
io "io"
|
||||
reflect "reflect"
|
||||
|
||||
crypto "github.com/ProtonMail/gopenpgp/crypto"
|
||||
pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
io "io"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockClient is a mock of Client interface
|
||||
|
||||
@ -46,7 +46,7 @@ func certFingerprint(cert *x509.Certificate) string {
|
||||
}
|
||||
|
||||
// ReportCertIssue reports a TLS key mismatch.
|
||||
func (p *PinChecker) ReportCertIssue(host, port, datetime string, connState tls.ConnectionState, appVersion string) {
|
||||
func (p *PinChecker) ReportCertIssue(host, port, datetime string, connState tls.ConnectionState, appVersion, userAgent string) {
|
||||
var certChain []string
|
||||
|
||||
if len(connState.VerifiedChains) > 0 {
|
||||
@ -57,7 +57,7 @@ func (p *PinChecker) ReportCertIssue(host, port, datetime string, connState tls.
|
||||
|
||||
report := NewTLSReport(host, port, connState.ServerName, certChain, p.trustedPins, appVersion)
|
||||
|
||||
go postCertIssueReport(report)
|
||||
go postCertIssueReport(report, userAgent)
|
||||
}
|
||||
|
||||
func marshalCert7468(certs []*x509.Certificate) (pemCerts []string) {
|
||||
|
||||
@ -26,13 +26,8 @@ import (
|
||||
)
|
||||
|
||||
// NewRequest creates a new request.
|
||||
func (c *client) NewRequest(method, path string, body io.Reader) (req *http.Request, err error) {
|
||||
req, err = http.NewRequest(method, c.cm.GetRootURL()+path, body)
|
||||
|
||||
if req != nil {
|
||||
req.Header.Set("User-Agent", CurrentUserAgent)
|
||||
}
|
||||
return
|
||||
func (c *client) NewRequest(method, path string, body io.Reader) (*http.Request, error) {
|
||||
return http.NewRequest(method, c.cm.GetRootURL()+path, body)
|
||||
}
|
||||
|
||||
// NewJSONRequest create a new JSON request.
|
||||
|
||||
@ -109,7 +109,7 @@ func NewTLSReport(host, port, server string, certChain, knownPins []string, appV
|
||||
}
|
||||
|
||||
// postCertIssueReport posts the given TLS report to the standard TLS Report URI.
|
||||
func postCertIssueReport(report TLSReport) {
|
||||
func postCertIssueReport(report TLSReport, userAgent string) {
|
||||
b, err := json.Marshal(report)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("Failed to marshal TLS report")
|
||||
@ -123,7 +123,7 @@ func postCertIssueReport(report TLSReport) {
|
||||
}
|
||||
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", CurrentUserAgent)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
req.Header.Set("x-pm-apiversion", strconv.Itoa(Version))
|
||||
req.Header.Set("x-pm-appversion", report.AppVersion)
|
||||
|
||||
|
||||
37
pkg/pmapi/useragent.go
Normal file
37
pkg/pmapi/useragent.go
Normal file
@ -0,0 +1,37 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func formatUserAgent(clientName, clientVersion, os string) string {
|
||||
client := ""
|
||||
if clientName != "" {
|
||||
client = clientName
|
||||
if clientVersion != "" {
|
||||
client += "/" + clientVersion
|
||||
}
|
||||
}
|
||||
if os == "" {
|
||||
os = runtime.GOOS
|
||||
}
|
||||
return fmt.Sprintf("%s (%s)", client, os)
|
||||
}
|
||||
50
pkg/pmapi/useragent_test.go
Normal file
50
pkg/pmapi/useragent_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
// 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 (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUpdateCurrentUserAgentGOOS(t *testing.T) {
|
||||
userAgent := formatUserAgent("", "", "")
|
||||
assert.Equal(t, " ("+runtime.GOOS+")", userAgent)
|
||||
}
|
||||
|
||||
func TestUpdateCurrentUserAgentOS(t *testing.T) {
|
||||
userAgent := formatUserAgent("", "", "os")
|
||||
assert.Equal(t, " (os)", userAgent)
|
||||
}
|
||||
|
||||
func TestUpdateCurrentUserAgentClientVer(t *testing.T) {
|
||||
userAgent := formatUserAgent("", "ver", "os")
|
||||
assert.Equal(t, " (os)", userAgent)
|
||||
}
|
||||
|
||||
func TestUpdateCurrentUserAgentClientName(t *testing.T) {
|
||||
userAgent := formatUserAgent("mail", "", "os")
|
||||
assert.Equal(t, "mail (os)", userAgent)
|
||||
}
|
||||
|
||||
func TestUpdateCurrentUserAgentClientNameAndVersion(t *testing.T) {
|
||||
userAgent := formatUserAgent("mail", "ver", "os")
|
||||
assert.Equal(t, "mail/ver (os)", userAgent)
|
||||
}
|
||||
Reference in New Issue
Block a user