View Javadoc
1   /*
2    * This file is part of dependency-check-ant.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.taskdefs;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.List;
24  import java.util.logging.Level;
25  import java.util.logging.Logger;
26  import org.apache.tools.ant.BuildException;
27  import org.apache.tools.ant.Task;
28  import org.apache.tools.ant.types.EnumeratedAttribute;
29  import org.apache.tools.ant.types.Reference;
30  import org.apache.tools.ant.types.Resource;
31  import org.apache.tools.ant.types.ResourceCollection;
32  import org.apache.tools.ant.types.resources.FileProvider;
33  import org.apache.tools.ant.types.resources.Resources;
34  import org.owasp.dependencycheck.Engine;
35  import org.owasp.dependencycheck.data.nvdcve.CveDB;
36  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
37  import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
38  import org.owasp.dependencycheck.dependency.Dependency;
39  import org.owasp.dependencycheck.dependency.Identifier;
40  import org.owasp.dependencycheck.dependency.Vulnerability;
41  import org.owasp.dependencycheck.reporting.ReportGenerator;
42  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
43  import org.owasp.dependencycheck.utils.LogUtils;
44  import org.owasp.dependencycheck.utils.Settings;
45  
46  /**
47   * An Ant task definition to execute dependency-check during an Ant build.
48   *
49   * @author Jeremy Long <jeremy.long@owasp.org>
50   */
51  public class DependencyCheckTask extends Task {
52  
53      /**
54       * The properties file location.
55       */
56      private static final String PROPERTIES_FILE = "task.properties";
57      /**
58       * Name of the logging properties file.
59       */
60      private static final String LOG_PROPERTIES_FILE = "log.properties";
61      /**
62       * System specific new line character.
63       */
64      private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
65      /**
66       * The logger.
67       */
68      private static final Logger LOGGER = Logger.getLogger(DependencyCheckTask.class.getName());
69  
70      /**
71       * Construct a new DependencyCheckTask.
72       */
73      public DependencyCheckTask() {
74          super();
75      }
76      //The following code was copied Apache Ant PathConvert
77      //BEGIN COPY from org.apache.tools.ant.taskdefs.PathConvert
78      /**
79       * Path to be converted
80       */
81      private Resources path = null;
82      /**
83       * Reference to path/fileset to convert
84       */
85      private Reference refid = null;
86  
87      /**
88       * Add an arbitrary ResourceCollection.
89       *
90       * @param rc the ResourceCollection to add.
91       * @since Ant 1.7
92       */
93      public void add(ResourceCollection rc) {
94          if (isReference()) {
95              throw new BuildException("Nested elements are not allowed when using the refid attribute.");
96          }
97          getPath().add(rc);
98      }
99  
100     /**
101      * Returns the path. If the path has not been initialized yet, this class is synchronized, and will instantiate the
102      * path object.
103      *
104      * @return the path
105      */
106     private synchronized Resources getPath() {
107         if (path == null) {
108             path = new Resources(getProject());
109             path.setCache(true);
110         }
111         return path;
112     }
113 
114     /**
115      * Learn whether the refid attribute of this element been set.
116      *
117      * @return true if refid is valid.
118      */
119     public boolean isReference() {
120         return refid != null;
121     }
122 
123     /**
124      * Add a reference to a Path, FileSet, DirSet, or FileList defined elsewhere.
125      *
126      * @param r the reference to a path, fileset, dirset or filelist.
127      */
128     public void setRefid(Reference r) {
129         if (path != null) {
130             throw new BuildException("Nested elements are not allowed when using the refid attribute.");
131         }
132         refid = r;
133     }
134 
135     /**
136      * If this is a reference, this method will add the referenced resource collection to the collection of paths.
137      *
138      * @throws BuildException if the reference is not to a resource collection
139      */
140     private void dealWithReferences() throws BuildException {
141         if (isReference()) {
142             final Object o = refid.getReferencedObject(getProject());
143             if (!(o instanceof ResourceCollection)) {
144                 throw new BuildException("refid '" + refid.getRefId()
145                         + "' does not refer to a resource collection.");
146             }
147             getPath().add((ResourceCollection) o);
148         }
149     }
150     // END COPY from org.apache.tools.ant.taskdefs
151     /**
152      * The application name for the report.
153      */
154     private String applicationName = "Dependency-Check";
155 
156     /**
157      * Get the value of applicationName.
158      *
159      * @return the value of applicationName
160      */
161     public String getApplicationName() {
162         return applicationName;
163     }
164 
165     /**
166      * Set the value of applicationName.
167      *
168      * @param applicationName new value of applicationName
169      */
170     public void setApplicationName(String applicationName) {
171         this.applicationName = applicationName;
172     }
173     /**
174      * The location of the data directory that contains
175      */
176     private String dataDirectory = null;
177 
178     /**
179      * Get the value of dataDirectory.
180      *
181      * @return the value of dataDirectory
182      */
183     public String getDataDirectory() {
184         return dataDirectory;
185     }
186 
187     /**
188      * Set the value of dataDirectory.
189      *
190      * @param dataDirectory new value of dataDirectory
191      */
192     public void setDataDirectory(String dataDirectory) {
193         this.dataDirectory = dataDirectory;
194     }
195     /**
196      * Specifies the destination directory for the generated Dependency-Check report.
197      */
198     private String reportOutputDirectory = ".";
199 
200     /**
201      * Get the value of reportOutputDirectory.
202      *
203      * @return the value of reportOutputDirectory
204      */
205     public String getReportOutputDirectory() {
206         return reportOutputDirectory;
207     }
208 
209     /**
210      * Set the value of reportOutputDirectory.
211      *
212      * @param reportOutputDirectory new value of reportOutputDirectory
213      */
214     public void setReportOutputDirectory(String reportOutputDirectory) {
215         this.reportOutputDirectory = reportOutputDirectory;
216     }
217     /**
218      * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11
219      * which means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11.
220      * The valid range for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
221      */
222     private float failBuildOnCVSS = 11;
223 
224     /**
225      * Get the value of failBuildOnCVSS.
226      *
227      * @return the value of failBuildOnCVSS
228      */
229     public float getFailBuildOnCVSS() {
230         return failBuildOnCVSS;
231     }
232 
233     /**
234      * Set the value of failBuildOnCVSS.
235      *
236      * @param failBuildOnCVSS new value of failBuildOnCVSS
237      */
238     public void setFailBuildOnCVSS(float failBuildOnCVSS) {
239         this.failBuildOnCVSS = failBuildOnCVSS;
240     }
241     /**
242      * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to
243      * false. Default is true.
244      */
245     private boolean autoUpdate = true;
246 
247     /**
248      * Get the value of autoUpdate.
249      *
250      * @return the value of autoUpdate
251      */
252     public boolean isAutoUpdate() {
253         return autoUpdate;
254     }
255 
256     /**
257      * Set the value of autoUpdate.
258      *
259      * @param autoUpdate new value of autoUpdate
260      */
261     public void setAutoUpdate(boolean autoUpdate) {
262         this.autoUpdate = autoUpdate;
263     }
264     /**
265      * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this
266      * within the Site plugin unless the externalReport is set to true. Default is HTML.
267      */
268     private String reportFormat = "HTML";
269 
270     /**
271      * Get the value of reportFormat.
272      *
273      * @return the value of reportFormat
274      */
275     public String getReportFormat() {
276         return reportFormat;
277     }
278 
279     /**
280      * Set the value of reportFormat.
281      *
282      * @param reportFormat new value of reportFormat
283      */
284     public void setReportFormat(ReportFormats reportFormat) {
285         this.reportFormat = reportFormat.getValue();
286     }
287     /**
288      * The Proxy Server.
289      */
290     private String proxyServer;
291 
292     /**
293      * Get the value of proxyServer.
294      *
295      * @return the value of proxyServer
296      */
297     public String getProxyServer() {
298         return proxyServer;
299     }
300 
301     /**
302      * Set the value of proxyServer.
303      *
304      * @param server new value of proxyServer
305      */
306     public void setProxyServer(String server) {
307         this.proxyServer = server;
308     }
309 
310     /**
311      * Get the value of proxyServer.
312      *
313      * @return the value of proxyServer
314      * @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#getProxyServer()} instead
315      */
316     @Deprecated
317     public String getProxyUrl() {
318         return proxyServer;
319     }
320 
321     /**
322      * Set the value of proxyServer.
323      *
324      * @param proxyUrl new value of proxyServer
325      * @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#setProxyServer(java.lang.String)}
326      * instead
327      */
328     @Deprecated
329     public void setProxyUrl(String proxyUrl) {
330         LOGGER.warning("A deprecated configuration option 'proxyUrl' was detected; use 'proxyServer' instead.");
331         this.proxyServer = proxyUrl;
332     }
333     /**
334      * The Proxy Port.
335      */
336     private String proxyPort;
337 
338     /**
339      * Get the value of proxyPort.
340      *
341      * @return the value of proxyPort
342      */
343     public String getProxyPort() {
344         return proxyPort;
345     }
346 
347     /**
348      * Set the value of proxyPort.
349      *
350      * @param proxyPort new value of proxyPort
351      */
352     public void setProxyPort(String proxyPort) {
353         this.proxyPort = proxyPort;
354     }
355     /**
356      * The Proxy username.
357      */
358     private String proxyUsername;
359 
360     /**
361      * Get the value of proxyUsername.
362      *
363      * @return the value of proxyUsername
364      */
365     public String getProxyUsername() {
366         return proxyUsername;
367     }
368 
369     /**
370      * Set the value of proxyUsername.
371      *
372      * @param proxyUsername new value of proxyUsername
373      */
374     public void setProxyUsername(String proxyUsername) {
375         this.proxyUsername = proxyUsername;
376     }
377     /**
378      * The Proxy password.
379      */
380     private String proxyPassword;
381 
382     /**
383      * Get the value of proxyPassword.
384      *
385      * @return the value of proxyPassword
386      */
387     public String getProxyPassword() {
388         return proxyPassword;
389     }
390 
391     /**
392      * Set the value of proxyPassword.
393      *
394      * @param proxyPassword new value of proxyPassword
395      */
396     public void setProxyPassword(String proxyPassword) {
397         this.proxyPassword = proxyPassword;
398     }
399     /**
400      * The Connection Timeout.
401      */
402     private String connectionTimeout;
403 
404     /**
405      * Get the value of connectionTimeout.
406      *
407      * @return the value of connectionTimeout
408      */
409     public String getConnectionTimeout() {
410         return connectionTimeout;
411     }
412 
413     /**
414      * Set the value of connectionTimeout.
415      *
416      * @param connectionTimeout new value of connectionTimeout
417      */
418     public void setConnectionTimeout(String connectionTimeout) {
419         this.connectionTimeout = connectionTimeout;
420     }
421     /**
422      * The file path used for verbose logging.
423      */
424     private String logFile = null;
425 
426     /**
427      * Get the value of logFile.
428      *
429      * @return the value of logFile
430      */
431     public String getLogFile() {
432         return logFile;
433     }
434 
435     /**
436      * Set the value of logFile.
437      *
438      * @param logFile new value of logFile
439      */
440     public void setLogFile(String logFile) {
441         this.logFile = logFile;
442     }
443     /**
444      * The path to the suppression file.
445      */
446     private String suppressionFile;
447 
448     /**
449      * Get the value of suppressionFile.
450      *
451      * @return the value of suppressionFile
452      */
453     public String getSuppressionFile() {
454         return suppressionFile;
455     }
456 
457     /**
458      * Set the value of suppressionFile.
459      *
460      * @param suppressionFile new value of suppressionFile
461      */
462     public void setSuppressionFile(String suppressionFile) {
463         this.suppressionFile = suppressionFile;
464     }
465     /**
466      * flag indicating whether or not to show a summary of findings.
467      */
468     private boolean showSummary = true;
469 
470     /**
471      * Get the value of showSummary.
472      *
473      * @return the value of showSummary
474      */
475     public boolean isShowSummary() {
476         return showSummary;
477     }
478 
479     /**
480      * Set the value of showSummary.
481      *
482      * @param showSummary new value of showSummary
483      */
484     public void setShowSummary(boolean showSummary) {
485         this.showSummary = showSummary;
486     }
487 
488     /**
489      * Sets whether or not the analyzer is enabled.
490      *
491      * @param jarAnalyzerEnabled the value of the new setting
492      */
493     public void setJarAnalyzerEnabled(boolean jarAnalyzerEnabled) {
494         this.jarAnalyzerEnabled = jarAnalyzerEnabled;
495     }
496     /**
497      * Whether or not the Archive Analyzer is enabled.
498      */
499     private boolean archiveAnalyzerEnabled = true;
500 
501     /**
502      * Returns whether or not the analyzer is enabled.
503      *
504      * @return true if the analyzer is enabled
505      */
506     public boolean isArchiveAnalyzerEnabled() {
507         return archiveAnalyzerEnabled;
508     }
509     /**
510      * Whether or not the .NET Assembly Analyzer is enabled.
511      */
512     private boolean assemblyAnalyzerEnabled = true;
513 
514     /**
515      * Sets whether or not the analyzer is enabled.
516      *
517      * @param archiveAnalyzerEnabled the value of the new setting
518      */
519     public void setArchiveAnalyzerEnabled(boolean archiveAnalyzerEnabled) {
520         this.archiveAnalyzerEnabled = archiveAnalyzerEnabled;
521     }
522 
523     /**
524      * Returns whether or not the analyzer is enabled.
525      *
526      * @return true if the analyzer is enabled
527      */
528     public boolean isAssemblyAnalyzerEnabled() {
529         return assemblyAnalyzerEnabled;
530     }
531 
532     /**
533      * Sets whether or not the analyzer is enabled.
534      *
535      * @param assemblyAnalyzerEnabled the value of the new setting
536      */
537     public void setAssemblyAnalyzerEnabled(boolean assemblyAnalyzerEnabled) {
538         this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled;
539     }
540     /**
541      * Whether or not the .NET Nuspec Analyzer is enabled.
542      */
543     private boolean nuspecAnalyzerEnabled = true;
544 
545     /**
546      * Returns whether or not the analyzer is enabled.
547      *
548      * @return true if the analyzer is enabled
549      */
550     public boolean isNuspecAnalyzerEnabled() {
551         return nuspecAnalyzerEnabled;
552     }
553 
554     /**
555      * Sets whether or not the analyzer is enabled.
556      *
557      * @param nuspecAnalyzerEnabled the value of the new setting
558      */
559     public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
560         this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
561     }
562     /**
563      * Whether or not the central analyzer is enabled.
564      */
565     private boolean centralAnalyzerEnabled = false;
566 
567     /**
568      * Get the value of centralAnalyzerEnabled
569      *
570      * @return the value of centralAnalyzerEnabled
571      */
572     public boolean isCentralAnalyzerEnabled() {
573         return centralAnalyzerEnabled;
574     }
575 
576     /**
577      * Set the value of centralAnalyzerEnabled
578      *
579      * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
580      */
581     public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) {
582         this.centralAnalyzerEnabled = centralAnalyzerEnabled;
583     }
584 
585     /**
586      * Whether or not the nexus analyzer is enabled.
587      */
588     private boolean nexusAnalyzerEnabled = true;
589 
590     /**
591      * Get the value of nexusAnalyzerEnabled.
592      *
593      * @return the value of nexusAnalyzerEnabled
594      */
595     public boolean isNexusAnalyzerEnabled() {
596         return nexusAnalyzerEnabled;
597     }
598 
599     /**
600      * Set the value of nexusAnalyzerEnabled.
601      *
602      * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
603      */
604     public void setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) {
605         this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
606     }
607 
608     /**
609      * The URL of the Nexus server.
610      */
611     private String nexusUrl;
612 
613     /**
614      * Get the value of nexusUrl.
615      *
616      * @return the value of nexusUrl
617      */
618     public String getNexusUrl() {
619         return nexusUrl;
620     }
621 
622     /**
623      * Set the value of nexusUrl.
624      *
625      * @param nexusUrl new value of nexusUrl
626      */
627     public void setNexusUrl(String nexusUrl) {
628         this.nexusUrl = nexusUrl;
629     }
630     /**
631      * Whether or not the defined proxy should be used when connecting to Nexus.
632      */
633     private boolean nexusUsesProxy = true;
634 
635     /**
636      * Get the value of nexusUsesProxy.
637      *
638      * @return the value of nexusUsesProxy
639      */
640     public boolean isNexusUsesProxy() {
641         return nexusUsesProxy;
642     }
643 
644     /**
645      * Set the value of nexusUsesProxy.
646      *
647      * @param nexusUsesProxy new value of nexusUsesProxy
648      */
649     public void setNexusUsesProxy(boolean nexusUsesProxy) {
650         this.nexusUsesProxy = nexusUsesProxy;
651     }
652 
653     /**
654      * The database driver name; such as org.h2.Driver.
655      */
656     private String databaseDriverName;
657 
658     /**
659      * Get the value of databaseDriverName.
660      *
661      * @return the value of databaseDriverName
662      */
663     public String getDatabaseDriverName() {
664         return databaseDriverName;
665     }
666 
667     /**
668      * Set the value of databaseDriverName.
669      *
670      * @param databaseDriverName new value of databaseDriverName
671      */
672     public void setDatabaseDriverName(String databaseDriverName) {
673         this.databaseDriverName = databaseDriverName;
674     }
675 
676     /**
677      * The path to the database driver JAR file if it is not on the class path.
678      */
679     private String databaseDriverPath;
680 
681     /**
682      * Get the value of databaseDriverPath.
683      *
684      * @return the value of databaseDriverPath
685      */
686     public String getDatabaseDriverPath() {
687         return databaseDriverPath;
688     }
689 
690     /**
691      * Set the value of databaseDriverPath.
692      *
693      * @param databaseDriverPath new value of databaseDriverPath
694      */
695     public void setDatabaseDriverPath(String databaseDriverPath) {
696         this.databaseDriverPath = databaseDriverPath;
697     }
698     /**
699      * The database connection string.
700      */
701     private String connectionString;
702 
703     /**
704      * Get the value of connectionString.
705      *
706      * @return the value of connectionString
707      */
708     public String getConnectionString() {
709         return connectionString;
710     }
711 
712     /**
713      * Set the value of connectionString.
714      *
715      * @param connectionString new value of connectionString
716      */
717     public void setConnectionString(String connectionString) {
718         this.connectionString = connectionString;
719     }
720     /**
721      * The user name for connecting to the database.
722      */
723     private String databaseUser;
724 
725     /**
726      * Get the value of databaseUser.
727      *
728      * @return the value of databaseUser
729      */
730     public String getDatabaseUser() {
731         return databaseUser;
732     }
733 
734     /**
735      * Set the value of databaseUser.
736      *
737      * @param databaseUser new value of databaseUser
738      */
739     public void setDatabaseUser(String databaseUser) {
740         this.databaseUser = databaseUser;
741     }
742 
743     /**
744      * The password to use when connecting to the database.
745      */
746     private String databasePassword;
747 
748     /**
749      * Get the value of databasePassword.
750      *
751      * @return the value of databasePassword
752      */
753     public String getDatabasePassword() {
754         return databasePassword;
755     }
756 
757     /**
758      * Set the value of databasePassword.
759      *
760      * @param databasePassword new value of databasePassword
761      */
762     public void setDatabasePassword(String databasePassword) {
763         this.databasePassword = databasePassword;
764     }
765 
766     /**
767      * Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat
768      * like ZIP files.
769      */
770     private String zipExtensions;
771 
772     /**
773      * Get the value of zipExtensions.
774      *
775      * @return the value of zipExtensions
776      */
777     public String getZipExtensions() {
778         return zipExtensions;
779     }
780 
781     /**
782      * Set the value of zipExtensions.
783      *
784      * @param zipExtensions new value of zipExtensions
785      */
786     public void setZipExtensions(String zipExtensions) {
787         this.zipExtensions = zipExtensions;
788     }
789 
790     /**
791      * The url for the modified NVD CVE (1.2 schema).
792      */
793     private String cveUrl12Modified;
794 
795     /**
796      * Get the value of cveUrl12Modified.
797      *
798      * @return the value of cveUrl12Modified
799      */
800     public String getCveUrl12Modified() {
801         return cveUrl12Modified;
802     }
803 
804     /**
805      * Set the value of cveUrl12Modified.
806      *
807      * @param cveUrl12Modified new value of cveUrl12Modified
808      */
809     public void setCveUrl12Modified(String cveUrl12Modified) {
810         this.cveUrl12Modified = cveUrl12Modified;
811     }
812 
813     /**
814      * The url for the modified NVD CVE (2.0 schema).
815      */
816     private String cveUrl20Modified;
817 
818     /**
819      * Get the value of cveUrl20Modified.
820      *
821      * @return the value of cveUrl20Modified
822      */
823     public String getCveUrl20Modified() {
824         return cveUrl20Modified;
825     }
826 
827     /**
828      * Set the value of cveUrl20Modified.
829      *
830      * @param cveUrl20Modified new value of cveUrl20Modified
831      */
832     public void setCveUrl20Modified(String cveUrl20Modified) {
833         this.cveUrl20Modified = cveUrl20Modified;
834     }
835 
836     /**
837      * Base Data Mirror URL for CVE 1.2.
838      */
839     private String cveUrl12Base;
840 
841     /**
842      * Get the value of cveUrl12Base.
843      *
844      * @return the value of cveUrl12Base
845      */
846     public String getCveUrl12Base() {
847         return cveUrl12Base;
848     }
849 
850     /**
851      * Set the value of cveUrl12Base.
852      *
853      * @param cveUrl12Base new value of cveUrl12Base
854      */
855     public void setCveUrl12Base(String cveUrl12Base) {
856         this.cveUrl12Base = cveUrl12Base;
857     }
858 
859     /**
860      * Data Mirror URL for CVE 2.0.
861      */
862     private String cveUrl20Base;
863 
864     /**
865      * Get the value of cveUrl20Base.
866      *
867      * @return the value of cveUrl20Base
868      */
869     public String getCveUrl20Base() {
870         return cveUrl20Base;
871     }
872 
873     /**
874      * Set the value of cveUrl20Base.
875      *
876      * @param cveUrl20Base new value of cveUrl20Base
877      */
878     public void setCveUrl20Base(String cveUrl20Base) {
879         this.cveUrl20Base = cveUrl20Base;
880     }
881     /**
882      * The path to Mono for .NET assembly analysis on non-windows systems.
883      */
884     private String pathToMono;
885 
886     /**
887      * Get the value of pathToMono.
888      *
889      * @return the value of pathToMono
890      */
891     public String getPathToMono() {
892         return pathToMono;
893     }
894 
895     /**
896      * Set the value of pathToMono.
897      *
898      * @param pathToMono new value of pathToMono
899      */
900     public void setPathToMono(String pathToMono) {
901         this.pathToMono = pathToMono;
902     }
903 
904     @Override
905     public void execute() throws BuildException {
906         final InputStream in = DependencyCheckTask.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
907         LogUtils.prepareLogger(in, logFile);
908 
909         dealWithReferences();
910         validateConfiguration();
911         populateSettings();
912 
913         Engine engine = null;
914         try {
915             engine = new Engine(DependencyCheckTask.class.getClassLoader());
916 
917             for (Resource resource : path) {
918                 final FileProvider provider = resource.as(FileProvider.class);
919                 if (provider != null) {
920                     final File file = provider.getFile();
921                     if (file != null && file.exists()) {
922                         engine.scan(file);
923                     }
924                 }
925             }
926             try {
927                 engine.analyzeDependencies();
928                 DatabaseProperties prop = null;
929                 CveDB cve = null;
930                 try {
931                     cve = new CveDB();
932                     cve.open();
933                     prop = cve.getDatabaseProperties();
934                 } catch (DatabaseException ex) {
935                     LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
936                 } finally {
937                     if (cve != null) {
938                         cve.close();
939                     }
940                 }
941                 final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
942                 reporter.generateReports(reportOutputDirectory, reportFormat);
943 
944                 if (this.failBuildOnCVSS <= 10) {
945                     checkForFailure(engine.getDependencies());
946                 }
947                 if (this.showSummary) {
948                     showSummary(engine.getDependencies());
949                 }
950             } catch (IOException ex) {
951                 LOGGER.log(Level.FINE, "Unable to generate dependency-check report", ex);
952                 throw new BuildException("Unable to generate dependency-check report", ex);
953             } catch (Exception ex) {
954                 LOGGER.log(Level.FINE, "An exception occurred; unable to continue task", ex);
955                 throw new BuildException("An exception occurred; unable to continue task", ex);
956             }
957         } catch (DatabaseException ex) {
958             LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
959             LOGGER.log(Level.FINE, "", ex);
960         } finally {
961             Settings.cleanup(true);
962             if (engine != null) {
963                 engine.cleanup();
964             }
965         }
966     }
967 
968     /**
969      * Validate the configuration to ensure the parameters have been properly configured/initialized.
970      *
971      * @throws BuildException if the task was not configured correctly.
972      */
973     private void validateConfiguration() throws BuildException {
974         if (path == null) {
975             throw new BuildException("No project dependencies have been defined to analyze.");
976         }
977         if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) {
978             throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11.");
979         }
980     }
981 
982     /**
983      * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system
984      * properties required to change the proxy server, port, and connection timeout.
985      */
986     private void populateSettings() {
987         Settings.initialize();
988         InputStream taskProperties = null;
989         try {
990             taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
991             Settings.mergeProperties(taskProperties);
992         } catch (IOException ex) {
993             LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
994             LOGGER.log(Level.FINE, null, ex);
995         } finally {
996             if (taskProperties != null) {
997                 try {
998                     taskProperties.close();
999                 } catch (IOException ex) {
1000                     LOGGER.log(Level.FINEST, null, ex);
1001                 }
1002             }
1003         }
1004         if (dataDirectory != null) {
1005             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
1006         } else {
1007             final File jarPath = new File(DependencyCheckTask.class.getProtectionDomain().getCodeSource().getLocation().getPath());
1008             final File base = jarPath.getParentFile();
1009             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
1010             final File dataDir = new File(base, sub);
1011             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
1012         }
1013 
1014         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
1015 
1016         if (proxyServer != null && !proxyServer.isEmpty()) {
1017             Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
1018         }
1019         if (proxyPort != null && !proxyPort.isEmpty()) {
1020             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
1021         }
1022         if (proxyUsername != null && !proxyUsername.isEmpty()) {
1023             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
1024         }
1025         if (proxyPassword != null && !proxyPassword.isEmpty()) {
1026             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
1027         }
1028         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
1029             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
1030         }
1031         if (suppressionFile != null && !suppressionFile.isEmpty()) {
1032             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
1033         }
1034 
1035         //File Type Analyzer Settings
1036         //JAR ANALYZER
1037         Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
1038         //NUSPEC ANALYZER
1039         Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
1040         //CENTRAL ANALYZER
1041         Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
1042         //NEXUS ANALYZER
1043         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
1044         if (nexusUrl != null && !nexusUrl.isEmpty()) {
1045             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
1046         }
1047         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
1048         //ARCHIVE ANALYZER
1049         Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
1050         if (zipExtensions != null && !zipExtensions.isEmpty()) {
1051             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
1052         }
1053         //ASSEMBLY ANALYZER
1054         Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
1055         if (pathToMono != null && !pathToMono.isEmpty()) {
1056             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
1057         }
1058 
1059         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
1060             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
1061         }
1062         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
1063             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
1064         }
1065         if (connectionString != null && !connectionString.isEmpty()) {
1066             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
1067         }
1068         if (databaseUser != null && !databaseUser.isEmpty()) {
1069             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
1070         }
1071         if (databasePassword != null && !databasePassword.isEmpty()) {
1072             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
1073         }
1074         if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
1075             Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
1076         }
1077         if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
1078             Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
1079         }
1080         if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
1081             Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
1082         }
1083         if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
1084             Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
1085         }
1086     }
1087 
1088     /**
1089      * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
1090      * configuration.
1091      *
1092      * @param dependencies the list of dependency objects
1093      * @throws BuildException thrown if a CVSS score is found that is higher then the threshold set
1094      */
1095     private void checkForFailure(List<Dependency> dependencies) throws BuildException {
1096         final StringBuilder ids = new StringBuilder();
1097         for (Dependency d : dependencies) {
1098             for (Vulnerability v : d.getVulnerabilities()) {
1099                 if (v.getCvssScore() >= failBuildOnCVSS) {
1100                     if (ids.length() == 0) {
1101                         ids.append(v.getName());
1102                     } else {
1103                         ids.append(", ").append(v.getName());
1104                     }
1105                 }
1106             }
1107         }
1108         if (ids.length() > 0) {
1109             final String msg = String.format("%n%nDependency-Check Failure:%n"
1110                     + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
1111                     + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
1112             throw new BuildException(msg);
1113         }
1114     }
1115 
1116     /**
1117      * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
1118      *
1119      * @param dependencies a list of dependency objects
1120      */
1121     private void showSummary(List<Dependency> dependencies) {
1122         final StringBuilder summary = new StringBuilder();
1123         for (Dependency d : dependencies) {
1124             boolean firstEntry = true;
1125             final StringBuilder ids = new StringBuilder();
1126             for (Vulnerability v : d.getVulnerabilities()) {
1127                 if (firstEntry) {
1128                     firstEntry = false;
1129                 } else {
1130                     ids.append(", ");
1131                 }
1132                 ids.append(v.getName());
1133             }
1134             if (ids.length() > 0) {
1135                 summary.append(d.getFileName()).append(" (");
1136                 firstEntry = true;
1137                 for (Identifier id : d.getIdentifiers()) {
1138                     if (firstEntry) {
1139                         firstEntry = false;
1140                     } else {
1141                         summary.append(", ");
1142                     }
1143                     summary.append(id.getValue());
1144                 }
1145                 summary.append(") : ").append(ids).append(NEW_LINE);
1146             }
1147         }
1148         if (summary.length() > 0) {
1149             final String msg = String.format("%n%n"
1150                     + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
1151                     + "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
1152             LOGGER.log(Level.WARNING, msg);
1153         }
1154     }
1155 
1156     /**
1157      * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", etc..
1158      */
1159     public static class ReportFormats extends EnumeratedAttribute {
1160 
1161         /**
1162          * Returns the list of values for the report format.
1163          *
1164          * @return the list of values for the report format
1165          */
1166         @Override
1167         public String[] getValues() {
1168             int i = 0;
1169             final Format[] formats = Format.values();
1170             final String[] values = new String[formats.length];
1171             for (Format format : formats) {
1172                 values[i++] = format.name();
1173             }
1174             return values;
1175         }
1176     }
1177 
1178     /**
1179      * Whether or not the Jar Analyzer is enabled.
1180      */
1181     private boolean jarAnalyzerEnabled = true;
1182 
1183     /**
1184      * Returns whether or not the analyzer is enabled.
1185      *
1186      * @return true if the analyzer is enabled
1187      */
1188     public boolean isJarAnalyzerEnabled() {
1189         return jarAnalyzerEnabled;
1190     }
1191 }