123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- package main
- /*
- A Windows Door tester.
- */
- import (
- "flag"
- "fmt"
- "net"
- "os"
- "strconv"
- "strings"
- "syscall"
- "time"
- )
- const (
- connHost = "0.0.0.0"
- connPort = "8080"
- connType = "tcp"
- )
- func main() {
- var port int
- flag.IntVar(&port, "p", 0, "Port number to listen on")
- flag.Parse()
- if port == 0 && flag.NArg() != 1 {
- fmt.Println("I need a Port and a door command line to execute.")
- flag.PrintDefaults()
- os.Exit(2)
- }
- fmt.Println("Starting " + connType + " server on " + connHost + ":" + strconv.Itoa(port))
- l, err := net.Listen("tcp", "0.0.0.0:"+strconv.Itoa(port))
- if err != nil {
- fmt.Println("Error listening:", err.Error())
- os.Exit(1)
- }
- defer l.Close()
- for {
- c, err := l.Accept()
- if err != nil {
- fmt.Println("Error connecting:", err.Error())
- return
- }
- fmt.Println("Client connected.")
- fmt.Println("Client " + c.RemoteAddr().String() + " connected.")
- // Handle the connection in the background...
- go handleConnection(c, flag.Arg(0))
- c = nil
- }
- }
- func drain(conn net.Conn) {
- conn.SetReadDeadline(time.Now().Add(time.Second * 2))
- recvData := make([]byte, 32)
- n, err := conn.Read(recvData)
- if n > 0 {
- // do something with recvData[:n]
- fmt.Printf(" [%d]\n", n)
- }
- if err != nil {
- fmt.Printf("drain Error: %#v\n", err)
- }
- conn.SetReadDeadline(time.Time{})
- }
- func waitForIt(conn net.Conn, pid int) {
- process, _ := os.FindProcess(pid)
- state, _ := process.Wait()
- fmt.Printf("%d State: %#v\n", pid, state)
- conn.Write([]byte("\r\nThanks for calling!\r\n"))
- conn.Close()
- fmt.Println("Connection closed.")
- }
- func handleConnection(conn net.Conn, cmd string) {
- // Something here confuses the crap out of Windows Telnet Client!
- conn.Write([]byte("\xff\xfb\x01\xff\xfb\x03\xff\xfd\x10"))
- drain(conn)
- conn.Write([]byte("\n\rLaunching door\n\r"))
- time.Sleep(time.Second)
- fmt.Printf("%#v\n", conn)
- tcp, _ := conn.(*net.TCPConn)
- fmt.Printf("%#v\n", tcp)
- // https://github.com/golang/go/issues/10350
- // Duplicate the handle for passing off to the door.
- raw, err := tcp.SyscallConn()
- fmt.Printf("%#v, err: %#v\n", raw, err)
- var socket_fd uintptr
- raw.Control(func(fd uintptr) {
- socket_fd = fd
- })
- fmt.Printf("Socket FD: %#v\n", socket_fd)
- proc, _ := syscall.GetCurrentProcess()
- var dup_socket_fd syscall.Handle
- err = syscall.DuplicateHandle(proc, syscall.Handle(socket_fd),
- proc, &dup_socket_fd, syscall.DUPLICATE_SAME_ACCESS, true, 0)
- if err != nil {
- fmt.Printf("ERR DuplicateHandle: %#v\n", err)
- }
- fmt.Printf("Dup FD: %#v\n", dup_socket_fd)
- // windows: tcp.File() failes. net.OpError
- /*
- file, err := tcp.File()
- fd := file.Fd()
- fmt.Printf("FD %#v, %#v\n", fd, err)
- */
- /*
- tcp, _ := conn.(*net.TCPConn)
- file, _ := tcp.File()
- fd := file.Fd()
- */
- // what we actually put into the file
- filefd := int64(dup_socket_fd)
- // fdstr := strconv.Itoa(int(filefd))
- fp, _ := os.Create("door32.sys")
- fmt.Fprintf(fp, "2\n%d\n38400\nFake Door32\n1\nBugz Laundry\nBugz\n100\n120\n1\n1\n", filefd)
- fp.Close()
- parts := strings.Split(cmd, " ")
- // parts = append(parts, fdstr)
- // id, _ := syscall.ForkExec(parts[0], parts[1:], nil)
- fmt.Printf("Running: [%s] with %#v\n", parts[0], parts[1:])
- // https://stackoverflow.com/questions/35336131/createprocess-with-golang
- var si syscall.StartupInfo
- var pi syscall.ProcessInformation
- argv := syscall.StringToUTF16Ptr(cmd)
- err = syscall.CreateProcess(nil, argv, nil, nil, true, 0, nil, nil, &si, &pi)
- fmt.Printf("Door has launched. Return: %#v\n", err)
- raw = nil
- if err == nil {
- event, e := syscall.WaitForSingleObject(pi.Process, syscall.INFINITE)
- fmt.Printf("Event %#v, err: %#v\n", event, e)
- }
- fmt.Println("Close Duplicate.")
- // Close the duplicate...
- syscall.CloseHandle(dup_socket_fd)
- fmt.Println("Close Done.")
- /*
- exec_cmd := exec.Command(parts[0], parts[1:]...)
- fmt.Printf("exec_cmd: %#v\n", exec_cmd)
- err = exec_cmd.Run()
- if err != nil {
- fmt.Println("Error: ", err)
- }
- fmt.Println("Command completed.")
- // UH, WHAT? I didn't see that it started, and it certainly didn't keep running. :(
- */
- // id := 13
- /*
- id, _ := syscall.ForkExec(parts[0], parts,
- &syscall.ProcAttr{
- Env: os.Environ(),
- Sys: &syscall.SysProcAttr{
- Setsid: true,
- },
- Files: []uintptr{0, 1, 2, fd}, // print message to the same pty
- })
- */
- // go waitForIt(conn, id)
- // id, _, _ := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
- /*
- if id == 0 {
- // child process
- exec.Command(parts[0], parts[1:]...)
- os.Exit(2)
- }
- */
- // fmt.Printf("Child started: %d\n", id)
- // return
- fmt.Println("Welcome caller back.")
- conn.Write([]byte("Welcome back!\r\nSeeya!\r\n"))
- fmt.Println("Ok, shut this connection down.")
- // I can't seem to get this to close the connection. :(
- conn.Close()
- syscall.CloseHandle(syscall.Handle(socket_fd))
- tcp.SetLinger(0)
- tcp.Close()
- fmt.Println("Closed.")
- /*
- for {
- buffer, err := bufio.NewReader(conn).ReadBytes('\r') // HMM. \r ?
- if err != nil {
- fmt.Println("Client left.")
- conn.Close()
- return
- }
- // What am I seeing here?
- log.Println("Client message:", string(buffer[:len(buffer)-1]))
- conn.Write(buffer)
- conn.Write([]byte("\n"))
- }
- */
- }
|