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