door32.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "net"
  7. "os"
  8. "os/exec"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. connHost = "0.0.0.0"
  15. connPort = "8080"
  16. connType = "tcp"
  17. )
  18. func main() {
  19. var port int
  20. var drain int
  21. var cp437 bool
  22. flag.IntVar(&port, "p", 0, "Port number to listen on")
  23. flag.IntVar(&drain, "d", 2, "Drain seconds")
  24. flag.BoolVar(&cp437, "c", false, "Force CP437 translation")
  25. flag.Parse()
  26. if port == 0 && flag.NArg() != 1 {
  27. fmt.Println("I need a Port and a commandline to execute.")
  28. flag.PrintDefaults()
  29. os.Exit(2)
  30. }
  31. fmt.Println("Starting " + connType + " server on " + connHost + ":" + strconv.Itoa(port))
  32. l, err := net.Listen("tcp", "0.0.0.0:"+strconv.Itoa(port))
  33. if err != nil {
  34. log.Println("Error listening:", err)
  35. os.Exit(1)
  36. }
  37. defer l.Close()
  38. for {
  39. var c net.Conn
  40. var err error
  41. c, err = l.Accept()
  42. if err != nil {
  43. log.Println("Error connecting:", err)
  44. return
  45. }
  46. go Connection(c, drain, flag.Arg(0), cp437)
  47. }
  48. }
  49. func Conn_to_File(conn net.Conn) *os.File {
  50. var tcpconn *net.TCPConn = conn.(*net.TCPConn)
  51. // This creates a duplicate fd, but once closed -- the fd gets reused!
  52. var conn_file *os.File
  53. // var err error
  54. conn_file, _ = tcpconn.File()
  55. return conn_file
  56. }
  57. func ReadFrom_WriteTo(read net.Conn, write net.Conn, closed *bool) {
  58. var buff []byte = make([]byte, 128)
  59. var n int
  60. var err error
  61. defer func() {
  62. read.Close()
  63. write.Close()
  64. if !*closed {
  65. log.Println("*Closed*")
  66. *closed = true
  67. }
  68. }()
  69. for {
  70. n, err = read.Read(buff)
  71. if err != nil {
  72. return
  73. }
  74. n, err = write.Write(buff[:n])
  75. if err != nil {
  76. return
  77. }
  78. }
  79. }
  80. func ReadFrom_WriteToCP437(read net.Conn, write net.Conn, closed *bool) {
  81. var buff []byte = make([]byte, 128)
  82. var n int
  83. var err error
  84. defer func() {
  85. read.Close()
  86. write.Close()
  87. if !*closed {
  88. log.Println("*Closed*")
  89. *closed = true
  90. }
  91. }()
  92. for {
  93. n, err = read.Read(buff)
  94. if err != nil {
  95. return
  96. }
  97. var line = string(buff[:n])
  98. // This does convert everything to unicode
  99. // syncterm doesn't like it (because it doesn't understand
  100. // unicode!)
  101. // The "door" detects CP437 (not unicode)
  102. // This would allow a CP437 door to run as unicode.
  103. n, err = write.Write([]byte(CP437_to_Unicode(line)))
  104. if err != nil {
  105. return
  106. }
  107. }
  108. }
  109. func StartProxy(live net.Conn, monitor net.Conn, closed *bool, cp437 bool) {
  110. go ReadFrom_WriteTo(live, monitor, closed)
  111. if cp437 {
  112. go ReadFrom_WriteToCP437(monitor, live, closed)
  113. } else {
  114. go ReadFrom_WriteTo(monitor, live, closed)
  115. }
  116. }
  117. /*
  118. Read from live, write to server.
  119. Read from server, write to live.
  120. */
  121. func setup_monitor(live net.Conn, closed *bool, cp437 bool) (monitor net.Conn) {
  122. var err error
  123. var tempsock net.Listener
  124. tempsock, err = net.Listen("tcp", "127.0.0.1:0")
  125. if err != nil {
  126. panic(err)
  127. }
  128. // I only need address for making the connection.
  129. // Get address of listening socket
  130. var address string
  131. address = tempsock.Addr().String()
  132. monitor, err = net.Dial("tcp", address)
  133. if err != nil {
  134. panic(err)
  135. }
  136. var server net.Conn
  137. server, err = tempsock.Accept()
  138. if err != nil {
  139. panic(err)
  140. }
  141. tempsock.Close()
  142. *closed = false
  143. // monitor established - forward live <-> monitor
  144. go StartProxy(live, server, closed, cp437)
  145. return monitor
  146. }
  147. func Connection(conn net.Conn, drain int, cmd string, cp437 bool) {
  148. log.Println("Client " + conn.RemoteAddr().String() + " connected.")
  149. // Configure telnet connection to work
  150. // local echo off, handle CRNL.
  151. conn.Write([]byte("\xff\xfb\x01\xff\xfb\x03\xff\xfd\x10"))
  152. Drain(conn, drain)
  153. var closed bool
  154. var proxy net.Conn
  155. proxy = setup_monitor(conn, &closed, cp437)
  156. // Write out dropfile
  157. var conn_file *os.File = Conn_to_File(proxy)
  158. var handle int = 3
  159. var err error
  160. var fp *os.File
  161. fp, err = os.Create("door32.sys")
  162. if err != nil {
  163. log.Println("os.Create:", err)
  164. return
  165. }
  166. fmt.Fprintf(fp, "2\n%d\n38400\nFake Door32\n1\nBugz Laundry\nBugz\n100\n120\n1\n1\n", handle)
  167. fp.Close()
  168. var parts []string = strings.Split(cmd, " ")
  169. var Exe *exec.Cmd = exec.Command(parts[0], parts[1:]...)
  170. Exe.ExtraFiles = make([]*os.File, 1)
  171. Exe.ExtraFiles[0] = conn_file
  172. Exe.Stderr = os.Stderr
  173. Exe.Stdout = os.Stdout
  174. err = Exe.Start()
  175. if err != nil {
  176. log.Println("exec.Cmd.Start():", err)
  177. return
  178. }
  179. log.Println("Door running..." + conn.RemoteAddr().String())
  180. // Add a timeout here - to make sure the door isn't hung.
  181. // Is there a way to detect if the conn is disconnected?
  182. err = Exe.Wait()
  183. if err != nil {
  184. log.Println("exec.Cmd.Wait():", err)
  185. return
  186. }
  187. if closed {
  188. log.Println("Closed!")
  189. }
  190. log.Println("Door ended..." + conn.RemoteAddr().String())
  191. conn_file.Close()
  192. proxy.Close()
  193. conn.Write([]byte("\r\nWelcome back...\r\n"))
  194. conn.Close()
  195. }
  196. func Drain(conn net.Conn, drain int) {
  197. conn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(drain)))
  198. var buff []byte = make([]byte, 32)
  199. var n int
  200. var err error
  201. n, err = conn.Read(buff)
  202. if n > 0 {
  203. log.Printf("Drained %d bytes [%#v].\n", n, buff[:n])
  204. }
  205. if err != nil {
  206. log.Println("Drain:", err)
  207. }
  208. conn.SetReadDeadline(time.Time{})
  209. }