-
Notifications
You must be signed in to change notification settings - Fork 4.6k
ClientHandshake to return AuthInfo #956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
1165b1e
d1b12d3
0129b49
c62cf7b
5b3192c
ff332b6
915cb50
6c58b32
9d3e997
c980740
6fdee01
b792ae8
16853da
40952fe
1db9a22
848da09
49c5700
e7832cf
ecc30a5
74f10a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,7 +34,11 @@ | |
| package credentials | ||
|
|
||
| import ( | ||
| "crypto/tls" | ||
| "net" | ||
| "testing" | ||
|
|
||
| "golang.org/x/net/context" | ||
| ) | ||
|
|
||
| func TestTLSOverrideServerName(t *testing.T) { | ||
|
|
@@ -58,4 +62,173 @@ func TestTLSClone(t *testing.T) { | |
| if c.Info().ServerName != expectedServerName { | ||
| t.Fatalf("Change in clone should not affect the original, c.Info().ServerName = %v, want %v", c.Info().ServerName, expectedServerName) | ||
| } | ||
|
|
||
| } | ||
|
|
||
| const tlsDir = "../test/testdata/" | ||
|
|
||
| type serverHandshake func(net.Conn, *tls.ConnectionState) error | ||
|
|
||
| func TestClientHandshakeReturnsAuthInfo(t *testing.T) { | ||
| var serverConnState tls.ConnectionState | ||
| errChan := make(chan error, 1) | ||
| lisAddr, err := launchServer(t, &serverConnState, tlsServerHandshake, errChan) | ||
| if err != nil { | ||
| return | ||
| } | ||
| clientConnState, err := clientHandle(t, gRPCClientHandshake, lisAddr) | ||
| if err != nil { | ||
| return | ||
| } | ||
| // wait until server has populated the serverAuthInfo struct or failed. | ||
| if err = <-errChan; err != nil { | ||
| return | ||
| } | ||
| if !isEqualState(clientConnState, serverConnState) { | ||
| t.Fatalf("c.ClientHandshake(_, %v, _) = %v, want %v.", lisAddr, clientConnState, serverConnState) | ||
| } | ||
| } | ||
|
|
||
| func TestServerHandshakeReturnsAuthInfo(t *testing.T) { | ||
| var serverConnState tls.ConnectionState | ||
| errChan := make(chan error, 1) | ||
| lisAddr, err := launchServer(t, &serverConnState, gRPCServerHandshake, errChan) | ||
| if err != nil { | ||
| return | ||
| } | ||
| clientConnState, err := clientHandle(t, tlsClientHandshake, lisAddr) | ||
| if err != nil { | ||
| return | ||
| } | ||
| // wait until server has populated the serverAuthInfo struct or failed. | ||
| if err = <-errChan; err != nil { | ||
| return | ||
| } | ||
| if !isEqualState(clientConnState, serverConnState) { | ||
| t.Fatalf("ServerHandshake(_) = %v, want %v.", serverConnState, clientConnState) | ||
| } | ||
| } | ||
|
|
||
| func TestServerAndClientHandshake(t *testing.T) { | ||
| var serverConnState tls.ConnectionState | ||
| errChan := make(chan error, 1) | ||
| lisAddr, err := launchServer(t, &serverConnState, gRPCServerHandshake, errChan) | ||
| if err != nil { | ||
| return | ||
| } | ||
| clientConnState, err := clientHandle(t, gRPCClientHandshake, lisAddr) | ||
| if err != nil { | ||
| return | ||
| } | ||
| // wait until server has populated the serverAuthInfo struct or failed. | ||
| if err = <-errChan; err != nil { | ||
| return | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and the above client side logic can be wrapped into a function too:
|
||
| if !isEqualState(clientConnState, serverConnState) { | ||
| t.Fatalf("Connection states returened by server: %v and client: %v aren't same", serverConnState, clientConnState) | ||
| } | ||
| } | ||
|
|
||
| func isEqualState(state1, state2 tls.ConnectionState) bool { | ||
| if state1.Version == state2.Version && | ||
| state1.HandshakeComplete == state2.HandshakeComplete && | ||
| state1.CipherSuite == state2.CipherSuite && | ||
| state1.NegotiatedProtocol == state2.NegotiatedProtocol { | ||
| return true | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func launchServer(t *testing.T, serverConnState *tls.ConnectionState, hs serverHandshake, errChan chan error) (string, error) { | ||
| lis, err := net.Listen("tcp", "localhost:0") | ||
|
||
| if err != nil { | ||
| t.Errorf("Failed to listen: %v", err) | ||
|
||
| return "", err | ||
| } | ||
| go serverHandle(t, hs, serverConnState, errChan, lis) | ||
| return lis.Addr().String(), nil | ||
| } | ||
|
|
||
| // Is run in a seperate go routine. | ||
|
||
| func serverHandle(t *testing.T, hs func(net.Conn, *tls.ConnectionState) error, serverConnState *tls.ConnectionState, errChan chan error, lis net.Listener) { | ||
| defer lis.Close() | ||
| var err error | ||
| defer func() { | ||
| errChan <- err | ||
| }() | ||
| serverRawConn, err := lis.Accept() | ||
| if err != nil { | ||
| t.Errorf("Server failed to accept connection: %v", err) | ||
| return | ||
| } | ||
| err = hs(serverRawConn, serverConnState) | ||
| if err != nil { | ||
| t.Errorf("Error at server-side while handshake. Error: %v", err) | ||
| return | ||
| } | ||
| } | ||
|
|
||
| func clientHandle(t *testing.T, hs func(net.Conn, string) (tls.ConnectionState, error), lisAddr string) (tls.ConnectionState, error) { | ||
| conn, err := net.Dial("tcp", lisAddr) | ||
| if err != nil { | ||
| t.Errorf("Client failed to connect to %s. Error: %v", lisAddr, err) | ||
|
||
| return tls.ConnectionState{}, err | ||
| } | ||
| defer conn.Close() | ||
| clientConnState, err := hs(conn, lisAddr) | ||
| if err != nil { | ||
| t.Errorf("Error on client while handshake. Error: %v", err) | ||
|
||
| } | ||
| return clientConnState, err | ||
| } | ||
|
|
||
| // Server handshake implementation using gRPC. | ||
|
||
| func gRPCServerHandshake(conn net.Conn, serverConnState *tls.ConnectionState) error { | ||
| serverTLS, err := NewServerTLSFromFile(tlsDir+"server1.pem", tlsDir+"server1.key") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| _, serverAuthInfo, err := serverTLS.ServerHandshake(conn) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| *serverConnState = serverAuthInfo.(TLSInfo).State | ||
| return nil | ||
| } | ||
|
|
||
| // Client handshake implementation using gRPC. | ||
|
||
| func gRPCClientHandshake(conn net.Conn, lisAddr string) (tls.ConnectionState, error) { | ||
| clientTLS := NewTLS(&tls.Config{InsecureSkipVerify: true}) | ||
| _, authInfo, err := clientTLS.ClientHandshake(context.Background(), lisAddr, conn) | ||
| if err != nil { | ||
| return tls.ConnectionState{}, err | ||
| } | ||
| return authInfo.(TLSInfo).State, nil | ||
| } | ||
|
|
||
| // Server handshake implementation using tls. | ||
|
||
| func tlsServerHandshake(conn net.Conn, serverConnState *tls.ConnectionState) error { | ||
| cert, err := tls.LoadX509KeyPair(tlsDir+"server1.pem", tlsDir+"server1.key") | ||
| if err != nil { | ||
| return err | ||
| } | ||
| serverTLSConfig := &tls.Config{Certificates: []tls.Certificate{cert}} | ||
| serverConn := tls.Server(conn, serverTLSConfig) | ||
| err = serverConn.Handshake() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| *serverConnState = serverConn.ConnectionState() | ||
| return nil | ||
| } | ||
|
|
||
| // Client handskae implementation using tls. | ||
|
||
| func tlsClientHandshake(conn net.Conn, _ string) (tls.ConnectionState, error) { | ||
| clientTLSConfig := &tls.Config{InsecureSkipVerify: true} | ||
| clientConn := tls.Client(conn, clientTLSConfig) | ||
| err := clientConn.Handshake() | ||
|
||
| if err != nil { | ||
| return tls.ConnectionState{}, err | ||
| } | ||
| return clientConn.ConnectionState(), nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more like a channel to notify the completion of serverHandle. Can you rename it to "done"? Applies to all the tests you added.