All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.owasp.dependencycheck.analyzer.CMakeAnalyzer Maven / Gradle / Ivy

Go to download

dependency-check-core is the engine and reporting tool used to identify and report if there are any known, publicly disclosed vulnerabilities in the scanned project's dependencies. The engine extracts meta-data from the dependencies and uses this to do fuzzy key-word matching against the Common Platfrom Enumeration (CPE), if any CPE identifiers are found the associated Common Vulnerability and Exposure (CVE) entries are added to the generated report.

There is a newer version: 10.0.4
Show newest version
/*
 * This file is part of dependency-check-core.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright (c) 2015 Institute for Defense Analyses. All Rights Reserved.
 */
package org.owasp.dependencycheck.analyzer;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.dependency.EvidenceType;
import org.owasp.dependencycheck.exception.InitializationException;

/**
 * 

* Used to analyze CMake build files, and collect information that can be used * to determine the associated CPE.

*

* Note: This analyzer catches straightforward invocations of the project * command, plus some other observed patterns of version inclusion in real CMake * projects. Many projects make use of older versions of CMake and/or use custom * "homebrew" ways to insert version information. Hopefully as the newer CMake * call pattern grows in usage, this analyzer allow more CPEs to be * identified.

* * @author Dale Visser */ @Experimental public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { /** * A descriptor for the type of dependencies processed or added by this * analyzer. */ public static final String DEPENDENCY_ECOSYSTEM = "CMAKE"; /** * The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(CMakeAnalyzer.class); /** * Used when compiling file scanning regex patterns. */ private static final int REGEX_OPTIONS = Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE; /** * Regex to extract the product information. */ private static final Pattern PROJECT = Pattern.compile( "^ *project *\\([ \\n]*(\\w+)[ \\n]*.*?\\)", REGEX_OPTIONS); /** * Regex to extract product and version information. * * Group 1: Product * * Group 2: Version */ private static final Pattern SET_VERSION = Pattern.compile( "^ *set\\s*\\(\\s*(\\w+)_version\\s+\"?(\\d+(?:\\.\\d+)+)[\\s\"]?\\)", REGEX_OPTIONS); /** * Detects files that can be analyzed. */ private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(".cmake") .addFilenames("CMakeLists.txt").build(); /** * Returns the name of the CMake analyzer. * * @return the name of the analyzer */ @Override public String getName() { return "CMake Analyzer"; } /** * Tell that we are used for information collection. * * @return INFORMATION_COLLECTION */ @Override public AnalysisPhase getAnalysisPhase() { return AnalysisPhase.INFORMATION_COLLECTION; } /** * Returns the set of supported file extensions. * * @return the set of supported file extensions */ @Override protected FileFilter getFileFilter() { return FILTER; } /** * Initializes the analyzer. * * @param engine a reference to the dependency-check engine * @throws InitializationException thrown if an exception occurs getting an * instance of SHA1 */ @Override protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException { //do nothing } /** * Analyzes python packages and adds evidence to the dependency. * * @param dependency the dependency being analyzed * @param engine the engine being used to perform the scan * @throws AnalysisException thrown if there is an unrecoverable error * analyzing the dependency */ @Override protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { dependency.setEcosystem(DEPENDENCY_ECOSYSTEM); final File file = dependency.getActualFile(); final String name = file.getName(); final String contents; try { contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); } catch (IOException e) { throw new AnalysisException( "Problem occurred while reading dependency file.", e); } if (StringUtils.isNotBlank(contents)) { final Matcher m = PROJECT.matcher(contents); int count = 0; while (m.find()) { count++; LOGGER.debug(String.format( "Found project command match with %d groups: %s", m.groupCount(), m.group(0))); final String group = m.group(1); LOGGER.debug("Group 1: {}", group); dependency.addEvidence(EvidenceType.PRODUCT, name, "Project", group, Confidence.HIGH); dependency.addEvidence(EvidenceType.VENDOR, name, "Project", group, Confidence.HIGH); dependency.setName(group); } LOGGER.debug("Found {} matches.", count); analyzeSetVersionCommand(dependency, engine, contents); } } /** * Extracts the version information from the contents. If more then one * version is found additional dependencies are added to the dependency * list. * * @param dependency the dependency being analyzed * @param engine the dependency-check engine * @param contents the version information */ private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { Dependency currentDep = dependency; final Matcher m = SET_VERSION.matcher(contents); int count = 0; while (m.find()) { count++; LOGGER.debug("Found project command match with {} groups: {}", m.groupCount(), m.group(0)); String product = m.group(1); final String version = m.group(2); LOGGER.debug("Group 1: {}", product); LOGGER.debug("Group 2: {}", version); final String aliasPrefix = "ALIASOF_"; if (product.startsWith(aliasPrefix)) { product = product.replaceFirst(aliasPrefix, ""); } if (count > 1) { //TODO - refactor so we do not assign to the parameter (checkstyle) currentDep = new Dependency(dependency.getActualFile()); currentDep.setEcosystem(DEPENDENCY_ECOSYSTEM); final String filePath = String.format("%s:%s", dependency.getFilePath(), product); currentDep.setFilePath(filePath); currentDep.setSha1sum(Checksum.getSHA1Checksum(filePath)); currentDep.setSha256sum(Checksum.getSHA256Checksum(filePath)); currentDep.setMd5sum(Checksum.getMD5Checksum(filePath)); engine.addDependency(currentDep); } final String source = currentDep.getFileName(); currentDep.addEvidence(EvidenceType.PRODUCT, source, "Product", product, Confidence.MEDIUM); currentDep.addEvidence(EvidenceType.VENDOR, source, "Vendor", product, Confidence.MEDIUM); currentDep.addEvidence(EvidenceType.VERSION, source, "Version", version, Confidence.MEDIUM); currentDep.setName(product); currentDep.setVersion(version); } LOGGER.debug("Found {} matches.", count); } @Override protected String getAnalyzerEnabledSettingKey() { return Settings.KEYS.ANALYZER_CMAKE_ENABLED; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy