|
|
@@ -32,7 +32,7 @@ const (
|
|
|
protocolName = "Noise_IK_25519_ChaChaPoly_BLAKE2s"
|
|
|
// protocolVersion is the version of the control protocol that
|
|
|
// Client will use when initiating a handshake.
|
|
|
- protocolVersion uint16 = 1
|
|
|
+ //protocolVersion uint16 = 1
|
|
|
// protocolVersionPrefix is the name portion of the protocol
|
|
|
// name+version string that gets mixed into the handshake as a
|
|
|
// prologue.
|
|
|
@@ -66,7 +66,7 @@ type HandshakeContinuation func(context.Context, net.Conn) (*Conn, error)
|
|
|
// protocol switching. By splitting the handshake into an initial
|
|
|
// message and a continuation, we can embed the handshake initiation
|
|
|
// into the HTTP protocol switching request and avoid a bit of delay.
|
|
|
-func ClientDeferred(machineKey key.MachinePrivate, controlKey key.MachinePublic) (initialHandshake []byte, continueHandshake HandshakeContinuation, err error) {
|
|
|
+func ClientDeferred(machineKey key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16) (initialHandshake []byte, continueHandshake HandshakeContinuation, err error) {
|
|
|
var s symmetricState
|
|
|
s.Initialize()
|
|
|
|
|
|
@@ -78,7 +78,7 @@ func ClientDeferred(machineKey key.MachinePrivate, controlKey key.MachinePublic)
|
|
|
s.MixHash(controlKey.UntypedBytes())
|
|
|
|
|
|
// -> e, es, s, ss
|
|
|
- init := mkInitiationMessage()
|
|
|
+ init := mkInitiationMessage(protocolVersion)
|
|
|
machineEphemeral := key.NewMachine()
|
|
|
machineEphemeralPub := machineEphemeral.Public()
|
|
|
copy(init.EphemeralPub(), machineEphemeralPub.UntypedBytes())
|
|
|
@@ -96,7 +96,7 @@ func ClientDeferred(machineKey key.MachinePrivate, controlKey key.MachinePublic)
|
|
|
s.EncryptAndHash(cipher, init.Tag(), nil) // empty message payload
|
|
|
|
|
|
cont := func(ctx context.Context, conn net.Conn) (*Conn, error) {
|
|
|
- return continueClientHandshake(ctx, conn, &s, machineKey, machineEphemeral, controlKey)
|
|
|
+ return continueClientHandshake(ctx, conn, &s, machineKey, machineEphemeral, controlKey, protocolVersion)
|
|
|
}
|
|
|
return init[:], cont, nil
|
|
|
}
|
|
|
@@ -107,8 +107,8 @@ func ClientDeferred(machineKey key.MachinePrivate, controlKey key.MachinePublic)
|
|
|
// This is a helper for when you don't need the fancy
|
|
|
// continuation-style handshake, and just want to synchronously
|
|
|
// upgrade a net.Conn to a secure transport.
|
|
|
-func Client(ctx context.Context, conn net.Conn, machineKey key.MachinePrivate, controlKey key.MachinePublic) (*Conn, error) {
|
|
|
- init, cont, err := ClientDeferred(machineKey, controlKey)
|
|
|
+func Client(ctx context.Context, conn net.Conn, machineKey key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16) (*Conn, error) {
|
|
|
+ init, cont, err := ClientDeferred(machineKey, controlKey, protocolVersion)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -118,7 +118,7 @@ func Client(ctx context.Context, conn net.Conn, machineKey key.MachinePrivate, c
|
|
|
return cont(ctx, conn)
|
|
|
}
|
|
|
|
|
|
-func continueClientHandshake(ctx context.Context, conn net.Conn, s *symmetricState, machineKey, machineEphemeral key.MachinePrivate, controlKey key.MachinePublic) (*Conn, error) {
|
|
|
+func continueClientHandshake(ctx context.Context, conn net.Conn, s *symmetricState, machineKey, machineEphemeral key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16) (*Conn, error) {
|
|
|
// No matter what, this function can only run once per s. Ensure
|
|
|
// attempted reuse causes a panic.
|
|
|
defer func() {
|
|
|
@@ -193,13 +193,19 @@ func continueClientHandshake(ctx context.Context, conn net.Conn, s *symmetricSta
|
|
|
// Server initiates a control server handshake, returning the resulting
|
|
|
// control connection.
|
|
|
//
|
|
|
+// maxSupportedVersion is the highest handshake version the server is
|
|
|
+// willing to handshake with. The server will handshake with any
|
|
|
+// version from 0 to maxSupportedVersion inclusive, the caller should
|
|
|
+// inspect conn.Version() to determine what version of the handshake
|
|
|
+// was executed.
|
|
|
+//
|
|
|
// optionalInit can be the client's initial handshake message as
|
|
|
// returned by ClientDeferred, or nil in which case the initial
|
|
|
// message is read from conn.
|
|
|
//
|
|
|
// The context deadline, if any, covers the entire handshaking
|
|
|
// process.
|
|
|
-func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, optionalInit []byte) (*Conn, error) {
|
|
|
+func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, maxSupportedVersion uint16, optionalInit []byte) (*Conn, error) {
|
|
|
if deadline, ok := ctx.Deadline(); ok {
|
|
|
if err := conn.SetDeadline(deadline); err != nil {
|
|
|
return nil, fmt.Errorf("setting conn deadline: %w", err)
|
|
|
@@ -239,9 +245,16 @@ func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, o
|
|
|
} else if _, err := io.ReadFull(conn, init.Header()); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- if init.Version() != protocolVersion {
|
|
|
- return nil, sendErr("unsupported protocol version")
|
|
|
+ // Currently, these versions exclusively indicate what the upper
|
|
|
+ // RPC protocol understands, the Noise handshake is exactly the
|
|
|
+ // same in all versions. If that ever changes, this check will
|
|
|
+ // need to become more complex to handle different kinds of
|
|
|
+ // handshake.
|
|
|
+ if init.Version() > maxSupportedVersion {
|
|
|
+ return nil, sendErr("unsupported handshake version")
|
|
|
}
|
|
|
+ // Just a rename to make it more obvious what the value is
|
|
|
+ clientVersion := init.Version()
|
|
|
if init.Type() != msgTypeInitiation {
|
|
|
return nil, sendErr("unexpected handshake message type")
|
|
|
}
|
|
|
@@ -257,7 +270,7 @@ func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, o
|
|
|
|
|
|
// prologue. Can only do this once we at least think the client is
|
|
|
// handshaking using a supported version.
|
|
|
- s.MixHash(protocolVersionPrologue(protocolVersion))
|
|
|
+ s.MixHash(protocolVersionPrologue(clientVersion))
|
|
|
|
|
|
// <- s
|
|
|
// ...
|
|
|
@@ -310,7 +323,7 @@ func Server(ctx context.Context, conn net.Conn, controlKey key.MachinePrivate, o
|
|
|
|
|
|
c := &Conn{
|
|
|
conn: conn,
|
|
|
- version: protocolVersion,
|
|
|
+ version: clientVersion,
|
|
|
peer: machineKey,
|
|
|
handshakeHash: s.h,
|
|
|
tx: txState{
|