diff --git a/client.go b/client.go index 16e8f3d..ace1b34 100644 --- a/client.go +++ b/client.go @@ -22,7 +22,7 @@ var ( &DefaultClientSecurityHandler{}, &DefaultClientClientInitHandler{}, &DefaultClientServerInitHandler{}, - // &DefaultClientMessageHandler{}, + &DefaultClientMessageHandler{}, } ) @@ -39,9 +39,7 @@ func Connect(ctx context.Context, c net.Conn, cfg *ClientConfig) (*ClientConn, e } for _, h := range cfg.Handlers { - fmt.Printf("%#+v\n", h) if err := h.Handle(conn); err != nil { - fmt.Printf("rrr %v\n", err) conn.Close() cfg.ErrorCh <- err return nil, err @@ -57,6 +55,10 @@ func (c *ClientConn) Config() interface{} { return c.cfg } +func (c *ClientConn) Wait() { + <-c.quit +} + func (c *ClientConn) Conn() net.Conn { return c.c } @@ -80,6 +82,10 @@ func (c *ClientConn) Flush() error { } func (c *ClientConn) Close() error { + if c.quit != nil { + close(c.quit) + c.quit = nil + } return c.c.Close() } @@ -163,13 +169,11 @@ type ClientConn struct { pixelFormat *PixelFormat quitCh chan struct{} + quit chan struct{} errorCh chan error } func NewClientConn(c net.Conn, cfg *ClientConfig) (*ClientConn, error) { - if cfg.ServerMessages == nil { - return nil, fmt.Errorf("ServerMessages cannel is nil") - } if len(cfg.Encodings) == 0 { return nil, fmt.Errorf("client can't handle encodings") } @@ -182,6 +186,7 @@ func NewClientConn(c net.Conn, cfg *ClientConfig) (*ClientConn, error) { quitCh: cfg.QuitCh, errorCh: cfg.ErrorCh, pixelFormat: cfg.PixelFormat, + quit: make(chan struct{}), }, nil } @@ -471,14 +476,12 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error { cfg.ErrorCh <- err return } - msg, ok := serverMessages[messageType] if !ok { err = fmt.Errorf("unknown message-type: %v", messageType) cfg.ErrorCh <- err return } - parsedMsg, err := msg.Read(c) if err != nil { cfg.ErrorCh <- err @@ -511,4 +514,5 @@ type ClientConfig struct { ServerMessages []ServerMessage QuitCh chan struct{} ErrorCh chan error + quit chan struct{} } diff --git a/conn.go b/conn.go index 0b01f2b..84cea2f 100644 --- a/conn.go +++ b/conn.go @@ -23,5 +23,6 @@ type Conn interface { DesktopName() []byte SetDesktopName([]byte) Flush() error + Wait() SetProtoVersion(string) } diff --git a/handlers.go b/handlers.go index b89dc7c..960f9b7 100644 --- a/handlers.go +++ b/handlers.go @@ -91,7 +91,6 @@ func (*DefaultServerVersionHandler) Handle(c Conn) error { if err := binary.Read(c, binary.BigEndian, &version); err != nil { return err } - major, minor, err := ParseProtoVersion(version[:]) if err != nil { return err @@ -259,20 +258,50 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error { c.SetHeight(srvInit.FBHeight) c.SetPixelFormat(&srvInit.PixelFormat) + fmt.Printf("%s\n", srvInit) if c.Protocol() == "aten" { - fmt.Printf("$$$$$$\n") - var pad [28]byte - /* 12 - 8 byte unknown - 1 byte IKVMVideoEnable - 1 byte IKVMKMEnable - 1 byte IKVMKickEnable - 1 byte VUSBEnable - */ - if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + ikvm := struct { + _ [8]byte + IKVMVideoEnable uint8 + IKVMKMEnable uint8 + IKVMKickEnable uint8 + VUSBEnable uint8 + }{} + if err := binary.Read(c, binary.BigEndian, &ikvm); err != nil { return err } - fmt.Printf("rrrr\n") + 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) + } + */ } return nil } @@ -295,7 +324,6 @@ func (*DefaultServerServerInitHandler) Handle(c Conn) error { if err := binary.Write(c, binary.BigEndian, []byte(c.DesktopName())); err != nil { return err } - return c.Flush() } diff --git a/pixel_format.go b/pixel_format.go index 7256eb0..2e669a1 100644 --- a/pixel_format.go +++ b/pixel_format.go @@ -134,7 +134,7 @@ func (pf *PixelFormat) Unmarshal(data []byte) error { // String implements the fmt.Stringer interface. func (pf *PixelFormat) String() string { - return fmt.Sprintf("{ bpp: %d depth: %d big-endian: %s true-color: %s red-max: %d green-max: %d blue-max: %d red-shift: %d green-shift: %d blue-shift: %d }", + return fmt.Sprintf("{ bpp: %d depth: %d big-endian: %d true-color: %d red-max: %d green-max: %d blue-max: %d red-shift: %d green-shift: %d blue-shift: %d }", pf.BPP, pf.Depth, pf.BigEndian, pf.TrueColor, pf.RedMax, pf.GreenMax, pf.BlueMax, pf.RedShift, pf.GreenShift, pf.BlueShift) } diff --git a/security_aten.go b/security_aten.go index 54b1cb4..e491040 100644 --- a/security_aten.go +++ b/security_aten.go @@ -1,6 +1,7 @@ package vnc import ( + "bytes" "encoding/binary" "fmt" ) @@ -30,29 +31,68 @@ func charCodeAt(s string, n int) rune { func (auth *ClientAuthATEN) Auth(c Conn) error { var definedAuthLen = 24 + if len(auth.Username) > definedAuthLen || len(auth.Password) > definedAuthLen { + return fmt.Errorf("username/password is too long, allowed 0-23") + } + nt, err := readTightTunnels(c) if err != nil { return err } - if (nt&0xffff0ff0)>>0 == 0xaff90fb0 { + /* + fmt.Printf("tunnels %d\n", nt) + for i := uint32(0); i < nt; i++ { + code, vendor, signature, err := readTightCaps(c) + if err != nil { + return err + } + fmt.Printf("code %d vendor %s signature %s\n", code, vendor, signature) + } + */ + if ((nt&0xffff0ff0)>>0 == 0xaff90fb0) || (nt <= 0 || nt > 0x1000000) { c.SetProtoVersion("aten") var skip [20]byte binary.Read(c, binary.BigEndian, &skip) - fmt.Printf("skip %s\n", skip) + fmt.Printf("skip %v\n", skip) + } + + username := make([]byte, definedAuthLen) + password := make([]byte, definedAuthLen) + copy(username, auth.Username) + copy(password, auth.Password) + challenge := bytes.Join([][]byte{username, password}, []byte("")) + if err := binary.Write(c, binary.BigEndian, challenge); err != nil { + return err + } + + if err := c.Flush(); err != nil { + return err } /* - if len(auth.Username) > 24 || len(auth.Password) > 24 { - return fmt.Errorf("username/password > 24") + + sendUsername := make([]byte, definedAuthLen) + for i := 0; i < definedAuthLen; i++ { + if i < len(auth.Username) { + sendUsername[i] = byte(charCodeAt(string(auth.Username), i)) + } else { + sendUsername[i] = 0 + } } - username := make([]byte, 24-len(auth.Username)+1) - password := make([]byte, 24-len(auth.Password)+1) - copy(username, auth.Username) - copy(password, auth.Password) - username = append(username, []byte("\x00")...) - password = append(password, []byte("\x00")...) - challenge := bytes.Join([][]byte{username, password}, []byte(":")) - if err := binary.Write(c, binary.BigEndian, challenge); err != nil { + sendPassword := make([]byte, definedAuthLen) + + for i := 0; i < definedAuthLen; i++ { + if i < len(auth.Password) { + sendPassword[i] = byte(charCodeAt(string(auth.Password), i)) + } else { + sendPassword[i] = 0 + } + } + + if err := binary.Write(c, binary.BigEndian, sendUsername); err != nil { + return err + } + if err := binary.Write(c, binary.BigEndian, sendPassword); err != nil { return err } @@ -60,36 +100,6 @@ func (auth *ClientAuthATEN) Auth(c Conn) error { return err } */ - sendUsername := make([]byte, definedAuthLen) - for i := 0; i < definedAuthLen; i++ { - if i < len(auth.Username) { - sendUsername[i] = byte(charCodeAt(string(auth.Username), i)) - } else { - sendUsername[i] = 0 - } - } - - sendPassword := make([]byte, definedAuthLen) - - for i := 0; i < definedAuthLen; i++ { - if i < len(auth.Password) { - sendPassword[i] = byte(charCodeAt(string(auth.Password), i)) - } else { - sendPassword[i] = 0 - } - } - - if err := binary.Write(c, binary.BigEndian, sendUsername); err != nil { - return err - } - if err := binary.Write(c, binary.BigEndian, sendPassword); err != nil { - return err - } - - if err := c.Flush(); err != nil { - return err - } - //var pp [10]byte //binary.Read(c, binary.BigEndian, &pp) //fmt.Printf("ddd %v\n", pp) diff --git a/security_tight.go b/security_tight.go index 58a61ee..327b5cf 100644 --- a/security_tight.go +++ b/security_tight.go @@ -9,3 +9,19 @@ func readTightTunnels(c Conn) (uint32, error) { } return n, nil } + +func readTightCaps(c Conn) (int32, []byte, []byte, error) { + var code int32 + var vendor [4]byte + var signature [8]byte + if err := binary.Read(c, binary.BigEndian, &code); err != nil { + return 0, nil, nil, err + } + if err := binary.Read(c, binary.BigEndian, &vendor); err != nil { + return 0, nil, nil, err + } + if err := binary.Read(c, binary.BigEndian, &signature); err != nil { + return 0, nil, nil, err + } + return code, vendor[:], signature[:], nil +} diff --git a/security_vnc.go b/security_vnc.go index ed0cc60..61cce45 100644 --- a/security_vnc.go +++ b/security_vnc.go @@ -83,7 +83,6 @@ func (auth *ClientAuthVNC) Auth(c Conn) error { if err != nil { return err } - fmt.Printf("rrrr\n") // Send the encrypted challenge back to server if err := binary.Write(c, binary.BigEndian, encrypted); err != nil { return err diff --git a/server.go b/server.go index 002a5d3..135f3b0 100644 --- a/server.go +++ b/server.go @@ -25,6 +25,10 @@ type ServerInit struct { NameText []byte } +func (srvInit *ServerInit) String() string { + return fmt.Sprintf("Width: %d, Height: %d, PixelFormat: %s, Name: %s", srvInit.FBWidth, srvInit.FBHeight, &srvInit.PixelFormat, srvInit.NameText) +} + var _ Conn = (*ServerConn)(nil) func (c *ServerConn) Config() interface{} { @@ -35,6 +39,10 @@ func (c *ServerConn) Conn() net.Conn { return c.c } +func (c *ServerConn) Wait() { + <-c.quit +} + func (c *ServerConn) SetEncodings(encs []EncodingType) error { encodings := make(map[EncodingType]Encoding) for _, enc := range c.cfg.Encodings { @@ -57,6 +65,10 @@ func (c *ServerConn) Flush() error { } func (c *ServerConn) Close() error { + if c.quit != nil { + close(c.quit) + c.quit = nil + } return c.c.Close() } @@ -202,6 +214,8 @@ type ServerConn struct { // be modified. If you wish to set a new pixel format, use the // SetPixelFormat method. pixelFormat *PixelFormat + + quit chan struct{} } type ServerHandler interface { @@ -234,14 +248,6 @@ type ServerConfig struct { } func NewServerConn(c net.Conn, cfg *ServerConfig) (*ServerConn, error) { - if cfg.ClientMessageCh == nil { - return nil, fmt.Errorf("ClientMessageCh nil") - } - - if len(cfg.ClientMessages) == 0 { - return nil, fmt.Errorf("ClientMessage 0") - } - return &ServerConn{ c: c, br: bufio.NewReader(c), @@ -252,6 +258,7 @@ func NewServerConn(c net.Conn, cfg *ServerConfig) (*ServerConn, error) { pixelFormat: cfg.PixelFormat, fbWidth: cfg.Width, fbHeight: cfg.Height, + quit: make(chan struct{}), }, nil } @@ -274,7 +281,7 @@ func Serve(ctx context.Context, ln net.Listener, cfg *ServerConfig) error { for _, h := range cfg.Handlers { if err := h.Handle(conn); err != nil { conn.Close() - continue + break } } } @@ -306,7 +313,10 @@ func (*DefaultServerMessageHandler) Handle(c Conn) error { case msg := <-cfg.ServerMessageCh: if err = msg.Write(c); err != nil { cfg.errorCh <- err - close(quit) + if quit != nil { + close(quit) + quit = nil + } return } } @@ -324,7 +334,10 @@ func (*DefaultServerMessageHandler) Handle(c Conn) error { var messageType ClientMessageType if err := binary.Read(c, binary.BigEndian, &messageType); err != nil { cfg.errorCh <- err - close(quit) + if quit != nil { + close(quit) + quit = nil + } return } msg, ok := clientMessages[messageType] @@ -336,7 +349,10 @@ func (*DefaultServerMessageHandler) Handle(c Conn) error { parsedMsg, err := msg.Read(c) if err != nil { cfg.errorCh <- err - close(quit) + if quit != nil { + close(quit) + quit = nil + } return } cfg.ClientMessageCh <- parsedMsg