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")) } */ }