Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jul 31st, 2012  |  syntax: Perl  |  size: 7.41 KB  |  views: 40  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/perl -w
  2. #@(#)$Revision: 1.12 $
  3.  
  4. # A Perl script, which demonstrates the capabilities of the QualysGuard
  5. # API.
  6.  
  7. # With this script you can run maps, run maps and store the results
  8. # on Qualys servers, list, and display the stored maps.
  9.  
  10. # Indentation style: 1 tab = 4 spaces
  11.  
  12. use HTTP::Request;
  13. use LWP::UserAgent;
  14. require XML::Twig;
  15.  
  16. my $myname = "getmap";
  17.  
  18. my $map_count = 0;      # Saved map count, from map_report_list response
  19. my $request;    # HTTP request handle
  20. my $result;             # HTTP response handle
  21. my $server;             # QualysGuard server's FQDN hostname
  22. my $url;                # API access URL
  23. my $xml;                # Twig object handle
  24.  
  25. # $server may be read from the shell environment, or defaults to
  26. # qualysapi.qualys.com otherwise.
  27.  
  28. if ($ENV{QWSERV}) {
  29.         $server = $ENV{QWSERV};
  30. } else {
  31.         $server = "qualysapi.qualys.com";
  32. }
  33.  
  34. # Handlers and helper functions
  35.  
  36. sub error {
  37.         my ($xml, $element) = @_;
  38.  
  39.         my $number = $element->att('number');
  40.         my $message;
  41.  
  42.         # Some APIs return embedded "<SUMMARY>error summary text</SUMMARY>"
  43.         # elements, so detect and handle accordingly. NOTE: <SUMMARY>
  44.         # elements are usually included for reporting multiple errors with
  45.         # one error element.
  46.  
  47.         if (!($message = $element->first_child_trimmed_text('SUMMARY'))) {
  48.                 $message = $element->trimmed_text;
  49.         }
  50.  
  51.         if ($number) {
  52.                 printf STDERR "Request Status: FAILED\nError Number: %1d\nReason: %s\n", $number, $message;
  53.         } else {
  54.                 printf STDERR "Request Status: FAILED\nReason: %s\n", $message;
  55.         }
  56.  
  57.         exit 255;
  58. }
  59.  
  60. sub generic_return {
  61.         my ($xml, $element) = @_;
  62.  
  63.         my ($return, $status, $number, $message);
  64.  
  65.         # This is a GENERIC_RETURN element. So, display the RETURN element,
  66.         # which gives the detailed status.
  67.  
  68.         if ($return = $element->first_child('RETURN')) {
  69.                 $status  = $return->att('status');
  70.                 $number  = $return->att('number');
  71.                 $message = $return->trimmed_text;
  72.  
  73.                 if ($number) {
  74.                         printf STDERR "Request Status: %s\nError Number: %1d\nReason: %s\n", $status, $number, $message;
  75.                 } else {
  76.                         printf STDERR "Request Status: %s\nReason: %s\n", $status, $message;
  77.                 }
  78.         } else {
  79.                 # An XML recognition error; display the XML for the offending
  80.                 # element.
  81.  
  82.                 printf STDERR "Unrecognized XML Element:\n%s\n", $element->print;
  83.         }
  84.  
  85.         exit ($status eq "SUCCESS" ? 0 : 255);
  86. }
  87.  
  88. sub key {
  89.         my ($xml, $element) = @_;
  90.  
  91.         printf "%s: %s\n", $element->att('value'), $element->trimmed_text;
  92. }
  93.  
  94. sub map {
  95.         my ($xml, $element) = @_;
  96.  
  97.         # For a map results, just return the XML
  98.  
  99.         printf "%s\n", $result->content;
  100. }
  101.  
  102. sub map_report {
  103.         my ($xml, $element) = @_;
  104.  
  105.         $map_count++;   # Saw a list element, bump up the count
  106.  
  107.         printf "Map Ref: %s\n   Date: %s\n Domain: %s\n\n", $element->att("ref"), $element->att("date"), $element->att("domain");
  108. }
  109.  
  110. sub map_report_list {
  111.         my ($xml, $element) = @_;
  112. }
  113.  
  114. sub scan_running_list {
  115.         my ($xml, $element) = @_;
  116. }
  117.  
  118. sub scan {
  119.         my ($xml, $element) = @_;
  120. }
  121.  
  122. sub usage {
  123.         printf STDERR "usage: %s username password {{cancel|delete|retrieve} ref|list|running_list|{map|save} domain {iscanner_name}}\n", $myname;
  124.         exit 1;
  125. }
  126.  
  127. # The Perl LWP package gives sufficient capabilities to connect to
  128. # the QualysGuard API. To support the HTTP "Basic Authentication"
  129. # scheme, it's necessary to subclass LWP::UserAgent and define a
  130. # method called "get_basic_credentials", which will be called when
  131. # the server challenges the script for authentication. This method
  132. # returns the username and password, which simply are the second and
  133. # third command line parameters.
  134.  
  135. # A subclass of LWP::UserAgent to handle HTTP Basic Authentication.
  136.  
  137. {
  138.         package authUserAgent;
  139.         @ISA = qw(LWP::UserAgent);
  140.  
  141.         sub new {
  142.                 my $self = LWP::UserAgent::new(@_);
  143.                 $self;
  144.         }
  145.  
  146.         sub get_basic_credentials {
  147.                 return ($ARGV[0], $ARGV[1]);
  148.         }
  149. }
  150.  
  151. # Check for at least username, password, and command
  152.  
  153. usage if ($#ARGV < 2);
  154.  
  155. my $show_url = 0;
  156.  
  157. if ($ARGV[2] eq "-v") {
  158.         splice @ARGV, 2, 1;
  159.         $show_url = 1;
  160. }
  161.  
  162. # XML::Twig is a handy way to process an XML document. We use it to attach
  163. # various handlers, which are triggered whenever related tags are found
  164. # in the XML document. We also attach an error() handler, which is
  165. # triggered whenever Twig finds any errors. Note: The "process comments"
  166. # attribute is useful to recognize and return the error message
  167. # text. Finally, the generic_return() handler covers the case where a
  168. # <GENERIC_RETURN> element is encountered.
  169.  
  170. if ($ARGV[2] eq "map" or $ARGV[2] eq "save") {
  171.         usage if ($#ARGV < 3 or $#ARGV > 5);    # Need at least a Domain name or list to continue
  172.  
  173.         # Check for multiple domains to select map-2.php or map.php as appropriate.
  174.  
  175.         my $map_api = ($ARGV[3] =~ /[,\;:]/) ? "map-2" : "map";
  176.  
  177.         $url  = "https://$server/msp/${map_api}.php?domain=$ARGV[3]";   # map
  178.         $url .= "&save_report=yes" if ($ARGV[2] eq "save");                             # save
  179.  
  180.         # Check if iscanner_name parameter is present.
  181.  
  182.         if ($#ARGV > 3) {
  183.                 if ($#ARGV == 4) {
  184.                         $url .= "&iscanner_name=$ARGV[4]";                                              # appliance
  185.                 } else {
  186.                         usage;
  187.                 }
  188.         }
  189.  
  190.         $xml = new XML::Twig(
  191.                 TwigHandlers => {
  192.                         ERROR             => \&error,
  193.                         GENERIC_RETURN    => \&generic_return,
  194.                         MAP               => \&map,
  195.                 }
  196.         );
  197. } elsif ($ARGV[2] eq "list") {  # Needs no attributes
  198.         $url = "https://$server/msp/map_report_list.php";
  199.  
  200.         $xml = new XML::Twig(
  201.                 TwigHandlers => {
  202.                         ERROR             => \&error,
  203.                         GENERIC_RETURN    => \&generic_return,
  204.                         MAP_REPORT_LIST   => \&map_report_list,
  205.                         MAP_REPORT        => \&map_report,
  206.                 },
  207.                 comments => 'keep'
  208.         );
  209. } elsif ($ARGV[2] eq "retrieve") {
  210.         usage if ($#ARGV != 3);         # Need a map ref to continue
  211.         $url = "https://$server/msp/map_report.php?ref=$ARGV[3]";
  212.  
  213.         $xml = new XML::Twig(
  214.                 TwigHandlers => {
  215.                         ERROR             => \&error,
  216.                         GENERIC_RETURN    => \&generic_return,
  217.                         MAP               => \&map,
  218.                 }
  219.         );
  220. } elsif ($ARGV[2] eq "delete") {
  221.         usage if ($#ARGV != 3);         # Need a map ref to continue
  222.         $url = "https://$server/msp/scan_report_delete.php?ref=$ARGV[3]";
  223.  
  224.         $xml = new XML::Twig(
  225.                 TwigHandlers => {
  226.                         ERROR             => \&error,
  227.                         GENERIC_RETURN    => \&generic_return,
  228.                 },
  229.                 comments => 'keep'
  230.         );
  231. } elsif ($ARGV[2] eq "running_list") {  # Needs no attributes
  232.         $url = "https://$server/msp/scan_running_list.php";
  233.  
  234.         $xml = new XML::Twig(
  235.                 TwigHandlers => {
  236.                         ERROR             => \&error,
  237.                         GENERIC_RETURN    => \&generic_return,
  238.                         KEY               => \&key,
  239.                         SCAN_RUNNING_LIST => \&scan_running_list,
  240.                         SCAN              => \&scan,
  241.                 },
  242.                 comments => 'keep'
  243.         );
  244. } elsif ($ARGV[2] eq "cancel") {
  245.         usage if ($#ARGV != 3);         # Need a map ref to continue
  246.         $url = "https://$server/msp/scan_cancel.php?ref=$ARGV[3]";
  247.  
  248.         $xml = new XML::Twig(
  249.                 TwigHandlers => {
  250.                         ERROR             => \&error,
  251.                         GENERIC_RETURN    => \&generic_return,
  252.                 },
  253.                 comments => 'keep'
  254.         );
  255. } else {
  256.         usage;
  257. }
  258.  
  259. # Setup the request
  260.  
  261. $request = new HTTP::Request GET => $url;
  262.  
  263. # Create an instance of the authentication user agent
  264.  
  265. my $ua = authUserAgent->new;
  266.  
  267. # Make the request
  268.  
  269. print STDERR $url . "\n" if ($show_url);
  270. $result = $ua->request($request);
  271.  
  272. # Check the result
  273.  
  274. if ($result->is_success) {
  275.         # Parse the XML
  276.  
  277.         $xml->parse($result->content);
  278. } else {
  279.         # An HTTP related error
  280.  
  281.         printf STDERR "HTTP Error: %s\n", $result->status_line;
  282.         exit 1;
  283. }
  284.  
  285. if ($ARGV[2] eq "list") {
  286.         if ($map_count) {
  287.                 printf "Saved Maps: %1d total\n", $map_count if ($map_count > 1);
  288.         } else {
  289.                 print  "No saved maps found\n";
  290.         }
  291. }