Adding Inbound Version Negotiation
+ Error handling for missing private key setting
This commit is contained in:
parent
a2fa40492a
commit
f4ed1c244b
|
@ -75,6 +75,11 @@ func (ah *HiddenServiceAuthChannel) Closed(err error) {
|
||||||
// returned, it will be sent as the ChannelResult message.
|
// returned, it will be sent as the ChannelResult message.
|
||||||
// Remote -> [Open Authentication Channel] -> Local
|
// Remote -> [Open Authentication Channel] -> Local
|
||||||
func (ah *HiddenServiceAuthChannel) OpenInbound(channel *Channel, oc *Protocol_Data_Control.OpenChannel) ([]byte, error) {
|
func (ah *HiddenServiceAuthChannel) OpenInbound(channel *Channel, oc *Protocol_Data_Control.OpenChannel) ([]byte, error) {
|
||||||
|
|
||||||
|
if ah.PrivateKey == nil {
|
||||||
|
return nil, utils.PrivateKeyNotSetError
|
||||||
|
}
|
||||||
|
|
||||||
ah.channel = channel
|
ah.channel = channel
|
||||||
clientCookie, _ := proto.GetExtension(oc, Protocol_Data_AuthHiddenService.E_ClientCookie)
|
clientCookie, _ := proto.GetExtension(oc, Protocol_Data_AuthHiddenService.E_ClientCookie)
|
||||||
if len(clientCookie.([]byte)[:]) != 16 {
|
if len(clientCookie.([]byte)[:]) != 16 {
|
||||||
|
@ -92,6 +97,12 @@ func (ah *HiddenServiceAuthChannel) OpenInbound(channel *Channel, oc *Protocol_D
|
||||||
// returned, it will be sent as the OpenChannel message.
|
// returned, it will be sent as the OpenChannel message.
|
||||||
// Local -> [Open Authentication Channel] -> Remote
|
// Local -> [Open Authentication Channel] -> Remote
|
||||||
func (ah *HiddenServiceAuthChannel) OpenOutbound(channel *Channel) ([]byte, error) {
|
func (ah *HiddenServiceAuthChannel) OpenOutbound(channel *Channel) ([]byte, error) {
|
||||||
|
|
||||||
|
if ah.PrivateKey == nil {
|
||||||
|
return nil, utils.PrivateKeyNotSetError
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ah.channel = channel
|
ah.channel = channel
|
||||||
messageBuilder := new(utils.MessageBuilder)
|
messageBuilder := new(utils.MessageBuilder)
|
||||||
return messageBuilder.OpenAuthenticationChannel(ah.channel.ID, ah.GenClientCookie()), nil
|
return messageBuilder.OpenAuthenticationChannel(ah.channel.ID, ah.GenClientCookie()), nil
|
||||||
|
|
|
@ -71,9 +71,10 @@ func GetOpenAuthenticationChannelMessage() *Protocol_Data_Control.OpenChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthenticationOpenInbound(t *testing.T) {
|
func TestAuthenticationOpenInbound(t *testing.T) {
|
||||||
|
privateKey, _ := utils.LoadPrivateKeyFromFile("../testing/private_key")
|
||||||
opm := GetOpenAuthenticationChannelMessage()
|
opm := GetOpenAuthenticationChannelMessage()
|
||||||
authHandler := new(HiddenServiceAuthChannel)
|
authHandler := new(HiddenServiceAuthChannel)
|
||||||
|
authHandler.PrivateKey = privateKey
|
||||||
channel := Channel{ID: 1}
|
channel := Channel{ID: 1}
|
||||||
response, err := authHandler.OpenInbound(&channel, opm)
|
response, err := authHandler.OpenInbound(&channel, opm)
|
||||||
|
|
||||||
|
@ -90,7 +91,9 @@ func TestAuthenticationOpenInbound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthenticationOpenOutbound(t *testing.T) {
|
func TestAuthenticationOpenOutbound(t *testing.T) {
|
||||||
|
privateKey, _ := utils.LoadPrivateKeyFromFile("../testing/private_key")
|
||||||
authHandler := new(HiddenServiceAuthChannel)
|
authHandler := new(HiddenServiceAuthChannel)
|
||||||
|
authHandler.PrivateKey = privateKey
|
||||||
channel := Channel{ID: 1}
|
channel := Channel{ID: 1}
|
||||||
response, err := authHandler.OpenOutbound(&channel)
|
response, err := authHandler.OpenOutbound(&channel)
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,9 @@ type AutoConnectionHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init ...
|
// Init ...
|
||||||
|
// TODO: Split this into client and server init
|
||||||
func (ach *AutoConnectionHandler) Init(privateKey *rsa.PrivateKey, serverHostname string) {
|
func (ach *AutoConnectionHandler) Init(privateKey *rsa.PrivateKey, serverHostname string) {
|
||||||
|
|
||||||
ach.handlerMap = make(map[string]func() channels.Handler)
|
ach.handlerMap = make(map[string]func() channels.Handler)
|
||||||
ach.RegisterChannelHandler("im.ricochet.auth.hidden-service", func() channels.Handler {
|
ach.RegisterChannelHandler("im.ricochet.auth.hidden-service", func() channels.Handler {
|
||||||
hsau := new(channels.HiddenServiceAuthChannel)
|
hsau := new(channels.HiddenServiceAuthChannel)
|
||||||
|
|
|
@ -35,6 +35,10 @@ func HandleInboundConnection(c *Connection) *InboundConnectionHandler {
|
||||||
// assume they are required to send a contact request before any other activity.
|
// assume they are required to send a contact request before any other activity.
|
||||||
func (ich *InboundConnectionHandler) ProcessAuthAsServer(privateKey *rsa.PrivateKey, sach func(hostname string, publicKey rsa.PublicKey) (allowed, known bool)) error {
|
func (ich *InboundConnectionHandler) ProcessAuthAsServer(privateKey *rsa.PrivateKey, sach func(hostname string, publicKey rsa.PublicKey) (allowed, known bool)) error {
|
||||||
|
|
||||||
|
if privateKey == nil {
|
||||||
|
return utils.PrivateKeyNotSetError
|
||||||
|
}
|
||||||
|
|
||||||
ach := new(AutoConnectionHandler)
|
ach := new(AutoConnectionHandler)
|
||||||
ach.Init(privateKey, ich.connection.RemoteHostname)
|
ach.Init(privateKey, ich.connection.RemoteHostname)
|
||||||
ach.SetServerAuthHandler(sach)
|
ach.SetServerAuthHandler(sach)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/s-rah/go-ricochet/channels"
|
"github.com/s-rah/go-ricochet/channels"
|
||||||
|
"github.com/s-rah/go-ricochet/utils"
|
||||||
"github.com/s-rah/go-ricochet/policies"
|
"github.com/s-rah/go-ricochet/policies"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
@ -33,6 +34,11 @@ func HandleOutboundConnection(c *Connection) *OutboundConnectionHandler {
|
||||||
// accepts us as a known contact. Unknown contacts will generally need to send a contact
|
// accepts us as a known contact. Unknown contacts will generally need to send a contact
|
||||||
// request before any other activity.
|
// request before any other activity.
|
||||||
func (och *OutboundConnectionHandler) ProcessAuthAsClient(privateKey *rsa.PrivateKey) (bool, error) {
|
func (och *OutboundConnectionHandler) ProcessAuthAsClient(privateKey *rsa.PrivateKey) (bool, error) {
|
||||||
|
|
||||||
|
if privateKey == nil {
|
||||||
|
return false, utils.PrivateKeyNotSetError
|
||||||
|
}
|
||||||
|
|
||||||
ach := new(AutoConnectionHandler)
|
ach := new(AutoConnectionHandler)
|
||||||
ach.Init(privateKey, och.connection.RemoteHostname)
|
ach.Init(privateKey, och.connection.RemoteHostname)
|
||||||
|
|
||||||
|
|
43
ricochet.go
43
ricochet.go
|
@ -53,3 +53,46 @@ func negotiateVersion(conn net.Conn, remoteHostname string) (*connection.Connect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NegotiateVersionInbound takes in a connection and performs version negotiation
|
||||||
|
// as if that connection was a client. Returns a ricochet connection if successful
|
||||||
|
// error otherwise.
|
||||||
|
func NegotiateVersionInbound(conn net.Conn) (*connection.Connection, error) {
|
||||||
|
versions := []byte{0x49, 0x4D, 0x01, 0x01}
|
||||||
|
// Read version response header
|
||||||
|
header := make([]byte, 3)
|
||||||
|
if _, err := io.ReadAtLeast(conn, header, len(header)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if header[0] != versions[0] || header[1] != versions[1] || header[2] < 1 {
|
||||||
|
return nil, utils.VersionNegotiationError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read list of supported versions (which is header[2] bytes long)
|
||||||
|
versionList := make([]byte, header[2])
|
||||||
|
if _, err := io.ReadAtLeast(conn, versionList, len(versionList)); err != nil {
|
||||||
|
return nil, utils.VersionNegotiationError
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedVersion := byte(0xff)
|
||||||
|
for _, v := range versionList {
|
||||||
|
if v == 0x01 {
|
||||||
|
selectedVersion = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n, err := conn.Write([]byte{selectedVersion}); err != nil || n < 1 {
|
||||||
|
return nil, utils.VersionNegotiationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedVersion == 0xff {
|
||||||
|
return nil, utils.VersionNegotiationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
rc := connection.NewInboundConnection(conn)
|
||||||
|
return rc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ const (
|
||||||
ActionTimedOutError = Error("ActionTimedOutError")
|
ActionTimedOutError = Error("ActionTimedOutError")
|
||||||
|
|
||||||
ClientFailedToAuthenticateError = Error("ClientFailedToAuthenticateError")
|
ClientFailedToAuthenticateError = Error("ClientFailedToAuthenticateError")
|
||||||
|
|
||||||
|
|
||||||
|
PrivateKeyNotSetError = Error("PrivateKeyNotSetError")
|
||||||
)
|
)
|
||||||
|
|
||||||
// RecoverFromError doesn't really recover from anything....see comment below
|
// RecoverFromError doesn't really recover from anything....see comment below
|
||||||
|
|
Loading…
Reference in New Issue