go-ricochet/connection/inboundconnectionhandler.go

67 lines
2.2 KiB
Go

package connection
import (
"crypto/rsa"
"github.com/s-rah/go-ricochet/channels"
"github.com/s-rah/go-ricochet/policies"
"github.com/s-rah/go-ricochet/utils"
)
// InboundConnectionHandler is a convieniance wrapper for handling inbound
// connections
type InboundConnectionHandler struct {
connection *Connection
}
// HandleInboundConnection returns an InboundConnectionHandler given a connection
func HandleInboundConnection(c *Connection) *InboundConnectionHandler {
ich := new(InboundConnectionHandler)
ich.connection = c
return ich
}
// ProcessAuthAsServer blocks until authentication has succeeded, failed, or the
// connection is closed. A non-nil error is returned in all cases other than successful
// and accepted authentication.
//
// ProcessAuthAsServer cannot be called at the same time as any other call to a Process
// function. Another Process function must be called after this function successfully
// returns to continue handling connection events.
//
// The acceptCallback function is called after receiving a valid authentication proof
// with the client's authenticated hostname and public key. acceptCallback must return
// true to accept authentication and allow the connection to continue, and also returns a
// boolean indicating whether the contact is known and recognized. Unknown contacts will
// 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 {
if privateKey == nil {
return utils.PrivateKeyNotSetError
}
ach := new(AutoConnectionHandler)
ach.Init(privateKey, ich.connection.RemoteHostname)
ach.SetServerAuthHandler(sach)
var authResult channels.AuthChannelResult
go func() {
authResult = ach.WaitForAuthenticationEvent()
ich.connection.Break()
}()
policy := policies.UnknownPurposeTimeout
err := policy.ExecuteAction(func() error {
return ich.connection.Process(ach)
})
if err == nil {
if authResult.Accepted == true {
ich.connection.RemoteHostname = authResult.Hostname
return nil
}
return utils.ClientFailedToAuthenticateError
}
return err
}