ruby-masscan 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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