Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2bbb298

Browse files
author
Anonymous
committedApr 14, 2022
Add tests
1 parent de5976d commit 2bbb298

File tree

1 file changed

+277
-1
lines changed

1 file changed

+277
-1
lines changed
 

‎conn_test.go

+277-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"crypto/tls"
1212
"crypto/x509"
1313
"encoding/hex"
14+
"encoding/pem"
1415
"errors"
1516
"fmt"
1617
"io"
@@ -2486,6 +2487,272 @@ func TestSessionResume(t *testing.T) {
24862487
}
24872488
_ = res.c.Close()
24882489
})
2490+
2491+
t.Run("resumed client cert", func(t *testing.T) {
2492+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
2493+
defer cancel()
2494+
2495+
type result struct {
2496+
c *Conn
2497+
err error
2498+
}
2499+
clientRes := make(chan result, 1)
2500+
2501+
commonCert, err := selfsign.GenerateSelfSignedWithDNS("example.com")
2502+
2503+
certPool := x509.NewCertPool()
2504+
certPool.AppendCertsFromPEM(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: commonCert.Certificate[0]}))
2505+
2506+
ss := &memSessStore{}
2507+
2508+
id, _ := hex.DecodeString("9b9fc92255634d9fb109febed42166717bb8ded8c738ba71bc7f2a0d9dae0306")
2509+
secret, _ := hex.DecodeString("2e942a37aca5241deb2295b5fcedac221c7078d2503d2b62aeb48c880d7da73c001238b708559686b9da6e829c05ead7")
2510+
2511+
s := Session{ID: id, Secret: secret}
2512+
2513+
ca, cb := dpipe.Pipe()
2514+
2515+
_ = ss.Set(id, s)
2516+
_ = ss.Set([]byte(ca.RemoteAddr().String()+"_"+commonCert.Leaf.Subject.CommonName), s)
2517+
2518+
go func() {
2519+
config := &Config{
2520+
CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2521+
ServerName: commonCert.Leaf.Subject.CommonName,
2522+
SessionStore: ss,
2523+
RootCAs: certPool,
2524+
Certificates: nil, // Client shouldn't need to send a cert to resume a session
2525+
MTU: 100,
2526+
}
2527+
c, err := ClientWithContext(ctx, ca, config)
2528+
clientRes <- result{c, err}
2529+
}()
2530+
2531+
config := &Config{
2532+
CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2533+
SessionStore: ss,
2534+
ClientCAs: certPool,
2535+
Certificates: []tls.Certificate{commonCert},
2536+
MTU: 100,
2537+
ClientAuth: RequireAndVerifyClientCert,
2538+
}
2539+
server, err := testServer(ctx, cb, config, true)
2540+
if err != nil {
2541+
t.Fatalf("TestSessionResume: Server failed(%v)", err)
2542+
}
2543+
2544+
actualSessionID := server.ConnectionState().SessionID
2545+
actualMasterSecret := server.ConnectionState().masterSecret
2546+
if !bytes.Equal(actualSessionID, id) {
2547+
t.Errorf("TestSessionResumetion: SessionID Mismatch: expected(%v) actual(%v)", id, actualSessionID)
2548+
}
2549+
if !bytes.Equal(actualMasterSecret, secret) {
2550+
t.Errorf("TestSessionResumetion: masterSecret Mismatch: expected(%v) actual(%v)", secret, actualMasterSecret)
2551+
}
2552+
2553+
defer func() {
2554+
_ = server.Close()
2555+
}()
2556+
2557+
res := <-clientRes
2558+
if res.err != nil {
2559+
t.Fatal(res.err)
2560+
}
2561+
_ = res.c.Close()
2562+
})
2563+
2564+
t.Run("new session client cert", func(t *testing.T) {
2565+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
2566+
defer cancel()
2567+
2568+
type result struct {
2569+
c *Conn
2570+
err error
2571+
}
2572+
clientRes := make(chan result, 1)
2573+
2574+
commonCert, err := selfsign.GenerateSelfSignedWithDNS("example.com")
2575+
2576+
certPool := x509.NewCertPool()
2577+
certPool.AppendCertsFromPEM(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: commonCert.Certificate[0]}))
2578+
2579+
s1 := &memSessStore{}
2580+
s2 := &memSessStore{}
2581+
2582+
ca, cb := dpipe.Pipe()
2583+
go func() {
2584+
config := &Config{
2585+
ServerName: commonCert.Leaf.Subject.CommonName,
2586+
SessionStore: s1,
2587+
RootCAs: certPool,
2588+
Certificates: []tls.Certificate{commonCert},
2589+
}
2590+
c, err := ClientWithContext(ctx, ca, config)
2591+
clientRes <- result{c, err}
2592+
}()
2593+
2594+
config := &Config{
2595+
SessionStore: s2,
2596+
ClientAuth: RequireAndVerifyClientCert,
2597+
ClientCAs: certPool,
2598+
Certificates: []tls.Certificate{commonCert},
2599+
}
2600+
server, err := testServer(ctx, cb, config, false)
2601+
if err != nil {
2602+
t.Fatalf("TestSessionResumetion: Server failed(%v)", err)
2603+
}
2604+
2605+
actualSessionID := server.ConnectionState().SessionID
2606+
actualMasterSecret := server.ConnectionState().masterSecret
2607+
ss, _ := s2.Get(actualSessionID)
2608+
if !bytes.Equal(actualMasterSecret, ss.Secret) {
2609+
t.Errorf("TestSessionResumetion: masterSecret Mismatch: expected/actual:\n(%v)\n(%v)", ss.Secret, actualMasterSecret)
2610+
}
2611+
2612+
if ss.Expiry.Unix() != commonCert.Leaf.NotAfter.Unix() {
2613+
t.Errorf("TestSessionResumption: expected server session store to contain certificate expiry")
2614+
}
2615+
2616+
defer func() {
2617+
_ = server.Close()
2618+
}()
2619+
2620+
res := <-clientRes
2621+
if res.err != nil {
2622+
t.Fatal(res.err)
2623+
}
2624+
cs, _ := s1.Get([]byte(ca.RemoteAddr().String() + "_" + commonCert.Leaf.Subject.CommonName))
2625+
if !bytes.Equal(actualMasterSecret, cs.Secret) {
2626+
t.Errorf("TestSessionResumetion: masterSecret Mismatch: expected/actual\n(%v)\n(%v)", cs.Secret, actualMasterSecret)
2627+
}
2628+
2629+
if cs.Expiry.Unix() != commonCert.Leaf.NotAfter.Unix() {
2630+
t.Errorf("TestSessionResumption: expected client session store to contain certificate expiry")
2631+
}
2632+
2633+
_ = res.c.Close()
2634+
})
2635+
2636+
t.Run("expire client cert session", func(t *testing.T) {
2637+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
2638+
defer cancel()
2639+
2640+
type result struct {
2641+
c *Conn
2642+
err error
2643+
}
2644+
clientRes := make(chan result, 1)
2645+
2646+
commonCert, err := selfsign.GenerateSelfSignedWithDNS("example.com")
2647+
2648+
if err != nil {
2649+
t.Fatal(err)
2650+
}
2651+
certPool := x509.NewCertPool()
2652+
certPool.AppendCertsFromPEM(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: commonCert.Certificate[0]}))
2653+
2654+
ss := &memSessStore{}
2655+
2656+
id, _ := hex.DecodeString("9b9fc92255634d9fb109febed42166717bb8ded8c738ba71bc7f2a0d9dae0306")
2657+
secret, _ := hex.DecodeString("2e942a37aca5241deb2295b5fcedac221c7078d2503d2b62aeb48c880d7da73c001238b708559686b9da6e829c05ead7")
2658+
2659+
oldClientSessionTime := time.Now().Add(time.Hour)
2660+
clientSession := Session{
2661+
ID: id,
2662+
Secret: secret,
2663+
Expiry: oldClientSessionTime,
2664+
}
2665+
2666+
expiredServerSession := Session{
2667+
ID: id,
2668+
Secret: secret,
2669+
Expiry: time.Now().Add(-time.Hour), // server should treat this as expired session and force a new cert verification
2670+
}
2671+
2672+
ca, cb := dpipe.Pipe()
2673+
2674+
_ = ss.Set(id, expiredServerSession)
2675+
_ = ss.Set([]byte(ca.RemoteAddr().String()+"_"+commonCert.Leaf.Subject.CommonName), clientSession)
2676+
2677+
go func() {
2678+
config := &Config{
2679+
CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2680+
ServerName: commonCert.Leaf.Subject.CommonName,
2681+
SessionStore: ss,
2682+
RootCAs: certPool,
2683+
Certificates: []tls.Certificate{commonCert},
2684+
MTU: 1200, // MTU must be able to fit cert chain in one packet
2685+
}
2686+
c, err := ClientWithContext(ctx, ca, config)
2687+
clientRes <- result{c, err}
2688+
}()
2689+
2690+
config := &Config{
2691+
CipherSuites: []CipherSuiteID{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2692+
SessionStore: ss,
2693+
ClientCAs: certPool,
2694+
Certificates: []tls.Certificate{commonCert},
2695+
MTU: 1200,
2696+
ClientAuth: RequireAndVerifyClientCert,
2697+
}
2698+
server, err := testServer(ctx, cb, config, false)
2699+
if err != nil {
2700+
t.Fatalf("TestSessionResume: Server failed(%v)", err)
2701+
}
2702+
2703+
actualSessionID := server.ConnectionState().SessionID
2704+
actualMasterSecret := server.ConnectionState().masterSecret
2705+
if bytes.Equal(actualSessionID, id) {
2706+
t.Errorf("TestSessionResumption: SessionID Mismatch: expected new session ID(%v) actual(%v)", id, actualSessionID)
2707+
}
2708+
2709+
if bytes.Equal(actualMasterSecret, secret) {
2710+
t.Errorf("TestSessionResumption: masterSecret Mismatch: expected new master secret (%v) actual(%v)", secret, actualMasterSecret)
2711+
}
2712+
2713+
defer func() {
2714+
_ = server.Close()
2715+
}()
2716+
2717+
res := <-clientRes
2718+
if res.err != nil {
2719+
t.Fatal(res.err)
2720+
}
2721+
2722+
_, ok := ss.Map.Load(hex.EncodeToString(expiredServerSession.ID))
2723+
if ok {
2724+
t.Errorf("expected server to have deleted session")
2725+
}
2726+
2727+
cSess, ok := ss.Map.Load(hex.EncodeToString([]byte(ca.RemoteAddr().String() + "_" + commonCert.Leaf.Subject.CommonName)))
2728+
if !ok {
2729+
t.Errorf("expected client store to have cached new session ID")
2730+
}
2731+
2732+
newClientSession := cSess.(Session)
2733+
if bytes.Equal(secret, newClientSession.Secret) {
2734+
t.Errorf("expected : expected client session store to contain new master secret (%v) actual(%v)", secret, newClientSession.Secret)
2735+
}
2736+
2737+
if newClientSession.Expiry.Unix() == oldClientSessionTime.Unix() {
2738+
t.Errorf("expected new client session to have updated")
2739+
}
2740+
2741+
if newClientSession.Expiry.Unix() != commonCert.Leaf.NotAfter.Unix() {
2742+
t.Errorf("expected new client session to expire with client cert")
2743+
}
2744+
2745+
sSess, ok := ss.Map.Load(hex.EncodeToString(newClientSession.ID))
2746+
if !ok {
2747+
t.Errorf("expected server store to have cached new client session ID")
2748+
}
2749+
newServerSession := sSess.(Session)
2750+
2751+
if !bytes.Equal(newServerSession.Secret, newClientSession.Secret) {
2752+
t.Errorf("expected : expected session store to contain new shared secret (%v) actual(%v)", newServerSession.Secret, newClientSession.Secret)
2753+
}
2754+
_ = res.c.Close()
2755+
})
24892756
}
24902757

24912758
type memSessStore struct {
@@ -2507,7 +2774,16 @@ func (ms *memSessStore) Get(key []byte) (Session, error) {
25072774
return Session{}, nil
25082775
}
25092776

2510-
return v.(Session), nil
2777+
session := v.(Session)
2778+
if session.Expiry.IsZero() {
2779+
return session, nil
2780+
}
2781+
2782+
if time.Now().After(session.Expiry) {
2783+
_ = ms.Del(key)
2784+
return Session{}, nil
2785+
}
2786+
return session, nil
25112787
}
25122788

25132789
func (ms *memSessStore) Del(key []byte) error {

0 commit comments

Comments
 (0)
Please sign in to comment.