ruby-masscan 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 221aba609e42676f60a8ff8ca50017f52b107ce4bbfd09b2d17fac243e876db8
4
- data.tar.gz: 92ffeee1fd37297f5a1731fb2af18d5409c99ceda7704beab4f762e9270e85e3
3
+ metadata.gz: f03fa94f7c501646be712a24b98fe07a6dd156c054c7ae27714cac80b1fbb5e8
4
+ data.tar.gz: a346c7b055da689cad8571a38383b43a5e797889d6206b85ca7d2a64e25b904f
5
5
  SHA512:
6
- metadata.gz: f3cb61b85ec433a38a77e5f3993902fb48c340ee8eb6a2476ad98afc8369f33a55ade52fb75f55bcde9f36251da1cea84e5215f717b33821af733744d22087e6
7
- data.tar.gz: 4224460de4162eeb091db2d5d194e66eec3c81bea585c64101adadbfc9c959dfdecae482c7c607717d828f2922ef82b99c2d52f99a0b146153cafe3b8e724add
6
+ metadata.gz: ecdea1cc3b62cf1d0dbb2b7771807c05f2e6339b573f6208dcfb21e94fdaad160e51adc077e158ec6c4b4bc9426c7925dfd376d53d455922c5e318e6ee999936
7
+ data.tar.gz: 88bbf9a1332946ae7688fae852a1a3565269a853eff17434dc8e0b1fd7eae2c3e14b09cc64fa3fc80a06781f3fd644b97e5f97fcc52ccd2aa71cbc2a32b15f3c
data/ChangeLog.md CHANGED
@@ -1,3 +1,10 @@
1
+ ### 0.1.1 / 2021-09-09
2
+
3
+ * Added missing {Masscan::Banner#ttl}.
4
+ * Fixed {Masscan::Parsers::Binary} to populate {Masscan::Banner#ttl}.
5
+ * Fixed {Masscan::Parsers::Binary#parse_status} to populate
6
+ {Masscan::Status#reason} and {Masscan::Status#ttl}.
7
+
1
8
  ### 0.1.0 / 2021-08-31
2
9
 
3
10
  * Initial release:
@@ -2,7 +2,37 @@ module Masscan
2
2
  #
3
3
  # Represents a banner record.
4
4
  #
5
- class Banner < Struct.new(:protocol,:port,:ip,:timestamp,:app_protocol,:payload)
5
+ class Banner < Struct.new(:protocol,:port,:ttl,:ip,:timestamp,:app_protocol,:payload)
6
+
7
+ #
8
+ # Initializes the banner.
9
+ #
10
+ # @param [:icmp, :tcp, :udp, :sctp] protocol
11
+ # The IP protocol.
12
+ #
13
+ # @param [Integer] port
14
+ # The port number.
15
+ #
16
+ # @param [Integer, nil] ttl
17
+ # The optional TTL.
18
+ #
19
+ # @param [IPAddr] ip
20
+ # The IP address.
21
+ #
22
+ # @param [Time] timestamp
23
+ # The record timestamp.
24
+ #
25
+ # @param [Symbol] app_protocol
26
+ # The application protocol.
27
+ #
28
+ # @param [String] payload
29
+ # The banner/capture payload.
30
+ #
31
+ # @api private
32
+ #
33
+ def initialize(protocol: , port: , ttl: nil, ip: , timestamp: , app_protocol: , payload: )
34
+ super(protocol,port,ttl,ip,timestamp,app_protocol,payload)
35
+ end
6
36
 
7
37
  alias service app_protocol
8
38
  alias banner payload
@@ -366,12 +366,14 @@ module Masscan
366
366
  end
367
367
 
368
368
  return Status.new(
369
- status,
370
- protocol,
371
- port,
372
- ip,
373
- timestamp,
374
- mac
369
+ status: status,
370
+ protocol: protocol,
371
+ port: port,
372
+ reason: reason,
373
+ ttl: ttl,
374
+ ip: ip,
375
+ timestamp: timestamp,
376
+ mac: mac
375
377
  )
376
378
  end
377
379
 
@@ -396,12 +398,13 @@ module Masscan
396
398
  ttl = 0
397
399
 
398
400
  return Banner.new(
399
- ip_proto,
400
- port,
401
- ip,
402
- timestamp,
403
- app_proto,
404
- payload
401
+ protocol: ip_proto,
402
+ port: port,
403
+ ttl: ttl,
404
+ ip: ip,
405
+ timestamp: timestamp,
406
+ app_protocol: app_proto,
407
+ payload: payload
405
408
  )
406
409
  end
407
410
 
@@ -419,7 +422,7 @@ module Masscan
419
422
  return
420
423
  end
421
424
 
422
- timestamp, ip, ip_prot, port, app_proto, payload = buffer.unpack('L>L>CS>S>A*')
425
+ timestamp, ip, ip_proto, port, app_proto, payload = buffer.unpack('L>L>CS>S>A*')
423
426
 
424
427
  timestamp = decode_timestamp(timestamp)
425
428
  ip = decode_ipv4(ip)
@@ -430,12 +433,13 @@ module Masscan
430
433
  ttl = 0
431
434
 
432
435
  return Banner.new(
433
- ip_proto,
434
- port,
435
- ip,
436
- timestamp,
437
- app_proto,
438
- payload
436
+ protocol: ip_proto,
437
+ port: port,
438
+ ttl: ttl,
439
+ ip: ip,
440
+ timestamp: timestamp,
441
+ app_protocol: app_proto,
442
+ payload: payload
439
443
  )
440
444
  end
441
445
 
@@ -467,14 +471,14 @@ module Masscan
467
471
  end
468
472
 
469
473
  return Status.new(
470
- status,
471
- ip_proto,
472
- port,
473
- reason,
474
- ttl,
475
- ip,
476
- timestamp,
477
- mac
474
+ status: status,
475
+ protocol: ip_proto,
476
+ port: port,
477
+ reason: reason,
478
+ ttl: ttl,
479
+ ip: ip,
480
+ timestamp: timestamp,
481
+ mac: mac
478
482
  )
479
483
  end
480
484
 
@@ -499,12 +503,13 @@ module Masscan
499
503
  app_proto = lookup_app_protocol(app_proto)
500
504
 
501
505
  return Banner.new(
502
- ip_proto,
503
- port,
504
- ip,
505
- timestamp,
506
- app_proto,
507
- payload
506
+ protocol: ip_proto,
507
+ port: port,
508
+ ttl: ttl,
509
+ ip: ip,
510
+ timestamp: timestamp,
511
+ app_protocol: app_proto,
512
+ payload: payload
508
513
  )
509
514
  end
510
515
 
@@ -541,13 +546,13 @@ module Masscan
541
546
  ipv6 = decode_ipv6(ipv6_hi,ipv6_lo)
542
547
 
543
548
  return Status.new(
544
- status,
545
- ip_proto,
546
- port,
547
- reason,
548
- ttl,
549
- ipv6,
550
- timestamp
549
+ status: status,
550
+ protocol: ip_proto,
551
+ port: port,
552
+ reason: reason,
553
+ ttl: ttl,
554
+ ip: ipv6,
555
+ timestamp: timestamp
551
556
  )
552
557
  end
553
558
 
@@ -577,12 +582,13 @@ module Masscan
577
582
  ipv6 = decode_ipv6(ipv6_hi,ipv6_lo)
578
583
 
579
584
  return Banner.new(
580
- ip_proto,
581
- port,
582
- ipv6,
583
- timestamp,
584
- app_proto,
585
- payload
585
+ protocol: ip_proto,
586
+ port: port,
587
+ ttl: ttl,
588
+ ip: ipv6,
589
+ timestamp: timestamp,
590
+ app_protocol: app_proto,
591
+ payload: payload
586
592
  )
587
593
  end
588
594
 
@@ -74,12 +74,12 @@ module Masscan
74
74
  service_banner = service_json['banner']
75
75
 
76
76
  yield Banner.new(
77
- proto,
78
- port,
79
- ip,
80
- timestamp,
81
- service_name,
82
- service_banner
77
+ protocol: proto,
78
+ port: port,
79
+ ip: ip,
80
+ timestamp: timestamp,
81
+ app_protocol: service_name,
82
+ payload: service_banner
83
83
  )
84
84
  else
85
85
  status = parse_status(port_json['status'])
@@ -87,13 +87,13 @@ module Masscan
87
87
  reason = parse_reason(port_json['reason'])
88
88
 
89
89
  yield Status.new(
90
- status,
91
- proto,
92
- port,
93
- reason,
94
- ttl,
95
- ip,
96
- timestamp
90
+ status: status,
91
+ protocol: proto,
92
+ port: port,
93
+ reason: reason,
94
+ ttl: ttl,
95
+ ip: ip,
96
+ timestamp: timestamp
97
97
  )
98
98
  end
99
99
  end
@@ -57,24 +57,22 @@ module Masscan
57
57
  type, ip_proto, port, ip, timestamp = line.split(' ',5)
58
58
 
59
59
  yield Status.new(
60
- parse_status(type),
61
- parse_ip_protocol(ip_proto),
62
- port.to_i,
63
- nil,
64
- nil,
65
- parse_ip(ip),
66
- parse_timestamp(timestamp)
60
+ status: parse_status(type),
61
+ protocol: parse_ip_protocol(ip_proto),
62
+ port: port.to_i,
63
+ ip: parse_ip(ip),
64
+ timestamp: parse_timestamp(timestamp)
67
65
  )
68
66
  elsif line.start_with?('banner ')
69
67
  type, ip_proto, port, ip, timestamp, app_proto, banner = line.split(' ',7)
70
68
 
71
69
  yield Banner.new(
72
- parse_ip_protocol(ip_proto),
73
- port.to_i,
74
- parse_ip(ip),
75
- parse_timestamp(timestamp),
76
- parse_app_protocol(app_proto),
77
- banner
70
+ protocol: parse_ip_protocol(ip_proto),
71
+ port: port.to_i,
72
+ ip: parse_ip(ip),
73
+ timestamp: parse_timestamp(timestamp),
74
+ app_protocol: parse_app_protocol(app_proto),
75
+ payload: banner
78
76
  )
79
77
  end
80
78
  end
@@ -3,5 +3,38 @@ module Masscan
3
3
  # Represents a port status record.
4
4
  #
5
5
  class Status < Struct.new(:status,:protocol,:port,:reason,:ttl,:ip,:timestamp,:mac)
6
+
7
+ #
8
+ # Initializes the status record.
9
+ #
10
+ # @param [:open, :closed] status
11
+ # The status of the port.
12
+ #
13
+ # @param [:icmp, :tcp, :udp, :sctp] protocol
14
+ # The IP protocol.
15
+ #
16
+ # @param [Integer] port
17
+ # The port number.
18
+ #
19
+ # @param [Array<:fin, :syn, :rst, :psh, :ack, :urg, :ece, :cwr>, nil] reason
20
+ # Flags indicating why the port was open or closed.
21
+ #
22
+ # @param [Integer, nil] ttl
23
+ # TTL.
24
+ #
25
+ # @param [IPAddr] ip
26
+ # The IP address.
27
+ #
28
+ # @param [Time] timestamp
29
+ # The record timestamp.
30
+ #
31
+ # @param [String, nil] mac
32
+ # Optional mac address.
33
+ #
34
+ # @api private
35
+ #
36
+ def initialize(status: , protocol: , port: , reason: nil, ttl: nil, ip: , timestamp: , mac: nil)
37
+ super(status,protocol,port,reason,ttl,ip,timestamp,mac)
38
+ end
6
39
  end
7
40
  end
@@ -1,4 +1,4 @@
1
1
  module Masscan
2
2
  # ruby-masscan version
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
@@ -221,4 +221,508 @@ describe Masscan::Parsers::Binary do
221
221
  end
222
222
  end
223
223
  end
224
+
225
+ describe ".parse_status" do
226
+ let(:timestamp) { 1629960470 }
227
+ let(:time) { Time.at(timestamp) }
228
+
229
+ let(:ipaddr) { IPAddr.new("1.2.3.4") }
230
+ let(:ip_uint) { ipaddr.to_i }
231
+
232
+ let(:ip_proto) { :tcp }
233
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
234
+
235
+ let(:port) { 1111 }
236
+
237
+ let(:ttl) { 54 }
238
+
239
+ let(:reason) { [:syn, :ack] }
240
+ let(:reason_uint) { 0x02 | 0x10 }
241
+
242
+ let(:buffer) do
243
+ [
244
+ timestamp, ip_uint, port, reason_uint, ttl
245
+ ].pack("L>L>S>CC")
246
+ end
247
+
248
+ let(:status) { :open }
249
+
250
+ subject { super().parse_status(buffer,status) }
251
+
252
+ context "when the buffer length is less than 12" do
253
+ let(:buffer) { "A" * 11 }
254
+
255
+ it "must return nil" do
256
+ expect(subject).to be(nil)
257
+ end
258
+ end
259
+
260
+ it "must decode the timestamp field" do
261
+ expect(subject.timestamp).to eq(time)
262
+ end
263
+
264
+ it "must set #status" do
265
+ expect(subject.status).to eq(status)
266
+ end
267
+
268
+ it "must decode the ip field" do
269
+ expect(subject.ip).to eq(ipaddr)
270
+ end
271
+
272
+ context "when the port is 53" do
273
+ let(:port) { 53 }
274
+ let(:ip_proto) { :udp }
275
+
276
+ it "must default the ip_proto :udp" do
277
+ expect(subject.protocol).to eq(ip_proto)
278
+ end
279
+ end
280
+
281
+ context "when the port is 123" do
282
+ let(:port) { 123 }
283
+ let(:ip_proto) { :udp }
284
+
285
+ it "must default the ip_proto :udp" do
286
+ expect(subject.protocol).to eq(ip_proto)
287
+ end
288
+ end
289
+
290
+ context "when the port is 137" do
291
+ let(:port) { 137 }
292
+ let(:ip_proto) { :udp }
293
+
294
+ it "must default the ip_proto :udp" do
295
+ expect(subject.protocol).to eq(ip_proto)
296
+ end
297
+ end
298
+
299
+ context "when the port is 161" do
300
+ let(:port) { 161 }
301
+ let(:ip_proto) { :udp }
302
+
303
+ it "must default the ip_proto :udp" do
304
+ expect(subject.protocol).to eq(ip_proto)
305
+ end
306
+ end
307
+
308
+ context "when the port is 36422" do
309
+ let(:port) { 36422 }
310
+ let(:ip_proto) { :sctp }
311
+
312
+ it "must default the ip_proto :sctp" do
313
+ expect(subject.protocol).to eq(ip_proto)
314
+ end
315
+ end
316
+
317
+ context "when the port is 36412" do
318
+ let(:port) { 36412 }
319
+ let(:ip_proto) { :sctp }
320
+
321
+ it "must default the ip_proto :sctp" do
322
+ expect(subject.protocol).to eq(ip_proto)
323
+ end
324
+ end
325
+
326
+ context "when the port is 2905" do
327
+ let(:port) { 2905 }
328
+ let(:ip_proto) { :sctp }
329
+
330
+ it "must default the ip_proto :sctp" do
331
+ expect(subject.protocol).to eq(ip_proto)
332
+ end
333
+ end
334
+
335
+ it "must default the ip_proto to :tcp" do
336
+ expect(subject.protocol).to eq(:tcp)
337
+ end
338
+
339
+ it "must decode the port field" do
340
+ expect(subject.port).to eq(port)
341
+ end
342
+
343
+ it "must decode the ttl field" do
344
+ expect(subject.ttl).to eq(ttl)
345
+ end
346
+
347
+ it "must decode the reason field" do
348
+ expect(subject.reason).to eq(reason)
349
+ end
350
+ end
351
+
352
+ describe ".parser_banner3" do
353
+ let(:timestamp) { 1629960470 }
354
+ let(:time) { Time.at(timestamp) }
355
+
356
+ let(:ipaddr) { IPAddr.new("1.2.3.4") }
357
+ let(:ip_uint) { ipaddr.to_i }
358
+
359
+ let(:port) { 1111 }
360
+
361
+ let(:app_proto) { :html_title }
362
+ let(:app_proto_uint) do
363
+ described_class::APP_PROTOCOLS.index(app_proto)
364
+ end
365
+
366
+ let(:payload) { "404 - Not Found" }
367
+
368
+ let(:buffer) do
369
+ p([timestamp, ip_uint, port, app_proto_uint, payload]).pack("L>L>S>S>A*")
370
+ end
371
+
372
+ subject { super().parse_banner3(buffer) }
373
+
374
+ it "must default #ip_proto to :tcp" do
375
+ expect(subject.protocol).to eq(:tcp)
376
+ end
377
+
378
+ it "must default #ttl to 0" do
379
+ expect(subject.ttl).to eq(0)
380
+ end
381
+
382
+ it "must decode the port field" do
383
+ expect(subject.port).to eq(port)
384
+ end
385
+
386
+ it "must decode the ip field" do
387
+ expect(subject.ip).to eq(ipaddr)
388
+ end
389
+
390
+ it "must decode the timestamp field" do
391
+ expect(subject.timestamp).to eq(time)
392
+ end
393
+
394
+ it "must decode the app_proto field" do
395
+ expect(subject.app_protocol).to eq(app_proto)
396
+ end
397
+
398
+ it "must decode the payload field" do
399
+ expect(subject.payload).to eq(payload)
400
+ end
401
+ end
402
+
403
+ describe ".parser_banner4" do
404
+ let(:timestamp) { 1629960470 }
405
+ let(:time) { Time.at(timestamp) }
406
+
407
+ let(:ipaddr) { IPAddr.new("1.2.3.4") }
408
+ let(:ip_uint) { ipaddr.to_i }
409
+
410
+ let(:ip_proto) { :tcp }
411
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
412
+
413
+ let(:port) { 1111 }
414
+
415
+ let(:app_proto) { :html_title }
416
+ let(:app_proto_uint) do
417
+ described_class::APP_PROTOCOLS.index(app_proto)
418
+ end
419
+
420
+ let(:payload) { "404 - Not Found" }
421
+
422
+ let(:buffer) do
423
+ [
424
+ timestamp, ip_uint, ip_proto_uint, port, app_proto_uint, payload
425
+ ].pack("L>L>CS>S>A*")
426
+ end
427
+
428
+ subject { super().parse_banner4(buffer) }
429
+
430
+ context "when the buffer length is less than 13" do
431
+ let(:buffer) { "A" * 12 }
432
+
433
+ it "must return nil" do
434
+ expect(subject).to be(nil)
435
+ end
436
+ end
437
+
438
+ it "must decode the ip_proto field" do
439
+ expect(subject.protocol).to eq(:tcp)
440
+ end
441
+
442
+ it "must default #ttl to 0" do
443
+ expect(subject.ttl).to eq(0)
444
+ end
445
+
446
+ it "must decode the port field" do
447
+ expect(subject.port).to eq(port)
448
+ end
449
+
450
+ it "must decode the ip field" do
451
+ expect(subject.ip).to eq(ipaddr)
452
+ end
453
+
454
+ it "must decode the timestamp field" do
455
+ expect(subject.timestamp).to eq(time)
456
+ end
457
+
458
+ it "must decode the app_proto field" do
459
+ expect(subject.app_protocol).to eq(app_proto)
460
+ end
461
+
462
+ it "must decode the payload field" do
463
+ expect(subject.payload).to eq(payload)
464
+ end
465
+ end
466
+
467
+ describe ".parse_status2" do
468
+ let(:timestamp) { 1629960470 }
469
+ let(:time) { Time.at(timestamp) }
470
+
471
+ let(:ipaddr) { IPAddr.new("1.2.3.4") }
472
+ let(:ip_uint) { ipaddr.to_i }
473
+
474
+ let(:ip_proto) { :tcp }
475
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
476
+
477
+ let(:port) { 1111 }
478
+
479
+ let(:ttl) { 54 }
480
+
481
+ let(:reason) { [:syn, :ack] }
482
+ let(:reason_uint) { 0x02 | 0x10 }
483
+
484
+ let(:buffer) do
485
+ [
486
+ timestamp, ip_uint, ip_proto_uint, port, reason_uint, ttl
487
+ ].pack("L>L>CS>CC")
488
+ end
489
+
490
+ let(:status) { :open }
491
+
492
+ subject { super().parse_status2(buffer,status) }
493
+
494
+ context "when the buffer length is less than 13" do
495
+ let(:buffer) { "A" * 12 }
496
+
497
+ it "must return nil" do
498
+ expect(subject).to be(nil)
499
+ end
500
+ end
501
+
502
+ it "must decode the timestamp field" do
503
+ expect(subject.timestamp).to eq(time)
504
+ end
505
+
506
+ it "must set #status" do
507
+ expect(subject.status).to eq(status)
508
+ end
509
+
510
+ it "must decode the ip field" do
511
+ expect(subject.ip).to eq(ipaddr)
512
+ end
513
+
514
+ it "must decode the ip_proto field" do
515
+ expect(subject.protocol).to eq(ip_proto)
516
+ end
517
+
518
+ it "must decode the port field" do
519
+ expect(subject.port).to eq(port)
520
+ end
521
+
522
+ it "must decode the ttl field" do
523
+ expect(subject.ttl).to eq(ttl)
524
+ end
525
+
526
+ it "must decode the reason field" do
527
+ expect(subject.reason).to eq(reason)
528
+ end
529
+ end
530
+
531
+ describe ".parser_banner9" do
532
+ let(:timestamp) { 1629960470 }
533
+ let(:time) { Time.at(timestamp) }
534
+
535
+ let(:ipaddr) { IPAddr.new("1.2.3.4") }
536
+ let(:ip_uint) { ipaddr.to_i }
537
+
538
+ let(:ip_proto) { :tcp }
539
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
540
+
541
+ let(:port) { 1111 }
542
+
543
+ let(:app_proto) { :html_title }
544
+ let(:app_proto_uint) do
545
+ described_class::APP_PROTOCOLS.index(app_proto)
546
+ end
547
+
548
+ let(:ttl) { 54 }
549
+
550
+ let(:payload) { "404 - Not Found" }
551
+
552
+ let(:buffer) do
553
+ [
554
+ timestamp, ip_uint, ip_proto_uint, port, app_proto_uint, ttl, payload
555
+ ].pack("L>L>CS>S>CA*")
556
+ end
557
+
558
+ subject { super().parse_banner9(buffer) }
559
+
560
+ context "when the buffer length is less than 14" do
561
+ let(:buffer) { "A" * 13 }
562
+
563
+ it "must return nil" do
564
+ expect(subject).to be(nil)
565
+ end
566
+ end
567
+
568
+ it "must decode the ip_proto field" do
569
+ expect(subject.protocol).to eq(:tcp)
570
+ end
571
+
572
+ it "must decode the ttl field" do
573
+ expect(subject.ttl).to eq(ttl)
574
+ end
575
+
576
+ it "must decode the port field" do
577
+ expect(subject.port).to eq(port)
578
+ end
579
+
580
+ it "must decode the ip field" do
581
+ expect(subject.ip).to eq(ipaddr)
582
+ end
583
+
584
+ it "must decode the timestamp field" do
585
+ expect(subject.timestamp).to eq(time)
586
+ end
587
+
588
+ it "must decode the app_proto field" do
589
+ expect(subject.app_protocol).to eq(app_proto)
590
+ end
591
+
592
+ it "must decode the payload field" do
593
+ expect(subject.payload).to eq(payload)
594
+ end
595
+ end
596
+
597
+ describe ".parse_status6" do
598
+ let(:timestamp) { 1629960470 }
599
+ let(:time) { Time.at(timestamp) }
600
+
601
+ let(:ipaddr) { IPAddr.new("2606:2800:220:1:248:1893:25c8:1946") }
602
+ let(:ip_uint) { ipaddr.to_i }
603
+ let(:ipv6_hi) { (ip_uint & (0xffffffff_ffffffff << 64)) >> 64 }
604
+ let(:ipv6_lo) { (ip_uint & 0xffffffff_ffffffff) }
605
+
606
+ let(:ip_version) { 6 }
607
+
608
+ let(:ip_proto) { :tcp }
609
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
610
+
611
+ let(:port) { 1111 }
612
+
613
+ let(:ttl) { 54 }
614
+
615
+ let(:reason) { [:syn, :ack] }
616
+ let(:reason_uint) { 0x02 | 0x10 }
617
+
618
+ let(:buffer) do
619
+ [
620
+ timestamp, ip_proto_uint, port, reason_uint, ttl, ip_version, ipv6_hi, ipv6_lo
621
+ ].pack("L>CS>CCCQ>Q>")
622
+ end
623
+
624
+ let(:status) { :open }
625
+
626
+ subject { super().parse_status6(buffer,status) }
627
+
628
+ context "if the ip_version is not 6" do
629
+ let(:ip_version) { 9 }
630
+
631
+ it do
632
+ expect {
633
+ described_class.parse_status6(buffer,status)
634
+ }.to raise_error(described_class::CorruptedFile,"expected ip_version to be 6: #{ip_version.inspect}")
635
+ end
636
+ end
637
+
638
+ it "must decode the timestamp field" do
639
+ expect(subject.timestamp).to eq(time)
640
+ end
641
+
642
+ it "must set #status" do
643
+ expect(subject.status).to eq(status)
644
+ end
645
+
646
+ it "must decode the ip field" do
647
+ expect(subject.ip).to eq(ipaddr)
648
+ end
649
+
650
+ it "must decode the ip_proto field" do
651
+ expect(subject.protocol).to eq(ip_proto)
652
+ end
653
+
654
+ it "must decode the port field" do
655
+ expect(subject.port).to eq(port)
656
+ end
657
+
658
+ it "must decode the ttl field" do
659
+ expect(subject.ttl).to eq(ttl)
660
+ end
661
+
662
+ it "must decode the reason field" do
663
+ expect(subject.reason).to eq(reason)
664
+ end
665
+ end
666
+
667
+ describe ".parser_banner6" do
668
+ let(:timestamp) { 1629960470 }
669
+ let(:time) { Time.at(timestamp) }
670
+
671
+ let(:ipaddr) { IPAddr.new("2606:2800:220:1:248:1893:25c8:1946") }
672
+ let(:ip_uint) { ipaddr.to_i }
673
+ let(:ipv6_hi) { (ip_uint & (0xffffffff_ffffffff << 64)) >> 64 }
674
+ let(:ipv6_lo) { (ip_uint & 0xffffffff_ffffffff) }
675
+
676
+ let(:ip_version) { 6 }
677
+
678
+ let(:ip_proto) { :tcp }
679
+ let(:ip_proto_uint) { described_class::IP_PROTOCOLS.invert[:tcp] }
680
+
681
+ let(:port) { 1111 }
682
+
683
+ let(:app_proto) { :html_title }
684
+ let(:app_proto_uint) do
685
+ described_class::APP_PROTOCOLS.index(app_proto)
686
+ end
687
+
688
+ let(:ttl) { 54 }
689
+
690
+ let(:payload) { "404 - Not Found" }
691
+
692
+ let(:buffer) do
693
+ [
694
+ timestamp, ip_proto_uint, port, app_proto_uint, ttl, ip_version, ipv6_hi, ipv6_lo, payload
695
+ ].pack("L>CS>S>CCQ>Q>A*")
696
+ end
697
+
698
+ subject { super().parse_banner6(buffer) }
699
+
700
+ it "must decode the ip_proto field" do
701
+ expect(subject.protocol).to eq(:tcp)
702
+ end
703
+
704
+ it "must decode the ttl field" do
705
+ expect(subject.ttl).to eq(ttl)
706
+ end
707
+
708
+ it "must decode the port field" do
709
+ expect(subject.port).to eq(port)
710
+ end
711
+
712
+ it "must decode the ip field" do
713
+ expect(subject.ip).to eq(ipaddr)
714
+ end
715
+
716
+ it "must decode the timestamp field" do
717
+ expect(subject.timestamp).to eq(time)
718
+ end
719
+
720
+ it "must decode the app_proto field" do
721
+ expect(subject.app_protocol).to eq(app_proto)
722
+ end
723
+
724
+ it "must decode the payload field" do
725
+ expect(subject.payload).to eq(payload)
726
+ end
727
+ end
224
728
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-masscan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-31 00:00:00.000000000 Z
11
+ date: 2021-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rprogram