Passed
Pull Request — master (#52)
by Stefano
02:05
created

cmd_test.TestScanWithMalformedHeaderShouldErr   A

Complexity

Conditions 2

Size

Total Lines 30
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 23
nop 1
dl 0
loc 30
rs 9.328
c 0
b 0
f 0
1
package cmd_test
2
3
import (
4
	"net"
5
	"net/http"
6
	"net/http/httptest"
7
	"sync"
8
	"testing"
9
	"time"
10
11
	"github.com/armon/go-socks5"
12
	"github.com/stefanoj3/dirstalk/pkg/common/test"
13
	"github.com/stretchr/testify/assert"
14
)
15
16
func TestScanCommand(t *testing.T) {
17
	logger, _ := test.NewLogger()
18
19
	c, err := createCommand(logger)
20
	assert.NoError(t, err)
21
	assert.NotNil(t, c)
22
23
	testServer, serverAssertion := test.NewServerWithAssertion(
24
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
25
			w.WriteHeader(http.StatusNotFound)
26
		}),
27
	)
28
	defer testServer.Close()
29
30
	_, _, err = executeCommand(
31
		c,
32
		"scan",
33
		testServer.URL,
34
		"--dictionary",
35
		"testdata/dict.txt",
36
		"-v",
37
		"--http-timeout",
38
		"300",
39
	)
40
	assert.NoError(t, err)
41
42
	assert.Equal(t, 3, serverAssertion.Len())
43
}
44
45
func TestScanWithRemoteDictionary(t *testing.T) {
46
	logger, _ := test.NewLogger()
47
48
	c, err := createCommand(logger)
49
	assert.NoError(t, err)
50
	assert.NotNil(t, c)
51
52
	dictionaryServer := httptest.NewServer(
53
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
54
			dict := `home
55
home/index.php
56
blabla
57
`
58
			w.WriteHeader(http.StatusOK)
59
			_, _ = w.Write([]byte(dict))
60
		}),
61
	)
62
	defer dictionaryServer.Close()
63
64
	testServer, serverAssertion := test.NewServerWithAssertion(
65
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
66
			w.WriteHeader(http.StatusNotFound)
67
		}),
68
	)
69
	defer testServer.Close()
70
71
	_, _, err = executeCommand(
72
		c,
73
		"scan",
74
		testServer.URL,
75
		"--dictionary",
76
		dictionaryServer.URL,
77
		"--http-timeout",
78
		"300",
79
	)
80
	assert.NoError(t, err)
81
82
	assert.Equal(t, 3, serverAssertion.Len())
83
}
84
85
func TestScanWithUserAgentFlag(t *testing.T) {
86
	const testUserAgent = "my_test_user_agent"
87
88
	logger, loggerBuffer := test.NewLogger()
89
90
	c, err := createCommand(logger)
91
	assert.NoError(t, err)
92
	assert.NotNil(t, c)
93
94
	testServer, serverAssertion := test.NewServerWithAssertion(
95
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
96
			w.WriteHeader(http.StatusNotFound)
97
		}),
98
	)
99
	defer testServer.Close()
100
101
	_, _, err = executeCommand(
102
		c,
103
		"scan",
104
		testServer.URL,
105
		"--user-agent",
106
		testUserAgent,
107
		"--dictionary",
108
		"testdata/dict.txt",
109
		"--http-timeout",
110
		"300",
111
	)
112
	assert.NoError(t, err)
113
114
	assert.Equal(t, 3, serverAssertion.Len())
115
	serverAssertion.Range(func(_ int, r http.Request) {
116
		assert.Equal(t, testUserAgent, r.Header.Get("User-Agent"))
117
	})
118
119
	// to ensure we print the user agent to the cli
120
	assert.Contains(t, loggerBuffer.String(), testUserAgent)
121
}
122
123
func TestScanWithCookies(t *testing.T) {
124
	logger, loggerBuffer := test.NewLogger()
125
126
	c, err := createCommand(logger)
127
	assert.NoError(t, err)
128
	assert.NotNil(t, c)
129
130
	testServer, serverAssertion := test.NewServerWithAssertion(
131
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
132
	)
133
	defer testServer.Close()
134
135
	_, _, err = executeCommand(
136
		c,
137
		"scan",
138
		testServer.URL,
139
		"--cookie",
140
		"name1=val1",
141
		"--cookie",
142
		"name2=val2",
143
		"--dictionary",
144
		"testdata/dict.txt",
145
		"--http-timeout",
146
		"300",
147
	)
148
	assert.NoError(t, err)
149
150
	serverAssertion.Range(func(_ int, r http.Request) {
151
		assert.Equal(t, 2, len(r.Cookies()))
152
153
		assert.Equal(t, r.Cookies()[0].Name, "name1")
154
		assert.Equal(t, r.Cookies()[0].Value, "val1")
155
156
		assert.Equal(t, r.Cookies()[1].Name, "name2")
157
		assert.Equal(t, r.Cookies()[1].Value, "val2")
158
	})
159
160
	// to ensure we print the cookies to the cli
161
	assert.Contains(t, loggerBuffer.String(), "name1=val1")
162
	assert.Contains(t, loggerBuffer.String(), "name2=val2")
163
}
164
165
func TestWhenProvidingCookiesInWrongFormatShouldErr(t *testing.T) {
166
	const malformedCookie = "gibberish"
167
168
	logger, _ := test.NewLogger()
169
170
	c, err := createCommand(logger)
171
	assert.NoError(t, err)
172
	assert.NotNil(t, c)
173
174
	testServer, serverAssertion := test.NewServerWithAssertion(
175
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
176
			w.WriteHeader(http.StatusNotFound)
177
		}),
178
	)
179
	defer testServer.Close()
180
181
	_, _, err = executeCommand(
182
		c,
183
		"scan",
184
		testServer.URL,
185
		"--cookie",
186
		malformedCookie,
187
		"--dictionary",
188
		"testdata/dict.txt",
189
	)
190
	assert.Error(t, err)
191
	assert.Contains(t, err.Error(), "cookie format is invalid")
192
	assert.Contains(t, err.Error(), malformedCookie)
193
194
	assert.Equal(t, 0, serverAssertion.Len())
195
}
196
197
func TestScanWithCookieJar(t *testing.T) {
198
	const (
199
		serverCookieName  = "server_cookie_name"
200
		serverCookieValue = "server_cookie_value"
201
	)
202
203
	logger, _ := test.NewLogger()
204
205
	c, err := createCommand(logger)
206
	assert.NoError(t, err)
207
	assert.NotNil(t, c)
208
209
	once := sync.Once{}
210
	testServer, serverAssertion := test.NewServerWithAssertion(
211
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
212
			once.Do(func() {
213
				http.SetCookie(
214
					w,
215
					&http.Cookie{
216
						Name:    serverCookieName,
217
						Value:   serverCookieValue,
218
						Expires: time.Now().AddDate(0, 1, 0),
219
					},
220
				)
221
			})
222
		}),
223
	)
224
	defer testServer.Close()
225
226
	_, _, err = executeCommand(
227
		c,
228
		"scan",
229
		testServer.URL,
230
		"--use-cookie-jar",
231
		"--dictionary",
232
		"testdata/dict.txt",
233
		"--http-timeout",
234
		"300",
235
		"-t",
236
		"1",
237
	)
238
	assert.NoError(t, err)
239
240
	serverAssertion.Range(func(index int, r http.Request) {
241
		if index == 0 { // first request should have no cookies
242
			assert.Equal(t, 0, len(r.Cookies()))
243
			return
244
		}
245
246
		assert.Equal(t, 1, len(r.Cookies()))
247
		assert.Equal(t, r.Cookies()[0].Name, serverCookieName)
248
		assert.Equal(t, r.Cookies()[0].Value, serverCookieValue)
249
	})
250
}
251
252
func TestScanWithUnknownFlagShouldErr(t *testing.T) {
253
	logger, _ := test.NewLogger()
254
255
	c, err := createCommand(logger)
256
	assert.NoError(t, err)
257
	assert.NotNil(t, c)
258
259
	testServer, serverAssertion := test.NewServerWithAssertion(
260
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
261
	)
262
	defer testServer.Close()
263
264
	_, _, err = executeCommand(
265
		c,
266
		"scan",
267
		testServer.URL,
268
		"--gibberishflag",
269
		"--dictionary",
270
		"testdata/dict.txt",
271
	)
272
	assert.Error(t, err)
273
	assert.Contains(t, err.Error(), "unknown flag")
274
275
	assert.Equal(t, 0, serverAssertion.Len())
276
}
277
278
func TestScanWithHeaders(t *testing.T) {
279
	logger, loggerBuffer := test.NewLogger()
280
281
	c, err := createCommand(logger)
282
	assert.NoError(t, err)
283
	assert.NotNil(t, c)
284
285
	testServer, serverAssertion := test.NewServerWithAssertion(
286
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
287
	)
288
	defer testServer.Close()
289
290
	_, _, err = executeCommand(
291
		c,
292
		"scan",
293
		testServer.URL,
294
		"--header",
295
		"Accept-Language: en-US,en;q=0.5",
296
		"--header",
297
		`"Authorization: Bearer 123"`,
298
		"--dictionary",
299
		"testdata/dict.txt",
300
		"--http-timeout",
301
		"300",
302
	)
303
	assert.NoError(t, err)
304
305
	serverAssertion.Range(func(_ int, r http.Request) {
306
		assert.Equal(t, 2, len(r.Header))
307
308
		assert.Equal(t, "en-US,en;q=0.5", r.Header.Get("Accept-Language"))
309
		assert.Equal(t, "Bearer 123", r.Header.Get("Authorization"))
310
	})
311
312
	// to ensure we print the headers to the cli
313
	assert.Contains(t, loggerBuffer.String(), "Accept-Language")
314
	assert.Contains(t, loggerBuffer.String(), "Authorization")
315
	assert.Contains(t, loggerBuffer.String(), "Bearer 123")
316
}
317
318
func TestScanWithMalformedHeaderShouldErr(t *testing.T) {
319
	const malformedHeader = "gibberish"
320
321
	logger, _ := test.NewLogger()
322
323
	c, err := createCommand(logger)
324
	assert.NoError(t, err)
325
	assert.NotNil(t, c)
326
327
	testServer, serverAssertion := test.NewServerWithAssertion(
328
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
329
	)
330
	defer testServer.Close()
331
332
	_, _, err = executeCommand(
333
		c,
334
		"scan",
335
		testServer.URL,
336
		"--header",
337
		"Accept-Language: en-US,en;q=0.5",
338
		"--header",
339
		malformedHeader,
340
		"--dictionary",
341
		"testdata/dict.txt",
342
	)
343
	assert.Error(t, err)
344
	assert.Contains(t, err.Error(), malformedHeader)
345
	assert.Contains(t, err.Error(), "header is in invalid format")
346
347
	assert.Equal(t, 0, serverAssertion.Len())
348
}
349
350
func TestStartScanWithSocks5ShouldFindResultsWhenAServerIsAvailable(t *testing.T) {
351
	logger, _ := test.NewLogger()
352
353
	c, err := createCommand(logger)
354
	assert.NoError(t, err)
355
	assert.NotNil(t, c)
356
357
	testServer, serverAssertion := test.NewServerWithAssertion(
358
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
359
			w.WriteHeader(http.StatusNotFound)
360
		}),
361
	)
362
	defer testServer.Close()
363
364
	socks5Server := startSocks5TestServer(t)
365
	defer socks5Server.Close()
366
367
	_, _, err = executeCommand(
368
		c,
369
		"scan",
370
		testServer.URL,
371
		"--dictionary",
372
		"testdata/dict.txt",
373
		"-v",
374
		"--http-timeout",
375
		"300",
376
		"--socks5",
377
		socks5TestServerHost,
378
	)
379
	assert.NoError(t, err)
380
381
	assert.Equal(t, 3, serverAssertion.Len())
382
}
383
384
func TestShouldFailToScanWithAnUnreachableSocks5Server(t *testing.T) {
385
	logger, loggerBuffer := test.NewLogger()
386
387
	c, err := createCommand(logger)
388
	assert.NoError(t, err)
389
	assert.NotNil(t, c)
390
391
	testServer, serverAssertion := test.NewServerWithAssertion(
392
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
393
			w.WriteHeader(http.StatusNotFound)
394
		}),
395
	)
396
	defer testServer.Close()
397
398
	socks5Server := startSocks5TestServer(t)
399
	defer socks5Server.Close()
400
401
	_, _, err = executeCommand(
402
		c,
403
		"scan",
404
		testServer.URL,
405
		"--dictionary",
406
		"testdata/dict.txt",
407
		"-v",
408
		"--http-timeout",
409
		"300",
410
		"--socks5",
411
		"127.0.0.1:9555", // invalid
412
	)
413
	assert.NoError(t, err)
414
415
	assert.Equal(t, 0, serverAssertion.Len())
416
	assert.Contains(t, loggerBuffer.String(), "failed to perform request")
417
	assert.Contains(t, loggerBuffer.String(), "socks connect tcp")
418
	assert.Contains(t, loggerBuffer.String(), "connect: connection refused")
419
}
420
421
func startSocks5TestServer(t *testing.T) net.Listener {
422
	conf := &socks5.Config{}
423
	server, err := socks5.New(conf)
424
	if err != nil {
425
		t.Fatalf("failed to create socks5: %s", err.Error())
426
	}
427
428
	listener, err := net.Listen("tcp", socks5TestServerHost)
429
	if err != nil {
430
		t.Fatalf("failed to create listener: %s", err.Error())
431
	}
432
433
	go func() {
434
		// Create SOCKS5 proxy on localhost port 8000
435
		if err := server.Serve(listener); err != nil {
436
			t.Logf("socks5 stopped serving: %s", err.Error())
437
		}
438
	}()
439
440
	return listener
441
}
442