1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.data.update.nvd;
19
20 import com.fasterxml.jackson.core.JsonParser;
21 import com.fasterxml.jackson.core.JsonToken;
22 import com.fasterxml.jackson.databind.DeserializationFeature;
23 import com.fasterxml.jackson.databind.Module;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.fasterxml.jackson.databind.ObjectReader;
26 import com.fasterxml.jackson.databind.json.JsonMapper;
27 import com.fasterxml.jackson.module.blackbird.BlackbirdModule;
28 import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
29
30 import java.io.EOFException;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import static java.nio.charset.StandardCharsets.UTF_8;
38 import java.util.zip.GZIPInputStream;
39 import java.util.zip.ZipException;
40
41 import org.owasp.dependencycheck.data.nvdcve.CveDB;
42 import org.owasp.dependencycheck.data.update.exception.CorruptedDatastreamException;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
46 import org.owasp.dependencycheck.data.nvd.ecosystem.CveEcosystemMapper;
47 import org.owasp.dependencycheck.data.update.exception.UpdateException;
48 import org.owasp.dependencycheck.utils.Settings;
49 import org.owasp.dependencycheck.utils.Utils;
50
51
52
53
54
55
56 public final class NvdCveParser {
57
58
59
60
61 private static final Logger LOGGER = LoggerFactory.getLogger(NvdCveParser.class);
62
63
64
65 private final CveDB cveDB;
66
67
68
69 private final Settings settings;
70
71
72
73
74
75
76
77 public NvdCveParser(Settings settings, CveDB db) {
78 this.settings = settings;
79 this.cveDB = db;
80 }
81
82
83
84
85
86
87
88
89
90 public void parse(File file) throws UpdateException, CorruptedDatastreamException {
91 LOGGER.debug("Parsing " + file.getName());
92
93 final Module module;
94 if (Utils.getJavaVersion() <= 8) {
95 module = new AfterburnerModule();
96 } else {
97 module = new BlackbirdModule();
98 }
99 final ObjectMapper objectMapper = JsonMapper.builder()
100 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
101 .addModule(module)
102 .build();
103
104 final ObjectReader objectReader = objectMapper.readerFor(DefCveItem.class);
105
106 try (InputStream fin = new FileInputStream(file);
107 InputStream in = new GZIPInputStream(fin);
108 InputStreamReader isr = new InputStreamReader(in, UTF_8);
109 JsonParser parser = objectReader.getFactory().createParser(isr)) {
110
111 final CveEcosystemMapper mapper = new CveEcosystemMapper();
112 init(parser);
113 while (parser.nextToken() == JsonToken.START_OBJECT) {
114 final DefCveItem cve = objectReader.readValue(parser);
115 cveDB.updateVulnerability(cve, mapper.getEcosystem(cve));
116 }
117 } catch (FileNotFoundException ex) {
118 LOGGER.error(ex.getMessage());
119 throw new UpdateException("Unable to find the NVD CVE file, `" + file + "`, to parse", ex);
120 } catch (ZipException | EOFException ex) {
121 throw new CorruptedDatastreamException("Error parsing NVD CVE file", ex);
122 } catch (IOException ex) {
123 LOGGER.error("Error reading NVD JSON data: {}", file);
124 LOGGER.debug("Error extracting the NVD JSON data from: " + file, ex);
125 throw new UpdateException("Unable to find the NVD CVE file to parse", ex);
126 }
127 }
128
129 void init(JsonParser parser) throws IOException {
130 JsonToken nextToken = parser.nextToken();
131 if (nextToken != JsonToken.START_OBJECT) {
132 throw new IOException("Expected " + JsonToken.START_OBJECT + ", got " + nextToken);
133 }
134
135 do {
136 nextToken = parser.nextToken();
137 if (nextToken == null) {
138 break;
139 }
140
141 if (nextToken.isStructStart()) {
142 if (nextToken == JsonToken.START_ARRAY) {
143 break;
144 } else {
145 parser.skipChildren();
146 }
147 }
148 } while (true);
149 }
150 }