Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c2eda7d
MEN-3730 OpenSSL via spacemonkey.
merlin-northern Jul 23, 2020
bbcc05c
take 0
merlin-northern Jul 29, 2020
af76488
take 1
merlin-northern Jul 29, 2020
7fd8f02
take 2
merlin-northern Jul 29, 2020
5ed7ea3
take 3
merlin-northern Jul 30, 2020
b6219b0
(go mod) take 4
merlin-northern Jul 30, 2020
6a063ce
take 5
merlin-northern Jul 30, 2020
acf1da3
take 6
merlin-northern Aug 1, 2020
0811fd5
take 7
merlin-northern Aug 1, 2020
9b905d9
take 8
merlin-northern Aug 1, 2020
2bf137f
take 9
merlin-northern Aug 1, 2020
23fece0
take client/client_update_test.go
merlin-northern Aug 1, 2020
0918cd0
take 12
merlin-northern Aug 1, 2020
9e584c4
0x12 and 0x42 tests and refactor starthttps test helper to separate file
merlin-northern Aug 3, 2020
80aa7df
unit fix
merlin-northern Aug 3, 2020
d0fc441
go fmt
merlin-northern Aug 3, 2020
522e74f
TestClientAuthCertificateAuthorityKeyTooSmall added
merlin-northern Aug 3, 2020
2e55964
TestClientAuthCertificateAuthorityKeyTooSmall cert fix
merlin-northern Aug 3, 2020
d6aa761
fixes
merlin-northern Aug 3, 2020
db05fc9
removing CA key too short test
merlin-northern Aug 3, 2020
5c6cb2a
license on new file
merlin-northern Aug 3, 2020
ce4834b
old go version in build_servers fix
merlin-northern Aug 3, 2020
3828a85
TestClientAuthUnknownAuthorityCert on
merlin-northern Aug 3, 2020
6e67adf
fake certificate and TestClientAuthUnknownAuthorityCert back on
merlin-northern Aug 3, 2020
adf5147
lets see
merlin-northern Aug 3, 2020
b2f7e6c
host validation off for TestClientAuthUnknownAuthorityCert
merlin-northern Aug 3, 2020
1771412
host verification error fixed
merlin-northern Aug 3, 2020
6e6aac0
host verification error fixed
merlin-northern Aug 3, 2020
7cb4dbb
hosts update for the units
merlin-northern Aug 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ mender

# Go test coverage output
*coverage*.txt

# IDE and editors
.idea
*.swp
7 changes: 7 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ test:
- apt-get update && apt-get install -yyq liblzma-dev libssl-dev
- make get-tools
script:
# - cat /etc/ssl/openssl.cnf
# - sed -i -e 's/CipherString = DEFAULT@SECLEVEL=.*/CipherString = DEFAULT@SECLEVEL=-1/' /etc/ssl/openssl.cnf
# - cat /etc/ssl/openssl.cnf
# - pwd
# - find . -name server.crt
# - go mod vendor
- echo "127.0.0.1 www.dimi.fr" >> /etc/hosts
- make extracheck
- make coverage
- make
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,13 @@ check: test extracheck
test:
$(GO) test $(BUILDV) $(PKGS)

extracheck: gofmt govet godeadcode govarcheck gocyclo
extracheck: gomod gofmt govet godeadcode govarcheck gocyclo
echo "All extra-checks passed!"

gomod:
echo "-- checking if code is gofmt'ed"
$(GO) mod vendor

gofmt:
echo "-- checking if code is gofmt'ed"
if [ -n "$$($(GOFMT) -d $(PKGFILES))" ]; then \
Expand Down
44 changes: 44 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"
"time"

openssl "github.com/Linutronix/golang-openssl"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"golang.org/x/net/http2"
Expand Down Expand Up @@ -280,9 +281,49 @@ func newHttpClient() *http.Client {
return &http.Client{}
}

func dialOpenSSL(conf Config, network string, addr string) (net.Conn, error) {
contextSSL, err := openssl.NewCtx() // probably should consider reusing the context, but we
// have to propagate it with every request
err = contextSSL.LoadVerifyLocations(conf.ServerCert, "")
if err != nil {
return nil, err
}
flags := openssl.DialFlags(0)

if conf.NoVerify {
flags = openssl.InsecureSkipHostVerification
}

conn, err := openssl.Dial("tcp", addr, contextSSL, flags)
if conn == nil || err != nil {
return nil, err
}

conn.VerifyMode()
conn.PeerCertificate()
v := conn.VerifyResult()
if v != openssl.Ok {
if v == openssl.CertHasExpired {
return nil, errors.Errorf("certificate has expired, openssl verify rc: %d server cert file: %s", v, conf.ServerCert)
}
if v == openssl.DepthZeroSelfSignedCert {
return nil, errors.Errorf("depth zero self-signed certificate, openssl verify rc: %d server cert file: %s", v, conf.ServerCert)
}
if v == 0x42 { //X509_V_ERR_EE_KEY_TOO_SMALL
return nil, errors.Errorf("end entity key too short, openssl verify rc: %d server cert file: %s", v, conf.ServerCert)
}
if v == 0x14 { //X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
return nil, errors.Errorf("certificate signed by unknown authority, openssl verify rc: %d server cert file: %s", v, conf.ServerCert)
}
return nil, errors.Errorf("not a valid certificate, openssl verify rc: %d server cert file: %s", v, conf.ServerCert)
}
return conn, err
}

func newHttpsClient(conf Config) (*http.Client, error) {
client := newHttpClient()

//conf.ServerCert = "/go/src/github.com/mendersoftware/mender/client/" + conf.ServerCert
trustedcerts := loadServerTrust(&conf)

if conf.NoVerify {
Expand All @@ -295,6 +336,9 @@ func newHttpsClient(conf Config) (*http.Client, error) {
transport := http.Transport{
TLSClientConfig: &tlsc,
Proxy: http.ProxyFromEnvironment,
DialTLS: func(network string, addr string) (net.Conn, error) {
return dialOpenSSL(conf, network, addr)
},
}

client.Transport = &transport
Expand Down
79 changes: 69 additions & 10 deletions client/client_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -88,13 +88,15 @@ func TestClientAuth(t *testing.T) {
http.Header{},
}

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
responder.headers = r.Header
w.WriteHeader(responder.httpStatus)
w.Header().Set("Content-Type", "application/json")

fmt.Fprint(w, responder.data)
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Expand Down Expand Up @@ -122,8 +124,9 @@ func TestClientAuth(t *testing.T) {
}

func TestClientAuthExpiredCert(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
}))
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
localhostCertExpired,
localhostKeyExpired)
defer ts.Close()

ac, err := NewApiClient(
Expand All @@ -145,8 +148,9 @@ func TestClientAuthExpiredCert(t *testing.T) {
}

func TestClientAuthUnknownAuthorityCert(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
}))
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
localhostCertUnknown,
localhostKeyUnknown)
defer ts.Close()

ac, err := NewApiClient(
Expand All @@ -161,15 +165,70 @@ func TestClientAuthUnknownAuthorityCert(t *testing.T) {
msger := &testAuthDataMessenger{
reqData: []byte("foobar"),
}
rsp, err := client.Request(ac, ts.URL, msger)
rsp, err := client.Request(ac, strings.ReplaceAll(ts.URL, "127.0.0.1", "www.dimi.fr"), msger)
assert.Error(t, err)
assert.Contains(t, err.Error(), "certificate signed by unknown authority")
// see https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/x509/x509_vfy.c#L3268
// for self-signed openssl always returns self-signed error; either
// X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT or X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
// and never X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT or X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
assert.Nil(t, rsp)
}

//X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
func TestClientAuthDepthZeroSelfSignedCert(t *testing.T) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Config{"server.zero.depth.self.signed.crt", true, false},
)
assert.NotNil(t, ac)
assert.NoError(t, err)

client := NewAuth()
assert.NotNil(t, client)

msger := &testAuthDataMessenger{
reqData: []byte("foobar"),
}
rsp, err := client.Request(ac, ts.URL, msger)
assert.Error(t, err)
assert.Contains(t, err.Error(), "depth zero self-signed certificate")
assert.Nil(t, rsp)
}

//X509_V_ERR_EE_KEY_TOO_SMALL
func TestClientAuthEndEntityKeyTooSmall(t *testing.T) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
localhostCertShortEEKey,
localhostKeyShortEEKey)
defer ts.Close()

ac, err := NewApiClient(
Config{"server.crt", true, false},
)
assert.NotNil(t, ac)
assert.NoError(t, err)

client := NewAuth()
assert.NotNil(t, client)

msger := &testAuthDataMessenger{
reqData: []byte("foobar"),
}
rsp, err := client.Request(ac, ts.URL, msger)
assert.Error(t, err)
assert.Contains(t, err.Error(), "end entity key too short")
assert.Nil(t, rsp)
}

func TestClientAuthNoCert(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
}))
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Expand Down
9 changes: 5 additions & 4 deletions client/client_inventory_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Northern.tech AS
// Copyright 2020 Northern.tech AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@ package client
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/pkg/errors"
Expand All @@ -35,12 +34,14 @@ func TestInventoryClient(t *testing.T) {
}

// Test server that always responds with 200 code, and specific payload
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(responder.httpStatus)

responder.recdata, _ = ioutil.ReadAll(r.Body)
responder.path = r.URL.Path
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Expand Down
9 changes: 5 additions & 4 deletions client/client_log_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Northern.tech AS
// Copyright 2020 Northern.tech AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@ package client
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/pkg/errors"
Expand All @@ -35,12 +34,14 @@ func TestLogUploadClient(t *testing.T) {
}

// Test server that always responds with 200 code, and specific payload
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(responder.httpStatus)

responder.recdata, _ = ioutil.ReadAll(r.Body)
responder.path = r.URL.Path
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Expand Down
9 changes: 5 additions & 4 deletions client/client_status_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018 Northern.tech AS
// Copyright 2020 Northern.tech AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@ package client
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/pkg/errors"
Expand All @@ -35,12 +34,14 @@ func TestStatusClient(t *testing.T) {
}

// Test server that always responds with 200 code, and specific payload
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(responder.httpStatus)

responder.recdata, _ = ioutil.ReadAll(r.Body)
responder.path = r.URL.Path
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

ac, err := NewApiClient(
Expand Down
19 changes: 12 additions & 7 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"errors"
"net"
"net/http"
"net/http/httptest"
"runtime"
"strings"
"testing"
Expand Down Expand Up @@ -81,11 +80,13 @@ func TestApiClientRequest(t *testing.T) {
http.Header{},
}

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
responder.headers = r.Header
w.WriteHeader(responder.httpStatus)
w.Header().Set("Content-Type", "application/json")
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

auth := false
Expand Down Expand Up @@ -138,10 +139,12 @@ func TestClientConnectionTimeout(t *testing.T) {
prevReadingTimeout := defaultClientReadingTimeout
defaultClientReadingTimeout = 10 * time.Millisecond

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// sleep so that client request will timeout
time.Sleep(defaultClientReadingTimeout + defaultClientReadingTimeout)
}))
}),
localhostCert,
localhostKey)

defer func() {
ts.Close()
Expand Down Expand Up @@ -360,11 +363,13 @@ func TestFailoverAPICall(t *testing.T) {
http.Header{},
}

ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ts := startTestHTTPS(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
responder.headers = r.Header
w.WriteHeader(responder.httpStatus)
w.Header().Set("Content-Type", "application/json")
}))
}),
localhostCert,
localhostKey)
defer ts.Close()

mulServerfunc := func() func() *MenderServer {
Expand Down
Loading