123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 |
- package telnet
- import "io"
- import "strings"
- import "fmt"
- import "compress/zlib"
- import "gitlab.com/beoran/woe/monolog"
- type TelnetState int
- const (
- data_state TelnetState = iota
- iac_state = iota
- will_state = iota
- wont_state = iota
- do_state = iota
- dont_state = iota
- sb_state = iota
- sb_data_state = iota
- sb_data_iac_state = iota
- )
- type EventType int
- const (
- TELNET_DATA_EVENT EventType = iota
- TELNET_NAWS_EVENT EventType = iota
- TELNET_TTYPE_EVENT EventType = iota
- TELNET_SUBNEGOTIATE_EVENT EventType = iota
- TELNET_IAC_EVENT EventType = iota
- TELNET_COMPRESS_EVENT EventType = iota
- TELNET_ENVIRONMENT_EVENT EventType = iota
- TELNET_MSSP_EVENT EventType = iota
- TELNET_ZMP_EVENT EventType = iota
- TELNET_WILL_EVENT EventType = iota
- TELNET_WONT_EVENT EventType = iota
- TELNET_DO_EVENT EventType = iota
- TELNET_DONT_EVENT EventType = iota
- TELNET_ERROR_EVENT EventType = iota
- TELNET_UNKNOWN_EVENT EventType = iota
- TELNET_NIL_EVENT EventType = iota
- )
- type Event interface {
- Type() EventType
- }
- type DataEvent struct {
- Data []byte
- }
- func (me DataEvent) Type() EventType { return TELNET_DATA_EVENT }
- type NAWSEvent struct {
- W int
- H int
- }
- func (me NAWSEvent) Type() EventType { return TELNET_NAWS_EVENT }
- type TTypeEvent struct {
- Telopt byte
- Name string
- }
- func (me TTypeEvent) Type() EventType { return TELNET_TTYPE_EVENT }
- type SubnegotiateEvent struct {
- Telopt byte
- Buffer []byte
- }
- func (me SubnegotiateEvent) Type() EventType { return TELNET_SUBNEGOTIATE_EVENT }
- type IACEvent struct {
- Telopt byte
- }
- func (me IACEvent) Type() EventType { return TELNET_IAC_EVENT }
- type CompressEvent struct {
- Compress bool
- }
- func (me CompressEvent) Type() EventType { return TELNET_COMPRESS_EVENT }
- type Environment struct {
- Type byte
- Value string
- }
- type EnvironmentEvent struct {
- Telopt byte
- Vars []Environment
- }
- func (me EnvironmentEvent) Type() EventType { return TELNET_ENVIRONMENT_EVENT }
- type MSSPEvent struct {
- Telopt byte
- Vars map[string]string
- }
- func (me MSSPEvent) Type() EventType { return TELNET_MSSP_EVENT }
- type ZMPEvent struct {
- Vars []string
- }
- func (me ZMPEvent) Type() EventType { return TELNET_ZMP_EVENT }
- type WillEvent struct {
- Telopt byte
- }
- func (me WillEvent) Type() EventType { return TELNET_WILL_EVENT }
- type WontEvent struct {
- Telopt byte
- }
- func (me WontEvent) Type() EventType { return TELNET_WONT_EVENT }
- type DoEvent struct {
- Telopt byte
- }
- func (me DoEvent) Type() EventType { return TELNET_DO_EVENT }
- type DontEvent struct {
- Telopt byte
- }
- func (me DontEvent) Type() EventType { return TELNET_DONT_EVENT }
- type ErrorEvent struct {
- error string
- }
- func (me ErrorEvent) Type() EventType { return TELNET_ERROR_EVENT }
- func EventTypeOf(event Event) EventType {
- if event == nil {
- return TELNET_NIL_EVENT
- }
- return event.Type()
- }
- func IsEventType(event Event, typ EventType) bool {
- return EventTypeOf(event) == typ
- }
- type EventChannel chan (Event)
- type Telopt struct {
- telopt byte
- us byte
- him byte
- }
- type Telnet struct {
- Events EventChannel
- ToClient chan ([]byte)
- telopts map[byte]Telopt
- state TelnetState
- compress bool
- zwriter zlib.Writer
- zreader io.ReadCloser
- buffer []byte
- sb_telopt byte
- }
- func New() (telnet *Telnet) {
- events := make(EventChannel, 64)
- toclient := make(chan ([]byte), 64)
- telopts := make(map[byte]Telopt)
- state := data_state
- compress := false
- var zwriter zlib.Writer
- var zreader io.ReadCloser
- var buffer []byte = nil
- sb_telopt := byte(0)
- telnet = &Telnet{events, toclient, telopts, state, compress, zwriter, zreader, buffer, sb_telopt}
- return telnet
- }
- func (me *Telnet) StartCompression() {
-
-
-
- }
- func (me *Telnet) Close() {
- if me.compress {
- me.zwriter.Close()
- me.zreader.Close()
- }
- }
- func (me *Telnet) SendRaw(in []byte) {
-
- me.ToClient <- in
- }
- func (me *Telnet) SendEscaped(in []byte) {
- buffer := make([]byte, len(in)*2, len(in)*2)
- outdex := 0
-
- for index := 0; index < len(in); index++ {
- now := in[index]
- if now == TELNET_IAC {
- buffer[outdex] = TELNET_IAC
- outdex++
- }
- buffer[outdex] = now
- outdex++
- }
- me.SendRaw(buffer)
- }
- func (me *Telnet) SendNegotiate(cmd byte, telopt byte) {
- buffer := make([]byte, 3)
- buffer[0] = TELNET_IAC
- buffer[1] = cmd
- buffer[2] = telopt
- me.SendRaw(buffer)
- }
- func (me *Telnet) SendEvent(event Event) {
- me.Events <- event
- }
- func (me *Telnet) SubnegotiateNAWS(buffer []byte) {
-
- if buffer == nil || len(buffer) != 4 {
- monolog.Warning("Bad NAWS negotiation: #{buffer}")
- return
- }
- var w int = (int(buffer[0]) << 8) + int(buffer[1])
- var h int = (int(buffer[2]) << 8) + int(buffer[3])
- me.SendEvent(&NAWSEvent{w, h})
- }
- func (me *Telnet) SubnegotiateEnviron(buffer []byte) {
- var vars []Environment
- var cmd []byte
- fb := buffer[0]
-
- if fb != TELNET_ENVIRON_SEND && fb != TELNET_ENVIRON_IS && fb != TELNET_ENVIRON_INFO {
- monolog.Warning("telopt environment subneg command not valid")
- }
- cmd = append(cmd, fb)
- if len(buffer) == 1 {
- me.SendEvent(&EnvironmentEvent{fb, vars})
- return
- }
-
- sb := buffer[1]
- if sb != TELNET_ENVIRON_VAR && fb != TELNET_ENVIRON_USERVAR {
- monolog.Warning("telopt environment subneg missing variable type")
- return
- }
-
- lb := buffer[len(buffer)-1]
- if lb == TELNET_ENVIRON_ESC {
- monolog.Warning("telopt environment subneg ends with ESC")
- return
- }
-
- }
- const (
- MSTATE_NONE = 0
- MSTATE_VAR = 1
- MSTATE_VAL = 2
- )
- func (me *Telnet) SubnegotiateMSSP(buffer []byte) {
- if len(buffer) < 1 {
- return
- }
- fb := buffer[0]
-
- if fb != TELNET_MSSP_VAR {
- monolog.Warning("telopt MSSP subneg data not valid")
- return
- }
- variables := make(map[string]string)
- var variable []byte
- var value []byte
- mstate := MSTATE_NONE
- for index := 0; index < len(buffer); index++ {
- c := buffer[index]
- switch c {
- case TELNET_MSSP_VAR:
- mstate = MSTATE_VAR
- if mstate == MSTATE_VAR {
- variables[string(variable)] = string(value)
- variable = nil
- value = nil
- }
- case TELNET_MSSP_VAL:
- mstate = MSTATE_VAL
- default:
- if mstate == MSTATE_VAL {
- variable = append(variable, c)
- } else {
- value = append(value, c)
- }
- }
- }
- me.SendEvent(&MSSPEvent{fb, variables})
- }
- func (me *Telnet) SubnegotiateZMP(buffer []byte) {
- var vars []string
- var variable []byte
- var b byte
- for index := 0; index < len(buffer); index++ {
- b = buffer[index]
- if b == 0 {
- vars = append(vars, string(variable))
- variable = nil
- } else {
- variable = append(variable, b)
- }
- }
- me.SendEvent(&ZMPEvent{vars})
- }
- func (me *Telnet) SubnegotiateTType(buffer []byte) {
-
- if len(buffer) == 0 {
- monolog.Warning("Incomplete TERMINAL-TYPE request")
- return
- }
- fb := buffer[0]
- if fb != TELNET_TTYPE_IS && fb != TELNET_TTYPE_SEND {
- monolog.Warning("TERMINAL-TYPE request has invalid type %d (%v)", fb, buffer)
- return
- }
- term := string(buffer[1:])
- me.SendEvent(&TTypeEvent{fb, term})
- }
- func (me *Telnet) DoSubnegotiate(buffer []byte) bool {
- switch me.sb_telopt {
- case TELNET_TELOPT_COMPRESS2:
-
-
- me.compress = true
- me.SendEvent(&CompressEvent{me.compress})
- return true
-
- case TELNET_TELOPT_TTYPE:
- me.SubnegotiateTType(buffer)
- case TELNET_TELOPT_ENVIRON:
- me.SubnegotiateEnviron(buffer)
- case TELNET_TELOPT_NEW_ENVIRON:
- me.SubnegotiateEnviron(buffer)
- case TELNET_TELOPT_MSSP:
- me.SubnegotiateMSSP(buffer)
- case TELNET_TELOPT_NAWS:
- me.SubnegotiateNAWS(buffer)
- case TELNET_TELOPT_ZMP:
- me.SubnegotiateZMP(buffer)
- default:
-
- me.SendEvent(&SubnegotiateEvent{me.sb_telopt, buffer})
- }
- return false
- }
- func (me *Telnet) DoNegotiate(state TelnetState, telopt byte) bool {
- switch me.state {
- case will_state:
- me.SendEvent(&WillEvent{telopt})
- case wont_state:
- me.SendEvent(&WontEvent{telopt})
- case do_state:
- me.SendEvent(&DoEvent{telopt})
- case dont_state:
- me.SendEvent(&DontEvent{telopt})
- default:
- monolog.Warning("State not vvalid in telnet negotiation.")
- }
- me.state = data_state
- return false
- }
- func (me *Telnet) maybeSendDataEventAndEmptyBuffer() {
- if (me.buffer != nil) && (len(me.buffer) > 0) {
- me.SendEvent(&DataEvent{me.buffer})
- me.buffer = nil
- }
- }
- func (me *Telnet) appendByte(bin byte) {
- monolog.Log("TELNET", "Appending to telnet buffer: %d %d", len(me.buffer), cap(me.buffer))
- me.buffer = append(me.buffer, bin)
- }
- func (me *Telnet) dataStateProcessByte(bin byte) bool {
- if bin == TELNET_IAC {
-
- me.maybeSendDataEventAndEmptyBuffer()
- me.state = iac_state
- } else {
- me.appendByte(bin)
- }
- return false
- }
- func (me *Telnet) iacStateProcessByte(bin byte) bool {
- switch bin {
-
- case TELNET_SB:
- me.state = sb_state
-
- case TELNET_WILL:
- me.state = will_state
- case TELNET_WONT:
- me.state = wont_state
- case TELNET_DO:
- me.state = do_state
- case TELNET_DONT:
- me.state = dont_state
-
- case TELNET_IAC:
- me.appendByte(TELNET_IAC)
- me.maybeSendDataEventAndEmptyBuffer()
- me.state = data_state
-
- default:
- me.SendEvent(IACEvent{bin})
- me.state = data_state
- }
- return false
- }
- func (me *Telnet) sbdataStateProcessByte(bin byte) bool {
-
- if bin == TELNET_IAC {
- me.state = sb_data_iac_state
- } else if me.sb_telopt == TELNET_TELOPT_COMPRESS && bin == TELNET_WILL {
-
-
-
- me.state = data_state
- } else {
- me.appendByte(bin)
- }
- return false
- }
- func (me *Telnet) sbdataiacStateProcessByte(bin byte) bool {
- switch bin {
-
- case TELNET_SE:
- me.state = data_state
-
- compress := me.DoSubnegotiate(me.buffer)
-
-
-
- me.buffer = nil
- if compress {
- return true
- }
-
- case TELNET_IAC:
-
- me.appendByte(bin)
- me.state = sb_data_state
-
-
-
- default:
- monolog.Warning("Unexpected byte after IAC inside SB: %d", bin)
- me.state = iac_state
-
- compress := me.DoSubnegotiate(me.buffer)
-
-
-
- me.buffer = nil
- if compress {
- return true
- }
- }
- return false
- }
- func (me *Telnet) ProcessByte(bin byte) bool {
- monolog.Log("TELNET", "ProcessByte %d %d", bin, me.state)
- switch me.state {
-
- case data_state:
- return me.dataStateProcessByte(bin)
-
- case iac_state:
- return me.iacStateProcessByte(bin)
- case will_state, wont_state, do_state, dont_state:
- return me.DoNegotiate(me.state, bin)
-
- case sb_state:
- me.sb_telopt = bin
- me.state = sb_data_state
-
- case sb_data_state:
- return me.sbdataStateProcessByte(bin)
-
- case sb_data_iac_state:
- return me.sbdataiacStateProcessByte(bin)
- default:
-
- panic("Error in telnet state machine!")
- }
-
- return false
- }
- func (me *Telnet) ProcessBytes(bytes []byte) {
- for index := 0; index < len(bytes); {
- bin := bytes[index]
- compress := me.ProcessByte(bin)
- if compress {
-
-
-
-
- }
- index++
- }
- me.maybeSendDataEventAndEmptyBuffer()
- }
- func (me *Telnet) TelnetReceive(data []byte) {
-
-
-
- me.ProcessBytes(data)
- }
- func (me *Telnet) TelnetSendBytes(bytes ...byte) {
- me.SendRaw(bytes)
- }
- func (me *Telnet) TelnetSendIac(cmd byte) {
- me.TelnetSendBytes(TELNET_IAC, cmd)
- }
- func (me *Telnet) TelnetSendNegotiate(cmd byte, telopt byte) {
- me.TelnetSendBytes(TELNET_IAC, cmd, telopt)
- }
- func (me *Telnet) TelnetSend(buffer []byte) {
- me.SendEscaped(buffer)
- }
- func (me *Telnet) TelnetBeginSubnegotiation(telopt byte) {
- me.TelnetSendBytes(TELNET_IAC, TELNET_SB, telopt)
- }
- func (me *Telnet) TelnetEndSubnegotiation() {
- me.TelnetSendBytes(TELNET_IAC, TELNET_SE)
- }
- func (me *Telnet) TelnetSubnegotiation(telopt byte, buffer []byte) {
- me.TelnetBeginSubnegotiation(telopt)
- if buffer != nil {
- me.TelnetSend(buffer)
- }
- me.TelnetEndSubnegotiation()
- }
- func (me *Telnet) TelnetBeginCompress2() {
- me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_COMPRESS2, TELNET_IAC, TELNET_SE)
- me.compress = true
- }
- func (me *Telnet) TelnetRawPrintf(format string, args ...interface{}) {
- buf := fmt.Sprintf(format, args...)
- me.TelnetSend([]byte(buf))
- }
- const CRLF = "\r\n"
- const CRNUL = "\r\000"
- func (me *Telnet) TelnetPrintf(format string, args ...interface{}) {
- buf := fmt.Sprintf(format, args...)
- buf = strings.Replace(buf, "\r", CRNUL, -1)
- buf = strings.Replace(buf, "\n", CRLF, -1)
- me.TelnetSend([]byte(buf))
- }
- func (me *Telnet) TelnetNewenviron(cmd []byte) {
- me.TelnetSubnegotiation(TELNET_TELOPT_NEW_ENVIRON, cmd)
- }
- func (me *Telnet) TelnetTTypeSend() {
- me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_SEND, TELNET_IAC, TELNET_SE)
- }
- func (me *Telnet) TelnetTTypeIS(ttype string) {
- me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS)
- me.TelnetSend([]byte(ttype))
- }
- func (me *Telnet) TelnetSendMSSP(mssp map[string]string) {
- var buf []byte
- for key, val := range mssp {
- buf = append(buf, TELNET_MSSP_VAR)
- buf = append(buf, key...)
- buf = append(buf, TELNET_MSSP_VAL)
- buf = append(buf, val...)
- }
- me.TelnetSubnegotiation(TELNET_TELOPT_MSSP, buf)
- }
|