#!/usr/bin/perl # # ESGF JAR Security Scanner # # Generates a JAR manifest from the installed Tomcat and SOLR and then # searches CVEs for potential problems. # # On CentOS, this will require the following packages: # perl-Sort-Versions # perl-XML-Twig # perl-XML-XPath # perl-XML-XPathEngine # # You will also need to download CVRF files from: # https://cve.mitre.org/data/downloads/index.html # and put them in /tmp (location can be changed in $cvrfdir below) # Filename format will look like: # allitems-cvrf-year-XXXX.xml # You will need to download a file for each year listed in @cvrf_years # # Usage: # jar_security_scan > scan_output.txt # use strict; use warnings; use 5.010; use Cwd 'abs_path'; use Data::Dumper; use File::Basename; use Sort::Versions; use XML::Twig; my $tomcatdir = '/usr/local/tomcat'; my $cvrfdir = '/tmp'; my $cvrfprefix = '/allitems-cvrf-year-'; my @cvrf_years = ( '2015','2016','2017' ); my %cvrf_twigs; # %jar_searchregex is a hash of jar names to regular expressions that # should be used to search the description fields of CVRF files # instead of the simple jar name (which might be too short to be # useful) # # Each regular expression will be used with /i (case-insensitive match) # my %jar_searchregex = ( '52n-xml-gml-v321' => qr/52n/i, '52n-xml-om-v20' => qr/52n/i, 'activation' => qr/activation.*java/i, 'annotations' => qr/java.*annotations/i, 'ant' => qr/apache ant/i, 'antlr-runtime' => qr/antlr/i, 'asm' => qr/asm.*java/i, 'bsh' => qr/beanshell/i, 'commons-beanutils' => qr/(apache.*beanutils|commons-beanutils)/i, 'commons-cli' => qr/(apache.*cli|commons-cli)/i, 'commons-codec' => qr/(apache.*codec|commons-codec)/i, 'commons-collections' => qr/(apache.*collections|commons-collections)/i, 'commons-dbcp' => qr/(apache.*dbcp|commons-dbcp)/i, 'commons-dbutils' => qr/(apache.*dbutils|commons-dbutils)/i, 'commons-digester' => qr/(apache.*digester|commons-digester)/i, 'commons-discovery' => qr/(apache.*discovery|commons-discovery)/i, 'commons-fileupload' => qr/(apache.*fileupload|commons-fileupload)/i, 'commons-httpclient' => qr/(apache.*httpclient|commons-httpclient)/i, 'commons-lang' => qr/(apache.*lang|commons-lang)/i, 'commons-logging' => qr/(apache.*log|commons-log)/i, 'commons-pool' => qr/(apache.*pool|commons-pool)/i, 'commons-validator' => qr/(apache.*validator|commons-validator)/i, 'compiler' => qr/compiler.*java/i, 'encoder' => qr/encoder.*java/i, 'forms' => qr/forms.*java/i, 'geronimo-servlet_3.0_spec' => qr/geronimo/i, 'h2' => qr/h2 database/i, 'je' => qr/berkeley.*db/i, 'org.apache.aries.util' => qr/apache.*aries/i, 'oro' => qr/jakarta.*oro/i, 'jaxb-api' => qr/jaxb/i, 'json' => qr/json.*java/i, 'jstl' => qr/apache.*taglibs/i, 'lang' => qr/lang.*java/i, 'lucene-core' => qr/(apache.*lucene|lucene-core)/i, 'mail' => qr/mail.*java/i, 'org.apache.aries.blueprint.core' => qr/apache.*aries/i, 'org.apache.aries.proxy.api' => qr/apache.*aries/i, 'org.apache.aries.quiesce.api' => qr/apache.*aries/i, 'org.apache.aries.util' => qr/apache.*aries/i, 'org.restlet.ext.servlet' => qr/restlet/i, 'protobuf-java' => qr/(protocol buffers|protobuf)/i, 'rome' => qr/rome.*(java|rss)/i, 'sac' => qr/sac .*css/i, 'serializer' => qr/xalan/i, 'slf4j-api' => qr/(simple logging facade|slf4j)/i, 'solr-core' => qr/apache.*solr/i, 'spring-beans' => qr/spring.*framework/i, 'spring-core' => qr/spring.*framework/i, 'spring-security-config' => qr/spring.*security/i, 'spring-security-core' => qr/spring.*security/i, 'spring-security-openid' => qr/spring.*security/i, 'spring-security-taglibs' => qr/spring.*security/i, 'spring-security-web' => qr/spring.*security/i, 'standard' => qr/standard.*java/i, 'struts2-core' => qr/struts/i, 'tds' => qr/thredds/i, 'tiles-api' => qr/apache.*tiles/i, 'tiles-compat' => qr/apache.*tiles/i, 'tiles-servlet' => qr/apache.*tiles/i, 'tiles-template' => qr/apache.*tiles/i, 'velocity' => qr/velocity.*java/i, 'xercesImpl' => qr/xerces/i, 'xml-resolver' => qr/xml-resolver/i, ); # %falsepositives is a hash of vulnerability titles (generally CVE # codes) mapped to a string starting with the name of the person # declaring that the vulnerability is a false positive in this scan # followed by a colon followed by a short explanation of why it's a # false positive # # Keywords in use: # * unrelated: CVE is completely unrelated to the software being scanned # * oldversion: CVE applies only to versions older than any in use # * reject: CVE is flagged as rejected in the CVRFs my %falsepositives = ( 'CVE-2011-2731' => 'zed: unrelated (VMWare SpringSource)', 'CVE-2011-2732' => 'zed: unrelated (VMWare SpringSource)', 'CVE-2011-2894' => 'zed: oldversion (Spring Framework <= 3.0.5)', 'CVE-2011-4314' => 'zed: oldversion', 'CVE-2012-0004' => 'zed: unrelated (MS DirectShow)', 'CVE-2012-0391' => 'zed: oldversion (Struts < 2.2.3.1)', 'CVE-2012-0392' => 'zed: oldversion (Struts < 2.3.1.1)', 'CVE-2012-0393' => 'zed: oldversion (Struts < 2.3.1.1)', 'CVE-2012-0394' => 'zed: oldversion (Struts < 2.3.1.1)', 'CVE-2012-0657' => 'zed: unrelated (Apple Quartz Composer)', 'CVE-2012-0838' => 'zed: oldversion (Struts < 2.2.3.1)', 'CVE-2012-0936' => 'zed: unrelated (OpenNMS)', 'CVE-2012-1006' => 'zed: oldversion (Struts <= 2.2.3)', 'CVE-2012-1007' => 'zed: oldversion (struts 1.3.10)', 'CVE-2012-1621' => 'zed: unrelated (Apache OFBiz)', 'CVE-2012-2578' => 'zed: unrelated (SmarterMail)', 'CVE-2012-2586' => 'zed: unrelated (Mailtraq)', 'CVE-2012-4386' => 'zed: oldversion (Struts <= 2.3.4)', 'CVE-2012-4387' => 'zed: oldversion (Struts <= 2.3.4)', 'CVE-2012-5055' => 'zed: unrelated (VMWare SpringSource)', 'CVE-2012-5616' => 'zed: unrelated (Apache CloudStack/Citrix CloudPlatform)', 'CVE-2012-5783' => 'zed: oldversion (Apache HttpClient 3.x)', 'CVE-2012-6127' => 'zed: reject', 'CVE-2012-6153' => 'zed: oldversion (Apache HttpClient < 4.2.3)', 'CVE-2012-6573' => 'zed: unrelated (Solr for Drupal)', 'CVE-2012-6612' => 'zed: oldversion (Solr < 4.1)', 'CVE-2013-0077' => 'zed: unrelated (MS DirectShow)', 'CVE-2013-0753' => 'zed: unrelated (Firefox/Thunderbird/SeaMonkey)', 'CVE-2013-1777' => 'zed: unrelated (full Geronimo, not just servlet)', 'CVE-2013-1790' => 'zed: unrelated (Poppler)', 'CVE-2013-1856' => 'zed: unrelated (Ruby on Rails)', 'CVE-2013-1965' => 'zed: oldversion (Struts < 2.3.14.1)', 'CVE-2013-1966' => 'zed: oldversion (Struts < 2.3.14.1)', 'CVE-2013-2115' => 'zed: oldversion (Struts < 2.3.14.2)', 'CVE-2013-2134' => 'zed: oldversion (Struts < 2.3.14.3)', 'CVE-2013-2135' => 'zed: oldversion (Struts < 2.3.14.3)', 'CVE-2013-2186' => 'zed: oldversion (Apache Commons FileUpload < 1.3.1)', 'CVE-2013-2248' => 'zed: oldversion (Struts < 2.3.15)', 'CVE-2013-2251' => 'zed: oldversion (Struts < 2.3.15)', 'CVE-2013-3066' => 'zed: unrelated (Linksys EA6500)', 'CVE-2013-3219' => 'zed: unrelated (bitcoind)', 'CVE-2013-3220' => 'zed: unrelated (bitcoind)', 'CVE-2013-4152' => 'zed: oldversion (Spring Framework < 4.0.0.M1)', 'CVE-2013-4204' => 'zed: unrelated (Google Web Toolkit)', 'CVE-2013-4212' => 'zed: unrelated (Apache Roller)', 'CVE-2013-4310' => 'zed: oldversion (Struts < 2.3.15.1)', 'CVE-2013-4316' => 'zed: oldversion (Struts < 2.3.15.1)', 'CVE-2013-6288' => 'zed: unrelated (Apache Solr for TYPO3)', 'CVE-2013-6289' => 'zed: unrelated (Apache Solr for TYPO3)', 'CVE-2013-6348' => 'zed: oldversion (Struts < 2.3.15.3)', 'CVE-2013-6397' => 'zed: oldversion (Solr < 4.6)', 'CVE-2013-6407' => 'zed: oldversion (Solr < 4.1)', 'CVE-2013-6408' => 'zed: oldversion (Solr < 4.3.1)', 'CVE-2013-6429' => 'zed: oldversion (Spring Framework <= 4.0.0.RC1)', 'CVE-2013-7295' => 'zed: unrelated (Tor)', 'CVE-2013-7315' => 'zed: oldversion (Spring Framework <= 4.0.0.M3)', 'CVE-2013-7398' => 'zed: unrelated (async-http-client < 1.9.0)', 'CVE-2014-0085' => 'zed: unrelated (Actually a problem with Fuse Fabric, not Zookeeper)', 'CVE-2014-0094' => 'zed: oldversion (Struts < 2.3.16.1)', 'CVE-2014-0112' => 'zed: oldversion (Struts < 2.3.16.2)', 'CVE-2014-0050' => 'zed: oldversion (Apache Commons FileUpload < 1.3.1)', 'CVE-2014-0107' => 'zed: oldversion (Xalan < 2.7.2)', 'CVE-2014-0111' => 'zed: unrelated (Apache Syncope)', 'CVE-2014-0113' => 'zed: oldversion (Struts < 2.3.16.2)', 'CVE-2014-0114' => 'zed: oldversion (Apache Commons BeanUtils < 1.9.2)', 'CVE-2014-0116' => 'zed: oldversion (Struts < 2.3.16.3)', 'CVE-2014-0722' => 'zed: unrelated (Cisco UCM)', 'CVE-2014-0728' => 'zed: unrelated (Cisco UCM)', 'CVE-2014-1512' => 'zed: unrelated (Firefox/Thunderbird/Seamonkey)', 'CVE-2014-1904' => 'zed: oldversion (Spring Framework < 4.0.2)', 'CVE-2014-1904' => 'zed: oldversion (Spring Framework < 4.0.2)', 'CVE-2014-1972' => 'zed: unrelated (Apache Tapestry)', 'CVE-2014-2483' => 'zed: oldversion (OpenJDK < 7u65, Oracle Java < 7u60/8u5)', 'CVE-2014-3004' => 'zed: unrelated (Castor)', 'CVE-2014-3577' => 'zed: oldversion (Apache HttpClient < 4.3.5)', 'CVE-2014-3578' => 'zed: oldversion (Spring Framework < 4.0.5)', 'CVE-2014-3625' => 'zed: oldversion (Spring Framework < 4.1.2)', 'CVE-2014-3628' => 'zed: oldversion (SOLR < 4.10.3)', 'CVE-2014-5185' => 'zed: unrelated (WordPress Quartz plugin)', 'CVE-2014-5325' => 'zed: unrelated (Direct Web Remoting)', 'CVE-2014-5886' => 'zed: unrelated (iVysilani)', 'CVE-2014-6278' => 'zed: unrelated (GNU Bash)', 'CVE-2014-7809' => 'zed: oldversion (Struts < 2.3.20)', 'CVE-2014-8152' => 'zed: unrelated (Apache Santuario)', 'CVE-2014-8244' => 'zed: unrelated (Linksys SMART WiFi)', 'CVE-2015-0141' => 'zed: unrelated (IBM OpenPages)', 'CVE-2015-0201' => 'zed: oldversion (Spring Framework < 4.1.5)', 'CVE-2015-0231' => 'zed: unrelated (PHP)', 'CVE-2015-0252' => 'zed: urelated (Xerces C, not Java)', 'CVE-2015-0254' => 'zed: oldversion (Apache Standard Taglibs < 1.2.3)', 'CVE-2015-0274' => 'zed: unrelated (XFS)', 'CVE-2015-0279' => 'zed: unrelated (JBoss RichFaces)', 'CVE-2015-0383' => 'zed: oldversion (Oracle Java <= 8u6)', 'CVE-2015-0395' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0400' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0403' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0406' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0407' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0408' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0410' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0412' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0413' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0421' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0437' => 'zed: oldversion (Oracle Java <= 8u25)', 'CVE-2015-0458' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0459' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0460' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0469' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0470' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0477' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0478' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0480' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0484' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0486' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0488' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0491' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0492' => 'zed: oldversion (Oracle Java <= 8u40)', 'CVE-2015-0851' => 'zed: unrelated (OpenSAML-C, not Java)', 'CVE-2015-0899' => 'zed: oldversion (Struts <= 1.3.10)', 'CVE-2015-1058' => 'zed: unrelated (AdaptCMS)', 'CVE-2015-1235' => 'zed: unrelated (Google Chrome)', 'CVE-2015-1236' => 'zed: unrelated (Google Chrome)', 'CVE-2015-1261' => 'zed: unrelated (Google Chrome)', 'CVE-2015-1275' => 'zed: unrelated (Google Chrome)', 'CVE-2015-1442' => 'zed: unrelated (ZeroCMS)', 'CVE-2015-1643' => 'zed: unrelated (MS Server)', 'CVE-2015-1762' => 'zed: unrelated (MSSQL)', 'CVE-2015-1831' => 'zed: oldversion (Struts 2.3.20)', 'CVE-2015-1836' => 'zed: unrelated (Apache HBase)', 'CVE-2015-1875' => 'zed: unrelated (Elastix)', 'CVE-2015-2242' => 'zed: unrelated (Webshop hun)', 'CVE-2015-2243' => 'zed: unrelated (Webshop hun)', 'CVE-2015-2244' => 'zed: unrelated (Webshop hun)', 'CVE-2015-2327' => 'zed: unrelated (PCRE)', 'CVE-2015-2328' => 'zed: unrelated (PCRE)', 'CVE-2015-2335' => 'zed: unrelated (MyBB)', 'CVE-2015-2583' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2590' => 'zed: oldversion (Oracle Java <= 8u33)', 'CVE-2015-2596' => 'zed: oldversion (Oracle Java <= 7u80)', 'CVE-2015-2597' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2597' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2601' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2613' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2619' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2621' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2624' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2625' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2626' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2627' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2628' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2632' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2637' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2638' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2640' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2654' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2656' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-2659' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2664' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-2738' => 'zed: unrelated (Firefox)', 'CVE-2015-2787' => 'zed: unrelated (PHP)', 'CVE-2015-2838' => 'zed: unrelated (Citrix NetScaler)', 'CVE-2015-2839' => 'zed: unrelated (Citrix NetScaler)', 'CVE-2015-2858' => 'zed: unrelated (Datalex)', 'CVE-2015-2912' => 'zed: unrelated (OrientDB Server)', 'CVE-2015-2938' => 'zed: unrelated (MediaWiki)', 'CVE-2015-3192' => 'zed: oldversion (Spring Framework < 4.1.7)', 'CVE-2015-3227' => 'zed: unrelated (Ruby on Rails)', 'CVE-2015-3397' => 'zed: unrelated (Yii Framework)', 'CVE-2015-3834' => 'zed: unrelated (libstagefright)', 'CVE-2015-4027' => 'zed: unrelated (Acunetix Web Vulnerability Scanner)', 'CVE-2015-4478' => 'zed: unrelated (Mozilla Firefox)', 'CVE-2015-4590' => 'zed: unrelated (Arduino)', 'CVE-2015-4729' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4731' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4732' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4733' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4734' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4736' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4748' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4749' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4754' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4760' => 'zed: oldversion (Oracle Java <= 8u45)', 'CVE-2015-4764' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4774' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4775' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4776' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4777' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4778' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4779' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4780' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4781' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4782' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4783' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4784' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4785' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4786' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4787' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4788' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4789' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4790' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2015-4760' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4803' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4805' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4806' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4810' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4835' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4840' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4842' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4843' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4844' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4852' => 'zed: unrelated (WebLogic Server)', 'CVE-2015-4860' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4868' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4871' => 'zed: oldversion (Oracle Java <= 7u85)', 'CVE-2015-4872' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4881' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4882' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4883' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4893' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4901' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4902' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4903' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4906' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4908' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4911' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-4916' => 'zed: oldversion (Oracle Java <= 8u60)', 'CVE-2015-5250' => 'zed: unrelated (OpenShift Origin)', 'CVE-2015-5262' => 'zed: oldversion (Apache HttpClient < 4.3.6)', 'CVE-2015-5289' => 'zed: unrelated (PostgreSQL)', 'CVE-2015-5344' => 'zed: unrelated (Apache Camel)', 'CVE-2015-5506' => 'zed: unrelated (Drupal Solr)', 'CVE-2015-5571' => 'zed: unrelated (Adobe Flash/Air)', 'CVE-2015-5771' => 'zed: unrelated (Apple Quartz Composer)', 'CVE-2015-5916' => 'zed: unrelated (Apple iOS)', 'CVE-2015-6420' => 'zed: oldversion (Apache Commons Collections < 3.2.2)', 'CVE-2015-6718' => 'zed: unrelated (Adobe Reader/Acrobat)', 'CVE-2015-6719' => 'zed: unrelated (Adobe Reader/Acrobat)', 'CVE-2015-6721' => 'zed: unrelated (Adobe Reader/Acrobat)', 'CVE-2015-6722' => 'zed: unrelated (Adobe Reader/Acrobat)', 'CVE-2015-6761' => 'zed: unrelated (Google Chrome)', 'CVE-2015-6762' => 'zed: unrelated (Google Chrome)', 'CVE-2015-6763' => 'zed: unrelated (Google Chrome)', 'CVE-2015-6764' => 'zed: unrelated (Google V8)', 'CVE-2015-6934' => 'zed: unrelated (VMWare-specific)', 'CVE-2015-6968' => 'zed: unrelated (Serendipity)', 'CVE-2015-7192' => 'zed: unrelated (Mozilla Firefox)', 'CVE-2015-7392' => 'zed: unrelated (FreeSWITCH)', 'CVE-2015-7450' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2015-7766' => 'zed: unrelated (ZOHO ManageEngine OpManager)', 'CVE-2015-7834' => 'zed: unrelated (Google Chrome)', 'CVE-2015-8103' => 'zed: unrelated (Jenkins)', 'CVE-2015-8380' => 'zed: unrelated (PCRE)', 'CVE-2015-8381' => 'zed: unrelated (PCRE)', 'CVE-2015-8382' => 'zed: unrelated (PCRE)', 'CVE-2015-8383' => 'zed: unrelated (PCRE)', 'CVE-2015-8384' => 'zed: unrelated (PCRE)', 'CVE-2015-8385' => 'zed: unrelated (PCRE)', 'CVE-2015-8386' => 'zed: unrelated (PCRE)', 'CVE-2015-8387' => 'zed: unrelated (PCRE)', 'CVE-2015-8388' => 'zed: unrelated (PCRE)', 'CVE-2015-8389' => 'zed: unrelated (PCRE)', 'CVE-2015-8390' => 'zed: unrelated (PCRE)', 'CVE-2015-8391' => 'zed: unrelated (PCRE)', 'CVE-2015-8392' => 'zed: unrelated (PCRE)', 'CVE-2015-8394' => 'zed: unrelated (PCRE)', 'CVE-2015-8395' => 'zed: unrelated (PCRE)', 'CVE-2015-8765' => 'zed: duplicate (Apache commons issues)', 'CVE-2015-8795' => 'zed: oldversion (SOLR < 5.1)', 'CVE-2015-8796' => 'zed: oldversion (SOLR < 5.3)', 'CVE-2015-8797' => 'zed: oldversion (SOLR < 5.3.1)', 'CVE-2016-0231' => 'zed: unrelated (IBM FTM)', 'CVE-2016-0232' => 'zed: unrelated (IBM FTM)', 'CVE-2016-0402' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0448' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0466' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0475' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0483' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0494' => 'zed: oldversion (Oracle Java <= 8u66)', 'CVE-2016-0603' => 'zed: oldversion (Oracle Java <= 8u72)', 'CVE-2016-0636' => 'zed: oldversion (Oracle Java <= 8u74)', 'CVE-2016-0657' => 'zed: unrelated (MySQL)', 'CVE-2016-0682' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2016-0686' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-0687' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-0689' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2016-0692' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2016-0694' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2016-0695' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-0785' => 'zed: oldversion (Apache Struts < 2.3.28)', 'CVE-2016-0729' => 'zed: unrelated (Apache Xerces C)', 'CVE-2016-0792' => 'zed: unrelated (Jenkins via XStream, CVE-2016-3674)', 'CVE-2016-0811' => 'zed: unrelated (Android libmediaplayerservice)', 'CVE-2016-0828' => 'zed: unrelated (Android mediaserver)', 'CVE-2016-0829' => 'zed: unrelated (Android mediaserver)', 'CVE-2016-1000031' => 'zed: invalid', 'CVE-2016-1181' => 'zed: oldversion (Apache Struts <= 1.3.10)', 'CVE-2016-1182' => 'zed: oldversion (Apache Struts <= 1.3.10)', 'CVE-2016-1238' => 'zed: unrelated (Perl)', 'CVE-2016-1283' => 'zed: unrelated (PCRE)', 'CVE-2016-1406' => 'zed: unrelated (Cisco Prime Infrastructure)', 'CVE-2016-1688' => 'zed: unrelated (Google V8)', 'CVE-2016-1730' => 'zed: unrelated (WebSheet)', 'CVE-2016-1928' => 'zed: unrelated (SAP HANA)', 'CVE-2016-1985' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-1986' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-1997' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-1998' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-1999' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-2003' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-2045' => 'zed: unrelated (PHPMyAdmin)', 'CVE-2016-2099' => 'zed: unrelated (Apache Xerces C++)', 'CVE-2016-2170' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-2173' => 'zed: oldversion (Spring AMQP)', 'CVE-2016-2162' => 'zed: oldversion (Apache Struts < 2.3.25)', 'CVE-2016-2212' => 'zed: unrelated (Magento)', 'CVE-2016-2425' => 'zed: unrelated (AOSP Mail for Android)', 'CVE-2016-2458' => 'zed: unrelated (AOSP Mail for Android)', 'CVE-2016-2510' => 'zed: unrelated (BeanShell/bsh)', 'CVE-2016-2537' => 'zed: unrelated (node.js)', 'CVE-2016-2560' => 'zed: unrelated (PHPMyAdmin)', 'CVE-2016-3060' => 'zed: unrelated (IBM FTM)', 'CVE-2016-3081' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-3082' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-3087' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-3093' => 'zed: oldversion (Apache Struts <= 2.3.24.1)', 'CVE-2016-3168' => 'zed: unrelated (Drupal)', 'CVE-2016-3191' => 'zed: unrelated (PCRE)', 'CVE-2016-3341' => 'zed: unrelated (MS Windows Transaction Manager)', 'CVE-2016-3418' => 'zed: unrelated (Berkeley DB non-JE)', 'CVE-2016-3422' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3425' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3426' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3427' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3642' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-3443' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3449' => 'zed: oldversion (Oracle Java <= 8u77)', 'CVE-2016-3458' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3485' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3498' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3500' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3503' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3508' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3511' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3550' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3552' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3587' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3598' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3606' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3610' => 'zed: oldversion (Oracle Java <= 8u92)', 'CVE-2016-3674' => 'zed: oldversion (XStream < 1.4.9)', 'CVE-2016-3723' => 'zed: unrelated (Jenkins)', 'CVE-2016-3918' => 'zed: unrelated (AOSP Mail for Android)', 'CVE-2016-4003' => 'zed: unrelated (Apache Struts < 2.3.28)', 'CVE-2016-4303' => 'zed: unrelated (cJSON)', 'CVE-2016-4368' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-4369' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-4372' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-4385' => 'zed: duplicate (Apache Commons Collections, CVE-2015-6420)', 'CVE-2016-4425' => 'zed: unrelated (Jansson)', 'CVE-2016-4430' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-4431' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-4433' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-4436' => 'zed: oldversion (Apache Struts < 2.3.29)', 'CVE-2016-4438' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-4463' => 'zed: unrelated (Apache Xerces C++)', 'CVE-2016-4465' => 'zed: oldversion (Apache Struts < 2.3.28.1)', 'CVE-2016-4814' => 'zed: unrelated (Geospatial Information Authority of Japan)', 'CVE-2016-4849' => 'zed: unrelated (Geeklog IVYWE)', 'CVE-2016-4875' => 'zed: unrelated (Geeklog IVYWE)', 'CVE-2016-4974' => 'zed: unrelated (Apache Qpid)', 'CVE-2016-5160' => 'zed: unrelated (Google Chrome)', 'CVE-2016-5162' => 'zed: unrelated (Google Chrome)', 'CVE-2016-5229' => 'zed: duplicate (Atlassian Bamboo via XStream)', 'CVE-2016-5412' => 'zed: unrelated (Linux Kernel on PowerPC)', 'CVE-2016-5542' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5546' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5547' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5552' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5554' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5556' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5568' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5573' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5582' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5597' => 'zed: oldversion (Oracle Java <= 8u102)', 'CVE-2016-5668' => 'zed: unrelated (Crestron Electronics)', 'CVE-2016-5705' => 'zed: unrelated (phpMyAdmin)', 'CVE-2016-5828' => 'zed: unrelated (Linux Kernel on PowerPC)', 'CVE-2016-5981' => 'zed: unrelated (IBM FileNet)', 'CVE-2016-6317' => 'zed: unrelated (Ruby on Rails)', 'CVE-2016-6426' => 'zed: unrelated (Cisco Unified Intelligence Center)', 'CVE-2016-6494' => 'zed: unrelated (MongoDB)', 'CVE-2016-6629' => 'zed: unrelated (phpMyAdmin)', 'CVE-2016-7040' => 'zed: unrelated (RedHat CloudForms)', 'CVE-2016-7506' => 'zed: unrelated (Artifex)', 'CVE-2016-7867' => 'zed: unrelated (Adobe Flash)', 'CVE-2016-7868' => 'zed: unrelated (Adobe Flash)', 'CVE-2016-7869' => 'zed: unrelated (Adobe Flash)', 'CVE-2016-7870' => 'zed: unrelated (Adobe Flash)', 'CVE-2016-7964' => 'zed: unrelated (DokuWiki)', 'CVE-2016-8328' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2016-8905' => 'zed: unrelated (dotCMS)', 'CVE-2016-9108' => 'zed: unrelated (Artifex MuJS)', 'CVE-2016-9318' => 'zed: unrelated (LibXML2)', 'CVE-2016-10132' => 'zed: unrelated (Artifex MuJS)', 'CVE-2016-10141' => 'zed: unrelated (Artifex MuJS)', 'CVE-2017-3503' => 'zed: unrelated (Oracle Primavera Products Suite)', 'CVE-2017-3241' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3252' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3253' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3259' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3260' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3262' => 'zed: oldversion (Oracle Java <= 8u112)', 'CVE-2017-3511' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3512' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3514' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3526' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3533' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3544' => 'zed: oldversion (Oracle Java <= 8u121)', 'CVE-2017-3604' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3605' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3606' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3607' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3608' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3609' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3610' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3611' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3612' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3613' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3614' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3615' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3616' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-3617' => 'zed: unrelated (Berkeley DB)', 'CVE-2017-5586' => 'zed: unrelated (OpenText Documentum D2)', 'CVE-2017-5638' => 'zed: unrelated (Apache Struts < 2.5.10.1)', 'CVE-2017-5656' => 'zed: unrelated (Apache CXF/STSClient)', 'CVE-2017-6711' => 'zed: unrelated (Cisco Ultra Services Framework)', 'CVE-2017-9083' => 'zed: unrelated (Poppler)', 'CVE-2017-9304' => 'zed: unrelated (YARA)', 'CVE-2017-9438' => 'zed: unrelated (YARA)', 'CVE-2017-9791' => 'zed: oldversion (Apache Struts 2.3.x)', 'CVE-2017-1000061' => 'zed: oldversion (xmlsec <= 1.2.23)', ); # %jars is a global hash of hashes modified directly by other subs # Each key is the name of a jar, and the value is an anonymous hash of # webapp => jarversion my %jars; my %lowversions; # %found is a global hash keyed by CVE, where the value is an # anonymous hash of the following structure: # jars => array of all potentially relevant jars # text => text of the CVE # urls => array of URLs referenced by the CVE my %found; find_all_jars(\%jars); print_jars(%jars); say "\n===========\n"; %lowversions = lowest_jar_versions(%jars); foreach my $year (@cvrf_years) { say {*STDERR} "Parsing CVRF entries for $year... "; $cvrf_twigs{$year} = twig_cvrf($cvrfdir . $cvrfprefix . $year . '.xml'); } foreach my $year (@cvrf_years) { say {*STDERR} "Searching $year CVRFs for potential issues..."; foreach my $jar (sort keys %lowversions) { say {*STDERR} "- Checking $jar..."; my @notes; if ($jar_searchregex{$jar}) { @notes = $cvrf_twigs{$year}->descendants("Note[string() =~ /$jar_searchregex{$jar}/]"); } else { @notes = $cvrf_twigs{$year}->descendants("Note[string() =~ /$jar/i]"); } foreach my $note (@notes) { next if ($note->parent->gi eq 'DocumentNotes'); next if ($note->text =~ /\*\* REJECT \*\*/); my $vuln = $note->parent->parent; if(not $vuln) { die("Could not find grandparent of note!"); } my $title_element = $vuln->first_child('Title'); if(not $title_element) { die("Could not find title for note with text:\n",$note->text); } my $title = $title_element->text; next if $falsepositives{$title}; # TODO: The title has so far always been identical to CVE. # Just always use this, since we absolutely need CVE to # generate the links? my $cve_element = $vuln->first_child('CVE'); if(not $cve_element) { die("Could not find CVE for note with text:\n",$note->text); } my $cve = $cve_element->text; next if $falsepositives{$cve}; # Attempt to isolate the last mentioned version string in # the description. # # This may be a bad idea, as it's not strictly guaranteed # to be the highest version with an exploit, so it should # be at most used informationally. Sometimes the last # version mentioned is the last version including the # exploit, and sometimes the first version fixed. $note->text =~ /\s([0-9][0-9a-zA-Z;.-]+)(\s|,|\.)/; my $lastversionstring = $1 || ''; my @urlelements = $vuln->descendants('URL'); if(! $found{$cve}) { $found{$cve}->{'text'} = $note->text; foreach my $url (@urlelements) { push (@{$found{$cve}->{'urls'}},$url->text); } } push (@{$found{$cve}->{'jars'}},$jar); } } } foreach my $cve (sort keys %found) { say "${cve} is possibly related to:"; foreach my $jar (sort @{$found{$cve}->{'jars'}}) { foreach my $webapp (sort keys %{$jars{$jar}}) { say " $jar\t$webapp\t$jars{$jar}{$webapp}"; } } say "\n",$found{$cve}->{'text'}; say "https://web.nvd.nist.gov/view/vuln/detail?vulnId=" . $cve; foreach my $url (@{$found{$cve}->{'urls'}}) { say $url; } say "\n----------\n"; } ################## ### PROCEDURES ### ################## # sub find_all_jars # # Wrapper to find_webapp_jars that finds jars in every detected java module # # Arguments: # * $jars: global hashref of jar information (will be directly modified) # # Returns nothing # sub find_all_jars { my ($jars) = @_; my @webapps = list_webapps(); find_oracle_java($jars); find_misc_jars($jars); foreach my $webapp (sort @webapps) { find_webapp_jars($webapp,$jars); } return; } # sub find_oracle_java # # Creates a synthetic hashref entry specifically for Oracle Java SE # itself # # Arguments: # * hashref containing jar information that will be directly modified # Returns: nothing # sub find_oracle_java { my ($jars) = @_; my $javadir='/usr/local/java'; my $version; $javadir = basename(abs_path($javadir)); $javadir =~ /^jdk1\.(\d)\.0_(\d+)/x; if (not $2) { say {*STDERR} "WARNING: Unable to find Oracle Java version"; $version = 'unknown'; } else { $version = "${1}u${2}"; } $jars{'Oracle Java SE'}->{$javadir} = $version; return; } # sub find_misc_jars # # Updates the jars hashref to contain all informations on jars found # in miscellaneous specified directories # # Arguments: # * hashref containing jar information that will be directly modified # Returns: nothing # sub find_misc_jars { my ($jars) = @_; my $dirhandle; my @dirlist; my $appname; my $jarname; my $jarver; my %jardirs = ( '/usr/local/las-esgf/8.6.1/las-esgf-v8.6.1/lib' => 'las', '/usr/local/las-esgf/8.6.1/las-esgf-v8.6.1/WebContent/WEB-INF/lib' => 'las-webcontent', '/usr/local/solr/server/lib/' => 'solr-server', '/usr/local/solr/server/solr-webapp/webapp/WEB-INF/lib' => 'solr-webapp', ); foreach my $jardir (keys %jardirs) { $appname = $jardirs{$jardir}; opendir($dirhandle,$jardir) or die ("Unable to read ${jardir} !"); @dirlist = readdir $dirhandle; closedir($dirhandle); foreach my $entry (sort @dirlist) { next if ($entry eq '.'); next if ($entry eq '..'); if ( ($jarname,$jarver) = $entry =~ /([a-zA-Z0-9._-]+)-([0-9][a-zA-Z0-9.]+)\.jar/) { $jars{$jarname}->{$appname} = $jarver; } } } return; } # sub find_webapp_jars # # Updates the jars hashref to contain all information on jars found in # a particular webapp directory # # Arguments: # * webapp to search # * hashref containing jar information that will be directly modified # Returns: nothing sub find_webapp_jars { my ($webapp,$jars) = @_; my $dirhandle; my @dirlist; my $jarname; my $jarver; opendir($dirhandle,"${tomcatdir}/webapps/${webapp}/WEB-INF/lib") or die ("Unable to read ${tomcatdir}/webapps/${webapp}/WEB-INF/lib !"); @dirlist = readdir $dirhandle; closedir($dirhandle); foreach my $entry (sort @dirlist) { next if ($entry eq '.'); next if ($entry eq '..'); if ( ($jarname,$jarver) = $entry =~ /([a-zA-Z0-9._-]+)-([0-9][a-zA-Z0-9.]+)\.jar/) { $jars{$jarname}->{$webapp} = $jarver; } } return; } # sub lowest_jar_versions # # Arguments: # * %jars: hash containing jar information # # Returns a hash containing just the lowest version of each jar found # This can also be used to generate a unique list of jars # sub lowest_jar_versions { my %jars = @_; my %lowversion; foreach my $jarname (keys %jars) { foreach my $webapp (keys %{$jars{$jarname}}) { if(not $lowversion{$jarname} or versioncmp($jars{$jarname}->{$webapp},$lowversion{$jarname}) <= 0) { $lowversion{$jarname} = $jars{$jarname}->{$webapp}; } } } return %lowversion; } # sub print_jars # # Prints to the screen each jar name, the module it was found in, and # what version was found in that module, in tab-separated format. # # Arguments: # * %jars: hash containing jar information # # Returns nothing # sub print_jars { my %jars = @_; say "Java JAR manifest"; say "================="; foreach my $jar (sort keys %jars) { foreach my $webapp (sort keys %{$jars{$jar}}) { say "$jar\t$webapp\t$jars{$jar}{$webapp}"; } } return; } # sub list_webapps # # Arguments: none # Returns: array containing all webapps except ROOT # sub list_webapps { my @webapps; my $dirhandle; my @dirlist; opendir($dirhandle,"${tomcatdir}/webapps") or die ("Unable to read ${tomcatdir}/webapps directory!"); @dirlist = readdir $dirhandle; closedir($dirhandle); foreach my $entry (sort @dirlist) { next if ($entry eq '.'); next if ($entry eq '..'); next if ($entry eq 'ROOT'); if (-d "${tomcatdir}/webapps/${entry}") { push(@webapps,$entry); } } return @webapps; } # sub twig_cvrf # # Convert a CVRF file into a XML::Twig object for further usage # # Arguments: # $cvrf: full path to CVRF file # # Returns: # Scalar twig object # sub twig_cvrf { my ($cvrf) = @_; my $twig = XML::Twig->new( keep_atts_order => 1, output_encoding => 'utf-8', pretty_print => 'record' ); $twig->parsefile($cvrf) or die ("Failed to parse CVRF file ${cvrf}!"); return $twig; }