cisco_acl_intp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +3 -0
  6. data/.yardopts +4 -0
  7. data/Gemfile +19 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +132 -0
  10. data/Rakefile +78 -0
  11. data/acl_examples/err-acl.txt +49 -0
  12. data/acl_examples/named-ext-acl.txt +12 -0
  13. data/acl_examples/named-std-acl.txt +6 -0
  14. data/acl_examples/numd-acl.txt +21 -0
  15. data/cisco_acl_intp.gemspec +31 -0
  16. data/lib/cisco_acl_intp/ace.rb +432 -0
  17. data/lib/cisco_acl_intp/ace_ip.rb +136 -0
  18. data/lib/cisco_acl_intp/ace_other_qualifiers.rb +102 -0
  19. data/lib/cisco_acl_intp/ace_port.rb +146 -0
  20. data/lib/cisco_acl_intp/ace_proto.rb +319 -0
  21. data/lib/cisco_acl_intp/ace_srcdst.rb +114 -0
  22. data/lib/cisco_acl_intp/ace_tcp_flags.rb +65 -0
  23. data/lib/cisco_acl_intp/acl.rb +272 -0
  24. data/lib/cisco_acl_intp/acl_base.rb +111 -0
  25. data/lib/cisco_acl_intp/parser.rb +3509 -0
  26. data/lib/cisco_acl_intp/parser.ry +1397 -0
  27. data/lib/cisco_acl_intp/scanner.rb +176 -0
  28. data/lib/cisco_acl_intp/scanner_special_token_handler.rb +66 -0
  29. data/lib/cisco_acl_intp/version.rb +5 -0
  30. data/lib/cisco_acl_intp.rb +9 -0
  31. data/spec/cisco_acl_intp/ace_ip_spec.rb +111 -0
  32. data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +63 -0
  33. data/spec/cisco_acl_intp/ace_port_spec.rb +214 -0
  34. data/spec/cisco_acl_intp/ace_proto_spec.rb +200 -0
  35. data/spec/cisco_acl_intp/ace_spec.rb +605 -0
  36. data/spec/cisco_acl_intp/ace_srcdst_spec.rb +296 -0
  37. data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +38 -0
  38. data/spec/cisco_acl_intp/acl_spec.rb +523 -0
  39. data/spec/cisco_acl_intp/cisco_acl_intp_spec.rb +7 -0
  40. data/spec/cisco_acl_intp/parser_spec.rb +53 -0
  41. data/spec/cisco_acl_intp/scanner_spec.rb +122 -0
  42. data/spec/conf/extacl_objgrp_token_seq.yml +36 -0
  43. data/spec/conf/extacl_token_seq.yml +88 -0
  44. data/spec/conf/extended_acl.yml +226 -0
  45. data/spec/conf/scanner_spec_data.yml +120 -0
  46. data/spec/conf/single_tokens.yml +235 -0
  47. data/spec/conf/stdacl_token_seq.yml +8 -0
  48. data/spec/conf/tokens1.yml +158 -0
  49. data/spec/conf/tokens2.yml +206 -0
  50. data/spec/parser_fullfill_patterns.rb +145 -0
  51. data/spec/spec_helper.rb +54 -0
  52. data/tools/check_acl.rb +48 -0
  53. metadata +159 -0
@@ -0,0 +1,605 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe StandardAce do
5
+ describe '#to_s' do
6
+ context 'Normal case' do
7
+
8
+ it 'should be permit action and set ip/wildcard' do
9
+ sa = StandardAce.new(
10
+ action: 'permit',
11
+ src: {
12
+ ipaddr: '192.168.15.15',
13
+ wildcard: '0.0.7.6'
14
+ }
15
+ )
16
+ sa.to_s.should be_aclstr('permit 192.168.8.9 0.0.7.6')
17
+ end
18
+
19
+ it 'should be deny action and set ip/wildcard' do
20
+ sa = StandardAce.new(
21
+ action: 'deny',
22
+ src: {
23
+ ipaddr: '192.168.15.15',
24
+ wildcard: '0.0.0.127'
25
+ }
26
+ )
27
+ sa.to_s.should be_aclstr('deny 192.168.15.0 0.0.0.127')
28
+ end
29
+
30
+ it 'should be able set with AceSrcDstSpec object' do
31
+ asds = AceSrcDstSpec.new(
32
+ ipaddr: '192.168.3.144',
33
+ wildcard: '0.0.0.127'
34
+ )
35
+ sa = StandardAce.new(
36
+ action: 'permit',
37
+ src: asds
38
+ )
39
+ sa.to_s.should be_aclstr('permit 192.168.3.128 0.0.0.127')
40
+ end
41
+
42
+ end
43
+
44
+ context 'Argument error case' do
45
+
46
+ it 'should be rased exception when :action not specified' do
47
+ lambda do
48
+ StandardAce.new(
49
+ src: {
50
+ ipaddr: '192.168.3.3',
51
+ wildcard: '0.0.0.127'
52
+ }
53
+ )
54
+ end.should raise_error(AclArgumentError)
55
+ end
56
+
57
+ end
58
+ end
59
+
60
+ describe '#matches' do
61
+ before do
62
+ @sa = StandardAce.new(
63
+ action: 'permit',
64
+ src: {
65
+ ipaddr: '192.168.15.15',
66
+ wildcard: '0.0.7.6'
67
+ }
68
+ )
69
+ @ip_match = '192.168.9.11'
70
+ @ip_unmatch = '192.168.9.12'
71
+ end
72
+
73
+ it 'shoud be true with match ip addr' do
74
+ @sa.matches?(
75
+ src_ip: @ip_match
76
+ ).should be_true
77
+ end
78
+
79
+ it 'should be false with unmatch ip addr' do
80
+ @sa.matches?(
81
+ src_ip: @ip_unmatch
82
+ ).should be_false
83
+ end
84
+
85
+ it 'should raise error when not specified ip_src' do
86
+ lambda do
87
+ @sa.matches?(
88
+ dst_ip: @ip_match)
89
+ end.should raise_error(AclArgumentError)
90
+ end
91
+
92
+ end
93
+ end
94
+
95
+ describe ExtendedAce do
96
+ describe '#to_s' do
97
+ context 'Normal case' do
98
+ before do
99
+ @src = AceSrcDstSpec.new(
100
+ ipaddr: '192.168.15.15',
101
+ wildcard: '0.0.7.6'
102
+ )
103
+ @dst = AceSrcDstSpec.new(
104
+ ipaddr: '192.168.30.3',
105
+ wildcard: '0.0.0.0',
106
+ operator: 'range',
107
+ begin_port: AceTcpProtoSpec.new(
108
+ number: 1_024
109
+ ),
110
+ end_port: AceTcpProtoSpec.new(
111
+ number: 65_535
112
+ )
113
+ )
114
+ end
115
+
116
+ it 'should be protocol tcp, action permit' do
117
+ ea = ExtendedAce.new(
118
+ action: 'permit',
119
+ protocol: 'tcp',
120
+ src: @src,
121
+ dst: @dst
122
+ )
123
+ ea.to_s.should be_aclstr(
124
+ 'permit tcp 192.168.8.9 0.0.7.6 host 192.168.30.3 range 1024 65535'
125
+ )
126
+ end
127
+
128
+ it 'should be protocol tcp, action deny' do
129
+ ea = ExtendedAce.new(
130
+ action: 'deny',
131
+ protocol: 'tcp',
132
+ src: @src,
133
+ dst: @dst
134
+ )
135
+ ea.to_s.should be_aclstr(
136
+ 'deny tcp 192.168.8.9 0.0.7.6 host 192.168.30.3 range 1024 65535'
137
+ )
138
+ end
139
+
140
+ end
141
+
142
+ context 'Argument error case' do
143
+ before do
144
+ @src = AceSrcDstSpec.new(
145
+ ipaddr: '192.168.15.15',
146
+ wildcard: '0.0.7.6'
147
+ )
148
+ @dst = AceSrcDstSpec.new(
149
+ ipaddr: '192.168.30.3',
150
+ wildcard: '0.0.0.0',
151
+ operator: 'range',
152
+ begin_port: AceTcpProtoSpec.new(
153
+ number: 1_024
154
+ ),
155
+ end_port: AceTcpProtoSpec.new(
156
+ number: 65_535
157
+ )
158
+ )
159
+ end
160
+
161
+ it 'should be rased exception when :action not specified' do
162
+ lambda do
163
+ ExtendedAce.new(
164
+ protocol: 'tcp',
165
+ src: @src,
166
+ dst: @dst
167
+ )
168
+ end.should raise_error(AclArgumentError)
169
+ end
170
+
171
+ it 'should be rased exception when :protocol not specified' do
172
+ lambda do
173
+ ExtendedAce.new(
174
+ action: 'deny',
175
+ src: @src,
176
+ dst: @dst
177
+ )
178
+ end.should raise_error(AclArgumentError)
179
+ end
180
+
181
+ it 'should be rased exception when :src not specified' do
182
+ lambda do
183
+ ExtendedAce.new(
184
+ action: 'deny',
185
+ protocol: 'tcp',
186
+ dst: @dst
187
+ )
188
+ end.should raise_error(AclArgumentError)
189
+ end
190
+
191
+ it 'should be rased exception when :dst not specified' do
192
+ lambda do
193
+ ExtendedAce.new(
194
+ action: 'deny',
195
+ protocol: 'tcp',
196
+ src: @src
197
+ )
198
+ end.should raise_error(AclArgumentError)
199
+ end
200
+
201
+ end
202
+ end
203
+
204
+ describe '#matches?' do
205
+ context 'tcp src/dst ip/port full spec test' do
206
+ before do
207
+ src = AceSrcDstSpec.new(
208
+ ipaddr: '192.168.15.15',
209
+ wildcard: '0.0.7.6',
210
+ operator: 'gt',
211
+ port: AceTcpProtoSpec.new(
212
+ number: 32_767
213
+ )
214
+ )
215
+ dst = AceSrcDstSpec.new(
216
+ ipaddr: '192.168.30.3',
217
+ wildcard: '0.0.0.0',
218
+ operator: 'range',
219
+ begin_port: AceTcpProtoSpec.new(
220
+ number: 1_024
221
+ ),
222
+ end_port: AceTcpProtoSpec.new(
223
+ number: 65_535
224
+ )
225
+ )
226
+ @ea = ExtendedAce.new(
227
+ action: 'permit',
228
+ protocol: 'tcp',
229
+ src: src,
230
+ dst: dst
231
+ )
232
+ end # before
233
+
234
+ ## generate test pattern data
235
+ data_table = {
236
+ protocol_match: 'tcp',
237
+ protocol_unmatch: 'udp',
238
+ src_ip_match: '192.168.9.11',
239
+ src_ip_unmatch: '192.168.9.12',
240
+ src_port_match: 32_768,
241
+ src_port_unmatch: 8_080,
242
+ dst_ip_match: '192.168.30.3',
243
+ dst_ip_unmatch: '192.168.30.4',
244
+ dst_port_match: 3_366,
245
+ dst_port_unmatch: 100
246
+ }
247
+
248
+ bit = 5
249
+ test_data = [
250
+ :dst_port,
251
+ :dst_ip,
252
+ :src_port,
253
+ :src_ip,
254
+ :protocol
255
+ ]
256
+
257
+ tests = []
258
+ (0..(2**bit - 1)).each do |num|
259
+ opts = {}
260
+ flag = 1
261
+ (0...bit).each do |b|
262
+ pstr = ((num & flag) == 0 ? '_match' : '_unmatch')
263
+ key = test_data[b].to_s.concat(pstr)
264
+ opts[test_data[b]] = data_table[key.to_sym]
265
+ flag = flag << 1
266
+ end
267
+ tests.push(
268
+ opts: opts,
269
+ res: num > 0 ? false : true
270
+ )
271
+ end
272
+
273
+ tests.each do |each|
274
+ # run test
275
+ it "should be #{each[:res]}, \
276
+ when #{each[:opts][:protocol]};\
277
+ #{each[:opts][:src_ip]}/#{each[:opts][:src_port]} > \
278
+ #{each[:opts][:dst_ip]}/#{each[:opts][:dst_port]}" do
279
+ if each[:res]
280
+ @ea.matches?(each[:opts]).should be_true
281
+ else
282
+ @ea.matches?(each[:opts]).should be_false
283
+ end
284
+ end # it
285
+ end # tests.each
286
+
287
+ end # context full spec test
288
+
289
+ context 'ANY ip/port port exists case' do
290
+ before do
291
+ ip_any = AceIpSpec.new(
292
+ ipaddr: '0.0.0.0',
293
+ wildcard: '255.255.255.255'
294
+ )
295
+ port_any = AcePortSpec.new(
296
+ operator: 'any'
297
+ )
298
+ src_ip = AceIpSpec.new(
299
+ ipaddr: '192.168.15.15',
300
+ wildcard: '0.0.7.6'
301
+ )
302
+ src_port = AcePortSpec.new(
303
+ operator: 'gt',
304
+ port: AceTcpProtoSpec.new(
305
+ number: 32_767
306
+ )
307
+ )
308
+
309
+ dst_ip = AceIpSpec.new(
310
+ ipaddr: '192.168.30.3',
311
+ wildcard: '0.0.0.0'
312
+ )
313
+ dst_port = AcePortSpec.new(
314
+ operator: 'range',
315
+ begin_port: AceTcpProtoSpec.new(
316
+ number: 1_024
317
+ ),
318
+ end_port: AceTcpProtoSpec.new(
319
+ number: 65_535
320
+ )
321
+ )
322
+
323
+ @src0 = AceSrcDstSpec.new(
324
+ ip_spec: src_ip,
325
+ port_spec: src_port
326
+ )
327
+ @src1 = AceSrcDstSpec.new(
328
+ ip_spec: ip_any,
329
+ port_spec: src_port
330
+ )
331
+ @src2 = AceSrcDstSpec.new(
332
+ ip_spec: src_ip,
333
+ port_spec: port_any
334
+ )
335
+ @dst0 = AceSrcDstSpec.new(
336
+ ip_spec: dst_ip,
337
+ port_spec: dst_port
338
+ )
339
+ @dst1 = AceSrcDstSpec.new(
340
+ ip_spec: ip_any,
341
+ port_spec: dst_port
342
+ )
343
+ @dst2 = AceSrcDstSpec.new(
344
+ ip_spec: dst_ip,
345
+ port_spec: port_any
346
+ )
347
+
348
+ @src_ip_match = '192.168.9.11'
349
+ @src_ip_unmatch = '192.168.9.12'
350
+ @src_port_match = 32_768
351
+ @src_port_unmatch = 8_080
352
+ @dst_ip_match = '192.168.30.3'
353
+ @dst_ip_unmatch = '192.168.30.4'
354
+ @dst_port_match = 3_366
355
+ @dst_port_unmatch = 100
356
+ end
357
+
358
+ it 'should be true when any source ip' do
359
+ ea = ExtendedAce.new(
360
+ action: 'permit',
361
+ protocol: 'tcp',
362
+ src: @src1,
363
+ dst: @dst0
364
+ )
365
+ ea.matches?(
366
+ protocol: 'tcp',
367
+ src_ip: @src_ip_match,
368
+ src_port: @src_port_match,
369
+ dst_ip: @dst_ip_match,
370
+ dst_port: @dst_port_match
371
+ ).should be_true
372
+ ea.matches?(
373
+ protocol: 'tcp',
374
+ src_ip: @src_ip_unmatch,
375
+ src_port: @src_port_match,
376
+ dst_ip: @dst_ip_match,
377
+ dst_port: @dst_port_match
378
+ ).should be_true
379
+ end
380
+
381
+ it 'should be false when any source ip and unmatch port' do
382
+ ea = ExtendedAce.new(
383
+ action: 'permit',
384
+ protocol: 'tcp',
385
+ src: @src1,
386
+ dst: @dst0
387
+ )
388
+ ea.matches?(
389
+ protocol: 'tcp',
390
+ src_ip: @src_ip_match,
391
+ src_port: @src_port_unmatch,
392
+ dst_ip: @dst_ip_match,
393
+ dst_port: @dst_port_match
394
+ ).should be_false
395
+ ea.matches?(
396
+ protocol: 'tcp',
397
+ src_ip: @src_ip_unmatch,
398
+ src_port: @src_port_unmatch,
399
+ dst_ip: @dst_ip_match,
400
+ dst_port: @dst_port_match
401
+ ).should be_false
402
+ end
403
+
404
+ it 'should be true when any source port' do
405
+ ea = ExtendedAce.new(
406
+ action: 'permit',
407
+ protocol: 'tcp',
408
+ src: @src2,
409
+ dst: @dst0
410
+ )
411
+ ea.matches?(
412
+ protocol: 'tcp',
413
+ src_ip: @src_ip_match,
414
+ src_port: @src_port_match,
415
+ dst_ip: @dst_ip_match,
416
+ dst_port: @dst_port_match
417
+ ).should be_true
418
+ ea.matches?(
419
+ protocol: 'tcp',
420
+ src_ip: @src_ip_match,
421
+ src_port: @src_port_unmatch,
422
+ dst_ip: @dst_ip_match,
423
+ dst_port: @dst_port_match
424
+ ).should be_true
425
+ end
426
+
427
+ it 'should be false when any source port and unmatch ip' do
428
+ ea = ExtendedAce.new(
429
+ action: 'permit',
430
+ protocol: 'tcp',
431
+ src: @src2,
432
+ dst: @dst0
433
+ )
434
+ ea.matches?(
435
+ protocol: 'tcp',
436
+ src_ip: @src_ip_unmatch,
437
+ src_port: @src_port_match,
438
+ dst_ip: @dst_ip_match,
439
+ dst_port: @dst_port_match
440
+ ).should be_false
441
+ ea.matches?(
442
+ protocol: 'tcp',
443
+ src_ip: @src_ip_unmatch,
444
+ src_port: @src_port_unmatch,
445
+ dst_ip: @dst_ip_match,
446
+ dst_port: @dst_port_match
447
+ ).should be_false
448
+ end
449
+
450
+ it 'should be true when any destination ip' do
451
+ ea = ExtendedAce.new(
452
+ action: 'permit',
453
+ protocol: 'tcp',
454
+ src: @src0,
455
+ dst: @dst1
456
+ )
457
+ ea.matches?(
458
+ protocol: 'tcp',
459
+ src_ip: @src_ip_match,
460
+ src_port: @src_port_match,
461
+ dst_ip: @dst_ip_match,
462
+ dst_port: @dst_port_match
463
+ ).should be_true
464
+ ea.matches?(
465
+ protocol: 'tcp',
466
+ src_ip: @src_ip_match,
467
+ src_port: @src_port_match,
468
+ dst_ip: @dst_ip_unmatch,
469
+ dst_port: @dst_port_match
470
+ ).should be_true
471
+ end
472
+
473
+ it 'should be false when any destination ip and unmatch port' do
474
+ ea = ExtendedAce.new(
475
+ action: 'permit',
476
+ protocol: 'tcp',
477
+ src: @src0,
478
+ dst: @dst1
479
+ )
480
+ ea.matches?(
481
+ protocol: 'tcp',
482
+ src_ip: @src_ip_match,
483
+ src_port: @src_port_match,
484
+ dst_ip: @dst_ip_match,
485
+ dst_port: @dst_port_unmatch
486
+ ).should be_false
487
+ ea.matches?(
488
+ protocol: 'tcp',
489
+ src_ip: @src_ip_match,
490
+ src_port: @src_port_match,
491
+ dst_ip: @dst_ip_unmatch,
492
+ dst_port: @dst_port_unmatch
493
+ ).should be_false
494
+ end
495
+
496
+ it 'should be true when any destination port' do
497
+ ea = ExtendedAce.new(
498
+ action: 'permit',
499
+ protocol: 'tcp',
500
+ src: @src0,
501
+ dst: @dst2
502
+ )
503
+ ea.matches?(
504
+ protocol: 'tcp',
505
+ src_ip: @src_ip_match,
506
+ src_port: @src_port_match,
507
+ dst_ip: @dst_ip_match,
508
+ dst_port: @dst_port_match
509
+ ).should be_true
510
+ ea.matches?(
511
+ protocol: 'tcp',
512
+ src_ip: @src_ip_match,
513
+ src_port: @src_port_match,
514
+ dst_ip: @dst_ip_match,
515
+ dst_port: @dst_port_unmatch
516
+ ).should be_true
517
+ end
518
+
519
+ it 'should be false when any destination port and unmatch ip' do
520
+ ea = ExtendedAce.new(
521
+ action: 'permit',
522
+ protocol: 'tcp',
523
+ src: @src0,
524
+ dst: @dst2
525
+ )
526
+ ea.matches?(
527
+ protocol: 'tcp',
528
+ src_ip: @src_ip_match,
529
+ src_port: @src_port_match,
530
+ dst_ip: @dst_ip_unmatch,
531
+ dst_port: @dst_port_match
532
+ ).should be_false
533
+ ea.matches?(
534
+ protocol: 'tcp',
535
+ src_ip: @src_ip_match,
536
+ src_port: @src_port_match,
537
+ dst_ip: @dst_ip_unmatch,
538
+ dst_port: @dst_port_unmatch
539
+ ).should be_false
540
+ end
541
+ end # context exists any ip/port
542
+
543
+ end # describe matches?
544
+
545
+ end # describe ExtendedAce
546
+
547
+ describe RemarkAce do
548
+ describe '#to_s' do
549
+ it 'should be remark string' do
550
+ rmk = RemarkAce.new(' foo-bar _ baz @@ COMMENT')
551
+ rmk.to_s.should eq ' remark foo-bar _ baz @@ COMMENT'
552
+ end
553
+ end
554
+ describe '#matches?' do
555
+ it 'should be always false' do
556
+ rmk = RemarkAce.new('asdfjklj;')
557
+ rmk.matches?(
558
+ src_ip: '192.168.4.4',
559
+ dst_ip: '172.30.240.33'
560
+ ).should be_false
561
+ # with empty argments
562
+ rmk.matches?.should be_false
563
+ end
564
+ end
565
+ end
566
+
567
+ describe EvaluateAce do
568
+ describe '#to_s' do
569
+ it 'should be evaluate term' do
570
+ evl = EvaluateAce.new(
571
+ recursive_name: 'foobar_baz'
572
+ )
573
+ evl.to_s.should be_aclstr('evaluate foobar_baz')
574
+ end
575
+
576
+ it 'raise error if not specified recursive name' do
577
+ lambda do
578
+ EvaluateAce.new(
579
+ number: 30
580
+ )
581
+ end.should raise_error(AclArgumentError)
582
+ end
583
+ end
584
+ describe '#matches?' do
585
+ it 'should be always false' do
586
+ pending('not implemented yet')
587
+
588
+ evl = EvaluateAce.new(
589
+ recursive_name: 'asdf_0-98'
590
+ )
591
+ evl.matches?(
592
+ src_ip: '192.168.4.4',
593
+ dst_ip: '172.30.240.33'
594
+ ).should be_false
595
+ # with empty argments
596
+ evl.matches?.should be_false
597
+ end
598
+ end
599
+ end
600
+
601
+ ### Local variables:
602
+ ### mode: Ruby
603
+ ### coding: utf-8-unix
604
+ ### indent-tabs-mode: nil
605
+ ### End: