go-rfb/handlers.go
Vasiliy Tolstov cc43ee4e06 fix for oldeer vnc protocols
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
2017-07-11 02:37:02 +03:00

398 lines
9.7 KiB
Go

package vnc
import (
"encoding/binary"
"fmt"
)
// Handler represents handler of handshake
type Handler interface {
Handle(Conn) error
}
// ProtoVersionLength protocol version length
const ProtoVersionLength = 12
const (
// ProtoVersionUnknown unknown version
ProtoVersionUnknown = ""
// ProtoVersion33 sets if proto 003.003
ProtoVersion33 = "RFB 003.003\n"
// ProtoVersion38 sets if proto 003.008
ProtoVersion38 = "RFB 003.008\n"
// ProtoVersion37 sets if proto 003.007
ProtoVersion37 = "RFB 003.007\n"
)
// ParseProtoVersion parse protocol version
func ParseProtoVersion(pv []byte) (uint, uint, error) {
var major, minor uint
if len(pv) < ProtoVersionLength {
return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), ProtoVersionLength)
}
l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor)
if l != 2 {
return 0, 0, fmt.Errorf("error parsing protocol version")
}
if err != nil {
return 0, 0, err
}
return major, minor, nil
}
// DefaultClientVersionHandler represents default handler
type DefaultClientVersionHandler struct{}
// Handle provide version handler for client side
func (*DefaultClientVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion38
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(string(version[:]))
if err := binary.Write(c, binary.BigEndian, []byte(pv)); err != nil {
return err
}
return c.Flush()
}
// DefaultServerVersionHandler represents default server handler
type DefaultServerVersionHandler struct{}
// Handle provide server version handler
func (*DefaultServerVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Write(c, binary.BigEndian, []byte(ProtoVersion38)); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion33
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(pv)
return nil
}
// DefaultClientSecurityHandler used for client security handler
type DefaultClientSecurityHandler struct{}
// Handle provide client side security handler
func (*DefaultClientSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ClientConfig)
var numSecurityTypes uint8
if err := binary.Read(c, binary.BigEndian, &numSecurityTypes); err != nil {
return err
}
secTypes := make([]SecurityType, numSecurityTypes)
if err := binary.Read(c, binary.BigEndian, &secTypes); err != nil {
return err
}
var secType SecurityHandler
for _, st := range cfg.SecurityHandlers {
for _, sc := range secTypes {
if st.Type() == sc {
secType = st
}
}
}
if err := binary.Write(c, binary.BigEndian, cfg.SecurityHandlers[0].Type()); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
err := secType.Auth(c)
if err != nil {
return err
}
var authCode uint32
if err := binary.Read(c, binary.BigEndian, &authCode); err != nil {
return err
}
if authCode == 1 {
var reasonLength uint32
if err := binary.Read(c, binary.BigEndian, &reasonLength); err != nil {
return err
}
reasonText := make([]byte, reasonLength)
if err := binary.Read(c, binary.BigEndian, &reasonText); err != nil {
return err
}
return fmt.Errorf("%s", reasonText)
}
c.SetSecurityHandler(secType)
return nil
}
// DefaultServerSecurityHandler used for server security handler
type DefaultServerSecurityHandler struct{}
// Handle provide server side security handler
func (*DefaultServerSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ServerConfig)
var secType SecurityType
if c.Protocol() == ProtoVersion37 || c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint8(len(cfg.SecurityHandlers))); err != nil {
return err
}
for _, sectype := range cfg.SecurityHandlers {
if err := binary.Write(c, binary.BigEndian, sectype.Type()); err != nil {
return err
}
}
} else {
st := uint32(0)
for _, sectype := range cfg.SecurityHandlers {
if uint32(sectype.Type()) > st {
st = uint32(sectype.Type())
secType = sectype.Type()
}
}
if err := binary.Write(c, binary.BigEndian, st); err != nil {
return err
}
}
if err := c.Flush(); err != nil {
return err
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
return err
}
}
secTypes := make(map[SecurityType]SecurityHandler)
for _, sType := range cfg.SecurityHandlers {
secTypes[sType.Type()] = sType
}
sType, ok := secTypes[secType]
if !ok {
return fmt.Errorf("security type %d not implemented", secType)
}
var authCode uint32
authErr := sType.Auth(c)
if authErr != nil {
authCode = uint32(1)
}
if err := binary.Write(c, binary.BigEndian, authCode); err != nil {
return err
}
if authErr == nil {
if err := c.Flush(); err != nil {
return err
}
c.SetSecurityHandler(sType)
return nil
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint32(len(authErr.Error()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(authErr.Error())); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
}
return authErr
}
// DefaultClientServerInitHandler default client server init handler
type DefaultClientServerInitHandler struct{}
// Handle provide default server init handler
func (*DefaultClientServerInitHandler) Handle(c Conn) error {
var err error
srvInit := ServerInit{}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBWidth); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBHeight); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.PixelFormat); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.NameLength); err != nil {
return err
}
srvInit.NameText = make([]byte, srvInit.NameLength)
if err = binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil {
return err
}
c.SetDesktopName(srvInit.NameText)
if c.Protocol() == "aten1" {
c.SetWidth(800)
c.SetHeight(600)
c.SetPixelFormat(NewPixelFormatAten())
} else {
c.SetWidth(srvInit.FBWidth)
c.SetHeight(srvInit.FBHeight)
c.SetPixelFormat(srvInit.PixelFormat)
}
if c.Protocol() == "aten1" {
ikvm := struct {
_ [8]byte
IKVMVideoEnable uint8
IKVMKMEnable uint8
IKVMKickEnable uint8
VUSBEnable uint8
}{}
if err = binary.Read(c, binary.BigEndian, &ikvm); err != nil {
return err
}
}
/*
caps := struct {
ServerMessagesNum uint16
ClientMessagesNum uint16
EncodingsNum uint16
_ [2]byte
}{}
if err := binary.Read(c, binary.BigEndian, &caps); err != nil {
return err
}
caps.ServerMessagesNum = uint16(1)
var item [16]byte
for i := uint16(0); i < caps.ServerMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("server message cap %s\n", item)
}
for i := uint16(0); i < caps.ClientMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("client message cap %s\n", item)
}
for i := uint16(0); i < caps.EncodingsNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("encoding cap %s\n", item)
}
// var pad [1]byte
// if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
// return err
// }
}*/
return nil
}
// DefaultServerServerInitHandler default server server init handler
type DefaultServerServerInitHandler struct{}
// Handle provide default server server init handler
func (*DefaultServerServerInitHandler) Handle(c Conn) error {
if err := binary.Write(c, binary.BigEndian, c.Width()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.Height()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.PixelFormat()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, uint32(len(c.DesktopName()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(c.DesktopName())); err != nil {
return err
}
return c.Flush()
}
// DefaultClientClientInitHandler default client client init handler
type DefaultClientClientInitHandler struct{}
// Handle provide default client client init handler
func (*DefaultClientClientInitHandler) Handle(c Conn) error {
cfg := c.Config().(*ClientConfig)
var shared uint8
if cfg.Exclusive {
shared = 0
} else {
shared = 1
}
if err := binary.Write(c, binary.BigEndian, shared); err != nil {
return err
}
return c.Flush()
}
// DefaultServerClientInitHandler default server client init handler
type DefaultServerClientInitHandler struct{}
// Handle provide default server client init handler
func (*DefaultServerClientInitHandler) Handle(c Conn) error {
var shared uint8
if err := binary.Read(c, binary.BigEndian, &shared); err != nil {
return err
}
/* TODO
if shared != 1 {
c.SetShared(false)
}
*/
return nil
}