-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
162 lines (156 loc) · 3.98 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"io"
"log"
"math/rand"
"net"
"net/http"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
)
var (
port int
host string
name string
token string
chars = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
)
func init() {
flag.IntVar(&port, "p", 8000, "specify the port")
flag.StringVar(&host, "h", "0.0.0.0", "specify the host")
flag.StringVar(&name, "c", "sh", "name of the program to execute")
flag.StringVar(&token, "t", "", "secure the api with a token; set 'n' if no token is required")
}
func listen(network, address string) (*mux, error) {
ln, err := net.Listen(network, address)
if err != nil {
return nil, err
}
return multiplex(ln), nil
}
func run(name string, args []string, r io.Reader, w io.Writer) error {
cmd := exec.Command(name, args...)
cmd.Stdin = r
cmd.Stdout = w
return cmd.Run()
}
func main() {
flag.Parse()
rand.Seed(time.Now().UnixNano())
if token == "" {
var builder strings.Builder
for i := 0; i < 32; i++ {
builder.WriteRune(chars[rand.Intn(len(chars))])
}
token = fmt.Sprintf("0x%s", builder.String())
log.Printf("Using Generated Token %s\n", token)
} else if token == "n" {
token = ""
log.Printf("Selected Not To Use Any Tokens\n")
} else {
log.Printf("Using Configured Token %s\n", token)
}
args := os.Args[len(os.Args)-flag.NArg():]
argsMsg := fmt.Sprintf("Using Configured Command \"%s", name)
for _, arg := range args {
argsMsg = fmt.Sprintf("%s %s", argsMsg, arg)
}
log.Printf("%s\"\n", argsMsg)
pid, err := os.OpenFile("netpkg.pid", os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
log.Fatalf("failed to create pid file: %s", err.Error())
} else {
pid.Write([]byte(strconv.Itoa(syscall.Getpid())))
defer pid.Close()
}
sock, err := listen("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
log.Fatalf("failed to create listener: %s", err.Error())
}
defer sock.Close()
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
go func(name string, args []string) {
defer func() { sig <- syscall.SIGINT }()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("token") != token {
w.WriteHeader(http.StatusForbidden)
fmt.Fprint(w, "error validating token: token not correct\n")
return
}
if err := run(name, args, r.Body, w); err != nil {
w.WriteHeader(http.StatusInternalServerError)
err := fmt.Sprintf("error executing request: %+v\n", err)
fmt.Fprintf(w, "%+v\n", err)
log.Printf("%+v\n", err)
}
})
if err := http.Serve(sock.Listen([]byte{'G', 'P', 'D'}, "net/http"), nil); err != nil {
log.Printf("error listening on port: %+v\n", err)
}
}(name, args)
go func(shell string, args []string) {
defer func() { sig <- syscall.SIGINT }()
var rn byte = '0'
if token != "" {
rn = token[0]
}
ln := sock.Any(rn, "net/tcp")
defer ln.Close()
for {
conn, err := ln.Accept()
if err, ok := err.(interface {
Temporary() bool
}); ok && err.Temporary() {
log.Printf("error recieving request: %+v\n", err)
continue
}
if err != nil {
log.Printf("error listening on port: %+v\n", err)
return
}
go func(c net.Conn) {
defer c.Close()
r := bufio.NewReader(c)
for i := 0; i < len(token); i++ {
cmp, _, err := r.ReadRune()
if !(err == nil && byte(cmp) == token[i]) {
if err == nil {
err = errors.New("token not correct")
}
fmt.Fprintf(c, "error validating token: %+v\n", err)
return
}
}
if err := run(name, args, r, c); err != nil {
err := fmt.Sprintf("error executing request: %+v\n", err)
fmt.Fprintf(c, "%+v\n", err)
log.Printf("%+v\n", err)
return
}
}(conn)
}
}(name, args)
go func() {
defer func() { sig <- syscall.SIGINT }()
if err := sock.Serve(); err != nil {
log.Printf("error listening on port: %+v\n", err)
}
}()
for {
select {
case s := <-sig:
log.Printf("signal (%d) received, stopping", s)
return
}
}
}