telnet.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. package telnet
  2. import "bytes"
  3. import "compression/zlib"
  4. import "github.com/beoran/woe/monolog"
  5. // This Telnet struct implements a subset of the Telnet protocol.
  6. // Telnet states
  7. type TelnetState int
  8. const (
  9. data_state TelnetState = iota,
  10. iac_state = iota,
  11. will_state = iota,
  12. wont_state = iota,
  13. do_state = iota,
  14. dont_state = iota
  15. sb_state = iota,
  16. sb_data_state = iota,
  17. sb_data_iac_state = iota
  18. )
  19. // Telnet event types
  20. type Event interface {
  21. isEvent()
  22. }
  23. type DataEvent struct {
  24. Data [] byte
  25. }
  26. func (me DataEvent) isEvent() {}
  27. type NAWSEvent struct {
  28. W int
  29. H int
  30. }
  31. func (me NAWSEvent) isEvent() {}
  32. type TTypeEvent struct {
  33. Telopt byte
  34. Name string
  35. }
  36. func (me TTypeEvent) isEvent() {}
  37. type SubnegotioateEvent struct {
  38. Telopt byte
  39. Buffer [] byte
  40. }
  41. func (me SubnegotiateEvent) isEvent() {}
  42. type IACEvent struct {
  43. Telopt byte
  44. }
  45. func (me IACEvent) isEvent() {}
  46. type CompressionEvent struct {
  47. Compress bool
  48. }
  49. func (me CompressionEvent) isEvent() {}
  50. type EnvironmentEvent struct {
  51. Telopt byte
  52. Vars map[string] string
  53. }
  54. func (me EnvironmentEvent) isEvent() {}
  55. type MSSPEvent struct {
  56. Telopt byte
  57. Vars map[string] string
  58. }
  59. func (me MSSPEvent) isEvent() {}
  60. type ZMPEvent struct {
  61. Telopt byte
  62. Vars map[string] string
  63. }
  64. func (me ZMPEvent) isEvent() {}
  65. type EventChannel chan[Event]
  66. type Telopt struct {
  67. telopt byte
  68. us byte
  69. him byte
  70. }
  71. type Telnet struct {
  72. Events EventChannel
  73. telopts map[byte] Telopt
  74. state TelnetState
  75. compress bool
  76. zwriter Writer
  77. zreader Reader
  78. buffer []byte
  79. sb_telopt byte
  80. }
  81. func New() telnet * Telnet {
  82. events := make(EventChannel, 64)
  83. telopts := make (map[byte] Telopt)
  84. state := data_state
  85. compress := false
  86. zwriter := nil
  87. zreader := nil
  88. buffer := make([]byte, 1024, 1024)
  89. sb_telopt := 0
  90. telnet = &Telnet { events, telopts, state, compress,
  91. zwriter, zreader, buffer, sb_telopt
  92. }
  93. return telnet
  94. }
  95. // Starts compresssion
  96. func (me * Telnet) StartCompression() {
  97. // var zwbuf bytes.Buffer
  98. // me.zwriter = zlib.NewWriter(&zwbuf);
  99. }
  100. // Closes the telnet connection, send last compressed data if needed.
  101. func (me * Telnet) Close() {
  102. if me.compress {
  103. me.zwriter.Close()
  104. me.zreader.Close()
  105. }
  106. }
  107. // Filters raw text, only compressing it if needed.
  108. func (me * Telnet) FilterRaw(in []byte, out chan []byte) {
  109. // XXX Handle compression here later
  110. out <- in
  111. }
  112. // Filters text, escaping IAC bytes.
  113. func (me * Telnet) FilterRaw(in []byte, out chan []byte) {
  114. buffer := make([]byte, len(in) * 2, len(in) * 2)
  115. outdex := 0
  116. /* Double IAC characters to escape them. */
  117. for index := 0; index < len(in) ; index++ {
  118. now := in[index]
  119. if now == TELNET_IAC {
  120. buffer[outdex] = TELNET_IAC;
  121. outdex++;
  122. }
  123. buffer[outdex] = TELNET_IAC;
  124. outdex++;
  125. }
  126. out <- buffer
  127. }
  128. // Send negotiation bytes
  129. func (me * Telnet) SendNegotiate(cmd byte, telopt byte, out chan []byte) {
  130. buffer := make([]byte, 3)
  131. buffer[0] = TELNET_IAC
  132. buffer[1] = cmd
  133. buffer[2] = telopt
  134. me.FilterRaw(buffer, out)
  135. }
  136. // Parse a subnegotiation buffer for a naws event
  137. func (me * Telnet) SubnegotiateNAWS(buffer []byte, )
  138. // Some clients, like Gnome-Mud can't even get this right. Grrr!
  139. // XXx continue here
  140. if buffer.nil? || buffer.empty? || buffer.size != 4
  141. monolog.Info("Bad NAWS negotiation: #{buffer}")
  142. return nil
  143. end
  144. arr = buffer.bytes.to_a
  145. w = (arr[0] << 8) + arr[1]
  146. h = (arr[2] << 8) + arr[3]
  147. send_event(:naws, w, h)
  148. end
  149. # Storage for environment values
  150. class Environment
  151. attr_accessor :type
  152. attr_accessor :value
  153. def initialize(type, value)
  154. me.type = type
  155. me.value = value
  156. end
  157. end
  158. # process an ENVIRON/NEW-ENVIRON subnegotiation buffer
  159. def subnegotiate_environ(buffer)
  160. vars = []
  161. cmd = ""
  162. arr = buffer.bytes.to_a
  163. fb = arr.first
  164. # first byte must be a valid command
  165. if fb != TELNET_ENVIRON_SEND && fb != TELNET_ENVIRON_IS && fb != TELNET_ENVIRON_INFO
  166. log_error("telopt environment subneg command not valid")
  167. return 0
  168. end
  169. cmd << fb
  170. if (buffer.size == 1)
  171. send_event(:environment, fb, vars)
  172. return false
  173. end
  174. # Second byte must be VAR or USERVAR, if present
  175. sb = arr[1]
  176. if sb != TELNET_ENVIRON_VAR && fb != TELNET_ENVIRON_USEVAR
  177. log_error("telopt environment subneg missing variable type")
  178. return false
  179. end
  180. # ensure last byte is not an escape byte (makes parsing later easier)
  181. lb = arr.last
  182. if lb == TELNET_ENVIRON_ESC
  183. log_error("telopt environment subneg ends with ESC")
  184. return false
  185. end
  186. var = nil
  187. index = 1
  188. escape = false
  189. arr.shift
  190. arr.each do | c |
  191. case c
  192. when TELNET_ENVIRON_VAR
  193. when TELNET_ENVIRON_VALUE
  194. when TELNET_ENVIRON_USERVAR
  195. if escape
  196. escape = false
  197. var.value << c
  198. elsif var
  199. vars << var
  200. var = Environment.new(c, "")
  201. else
  202. var = Environment.new(c, "")
  203. end
  204. when TELNET_ENVIRON_ESC
  205. escape = true
  206. else
  207. var.value << c
  208. end # case
  209. end # each
  210. send_event(:environment, fb, vars)
  211. return false
  212. end
  213. # process an MSSP subnegotiation buffer
  214. def subnegotiate_mssp(buffer)
  215. telnet_event_t ev;
  216. struct telnet_environ_t *values;
  217. char *var = 0;
  218. char *c, *last, *out;
  219. size_t i, count;
  220. unsigned char next_type;
  221. if buffer.size < 1
  222. return 0
  223. end
  224. arr = buffer.bytes.to_a
  225. fb = arr.first
  226. # first byte must be a valid command
  227. if fb != TELNET_MSSSP_VAR
  228. log_error("telopt MSSP subneg data not valid")
  229. return false
  230. end
  231. vars = {}
  232. var = ""
  233. val = ""
  234. mstate = :var
  235. while index < arr.size
  236. c = arr[index]
  237. case c
  238. when TELNET_MSSP_VAR
  239. mstate = :var
  240. if mstate == :val
  241. vars[var] = val
  242. var = ""
  243. val = ""
  244. end
  245. when TELNET_MSSP_VAL
  246. mstate = :val
  247. else
  248. if mstate == :var
  249. var << c
  250. elsif mstate == :val
  251. val << c
  252. end
  253. end # case
  254. index += 1
  255. end # while
  256. send_event(:mssp, vars)
  257. return false
  258. end
  259. # parse ZMP command subnegotiation buffers
  260. def subnegotiate_zmp(buffer)
  261. args = []
  262. arg = ""
  263. buffer.each_byte do |b|
  264. if b == 0
  265. args << arg
  266. arg = ""
  267. else
  268. arg << byte
  269. end
  270. end
  271. send_event(:zmp, vars)
  272. return false
  273. end
  274. # parse TERMINAL-TYPE command subnegotiation buffers
  275. def subnegotiate_ttype(buffer)
  276. # make sure request is not empty
  277. if buffer.size == 0
  278. log_error("Incomplete TERMINAL-TYPE request");
  279. return 0
  280. end
  281. arr = buffer.bytes
  282. fb = arr.first
  283. term = nil
  284. if fb == TELNET_TTYPE_IS
  285. term = buffer[1, buffer.size]
  286. send_event(:ttype_is, term)
  287. elsif fb == TELNET_TTYPE_SEND
  288. term = buffer[1, buffer.size]
  289. send_event(:ttype_send, term)
  290. else
  291. log_error("TERMINAL-TYPE request has invalid type")
  292. return false
  293. end
  294. return false
  295. end
  296. # process a subnegotiation buffer; returns true if the current buffer
  297. # must be aborted and reprocessed due to COMPRESS2 being activated
  298. def do_subnegotiate(buffer)
  299. case me.sb_telopt
  300. when TELNET_TELOPT_COMPRESS2
  301. # received COMPRESS2 begin marker, setup our zlib box and
  302. # start handling the compressed stream if it's not already.
  303. me.compress = true
  304. send_event(:compress, me.compress)
  305. return true
  306. # specially handled subnegotiation telopt types
  307. when TELNET_TELOPT_ZMP
  308. return subnegotiate_zmp(buffer)
  309. when TELNET_TELOPT_TTYPE
  310. return subnegotiate_ttype(buffer)
  311. when TELNET_TELOPT_ENVIRON
  312. return subnegotiate_environ(buffer)
  313. when TELNET_TELOPT_NEW_ENVIRON
  314. return subnegotiate_environ(buffer)
  315. when TELNET_TELOPT_MSSP
  316. return subnegotiate_mssp(buffer)
  317. when TELNET_TELOPT_NAWS
  318. return subnegotiate_naws(buffer)
  319. else
  320. send_event(:subnegotiate, me.sb_telopt, buffer)
  321. return false
  322. end
  323. end
  324. def process_byte(byte)
  325. # p "process_byte, #{me.state} #{byte}"
  326. case me.state
  327. # regular data
  328. when :data
  329. if byte == TELNET_IAC
  330. # receive buffered bytes as data and go to IAC state if it's notempty
  331. send_event(:data, me.buffer) unless me.buffer.empty?
  332. me.buffer = ""
  333. me.state = :iac
  334. else
  335. me.buffer << byte
  336. end
  337. # IAC received before
  338. when :iac
  339. case byte
  340. # subnegotiation
  341. when TELNET_SB
  342. me.state = :sb
  343. # negotiation commands
  344. when TELNET_WILL
  345. me.state = :will
  346. when TELNET_WONT
  347. me.state = :wont
  348. when TELNET_DO
  349. me.state = :do
  350. when TELNET_DONT
  351. me.state = :dont
  352. # IAC escaping
  353. when TELNET_IAC
  354. me.buffer << TELNET_IAC.chr
  355. send_event(:data, me.buffer) unless me.buffer.empty?
  356. me.buffer = ""
  357. me.state = :data
  358. # some other command
  359. else
  360. send_event(:iac, byte)
  361. me.state = :data
  362. end
  363. # negotiation received before
  364. when :will, :wont, :do, :dont
  365. do_negotiate(byte)
  366. me.state = :data
  367. # subnegotiation started, determine option to subnegotiate
  368. when :sb
  369. me.sb_telopt = byte
  370. me.state = :sb_data
  371. # subnegotiation data, buffer bytes until the end request
  372. when :sb_data
  373. # IAC command in subnegotiation -- either IAC SE or IAC IAC
  374. if (byte == TELNET_IAC)
  375. me.state = :sb_data_iac
  376. elsif (me.sb_telopt == TELNET_TELOPT_COMPRESS && byte == TELNET_WILL)
  377. # MCCPv1 defined an invalid subnegotiation sequence (IAC SB 85 WILL SE)
  378. # to start compression. Catch and discard this case, only support
  379. # MMCPv2.
  380. me.state = data
  381. else
  382. me.buffer << byte
  383. end
  384. # IAC received inside a subnegotiation
  385. when :sb_data_iac
  386. case byte
  387. # end subnegotiation
  388. when TELNET_SE
  389. me.state = :data
  390. # process subnegotiation
  391. compress = do_subnegotiate(me.buffer)
  392. # if compression was negotiated, the rest of the stream is compressed
  393. # and processing it requires decompressing it. Return true to signal
  394. # this.
  395. me.buffer = ""
  396. return true if compress
  397. # escaped IAC byte
  398. when TELNET_IAC
  399. # push IAC into buffer */
  400. me.buffer << byte
  401. me.state = :sb_data
  402. # something else -- protocol error. attempt to process
  403. # content in subnegotiation buffer, then evaluate the
  404. # given command as an IAC code.
  405. else
  406. log_error("Unexpected byte after IAC inside SB: %d", byte)
  407. me.state = :iac
  408. # subnegotiate with the buffer anyway, even though it's an error
  409. compress = do_subnegotiate(me.buffer)
  410. # if compression was negotiated, the rest of the stream is compressed
  411. # and processing it requires decompressing it. Return true to signal
  412. # this.
  413. me.buffer = ""
  414. return true if compress
  415. end
  416. when :data
  417. # buffer any other bytes
  418. me.buffer << byte
  419. else
  420. # programing error, shouldn't happen
  421. raise "Error in telet state machine!"
  422. end
  423. # return false to signal compression needn't start
  424. return false
  425. end
  426. def process_bytes(bytes)
  427. # I have a feeling this way of handling strings isn't very efficient.. :p
  428. arr = bytes.bytes.to_a
  429. byte = arr.shift
  430. while byte
  431. compress = process_byte(byte)
  432. if compress
  433. # paper over this for a while...
  434. new_bytes = Zlib.inflate(arr.pack('c*')) rescue nil
  435. if new_bytes
  436. arr = new_bytes.bytes.to_a
  437. end
  438. end
  439. byte = arr.shift
  440. end
  441. send_event(:data, me.buffer) unless me.buffer.empty?
  442. me.buffer = ""
  443. end
  444. # Call this when the server receives data from the client
  445. def telnet_receive(data)
  446. # the COMPRESS2 protocol seems to be half-duplex in that only
  447. # the server's data stream is compressed (unless maybe if the client
  448. # is asked to also compress with a DO command ?)
  449. process_bytes(data)
  450. end
  451. # Send a bytes array (raw) to the client
  452. def telnet_send_bytes(*bytes)
  453. s = bytes.pack('C*')
  454. send_raw(s)
  455. end
  456. # send an iac command
  457. def telnet_send_iac(cmd)
  458. telnet_send_bytes(TELNET_IAC, cmd)
  459. end
  460. # send negotiation
  461. def telnet_send_negotiate(cmd, telopt)
  462. # get current option states
  463. q = rfc1143_get(telopt)
  464. unless q
  465. rfc1143_set(telopt)
  466. q = rfc1143_get(telopt)
  467. end
  468. act, arg = nil, nil
  469. case cmd
  470. when TELNET_WILL
  471. act, arg = q.send_will
  472. when TELNET_WONT
  473. act, arg = q.send_wont
  474. when TELNET_DO
  475. act, arg = q.send_do
  476. when TELNET_DONT
  477. act, arg = q.send_dont
  478. end
  479. return false unless act
  480. telnet_send_bytes(TELNET_IAC, act, telopt)
  481. end
  482. # send non-command data (escapes IAC bytes)
  483. def telnet_send(buffer)
  484. send_escaped(buffer)
  485. end
  486. # send subnegotiation header
  487. def telnet_begin_sb(telopt)
  488. telnet_send_bytes(TELNET_IAC, TELNET_SB, telopt)
  489. end
  490. # send subnegotiation ending
  491. def telnet_end_sb()
  492. telnet_send_bytes(TELNET_IAC, TELNET_SE)
  493. end
  494. # send complete subnegotiation
  495. def telnet_subnegotiation(telopt, buffer = nil)
  496. telnet_send_bytes(TELNET_IAC, TELNET_SB, telopt)
  497. telnet_send(buffer) if buffer;
  498. telnet_send_bytes(TELNET_IAC, TELNET_SE)
  499. end
  500. # start compress2 compression
  501. def telnet_begin_compress2()
  502. telnet_send_bytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_COMPRESS2, TELNET_IAC, TELNET_SE);
  503. me.compress = true
  504. end
  505. # send formatted data
  506. def telnet_raw_printf(fmt, *args)
  507. buf = sprintf(fmt, *args)
  508. telnet_send(buf)
  509. end
  510. CRLF = "\r\n"
  511. CRNUL = "\r\0"
  512. # send formatted data with \r and \n translation in addition to IAC IAC
  513. def telnet_printf(fmt, *args)
  514. buf = sprintf(fmt, *args)
  515. buf.gsub!("\r", CRNUL)
  516. buf.gsub!("\n", CRLF)
  517. telnet_send(buf)
  518. end
  519. # begin NEW-ENVIRON subnegotation
  520. def telnet_begin_newenviron(cmd)
  521. telnet_begin_sb(TELNET_TELOPT_NEW_ENVIRON)
  522. telnet_send_bytes(cmd)
  523. end
  524. # send a NEW-ENVIRON value
  525. def telnet_newenviron_value(type, value)
  526. telnet_send_bytes(type)
  527. telnet_send(string)
  528. end
  529. # send TERMINAL-TYPE SEND command
  530. def telnet_ttype_send()
  531. telnet_send_bytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_SEND, TELNET_IAC, TELNET_SE)
  532. end
  533. # send TERMINAL-TYPE IS command
  534. def telnet_ttype_is(ttype)
  535. telnet_send_bytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS)
  536. telnet_send(ttype)
  537. end
  538. # send MSSP data
  539. def telnet_send_mssp(mssp)
  540. buf = ""
  541. mssp.each do | key, val|
  542. buf << TELNET_MSSP_VAR.chr
  543. buf << key
  544. buf << TELNET_MSSP_VAL.chr
  545. buf << val
  546. end
  547. telnet_subnegotiation(TELNET_TELOPT_MSSP, buf)
  548. end
  549. end