Rework InsecureCryptoIvRule to use RuleChain on AllocationExpression
No need for Util. Use Symbol Table instead.
This commit is contained in:
@ -4,22 +4,19 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.security;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArguments;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTArrayInitializer;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
|
||||
|
||||
/**
|
||||
* Finds hardcoded static Initialization Vectors vectors used with cryptographic
|
||||
@ -38,73 +35,56 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
public class InsecureCryptoIvRule extends AbstractJavaRule {
|
||||
|
||||
public InsecureCryptoIvRule() {
|
||||
addRuleChainVisit(ASTClassOrInterfaceBodyDeclaration.class);
|
||||
addRuleChainVisit(ASTAllocationExpression.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) {
|
||||
Set<ASTLocalVariableDeclaration> foundLocalVars = new HashSet<>();
|
||||
// find new javax.crypto.spec.IvParameterSpec(...)
|
||||
Set<String> passedInIvVarNames = Util.findVariablesPassedToAnyParam(node, javax.crypto.spec.IvParameterSpec.class);
|
||||
public Object visit(ASTAllocationExpression node, Object data) {
|
||||
ASTClassOrInterfaceType declClassName = node.getFirstChildOfType(ASTClassOrInterfaceType.class);
|
||||
if (declClassName != null && TypeHelper.isA(declClassName, javax.crypto.spec.IvParameterSpec.class)) {
|
||||
Node firstArgument = null;
|
||||
|
||||
List<ASTLocalVariableDeclaration> localVars = node.findDescendantsOfType(ASTLocalVariableDeclaration.class);
|
||||
for (ASTLocalVariableDeclaration localVar : localVars) {
|
||||
foundLocalVars.addAll(extractPrimitiveTypes(localVar));
|
||||
ASTArguments arguments = node.getFirstChildOfType(ASTArguments.class);
|
||||
if (arguments.getArgumentCount() > 0) {
|
||||
firstArgument = arguments.getFirstChildOfType(ASTArgumentList.class).jjtGetChild(0);
|
||||
}
|
||||
|
||||
if (firstArgument != null) {
|
||||
ASTPrimaryPrefix prefix = firstArgument.getFirstDescendantOfType(ASTPrimaryPrefix.class);
|
||||
validateProperIv(data, prefix);
|
||||
}
|
||||
}
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
private void validateProperIv(Object data, ASTPrimaryPrefix firstArgumentExpression) {
|
||||
if (firstArgumentExpression == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<VariableNameDeclaration, List<NameOccurrence>> globalDecls = node.getScope()
|
||||
.getDeclarations(VariableNameDeclaration.class);
|
||||
|
||||
for (VariableNameDeclaration fieldVar : globalDecls.keySet()) {
|
||||
if (passedInIvVarNames.contains(fieldVar.getNode().getImage())) {
|
||||
ASTVariableDeclarator var = fieldVar.getNode().getFirstParentOfType(ASTVariableDeclarator.class);
|
||||
if (var != null) {
|
||||
validateProperIv(data, var.getFirstDescendantOfType(ASTVariableInitializer.class));
|
||||
// named variable
|
||||
ASTName namedVar = firstArgumentExpression.getFirstDescendantOfType(ASTName.class);
|
||||
if (namedVar != null) {
|
||||
// find where it's declared, if possible
|
||||
if (namedVar != null && namedVar.getNameDeclaration() instanceof VariableNameDeclaration) {
|
||||
VariableNameDeclaration varDecl = (VariableNameDeclaration) namedVar.getNameDeclaration();
|
||||
ASTVariableInitializer initializer = varDecl.getAccessNodeParent().getFirstDescendantOfType(ASTVariableInitializer.class);
|
||||
if (initializer != null) {
|
||||
validateProperIv(data, initializer.getFirstDescendantOfType(ASTPrimaryPrefix.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ASTLocalVariableDeclaration foundLocalVar : foundLocalVars) {
|
||||
if (passedInIvVarNames.contains(foundLocalVar.getVariableName())) {
|
||||
validateProperIv(data, foundLocalVar.getFirstDescendantOfType(ASTVariableInitializer.class));
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private Set<ASTLocalVariableDeclaration> extractPrimitiveTypes(ASTLocalVariableDeclaration localVar) {
|
||||
List<ASTPrimitiveType> types = localVar.findDescendantsOfType(ASTPrimitiveType.class);
|
||||
Set<ASTLocalVariableDeclaration> retVal = new HashSet<>();
|
||||
extractPrimitiveTypesInner(retVal, localVar, types);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private <T> void extractPrimitiveTypesInner(Set<T> retVal, T field, List<ASTPrimitiveType> types) {
|
||||
for (ASTPrimitiveType type : types) {
|
||||
if (type.hasImageEqualTo("byte")) {
|
||||
ASTReferenceType parent = type.getFirstParentOfType(ASTReferenceType.class);
|
||||
if (parent != null) {
|
||||
retVal.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateProperIv(Object data, ASTVariableInitializer varInit) {
|
||||
// hard coded array
|
||||
ASTArrayInitializer arrayInit = varInit.getFirstDescendantOfType(ASTArrayInitializer.class);
|
||||
ASTArrayInitializer arrayInit = firstArgumentExpression.getFirstDescendantOfType(ASTArrayInitializer.class);
|
||||
if (arrayInit != null) {
|
||||
addViolation(data, varInit);
|
||||
addViolation(data, firstArgumentExpression);
|
||||
}
|
||||
|
||||
// string literal
|
||||
ASTLiteral literal = varInit.getFirstDescendantOfType(ASTLiteral.class);
|
||||
ASTLiteral literal = firstArgumentExpression.getFirstDescendantOfType(ASTLiteral.class);
|
||||
if (literal != null && literal.isStringLiteral()) {
|
||||
addViolation(data, varInit);
|
||||
addViolation(data, firstArgumentExpression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.security;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
|
||||
|
||||
/**
|
||||
* @author sergeygorbaty
|
||||
*
|
||||
*/
|
||||
public final class Util {
|
||||
|
||||
private Util() {
|
||||
// intentionally
|
||||
}
|
||||
|
||||
public static Set<String> findVariablesPassedToAnyParam(ASTClassOrInterfaceBodyDeclaration node,
|
||||
Class<?> classToFind) {
|
||||
Set<String> passedInIvVarNames = new HashSet<>();
|
||||
|
||||
// find new javax.crypto.spec.SecretKeySpec(...)
|
||||
List<ASTAllocationExpression> allocations = node.findDescendantsOfType(ASTAllocationExpression.class);
|
||||
for (ASTAllocationExpression allocation : allocations) {
|
||||
|
||||
ASTClassOrInterfaceType declClassName = allocation.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
|
||||
if (declClassName != null) {
|
||||
Class<?> foundClass = declClassName.getType();
|
||||
if (foundClass != null && classToFind.isAssignableFrom(foundClass)) {
|
||||
ASTPrimaryExpression init = allocation.getFirstDescendantOfType(ASTPrimaryExpression.class);
|
||||
if (init != null) {
|
||||
ASTName name = init.getFirstDescendantOfType(ASTName.class);
|
||||
if (name != null) {
|
||||
if (name.getNameDeclaration() != null) {
|
||||
passedInIvVarNames.add(name.getNameDeclaration().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return passedInIvVarNames;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user