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
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 path
102      * 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 which
219      * 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
220      * 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 false. Default
243      * 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     private boolean updateOnly = false;
266 
267     /**
268      * Get the value of updateOnly
269      *
270      * @return the value of updateOnly
271      */
272     public boolean isUpdateOnly() {
273         return updateOnly;
274     }
275 
276     /**
277      * Set the value of updateOnly
278      *
279      * @param updateOnly new value of updateOnly
280      */
281     public void setUpdateOnly(boolean updateOnly) {
282         this.updateOnly = updateOnly;
283     }
284 
285     /**
286      * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the
287      * Site plugin unless the externalReport is set to true. Default is HTML.
288      */
289     private String reportFormat = "HTML";
290 
291     /**
292      * Get the value of reportFormat.
293      *
294      * @return the value of reportFormat
295      */
296     public String getReportFormat() {
297         return reportFormat;
298     }
299 
300     /**
301      * Set the value of reportFormat.
302      *
303      * @param reportFormat new value of reportFormat
304      */
305     public void setReportFormat(ReportFormats reportFormat) {
306         this.reportFormat = reportFormat.getValue();
307     }
308     /**
309      * The Proxy Server.
310      */
311     private String proxyServer;
312 
313     /**
314      * Get the value of proxyServer.
315      *
316      * @return the value of proxyServer
317      */
318     public String getProxyServer() {
319         return proxyServer;
320     }
321 
322     /**
323      * Set the value of proxyServer.
324      *
325      * @param server new value of proxyServer
326      */
327     public void setProxyServer(String server) {
328         this.proxyServer = server;
329     }
330 
331     /**
332      * Get the value of proxyServer.
333      *
334      * @return the value of proxyServer
335      * @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#getProxyServer()} instead
336      */
337     @Deprecated
338     public String getProxyUrl() {
339         return proxyServer;
340     }
341 
342     /**
343      * Set the value of proxyServer.
344      *
345      * @param proxyUrl new value of proxyServer
346      * @deprecated use {@link org.owasp.dependencycheck.taskdefs.DependencyCheckTask#setProxyServer(java.lang.String)} instead
347      */
348     @Deprecated
349     public void setProxyUrl(String proxyUrl) {
350         LOGGER.warning("A deprecated configuration option 'proxyUrl' was detected; use 'proxyServer' instead.");
351         this.proxyServer = proxyUrl;
352     }
353     /**
354      * The Proxy Port.
355      */
356     private String proxyPort;
357 
358     /**
359      * Get the value of proxyPort.
360      *
361      * @return the value of proxyPort
362      */
363     public String getProxyPort() {
364         return proxyPort;
365     }
366 
367     /**
368      * Set the value of proxyPort.
369      *
370      * @param proxyPort new value of proxyPort
371      */
372     public void setProxyPort(String proxyPort) {
373         this.proxyPort = proxyPort;
374     }
375     /**
376      * The Proxy username.
377      */
378     private String proxyUsername;
379 
380     /**
381      * Get the value of proxyUsername.
382      *
383      * @return the value of proxyUsername
384      */
385     public String getProxyUsername() {
386         return proxyUsername;
387     }
388 
389     /**
390      * Set the value of proxyUsername.
391      *
392      * @param proxyUsername new value of proxyUsername
393      */
394     public void setProxyUsername(String proxyUsername) {
395         this.proxyUsername = proxyUsername;
396     }
397     /**
398      * The Proxy password.
399      */
400     private String proxyPassword;
401 
402     /**
403      * Get the value of proxyPassword.
404      *
405      * @return the value of proxyPassword
406      */
407     public String getProxyPassword() {
408         return proxyPassword;
409     }
410 
411     /**
412      * Set the value of proxyPassword.
413      *
414      * @param proxyPassword new value of proxyPassword
415      */
416     public void setProxyPassword(String proxyPassword) {
417         this.proxyPassword = proxyPassword;
418     }
419     /**
420      * The Connection Timeout.
421      */
422     private String connectionTimeout;
423 
424     /**
425      * Get the value of connectionTimeout.
426      *
427      * @return the value of connectionTimeout
428      */
429     public String getConnectionTimeout() {
430         return connectionTimeout;
431     }
432 
433     /**
434      * Set the value of connectionTimeout.
435      *
436      * @param connectionTimeout new value of connectionTimeout
437      */
438     public void setConnectionTimeout(String connectionTimeout) {
439         this.connectionTimeout = connectionTimeout;
440     }
441     /**
442      * The file path used for verbose logging.
443      */
444     private String logFile = null;
445 
446     /**
447      * Get the value of logFile.
448      *
449      * @return the value of logFile
450      */
451     public String getLogFile() {
452         return logFile;
453     }
454 
455     /**
456      * Set the value of logFile.
457      *
458      * @param logFile new value of logFile
459      */
460     public void setLogFile(String logFile) {
461         this.logFile = logFile;
462     }
463     /**
464      * The path to the suppression file.
465      */
466     private String suppressionFile;
467 
468     /**
469      * Get the value of suppressionFile.
470      *
471      * @return the value of suppressionFile
472      */
473     public String getSuppressionFile() {
474         return suppressionFile;
475     }
476 
477     /**
478      * Set the value of suppressionFile.
479      *
480      * @param suppressionFile new value of suppressionFile
481      */
482     public void setSuppressionFile(String suppressionFile) {
483         this.suppressionFile = suppressionFile;
484     }
485     /**
486      * flag indicating whether or not to show a summary of findings.
487      */
488     private boolean showSummary = true;
489 
490     /**
491      * Get the value of showSummary.
492      *
493      * @return the value of showSummary
494      */
495     public boolean isShowSummary() {
496         return showSummary;
497     }
498 
499     /**
500      * Set the value of showSummary.
501      *
502      * @param showSummary new value of showSummary
503      */
504     public void setShowSummary(boolean showSummary) {
505         this.showSummary = showSummary;
506     }
507 
508     /**
509      * Sets whether or not the analyzer is enabled.
510      *
511      * @param jarAnalyzerEnabled the value of the new setting
512      */
513     public void setJarAnalyzerEnabled(boolean jarAnalyzerEnabled) {
514         this.jarAnalyzerEnabled = jarAnalyzerEnabled;
515     }
516     /**
517      * Whether or not the Archive Analyzer is enabled.
518      */
519     private boolean archiveAnalyzerEnabled = true;
520 
521     /**
522      * Returns whether or not the analyzer is enabled.
523      *
524      * @return true if the analyzer is enabled
525      */
526     public boolean isArchiveAnalyzerEnabled() {
527         return archiveAnalyzerEnabled;
528     }
529     /**
530      * Whether or not the .NET Assembly Analyzer is enabled.
531      */
532     private boolean assemblyAnalyzerEnabled = true;
533 
534     /**
535      * Sets whether or not the analyzer is enabled.
536      *
537      * @param archiveAnalyzerEnabled the value of the new setting
538      */
539     public void setArchiveAnalyzerEnabled(boolean archiveAnalyzerEnabled) {
540         this.archiveAnalyzerEnabled = archiveAnalyzerEnabled;
541     }
542 
543     /**
544      * Returns whether or not the analyzer is enabled.
545      *
546      * @return true if the analyzer is enabled
547      */
548     public boolean isAssemblyAnalyzerEnabled() {
549         return assemblyAnalyzerEnabled;
550     }
551 
552     /**
553      * Sets whether or not the analyzer is enabled.
554      *
555      * @param assemblyAnalyzerEnabled the value of the new setting
556      */
557     public void setAssemblyAnalyzerEnabled(boolean assemblyAnalyzerEnabled) {
558         this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled;
559     }
560     /**
561      * Whether or not the .NET Nuspec Analyzer is enabled.
562      */
563     private boolean nuspecAnalyzerEnabled = true;
564 
565     /**
566      * Returns whether or not the analyzer is enabled.
567      *
568      * @return true if the analyzer is enabled
569      */
570     public boolean isNuspecAnalyzerEnabled() {
571         return nuspecAnalyzerEnabled;
572     }
573 
574     /**
575      * Sets whether or not the analyzer is enabled.
576      *
577      * @param nuspecAnalyzerEnabled the value of the new setting
578      */
579     public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
580         this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
581     }
582     /**
583      * Whether or not the central analyzer is enabled.
584      */
585     private boolean centralAnalyzerEnabled = false;
586 
587     /**
588      * Get the value of centralAnalyzerEnabled.
589      *
590      * @return the value of centralAnalyzerEnabled
591      */
592     public boolean isCentralAnalyzerEnabled() {
593         return centralAnalyzerEnabled;
594     }
595 
596     /**
597      * Set the value of centralAnalyzerEnabled.
598      *
599      * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
600      */
601     public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) {
602         this.centralAnalyzerEnabled = centralAnalyzerEnabled;
603     }
604 
605     /**
606      * Whether or not the nexus analyzer is enabled.
607      */
608     private boolean nexusAnalyzerEnabled = true;
609 
610     /**
611      * Get the value of nexusAnalyzerEnabled.
612      *
613      * @return the value of nexusAnalyzerEnabled
614      */
615     public boolean isNexusAnalyzerEnabled() {
616         return nexusAnalyzerEnabled;
617     }
618 
619     /**
620      * Set the value of nexusAnalyzerEnabled.
621      *
622      * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
623      */
624     public void setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) {
625         this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
626     }
627 
628     /**
629      * The URL of the Nexus server.
630      */
631     private String nexusUrl;
632 
633     /**
634      * Get the value of nexusUrl.
635      *
636      * @return the value of nexusUrl
637      */
638     public String getNexusUrl() {
639         return nexusUrl;
640     }
641 
642     /**
643      * Set the value of nexusUrl.
644      *
645      * @param nexusUrl new value of nexusUrl
646      */
647     public void setNexusUrl(String nexusUrl) {
648         this.nexusUrl = nexusUrl;
649     }
650     /**
651      * Whether or not the defined proxy should be used when connecting to Nexus.
652      */
653     private boolean nexusUsesProxy = true;
654 
655     /**
656      * Get the value of nexusUsesProxy.
657      *
658      * @return the value of nexusUsesProxy
659      */
660     public boolean isNexusUsesProxy() {
661         return nexusUsesProxy;
662     }
663 
664     /**
665      * Set the value of nexusUsesProxy.
666      *
667      * @param nexusUsesProxy new value of nexusUsesProxy
668      */
669     public void setNexusUsesProxy(boolean nexusUsesProxy) {
670         this.nexusUsesProxy = nexusUsesProxy;
671     }
672 
673     /**
674      * The database driver name; such as org.h2.Driver.
675      */
676     private String databaseDriverName;
677 
678     /**
679      * Get the value of databaseDriverName.
680      *
681      * @return the value of databaseDriverName
682      */
683     public String getDatabaseDriverName() {
684         return databaseDriverName;
685     }
686 
687     /**
688      * Set the value of databaseDriverName.
689      *
690      * @param databaseDriverName new value of databaseDriverName
691      */
692     public void setDatabaseDriverName(String databaseDriverName) {
693         this.databaseDriverName = databaseDriverName;
694     }
695 
696     /**
697      * The path to the database driver JAR file if it is not on the class path.
698      */
699     private String databaseDriverPath;
700 
701     /**
702      * Get the value of databaseDriverPath.
703      *
704      * @return the value of databaseDriverPath
705      */
706     public String getDatabaseDriverPath() {
707         return databaseDriverPath;
708     }
709 
710     /**
711      * Set the value of databaseDriverPath.
712      *
713      * @param databaseDriverPath new value of databaseDriverPath
714      */
715     public void setDatabaseDriverPath(String databaseDriverPath) {
716         this.databaseDriverPath = databaseDriverPath;
717     }
718     /**
719      * The database connection string.
720      */
721     private String connectionString;
722 
723     /**
724      * Get the value of connectionString.
725      *
726      * @return the value of connectionString
727      */
728     public String getConnectionString() {
729         return connectionString;
730     }
731 
732     /**
733      * Set the value of connectionString.
734      *
735      * @param connectionString new value of connectionString
736      */
737     public void setConnectionString(String connectionString) {
738         this.connectionString = connectionString;
739     }
740     /**
741      * The user name for connecting to the database.
742      */
743     private String databaseUser;
744 
745     /**
746      * Get the value of databaseUser.
747      *
748      * @return the value of databaseUser
749      */
750     public String getDatabaseUser() {
751         return databaseUser;
752     }
753 
754     /**
755      * Set the value of databaseUser.
756      *
757      * @param databaseUser new value of databaseUser
758      */
759     public void setDatabaseUser(String databaseUser) {
760         this.databaseUser = databaseUser;
761     }
762 
763     /**
764      * The password to use when connecting to the database.
765      */
766     private String databasePassword;
767 
768     /**
769      * Get the value of databasePassword.
770      *
771      * @return the value of databasePassword
772      */
773     public String getDatabasePassword() {
774         return databasePassword;
775     }
776 
777     /**
778      * Set the value of databasePassword.
779      *
780      * @param databasePassword new value of databasePassword
781      */
782     public void setDatabasePassword(String databasePassword) {
783         this.databasePassword = databasePassword;
784     }
785 
786     /**
787      * Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat like ZIP
788      * files.
789      */
790     private String zipExtensions;
791 
792     /**
793      * Get the value of zipExtensions.
794      *
795      * @return the value of zipExtensions
796      */
797     public String getZipExtensions() {
798         return zipExtensions;
799     }
800 
801     /**
802      * Set the value of zipExtensions.
803      *
804      * @param zipExtensions new value of zipExtensions
805      */
806     public void setZipExtensions(String zipExtensions) {
807         this.zipExtensions = zipExtensions;
808     }
809 
810     /**
811      * The url for the modified NVD CVE (1.2 schema).
812      */
813     private String cveUrl12Modified;
814 
815     /**
816      * Get the value of cveUrl12Modified.
817      *
818      * @return the value of cveUrl12Modified
819      */
820     public String getCveUrl12Modified() {
821         return cveUrl12Modified;
822     }
823 
824     /**
825      * Set the value of cveUrl12Modified.
826      *
827      * @param cveUrl12Modified new value of cveUrl12Modified
828      */
829     public void setCveUrl12Modified(String cveUrl12Modified) {
830         this.cveUrl12Modified = cveUrl12Modified;
831     }
832 
833     /**
834      * The url for the modified NVD CVE (2.0 schema).
835      */
836     private String cveUrl20Modified;
837 
838     /**
839      * Get the value of cveUrl20Modified.
840      *
841      * @return the value of cveUrl20Modified
842      */
843     public String getCveUrl20Modified() {
844         return cveUrl20Modified;
845     }
846 
847     /**
848      * Set the value of cveUrl20Modified.
849      *
850      * @param cveUrl20Modified new value of cveUrl20Modified
851      */
852     public void setCveUrl20Modified(String cveUrl20Modified) {
853         this.cveUrl20Modified = cveUrl20Modified;
854     }
855 
856     /**
857      * Base Data Mirror URL for CVE 1.2.
858      */
859     private String cveUrl12Base;
860 
861     /**
862      * Get the value of cveUrl12Base.
863      *
864      * @return the value of cveUrl12Base
865      */
866     public String getCveUrl12Base() {
867         return cveUrl12Base;
868     }
869 
870     /**
871      * Set the value of cveUrl12Base.
872      *
873      * @param cveUrl12Base new value of cveUrl12Base
874      */
875     public void setCveUrl12Base(String cveUrl12Base) {
876         this.cveUrl12Base = cveUrl12Base;
877     }
878 
879     /**
880      * Data Mirror URL for CVE 2.0.
881      */
882     private String cveUrl20Base;
883 
884     /**
885      * Get the value of cveUrl20Base.
886      *
887      * @return the value of cveUrl20Base
888      */
889     public String getCveUrl20Base() {
890         return cveUrl20Base;
891     }
892 
893     /**
894      * Set the value of cveUrl20Base.
895      *
896      * @param cveUrl20Base new value of cveUrl20Base
897      */
898     public void setCveUrl20Base(String cveUrl20Base) {
899         this.cveUrl20Base = cveUrl20Base;
900     }
901     /**
902      * The path to Mono for .NET assembly analysis on non-windows systems.
903      */
904     private String pathToMono;
905 
906     /**
907      * Get the value of pathToMono.
908      *
909      * @return the value of pathToMono
910      */
911     public String getPathToMono() {
912         return pathToMono;
913     }
914 
915     /**
916      * Set the value of pathToMono.
917      *
918      * @param pathToMono new value of pathToMono
919      */
920     public void setPathToMono(String pathToMono) {
921         this.pathToMono = pathToMono;
922     }
923 
924     @Override
925     public void execute() throws BuildException {
926         final InputStream in = DependencyCheckTask.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
927         LogUtils.prepareLogger(in, logFile);
928 
929         dealWithReferences();
930         validateConfiguration();
931         populateSettings();
932 
933         Engine engine = null;
934         try {
935             engine = new Engine(DependencyCheckTask.class.getClassLoader());
936             //todo - should this be its own task?
937             if (updateOnly) {
938                 engine.doUpdates();
939             } else {
940                 try {
941                     for (Resource resource : path) {
942                         final FileProvider provider = resource.as(FileProvider.class);
943                         if (provider != null) {
944                             final File file = provider.getFile();
945                             if (file != null && file.exists()) {
946                                 engine.scan(file);
947                             }
948                         }
949                     }
950 
951                     engine.analyzeDependencies();
952                     DatabaseProperties prop = null;
953                     CveDB cve = null;
954                     try {
955                         cve = new CveDB();
956                         cve.open();
957                         prop = cve.getDatabaseProperties();
958                     } catch (DatabaseException ex) {
959                         LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
960                     } finally {
961                         if (cve != null) {
962                             cve.close();
963                         }
964                     }
965                     final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
966                     reporter.generateReports(reportOutputDirectory, reportFormat);
967 
968                     if (this.failBuildOnCVSS <= 10) {
969                         checkForFailure(engine.getDependencies());
970                     }
971                     if (this.showSummary) {
972                         showSummary(engine.getDependencies());
973                     }
974                 } catch (IOException ex) {
975                     LOGGER.log(Level.FINE, "Unable to generate dependency-check report", ex);
976                     throw new BuildException("Unable to generate dependency-check report", ex);
977                 } catch (Exception ex) {
978                     LOGGER.log(Level.FINE, "An exception occurred; unable to continue task", ex);
979                     throw new BuildException("An exception occurred; unable to continue task", ex);
980                 }
981             }
982         } catch (DatabaseException ex) {
983             LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
984             LOGGER.log(Level.FINE, "", ex);
985         } finally {
986             Settings.cleanup(true);
987             if (engine != null) {
988                 engine.cleanup();
989             }
990         }
991     }
992 
993     /**
994      * Validate the configuration to ensure the parameters have been properly configured/initialized.
995      *
996      * @throws BuildException if the task was not configured correctly.
997      */
998     private void validateConfiguration() throws BuildException {
999         if (path == null) {
1000             throw new BuildException("No project dependencies have been defined to analyze.");
1001         }
1002         if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) {
1003             throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11.");
1004         }
1005     }
1006 
1007     /**
1008      * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
1009      * required to change the proxy server, port, and connection timeout.
1010      */
1011     private void populateSettings() {
1012         Settings.initialize();
1013         InputStream taskProperties = null;
1014         try {
1015             taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
1016             Settings.mergeProperties(taskProperties);
1017         } catch (IOException ex) {
1018             LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
1019             LOGGER.log(Level.FINE, null, ex);
1020         } finally {
1021             if (taskProperties != null) {
1022                 try {
1023                     taskProperties.close();
1024                 } catch (IOException ex) {
1025                     LOGGER.log(Level.FINEST, null, ex);
1026                 }
1027             }
1028         }
1029         if (dataDirectory != null) {
1030             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
1031         } else {
1032             final File jarPath = new File(DependencyCheckTask.class.getProtectionDomain().getCodeSource().getLocation().getPath());
1033             final File base = jarPath.getParentFile();
1034             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
1035             final File dataDir = new File(base, sub);
1036             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
1037         }
1038 
1039         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
1040 
1041         if (proxyServer != null && !proxyServer.isEmpty()) {
1042             Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
1043         }
1044         if (proxyPort != null && !proxyPort.isEmpty()) {
1045             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
1046         }
1047         if (proxyUsername != null && !proxyUsername.isEmpty()) {
1048             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
1049         }
1050         if (proxyPassword != null && !proxyPassword.isEmpty()) {
1051             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
1052         }
1053         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
1054             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
1055         }
1056         if (suppressionFile != null && !suppressionFile.isEmpty()) {
1057             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
1058         }
1059 
1060         //File Type Analyzer Settings
1061         //JAR ANALYZER
1062         Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
1063         //NUSPEC ANALYZER
1064         Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
1065         //CENTRAL ANALYZER
1066         Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
1067         //NEXUS ANALYZER
1068         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
1069         if (nexusUrl != null && !nexusUrl.isEmpty()) {
1070             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
1071         }
1072         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
1073         //ARCHIVE ANALYZER
1074         Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
1075         if (zipExtensions != null && !zipExtensions.isEmpty()) {
1076             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
1077         }
1078         //ASSEMBLY ANALYZER
1079         Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
1080         if (pathToMono != null && !pathToMono.isEmpty()) {
1081             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
1082         }
1083 
1084         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
1085             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
1086         }
1087         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
1088             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
1089         }
1090         if (connectionString != null && !connectionString.isEmpty()) {
1091             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
1092         }
1093         if (databaseUser != null && !databaseUser.isEmpty()) {
1094             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
1095         }
1096         if (databasePassword != null && !databasePassword.isEmpty()) {
1097             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
1098         }
1099         if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
1100             Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
1101         }
1102         if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
1103             Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
1104         }
1105         if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
1106             Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
1107         }
1108         if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
1109             Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
1110         }
1111     }
1112 
1113     /**
1114      * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
1115      * configuration.
1116      *
1117      * @param dependencies the list of dependency objects
1118      * @throws BuildException thrown if a CVSS score is found that is higher then the threshold set
1119      */
1120     private void checkForFailure(List<Dependency> dependencies) throws BuildException {
1121         final StringBuilder ids = new StringBuilder();
1122         for (Dependency d : dependencies) {
1123             for (Vulnerability v : d.getVulnerabilities()) {
1124                 if (v.getCvssScore() >= failBuildOnCVSS) {
1125                     if (ids.length() == 0) {
1126                         ids.append(v.getName());
1127                     } else {
1128                         ids.append(", ").append(v.getName());
1129                     }
1130                 }
1131             }
1132         }
1133         if (ids.length() > 0) {
1134             final String msg = String.format("%n%nDependency-Check Failure:%n"
1135                     + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
1136                     + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
1137             throw new BuildException(msg);
1138         }
1139     }
1140 
1141     /**
1142      * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
1143      *
1144      * @param dependencies a list of dependency objects
1145      */
1146     private void showSummary(List<Dependency> dependencies) {
1147         final StringBuilder summary = new StringBuilder();
1148         for (Dependency d : dependencies) {
1149             boolean firstEntry = true;
1150             final StringBuilder ids = new StringBuilder();
1151             for (Vulnerability v : d.getVulnerabilities()) {
1152                 if (firstEntry) {
1153                     firstEntry = false;
1154                 } else {
1155                     ids.append(", ");
1156                 }
1157                 ids.append(v.getName());
1158             }
1159             if (ids.length() > 0) {
1160                 summary.append(d.getFileName()).append(" (");
1161                 firstEntry = true;
1162                 for (Identifier id : d.getIdentifiers()) {
1163                     if (firstEntry) {
1164                         firstEntry = false;
1165                     } else {
1166                         summary.append(", ");
1167                     }
1168                     summary.append(id.getValue());
1169                 }
1170                 summary.append(") : ").append(ids).append(NEW_LINE);
1171             }
1172         }
1173         if (summary.length() > 0) {
1174             final String msg = String.format("%n%n"
1175                     + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
1176                     + "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
1177             LOGGER.log(Level.WARNING, msg);
1178         }
1179     }
1180 
1181     /**
1182      * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", etc..
1183      */
1184     public static class ReportFormats extends EnumeratedAttribute {
1185 
1186         /**
1187          * Returns the list of values for the report format.
1188          *
1189          * @return the list of values for the report format
1190          */
1191         @Override
1192         public String[] getValues() {
1193             int i = 0;
1194             final Format[] formats = Format.values();
1195             final String[] values = new String[formats.length];
1196             for (Format format : formats) {
1197                 values[i++] = format.name();
1198             }
1199             return values;
1200         }
1201     }
1202 
1203     /**
1204      * Whether or not the Jar Analyzer is enabled.
1205      */
1206     private boolean jarAnalyzerEnabled = true;
1207 
1208     /**
1209      * Returns whether or not the analyzer is enabled.
1210      *
1211      * @return true if the analyzer is enabled
1212      */
1213     public boolean isJarAnalyzerEnabled() {
1214         return jarAnalyzerEnabled;
1215     }
1216 }