1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.analyzer;
19
20 import org.owasp.dependencycheck.Engine;
21 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
22 import org.owasp.dependencycheck.data.composer.ComposerDependency;
23 import org.owasp.dependencycheck.data.composer.ComposerException;
24 import org.owasp.dependencycheck.data.composer.ComposerLockParser;
25 import org.owasp.dependencycheck.dependency.Confidence;
26 import org.owasp.dependencycheck.dependency.Dependency;
27 import org.owasp.dependencycheck.utils.Checksum;
28 import org.owasp.dependencycheck.utils.FileFilterBuilder;
29 import org.owasp.dependencycheck.utils.Settings;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import java.io.FileFilter;
34 import java.io.FileInputStream;
35 import java.io.FileNotFoundException;
36 import java.nio.charset.Charset;
37 import java.security.MessageDigest;
38
39
40
41
42
43
44 public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
45
46
47
48
49 private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockAnalyzer.class);
50
51
52
53
54 private static final String ANALYZER_NAME = "Composer.lock analyzer";
55
56
57
58
59 private static final String COMPOSER_LOCK = "composer.lock";
60
61
62
63
64 private static final FileFilter FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(COMPOSER_LOCK).build();
65
66
67
68
69
70
71 @Override
72 protected FileFilter getFileFilter() {
73 return FILE_FILTER;
74 }
75
76
77
78
79
80
81 @Override
82 protected void initializeFileTypeAnalyzer() throws Exception {
83 sha1 = MessageDigest.getInstance("SHA1");
84 }
85
86
87
88
89 private MessageDigest sha1 = null;
90
91
92
93
94
95
96
97
98 @Override
99 protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
100 FileInputStream fis = null;
101 try {
102 fis = new FileInputStream(dependency.getActualFile());
103 final ComposerLockParser clp = new ComposerLockParser(fis);
104 LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath());
105 clp.process();
106 for (ComposerDependency dep : clp.getDependencies()) {
107 final Dependency d = new Dependency(dependency.getActualFile());
108 d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject()));
109 final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject());
110 d.setFilePath(filePath);
111 d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset()))));
112 d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
113 d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
114 d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
115 LOGGER.info("Adding dependency {}", d);
116 engine.getDependencies().add(d);
117 }
118 } catch (FileNotFoundException fnfe) {
119 LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath());
120 } catch (ComposerException ce) {
121 LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce);
122 } finally {
123 if (fis != null) {
124 try {
125 fis.close();
126 } catch (Exception e) {
127 LOGGER.debug("Unable to close file", e);
128 }
129 }
130 }
131 }
132
133
134
135
136
137
138 @Override
139 protected String getAnalyzerEnabledSettingKey() {
140 return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED;
141 }
142
143
144
145
146
147
148 @Override
149 public String getName() {
150 return ANALYZER_NAME;
151 }
152
153
154
155
156
157
158 @Override
159 public AnalysisPhase getAnalysisPhase() {
160 return AnalysisPhase.INFORMATION_COLLECTION;
161 }
162 }