@@ -68,11 +68,20 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
6868 */
6969 private static final FileFilter OPENSSLV_FILTER = FileFilterBuilder .newInstance ().addFilenames (OPENSSLV_H ).build ();
7070 /**
71- * Open SSL Version number pattern.
71+ * Open SSL Version number pattern (OpenSSL 1.x and earlier — literal hex constant) .
7272 */
7373 private static final Pattern VERSION_PATTERN = Pattern .compile (
7474 "define\\ s+OPENSSL_VERSION_NUMBER\\ s+0x([0-9a-zA-Z]{8})L" , Pattern .DOTALL
7575 | Pattern .CASE_INSENSITIVE );
76+ /**
77+ * Open SSL version string pattern (OpenSSL 3.x — {@code OPENSSL_VERSION_STR "X.Y.Z"}).
78+ * In 3.x, {@code OPENSSL_VERSION_NUMBER} is a macro expression that the
79+ * legacy {@link #VERSION_PATTERN} cannot match, so this is the authoritative
80+ * source of the version on 3.x headers.
81+ */
82+ private static final Pattern VERSION_STR_PATTERN = Pattern .compile (
83+ "define\\ s+OPENSSL_VERSION_STR\\ s+\" ([^\" ]+)\" " , Pattern .DOTALL
84+ | Pattern .CASE_INSENSITIVE );
7685 /**
7786 * The offset of the major version number.
7887 */
@@ -191,28 +200,31 @@ protected void analyzeDependency(Dependency dependency, Engine engine)
191200 throws AnalysisException {
192201 final File file = dependency .getActualFile ();
193202 final String parentName = file .getParentFile ().getName ();
194- boolean found = false ;
195203 final String contents = getFileContents (file );
204+ String version = null ;
196205 if (!contents .isEmpty ()) {
197- final Matcher matcher = VERSION_PATTERN .matcher (contents );
198- if (matcher .find ()) {
199- found = true ;
200- final String version = getOpenSSLVersion (Long .parseLong (matcher .group (1 ), HEXADECIMAL ));
201- dependency .addEvidence (EvidenceType .VERSION , OPENSSLV_H , "Version Constant" ,
202- version , Confidence .HIGH );
203- try {
204- final PackageURL purl = PackageURLBuilder .aPackageURL ().withType ("generic" )
205- .withName ("openssl" ).withVersion (version ).build ();
206- dependency .addSoftwareIdentifier (new PurlIdentifier (purl , Confidence .HIGHEST ));
207- } catch (MalformedPackageURLException ex ) {
208- LOGGER .debug ("Unable to build package url for openssl" , ex );
209- final GenericIdentifier id = new GenericIdentifier ("generic:openssl@" + version , Confidence .HIGHEST );
210- dependency .addSoftwareIdentifier (id );
206+ final Matcher strMatcher = VERSION_STR_PATTERN .matcher (contents );
207+ if (strMatcher .find ()) {
208+ version = strMatcher .group (1 );
209+ } else {
210+ final Matcher matcher = VERSION_PATTERN .matcher (contents );
211+ if (matcher .find ()) {
212+ version = getOpenSSLVersion (Long .parseLong (matcher .group (1 ), HEXADECIMAL ));
211213 }
212-
213214 }
214215 }
215- if (found ) {
216+ if (version != null ) {
217+ dependency .addEvidence (EvidenceType .VERSION , OPENSSLV_H , "Version Constant" ,
218+ version , Confidence .HIGH );
219+ try {
220+ final PackageURL purl = PackageURLBuilder .aPackageURL ().withType ("generic" )
221+ .withName ("openssl" ).withVersion (version ).build ();
222+ dependency .addSoftwareIdentifier (new PurlIdentifier (purl , Confidence .HIGHEST ));
223+ } catch (MalformedPackageURLException ex ) {
224+ LOGGER .debug ("Unable to build package url for openssl" , ex );
225+ final GenericIdentifier id = new GenericIdentifier ("generic:openssl@" + version , Confidence .HIGHEST );
226+ dependency .addSoftwareIdentifier (id );
227+ }
216228 dependency .setDisplayFileName (parentName + File .separatorChar + OPENSSLV_H );
217229 dependency .addEvidence (EvidenceType .VENDOR , OPENSSLV_H , "Vendor" , "OpenSSL" , Confidence .HIGHEST );
218230 dependency .addEvidence (EvidenceType .PRODUCT , OPENSSLV_H , "Product" , "OpenSSL" , Confidence .HIGHEST );
0 commit comments