Skip to content

Commit cffb0f8

Browse files
committed
Merge pull request #35 from jvazquez-r7/review_6030
Merge code changes from Juan
2 parents 418374b + 5862a66 commit cffb0f8

File tree

2 files changed

+63
-46
lines changed

2 files changed

+63
-46
lines changed

spec/tools/msu_finder_spec.rb

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
require 'nokogiri'
44
require 'uri'
55

6-
describe MicrosoftPatch do
6+
describe MicrosoftPatchFinder do
77

88
before(:each) do
99
cli = Rex::Proto::Http::Client.new('127.0.0.1')
@@ -14,18 +14,18 @@
1414
end
1515

1616
let(:technet) do
17-
MicrosoftPatch::SiteInfo::TECHNET
17+
MicrosoftPatchFinder::SiteInfo::TECHNET
1818
end
1919

2020
let(:microsoft) do
21-
MicrosoftPatch::SiteInfo::MICROSOFT
21+
MicrosoftPatchFinder::SiteInfo::MICROSOFT
2222
end
2323

2424
let(:googleapis) do
25-
MicrosoftPatch::SiteInfo::GOOGLEAPIS
25+
MicrosoftPatchFinder::SiteInfo::GOOGLEAPIS
2626
end
2727

28-
describe MicrosoftPatch::SiteInfo do
28+
describe MicrosoftPatchFinder::SiteInfo do
2929
context 'Constants' do
3030
context 'TECHNET' do
3131
it 'returns 157.56.148.23 as the IP' do
@@ -59,7 +59,7 @@
5959
end
6060
end
6161

62-
describe MicrosoftPatch::Base do
62+
describe MicrosoftPatchFinder::Helper do
6363

6464
def get_stdout(&block)
6565
out = $stdout
@@ -84,7 +84,9 @@ def get_stderr(&block)
8484
end
8585

8686
subject do
87-
MicrosoftPatch::Base.new
87+
mod = Object.new
88+
mod.extend MicrosoftPatchFinder::Helper
89+
mod
8890
end
8991

9092
describe '#print_debug' do
@@ -119,14 +121,14 @@ def get_stderr(&block)
119121
describe '#send_http_request' do
120122
it 'returns a Rex::Proto::Http::Response object' do
121123
allow(subject).to receive(:print_debug)
122-
res = subject.send_http_request(MicrosoftPatch::SiteInfo::TECHNET)
124+
res = subject.send_http_request(MicrosoftPatchFinder::SiteInfo::TECHNET)
123125
expect(res).to be_kind_of(Rex::Proto::Http::Response)
124126
end
125127
end
126128

127129
end
128130

129-
describe MicrosoftPatch::PatchLinkCollector do
131+
describe MicrosoftPatchFinder::PatchLinkCollector do
130132

131133
let(:ms15_100_html) do
132134
%Q|
@@ -199,7 +201,7 @@ def get_stderr(&block)
199201
end
200202

201203
subject do
202-
MicrosoftPatch::PatchLinkCollector.new
204+
MicrosoftPatchFinder::PatchLinkCollector.new
203205
end
204206

205207
before(:each) do
@@ -361,15 +363,15 @@ def get_stderr(&block)
361363

362364
end
363365

364-
describe MicrosoftPatch::TechnetMsbSearch do
366+
describe MicrosoftPatchFinder::TechnetMsbSearch do
365367

366368
subject do
367-
MicrosoftPatch::TechnetMsbSearch.new
369+
MicrosoftPatchFinder::TechnetMsbSearch.new
368370
end
369371

370372
before(:each) do
371-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:print_debug)
372-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:send_http_request) { |info_obj, info_opts, opts|
373+
allow_any_instance_of(MicrosoftPatchFinder::TechnetMsbSearch).to receive(:print_debug)
374+
allow_any_instance_of(MicrosoftPatchFinder::TechnetMsbSearch).to receive(:send_http_request) { |info_obj, info_opts, opts|
373375
case opts['uri']
374376
when /\/en\-us\/security\/bulletin\/dn602597\.aspx/
375377
html = %Q|
@@ -465,10 +467,10 @@ def get_stderr(&block)
465467

466468
end
467469

468-
describe MicrosoftPatch::GoogleMsbSearch do
470+
describe MicrosoftPatchFinder::GoogleMsbSearch do
469471

470472
subject do
471-
MicrosoftPatch::GoogleMsbSearch.new
473+
MicrosoftPatchFinder::GoogleMsbSearch.new
472474
end
473475

474476
let(:json_data) do
@@ -555,8 +557,8 @@ def get_stderr(&block)
555557
end
556558

557559
before(:each) do
558-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:print_debug)
559-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:send_http_request) { |info_obj, info_opts, opts|
560+
allow_any_instance_of(MicrosoftPatchFinder::GoogleMsbSearch).to receive(:print_debug)
561+
allow_any_instance_of(MicrosoftPatchFinder::GoogleMsbSearch).to receive(:send_http_request) { |info_obj, info_opts, opts|
560562
res = Rex::Proto::Http::Response.new
561563
allow(res).to receive(:body).and_return(json_data)
562564
res
@@ -608,7 +610,7 @@ def get_stderr(&block)
608610

609611
end
610612

611-
describe MicrosoftPatch::Module do
613+
describe MicrosoftPatchFinder::Driver do
612614

613615
let(:msb) do
614616
'ms15-100'
@@ -620,17 +622,19 @@ def get_stderr(&block)
620622

621623
before(:each) do
622624
opts = { keyword: msb }
623-
allow(MicrosoftPatch::OptsConsole).to receive(:get_parsed_options).and_return(opts)
624-
allow_any_instance_of(MicrosoftPatch::PatchLinkCollector).to receive(:download_advisory).and_return(Rex::Proto::Http::Response.new)
625-
allow_any_instance_of(MicrosoftPatch::PatchLinkCollector).to receive(:get_details_aspx).and_return([expected_link])
626-
allow_any_instance_of(MicrosoftPatch::PatchLinkCollector).to receive(:get_download_page).and_return(Rex::Proto::Http::Response.new)
627-
allow_any_instance_of(MicrosoftPatch::PatchLinkCollector).to receive(:get_download_links).and_return([expected_link])
628-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:print_debug)
629-
allow_any_instance_of(MicrosoftPatch::Base).to receive(:print_error)
625+
allow(MicrosoftPatchFinder::OptsConsole).to receive(:get_parsed_options).and_return(opts)
626+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:download_advisory).and_return(Rex::Proto::Http::Response.new)
627+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_details_aspx).and_return([expected_link])
628+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_download_page).and_return(Rex::Proto::Http::Response.new)
629+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:get_download_links).and_return([expected_link])
630+
allow_any_instance_of(MicrosoftPatchFinder::Driver).to receive(:print_debug)
631+
allow_any_instance_of(MicrosoftPatchFinder::Driver).to receive(:print_error)
632+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:print_debug)
633+
allow_any_instance_of(MicrosoftPatchFinder::PatchLinkCollector).to receive(:print_error)
630634
end
631635

632636
subject do
633-
MicrosoftPatch::Module.new
637+
MicrosoftPatchFinder::Driver.new
634638
end
635639

636640
describe '#get_download_links' do
@@ -643,13 +647,13 @@ def get_stderr(&block)
643647

644648
describe '#google_search' do
645649
it 'returns search results' do
646-
skip('See rspec for MicrosoftPatch::GoogleMsbSearch#find_msb_numbers')
650+
skip('See rspec for MicrosoftPatchFinder::GoogleMsbSearch#find_msb_numbers')
647651
end
648652
end
649653

650654
describe '#technet_search' do
651655
it 'returns search results' do
652-
skip('See rspec for MicrosoftPatch::TechnetMsbSearch#find_msb_numbers')
656+
skip('See rspec for MicrosoftPatchFinder::TechnetMsbSearch#find_msb_numbers')
653657
end
654658
end
655659

tools/msu_finder.rb

100644100755
Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
require 'json'
2222
require 'optparse'
2323

24-
module MicrosoftPatch
24+
module MicrosoftPatchFinder
2525

2626
module SiteInfo
2727
TECHNET = {
@@ -40,8 +40,8 @@ module SiteInfo
4040
}
4141
end
4242

43-
# This class provides whatever other classes need.
44-
class Base
43+
# This provides whatever other classes need.
44+
module Helper
4545

4646
# Prints a debug message.
4747
#
@@ -77,7 +77,7 @@ def print_line(msg='')
7777

7878
# Sends an HTTP request with Rex.
7979
#
80-
# @param rhost [Hash] Information about the target host. Use MicrosoftPatch::SiteInfo.
80+
# @param rhost [Hash] Information about the target host. Use MicrosoftPatchFinder::SiteInfo.
8181
# @option rhost [String] :vhost
8282
# @option rhost [String] :ip IPv4 address
8383
# @param opts [Hash] Information about the Rex request.
@@ -114,7 +114,8 @@ def send_http_request(rhost, opts={})
114114

115115

116116
# Collects MSU download links from Technet.
117-
class PatchLinkCollector < Base
117+
class PatchLinkCollector
118+
include MicrosoftPatchFinder::Helper
118119

119120
# Returns a response of an advisory page.
120121
#
@@ -197,7 +198,7 @@ def get_details_aspx(res)
197198

198199
# Returns the redirected page.
199200
#
200-
# @param rhost [Hash] From MicrosoftPatch::SiteInfo
201+
# @param rhost [Hash] From MicrosoftPatchFinder::SiteInfo
201202
# @param res [Rex::Proto::Http::Response]
202203
# @return [Rex::Proto::Http::Response]
203204
def follow_redirect(rhost, res)
@@ -278,7 +279,9 @@ def is_valid_msb?(msb)
278279

279280

280281
# A class that searches advisories from Technet.
281-
class TechnetMsbSearch < Base
282+
class TechnetMsbSearch
283+
include MicrosoftPatchFinder::Helper
284+
282285
def initialize
283286
opts = {
284287
'method' => 'GET',
@@ -387,7 +390,9 @@ def get_product_dropdown_list
387390
attr_reader :firstpage
388391
end
389392

390-
class GoogleMsbSearch < Base
393+
class GoogleMsbSearch
394+
include MicrosoftPatchFinder::Helper
395+
391396
# API Doc:
392397
# https://developers.google.com/custom-search/json-api/v1/using_rest
393398
# Known bug:
@@ -430,7 +435,7 @@ def find_msb_numbers(keyword)
430435
end
431436
rescue RuntimeError => e
432437
print_error(e.message)
433-
return msb_numbers
438+
return msb_numbers.uniq
434439
end
435440

436441
msb_numbers.uniq
@@ -634,11 +639,12 @@ def self.get_parsed_options
634639
end
635640
end
636641

637-
class Module < Base
642+
class Driver
643+
include MicrosoftPatchFinder::Helper
638644

639645
def initialize
640646
begin
641-
@args = MicrosoftPatch::OptsConsole.get_parsed_options
647+
@args = MicrosoftPatchFinder::OptsConsole.get_parsed_options
642648
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
643649
print_error(e.message)
644650
exit
@@ -651,7 +657,7 @@ def initialize
651657
# @param regex [String] The regex pattern to use to collect specific download URLs.
652658
# @return [Array<String>] Download links
653659
def get_download_links(msb, regex=nil)
654-
msft = MicrosoftPatch::PatchLinkCollector.new
660+
msft = MicrosoftPatchFinder::PatchLinkCollector.new
655661

656662
unless msft.is_valid_msb?(msb)
657663
print_error "Not a valid MSB format."
@@ -695,19 +701,19 @@ def get_download_links(msb, regex=nil)
695701
# @param keyword [String] The keyword to search
696702
# @param api_key [String] Google API key
697703
# @param cx [String] Google Search Engine Key
698-
# @return [Array<String>] See MicrosoftPatch::GoogleMsbSearch#find_msb_numbers
704+
# @return [Array<String>] See MicrosoftPatchFinder::GoogleMsbSearch#find_msb_numbers
699705
def google_search(keyword, api_key, cx)
700-
search = MicrosoftPatch::GoogleMsbSearch.new(api_key: api_key, search_engine_id: cx)
706+
search = MicrosoftPatchFinder::GoogleMsbSearch.new(api_key: api_key, search_engine_id: cx)
701707
search.find_msb_numbers(keyword)
702708
end
703709

704710

705711
# Performs a search via Technet
706712
#
707713
# @param keyword [String] The keyword to search
708-
# @return [Array<String>] See MicrosoftPatch::TechnetMsbSearch#find_msb_numbers
714+
# @return [Array<String>] See MicrosoftPatchFinder::TechnetMsbSearch#find_msb_numbers
709715
def technet_search(keyword)
710-
search = MicrosoftPatch::TechnetMsbSearch.new
716+
search = MicrosoftPatchFinder::TechnetMsbSearch.new
711717
search.find_msb_numbers(keyword)
712718
end
713719

@@ -750,11 +756,18 @@ def run
750756

751757

752758
if __FILE__ == $PROGRAM_NAME
753-
mod = MicrosoftPatch::Module.new
759+
mod = MicrosoftPatchFinder::Driver.new
754760
begin
755761
mod.run
756762
rescue Interrupt
757763
$stdout.puts
758764
$stdout.puts "Good bye"
759765
end
760766
end
767+
768+
=begin
769+
TODO:
770+
* Make a gem
771+
* Make it generic in order to manage different kind of patches and providers
772+
* Multithreading
773+
=end

0 commit comments

Comments
 (0)