door32w.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package main
  2. /*
  3. A Windows Door tester.
  4. */
  5. import (
  6. "flag"
  7. "fmt"
  8. "net"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "syscall"
  13. "time"
  14. )
  15. const (
  16. connHost = "0.0.0.0"
  17. connPort = "8080"
  18. connType = "tcp"
  19. )
  20. func main() {
  21. var port int
  22. flag.IntVar(&port, "p", 0, "Port number to listen on")
  23. flag.Parse()
  24. if port == 0 && flag.NArg() != 1 {
  25. fmt.Println("I need a Port and a door command line to execute.")
  26. flag.PrintDefaults()
  27. os.Exit(2)
  28. }
  29. fmt.Println("Starting " + connType + " server on " + connHost + ":" + strconv.Itoa(port))
  30. l, err := net.Listen("tcp", "0.0.0.0:"+strconv.Itoa(port))
  31. if err != nil {
  32. fmt.Println("Error listening:", err.Error())
  33. os.Exit(1)
  34. }
  35. defer l.Close()
  36. for {
  37. c, err := l.Accept()
  38. if err != nil {
  39. fmt.Println("Error connecting:", err.Error())
  40. return
  41. }
  42. fmt.Println("Client connected.")
  43. fmt.Println("Client " + c.RemoteAddr().String() + " connected.")
  44. // Handle the connection in the background...
  45. go handleConnection(c, flag.Arg(0))
  46. c = nil
  47. }
  48. }
  49. func drain(conn net.Conn) {
  50. conn.SetReadDeadline(time.Now().Add(time.Second * 2))
  51. recvData := make([]byte, 32)
  52. n, err := conn.Read(recvData)
  53. if n > 0 {
  54. // do something with recvData[:n]
  55. fmt.Printf(" [%d]\n", n)
  56. }
  57. if err != nil {
  58. fmt.Printf("drain Error: %#v\n", err)
  59. }
  60. conn.SetReadDeadline(time.Time{})
  61. }
  62. func waitForIt(conn net.Conn, pid int) {
  63. process, _ := os.FindProcess(pid)
  64. state, _ := process.Wait()
  65. fmt.Printf("%d State: %#v\n", pid, state)
  66. conn.Write([]byte("\r\nThanks for calling!\r\n"))
  67. conn.Close()
  68. fmt.Println("Connection closed.")
  69. }
  70. func handleConnection(conn net.Conn, cmd string) {
  71. // Something here confuses the crap out of Windows Telnet Client!
  72. conn.Write([]byte("\xff\xfb\x01\xff\xfb\x03\xff\xfd\x10"))
  73. drain(conn)
  74. conn.Write([]byte("\n\rLaunching door\n\r"))
  75. time.Sleep(time.Second)
  76. fmt.Printf("%#v\n", conn)
  77. tcp, _ := conn.(*net.TCPConn)
  78. fmt.Printf("%#v\n", tcp)
  79. // https://github.com/golang/go/issues/10350
  80. // Duplicate the handle for passing off to the door.
  81. raw, err := tcp.SyscallConn()
  82. fmt.Printf("%#v, err: %#v\n", raw, err)
  83. var socket_fd uintptr
  84. raw.Control(func(fd uintptr) {
  85. socket_fd = fd
  86. })
  87. fmt.Printf("Socket FD: %#v\n", socket_fd)
  88. proc, _ := syscall.GetCurrentProcess()
  89. var dup_socket_fd syscall.Handle
  90. err = syscall.DuplicateHandle(proc, syscall.Handle(socket_fd),
  91. proc, &dup_socket_fd, syscall.DUPLICATE_SAME_ACCESS, true, 0)
  92. if err != nil {
  93. fmt.Printf("ERR DuplicateHandle: %#v\n", err)
  94. }
  95. fmt.Printf("Dup FD: %#v\n", dup_socket_fd)
  96. // windows: tcp.File() failes. net.OpError
  97. /*
  98. file, err := tcp.File()
  99. fd := file.Fd()
  100. fmt.Printf("FD %#v, %#v\n", fd, err)
  101. */
  102. /*
  103. tcp, _ := conn.(*net.TCPConn)
  104. file, _ := tcp.File()
  105. fd := file.Fd()
  106. */
  107. // what we actually put into the file
  108. filefd := int64(dup_socket_fd)
  109. // fdstr := strconv.Itoa(int(filefd))
  110. fp, _ := os.Create("door32.sys")
  111. fmt.Fprintf(fp, "2\n%d\n38400\nFake Door32\n1\nBugz Laundry\nBugz\n100\n120\n1\n1\n", filefd)
  112. fp.Close()
  113. parts := strings.Split(cmd, " ")
  114. // parts = append(parts, fdstr)
  115. // id, _ := syscall.ForkExec(parts[0], parts[1:], nil)
  116. fmt.Printf("Running: [%s] with %#v\n", parts[0], parts[1:])
  117. // https://stackoverflow.com/questions/35336131/createprocess-with-golang
  118. var si syscall.StartupInfo
  119. var pi syscall.ProcessInformation
  120. argv := syscall.StringToUTF16Ptr(cmd)
  121. err = syscall.CreateProcess(nil, argv, nil, nil, true, 0, nil, nil, &si, &pi)
  122. fmt.Printf("Door has launched. Return: %#v\n", err)
  123. raw = nil
  124. if err == nil {
  125. event, e := syscall.WaitForSingleObject(pi.Process, syscall.INFINITE)
  126. fmt.Printf("Event %#v, err: %#v\n", event, e)
  127. }
  128. fmt.Println("Close Duplicate.")
  129. // Close the duplicate...
  130. syscall.CloseHandle(dup_socket_fd)
  131. fmt.Println("Close Done.")
  132. /*
  133. exec_cmd := exec.Command(parts[0], parts[1:]...)
  134. fmt.Printf("exec_cmd: %#v\n", exec_cmd)
  135. err = exec_cmd.Run()
  136. if err != nil {
  137. fmt.Println("Error: ", err)
  138. }
  139. fmt.Println("Command completed.")
  140. // UH, WHAT? I didn't see that it started, and it certainly didn't keep running. :(
  141. */
  142. // id := 13
  143. /*
  144. id, _ := syscall.ForkExec(parts[0], parts,
  145. &syscall.ProcAttr{
  146. Env: os.Environ(),
  147. Sys: &syscall.SysProcAttr{
  148. Setsid: true,
  149. },
  150. Files: []uintptr{0, 1, 2, fd}, // print message to the same pty
  151. })
  152. */
  153. // go waitForIt(conn, id)
  154. // id, _, _ := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
  155. /*
  156. if id == 0 {
  157. // child process
  158. exec.Command(parts[0], parts[1:]...)
  159. os.Exit(2)
  160. }
  161. */
  162. // fmt.Printf("Child started: %d\n", id)
  163. // return
  164. fmt.Println("Welcome caller back.")
  165. conn.Write([]byte("Welcome back!\r\nSeeya!\r\n"))
  166. fmt.Println("Ok, shut this connection down.")
  167. // I can't seem to get this to close the connection. :(
  168. conn.Close()
  169. syscall.CloseHandle(syscall.Handle(socket_fd))
  170. tcp.SetLinger(0)
  171. tcp.Close()
  172. fmt.Println("Closed.")
  173. /*
  174. for {
  175. buffer, err := bufio.NewReader(conn).ReadBytes('\r') // HMM. \r ?
  176. if err != nil {
  177. fmt.Println("Client left.")
  178. conn.Close()
  179. return
  180. }
  181. // What am I seeing here?
  182. log.Println("Client message:", string(buffer[:len(buffer)-1]))
  183. conn.Write(buffer)
  184. conn.Write([]byte("\n"))
  185. }
  186. */
  187. }