-
Notifications
You must be signed in to change notification settings - Fork 0
/
oc_middleman_server.go
162 lines (132 loc) · 4.1 KB
/
oc_middleman_server.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 (
"bytes"
"fmt"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
"strings"
"golang.org/x/net/proxy"
)
const (
serverPassword = "secretPassword" // Set your desired server password here
maxFileSize = 42 * 1024 // 42 KB in bytes
)
func main() {
http.HandleFunc("/upload", handleUpload)
fmt.Println("Server is running on http://localhost:8085")
log.Fatal(http.ListenAndServe(":8085", nil))
}
func handleUpload(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Only POST requests are allowed", http.StatusMethodNotAllowed)
return
}
// Password check
if r.Header.Get("X-Password") != serverPassword {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Limit the request body size to maxFileSize
r.Body = http.MaxBytesReader(w, r.Body, maxFileSize)
err := r.ParseMultipartForm(maxFileSize)
if err != nil {
http.Error(w, "File too large or error parsing form", http.StatusBadRequest)
return
}
file, _, err := r.FormFile("file")
if err != nil {
http.Error(w, "Error retrieving file from form", http.StatusBadRequest)
return
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
http.Error(w, "Error reading file content", http.StatusInternalServerError)
return
}
if len(content) > maxFileSize {
http.Error(w, "Maximun allowed message size 42 KB!", http.StatusBadRequest)
return
}
lines := strings.Split(string(content), "\n")
var headers []string
var messageBody string
for i, line := range lines {
if strings.TrimSpace(line) == "" {
messageBody = strings.Join(lines[i+1:], "\n")
break
}
headers = append(headers, line)
}
if len(headers) == 0 {
http.Error(w, "No valid headers found", http.StatusBadRequest)
return
}
// Processing the first header
headerParts := strings.SplitN(headers[0], " ", 3)
if len(headerParts) != 3 || headerParts[0] != "X-OC-To:" {
http.Error(w, "Invalid header format", http.StatusBadRequest)
return
}
onionAddress := headerParts[1]
password := strings.TrimSpace(headerParts[2])
// Create new message without first header
newMessage := strings.Join(append(headers[1:], "", messageBody), "\n")
response, err := sendToOnionAddress([]byte(newMessage), onionAddress, password)
if err != nil {
log.Printf("Error sending to onion address: %v", err)
http.Error(w, fmt.Sprintf("Error sending to onion address: %v", err), http.StatusInternalServerError)
return
}
responseMsg := "File received and sent.\n"
responseMsg += "No data is stored or logged by Onion Courier.\n\n"
responseMsg += "Onion Courier Response: %s\n"
fmt.Fprintf(w, responseMsg, response)
}
func sendToOnionAddress(message []byte, onionAddress, password string) (string, error) {
dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct)
if err != nil {
return "", fmt.Errorf("error creating SOCKS5 dialer: %v", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
Dial: dialer.Dial,
},
}
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "message.txt")
if err != nil {
return "", fmt.Errorf("error creating form file: %v", err)
}
_, err = part.Write(message)
if err != nil {
return "", fmt.Errorf("error writing message to form file: %v", err)
}
err = writer.Close()
if err != nil {
return "", fmt.Errorf("error closing multipart writer: %v", err)
}
url := fmt.Sprintf("http://%s/upload", onionAddress)
req, err := http.NewRequest("POST", url, body)
if err != nil {
return "", fmt.Errorf("error creating request: %v", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-Password", password)
resp, err := httpClient.Do(req)
if err != nil {
return "", fmt.Errorf("error sending request: %v", err)
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("error reading response: %v", err)
}
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("server returned non-OK status: %d - %s", resp.StatusCode, string(respBody))
}
return string(respBody), nil
}