rdpgw/transport/legacy.go
2020-07-20 18:51:00 +02:00

82 lines
1.9 KiB
Go

package transport
import (
"bufio"
"errors"
"io"
"math/rand"
"net"
"net/http"
"net/http/httputil"
"time"
)
const (
crlf = "\r\n"
HttpOK = "HTTP/1.1 200 OK\r\n"
)
type LegacyPKT struct {
Conn net.Conn
ChunkedReader io.Reader
Writer *bufio.Writer
}
func NewLegacy(w http.ResponseWriter) (*LegacyPKT, error) {
hj, ok := w.(http.Hijacker)
if ok {
conn, rw, err := hj.Hijack()
l := &LegacyPKT{
Conn: conn,
ChunkedReader: httputil.NewChunkedReader(rw.Reader),
Writer: rw.Writer,
}
return l, err
}
return nil, errors.New("cannot hijack connection")
}
func (t *LegacyPKT) ReadPacket() (n int, p []byte, err error){
buf := make([]byte, 4096) // bufio.defaultBufSize
n, err = t.ChunkedReader.Read(buf)
p = make([]byte, n)
copy(p, buf)
return n, p, err
}
func (t *LegacyPKT) WritePacket(b []byte) (n int, err error) {
return t.Conn.Write(b)
}
func (t *LegacyPKT) Close() error {
return t.Conn.Close()
}
// [MS-TSGU]: Terminal Services Gateway Server Protocol version 39.0
// The server sends back the final status code 200 OK, and also a random entity body of limited size (100 bytes).
// This enables a reverse proxy to start allowing data from the RDG server to the RDG client. The RDG server does
// not specify an entity length in its response. It uses HTTP 1.0 semantics to send the entity body and closes the
// connection after the last byte is sent.
func (t *LegacyPKT) SendAccept(doSeed bool) {
t.Writer.WriteString(HttpOK)
t.Writer.WriteString("Date: " + time.Now().Format(time.RFC1123) + crlf)
if !doSeed {
t.Writer.WriteString("Content-Length: 0" + crlf)
}
t.Writer.WriteString(crlf)
if doSeed {
seed := make([]byte, 10)
rand.Read(seed)
// docs say it's a seed but 2019 responds with ab cd * 5
t.Writer.Write(seed)
}
t.Writer.Flush()
}
func (t *LegacyPKT) Drain() {
p := make([]byte, 32767)
t.Conn.Read(p)
}