private static PropertySetAbstractValueKind PropertySetToTrueCallback(ValueContentAbstractValue valueContentAbstractValue, bool auditMode)
        {
            var val = PropertySetCallbacks.EvaluateLiteralValues(valueContentAbstractValue, o => o != null && o.Equals(false));

            if (val == PropertySetAbstractValueKind.Unknown)
            {
                val = auditMode ? PropertySetAbstractValueKind.MaybeFlagged : PropertySetAbstractValueKind.Unflagged;
            }
            return(val);
        }
        private static PropertySetAbstractValueKind PropertyLenCallback(ValueContentAbstractValue valueContentAbstractValue, bool auditMode, int minLen)
        {
            var val = PropertySetCallbacks.EvaluateLiteralValues(
                valueContentAbstractValue,
                o => o != null && Convert.ToInt32(o, CultureInfo.InvariantCulture) < minLen);

            if (val == PropertySetAbstractValueKind.Unknown)
            {
                val = auditMode ? PropertySetAbstractValueKind.MaybeFlagged : PropertySetAbstractValueKind.Unflagged;
            }
            return(val);
        }
Exemplo n.º 3
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            HazardousUsageEvaluatorCollection hazardousUsageEvaluators = new HazardousUsageEvaluatorCollection(
                new HazardousUsageEvaluator("Add", HazardousUsageCallback));

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation);

                if (!wellKnownTypeProvider.TryGetTypeByMetadataName(WellKnownTypeNames.SystemSecurityCryptographyX509CertificatesX509Store, out var x509TypeSymbol))
                {
                    return;
                }

                if (!wellKnownTypeProvider.TryGetTypeByMetadataName(WellKnownTypeNames.SystemSecurityCryptographyX509CertificatesStoreName, out var storeNameTypeSymbol))
                {
                    return;
                }

                // If X509Store is initialized with Root store, then that instance is flagged.
                var constructorMapper = new ConstructorMapper(
                    (IMethodSymbol constructorMethod, IReadOnlyList <ValueContentAbstractValue> argumentValueContentAbstractValues,
                     IReadOnlyList <PointsToAbstractValue> argumentPointsToAbstractValues) =>
                {
                    var kind = PropertySetAbstractValueKind.Unflagged;

                    if (constructorMethod.Parameters.Length > 0)
                    {
                        if (constructorMethod.Parameters[0].Type.Equals(storeNameTypeSymbol))
                        {
                            kind = PropertySetCallbacks.EvaluateLiteralValues(argumentValueContentAbstractValues[0], o => o.Equals(6));
                        }
                        else if (constructorMethod.Parameters[0].Type.SpecialType == SpecialType.System_String)
                        {
                            kind = PropertySetCallbacks.EvaluateLiteralValues(
                                argumentValueContentAbstractValues[0],
                                s => string.Equals(s.ToString(), "root", StringComparison.OrdinalIgnoreCase));
                        }
                    }

                    return(PropertySetAbstractValue.GetInstance(kind));
                });

                var rootOperationsNeedingAnalysis = PooledHashSet <(IOperation, ISymbol)> .GetInstance();

                compilationStartAnalysisContext.RegisterOperationBlockStartAction(
                    (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) =>
                {
                    operationBlockStartAnalysisContext.RegisterOperationAction(
                        (OperationAnalysisContext operationAnalysisContext) =>
                    {
                        var invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation;

                        if (x509TypeSymbol.Equals(invocationOperation.Instance?.Type) &&
                            invocationOperation.TargetMethod.Name == "Add")
                        {
                            lock (rootOperationsNeedingAnalysis)
                            {
                                rootOperationsNeedingAnalysis.Add((invocationOperation.GetRoot(), operationAnalysisContext.ContainingSymbol));
                            }
                        }
                    },
                        OperationKind.Invocation);

                    operationBlockStartAnalysisContext.RegisterOperationAction(
                        (OperationAnalysisContext operationAnalysisContext) =>
                    {
                        var argumentOperation = (IArgumentOperation)operationAnalysisContext.Operation;

                        if (x509TypeSymbol.Equals(argumentOperation.Parameter.Type))
                        {
                            lock (rootOperationsNeedingAnalysis)
                            {
                                rootOperationsNeedingAnalysis.Add((argumentOperation.GetRoot(), operationAnalysisContext.ContainingSymbol));
                            }
                        }
                    },
                        OperationKind.Argument);
                });

                compilationStartAnalysisContext.RegisterCompilationEndAction(
                    (CompilationAnalysisContext compilationAnalysisContext) =>
                {
                    PooledDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null;

                    try
                    {
                        lock (rootOperationsNeedingAnalysis)
                        {
                            if (!rootOperationsNeedingAnalysis.Any())
                            {
                                return;
                            }

                            allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages(
                                compilationAnalysisContext.Compilation,
                                rootOperationsNeedingAnalysis,
                                WellKnownTypeNames.SystemSecurityCryptographyX509CertificatesX509Store,
                                constructorMapper,
                                PropertyMappers,
                                hazardousUsageEvaluators,
                                InterproceduralAnalysisConfiguration.Create(
                                    compilationAnalysisContext.Options,
                                    SupportedDiagnostics,
                                    defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive,
                                    cancellationToken: compilationAnalysisContext.CancellationToken));
                        }

                        if (allResults == null)
                        {
                            return;
                        }

                        foreach (KeyValuePair <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> kvp
                                 in allResults)
                        {
                            DiagnosticDescriptor descriptor;
                            switch (kvp.Value)
                            {
                            case HazardousUsageEvaluationResult.Flagged:
                                descriptor = DefinitelyInstallRootCertRule;
                                break;

                            case HazardousUsageEvaluationResult.MaybeFlagged:
                                descriptor = MaybeInstallRootCertRule;
                                break;

                            default:
                                Debug.Fail($"Unhandled result value {kvp.Value}");
                                continue;
                            }

                            compilationAnalysisContext.ReportDiagnostic(
                                Diagnostic.Create(
                                    descriptor,
                                    kvp.Key.Location,
                                    kvp.Key.Method.ToDisplayString(
                                        SymbolDisplayFormat.MinimallyQualifiedFormat)));
                        }
                    }
                    finally
                    {
                        rootOperationsNeedingAnalysis.Free();
                        allResults?.Free();
                    }
                });
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            if (!Debugger.IsAttached) // prefer single thread for debugging in development
            {
                context.EnableConcurrentExecution();
            }

            if (context.IsAuditMode())
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
            }
            else
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            }

            if (!Debugger.IsAttached) // prefer single thread for debugging in development
            {
                context.EnableConcurrentExecution();
            }

            if (context.IsAuditMode())
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
            }
            else
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            }

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationContext) =>
            {
                Compilation compilation   = compilationContext.Compilation;
                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName("System.Xml.Xsl.XsltSettings", out var type))
                {
                    return;
                }

                var configuration = Configuration.GetOrCreate(compilationContext);

                compilationContext.RegisterOperationBlockStartAction(
                    operationBlockStartContext =>
                {
                    ISymbol owningSymbol                = operationBlockStartContext.OwningSymbol;
                    AnalyzerOptions options             = operationBlockStartContext.Options;
                    CancellationToken cancellationToken = operationBlockStartContext.CancellationToken;
                    if (options.IsConfiguredToSkipAnalysis(Rule, owningSymbol, compilation, cancellationToken))
                    {
                        return;
                    }

                    bool?GetValue(IOperation operation, IOperation value, OperationAnalysisContext operationAnalysisContext)
                    {
                        if (value.ConstantValue.HasValue && value.ConstantValue.Value is bool isEnableScript)
                        {
                            return(isEnableScript);
                        }

                        if (!operation.TryGetEnclosingControlFlowGraph(out var cfg))
                        {
                            return(null);
                        }

                        var valueContentResult = ValueContentAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider,
                                                                                            operationAnalysisContext.Options, Rule, PointsToAnalysisKind.Complete, operationAnalysisContext.CancellationToken);
                        if (valueContentResult == null)
                        {
                            return(null);
                        }

                        ValueContentAbstractValue abstractValue = valueContentResult[value.Kind, value.Syntax];

                        PropertySetAbstractValueKind kind = PropertySetCallbacks.EvaluateLiteralValues(abstractValue, (object?o) => o is true);
                        if (kind == PropertySetAbstractValueKind.MaybeFlagged || kind == PropertySetAbstractValueKind.Flagged)
                        {
                            return(true);
                        }

                        kind = PropertySetCallbacks.EvaluateLiteralValues(abstractValue, (object?o) => o is false);
                        if (kind == PropertySetAbstractValueKind.Flagged)
                        {
                            return(false);
                        }

                        return(null);
                    }

                    operationBlockStartContext.RegisterOperationAction(
                        ctx =>
                    {
                        IAssignmentOperation operation = (IAssignmentOperation)ctx.Operation;
                        if (!(operation.Target is IPropertyReferenceOperation propertyReferenceOperation))
                        {
                            return;
                        }

                        if (propertyReferenceOperation.Member.ContainingType != type)
                        {
                            return;
                        }

                        if (propertyReferenceOperation.Member.Name == "EnableScript")
                        {
                            var enableScript = GetValue(operation, operation.Value, ctx);
                            if ((enableScript.HasValue && enableScript.Value) ||
                                !enableScript.HasValue && configuration.AuditMode)
                            {
                                ctx.ReportDiagnostic(Diagnostic.Create(Rule, operation.Syntax.GetLocation()));
                            }
                        }
                    },
                        OperationKind.SimpleAssignment);

                    operationBlockStartContext.RegisterOperationAction(
                        ctx =>
                    {
                        var operation = (IPropertyReferenceOperation)ctx.Operation;
                        if (operation.Property.ContainingType != type || operation.Property.Name != "TrustedXslt")
                        {
                            return;
                        }

                        ctx.ReportDiagnostic(Diagnostic.Create(Rule, operation.Syntax.GetLocation()));
                    },
                        OperationKind.PropertyReference);

                    operationBlockStartContext.RegisterOperationAction(
                        ctx =>
                    {
                        IObjectCreationOperation invocationOperation = (IObjectCreationOperation)ctx.Operation;
                        if (invocationOperation.Constructor.ContainingType != type)
                        {
                            return;
                        }

                        var enableScriptArg = invocationOperation.Arguments.FirstOrDefault(x => x.Parameter.Name == "enableScript");
                        if (enableScriptArg == null)
                        {
                            return;
                        }

                        var enableScript = GetValue(invocationOperation, enableScriptArg.Value, ctx);
                        if ((enableScript.HasValue && enableScript.Value) ||
                            !enableScript.HasValue && configuration.AuditMode)
                        {
                            ctx.ReportDiagnostic(Diagnostic.Create(Rule, invocationOperation.Syntax.GetLocation()));
                        }
                    },
                        OperationKind.ObjectCreation);
                });
            });
        }
Exemplo n.º 5
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            HazardousUsageEvaluatorCollection hazardousUsageEvaluators = new HazardousUsageEvaluatorCollection(
                new HazardousUsageEvaluator("GetBytes", HazardousUsageCallback));

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation);

                if (!wellKnownTypeProvider.TryGetTypeByMetadataName(WellKnownTypeNames.SystemSecurityCryptographyRfc2898DeriveBytes, out var rfc2898DeriveBytesTypeSymbol))
                {
                    return;
                }

                var cancellationToken        = compilationStartAnalysisContext.CancellationToken;
                var sufficientIterationCount = compilationStartAnalysisContext.Options.GetUnsignedIntegralOptionValue(
                    optionName: EditorConfigOptionNames.SufficientIterationCountForWeakKDFAlgorithm,
                    rule: DefinitelyUseWeakKDFInsufficientIterationCountRule,
                    defaultValue: 100000,
                    cancellationToken: cancellationToken);
                var constructorMapper = new ConstructorMapper(
                    (IMethodSymbol constructorMethod, IReadOnlyList <ValueContentAbstractValue> argumentValueContentAbstractValues,
                     IReadOnlyList <PointsToAbstractValue> argumentPointsToAbstractValues) =>
                {
                    var kind = DefaultIterationCount >= sufficientIterationCount ? PropertySetAbstractValueKind.Unflagged : PropertySetAbstractValueKind.Flagged;

                    if (constructorMethod.Parameters.Length >= 3)
                    {
                        if (constructorMethod.Parameters[2].Name == "iterations" &&
                            constructorMethod.Parameters[2].Type.SpecialType == SpecialType.System_Int32)
                        {
                            kind = PropertySetCallbacks.EvaluateLiteralValues(argumentValueContentAbstractValues[2], o => Convert.ToInt32(o) < sufficientIterationCount);
                        }
                    }

                    return(PropertySetAbstractValue.GetInstance(kind));
                });
                var propertyMappers = new PropertyMapperCollection(
                    new PropertyMapper(
                        "IterationCount",
                        (ValueContentAbstractValue valueContentAbstractValue) =>
                {
                    return(PropertySetCallbacks.EvaluateLiteralValues(valueContentAbstractValue, o => Convert.ToInt32(o) < sufficientIterationCount));
                }));
                var rootOperationsNeedingAnalysis = PooledHashSet <(IOperation, ISymbol)> .GetInstance();

                compilationStartAnalysisContext.RegisterOperationBlockStartAction(
                    (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) =>
                {
                    // TODO: Handle case when exactly one of the below rules is configured to skip analysis.
                    if (operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options,
                                                                                                   DefinitelyUseWeakKDFInsufficientIterationCountRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) &&
                        operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options,
                                                                                                   MaybeUseWeakKDFInsufficientIterationCountRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken))
                    {
                        return;
                    }

                    operationBlockStartAnalysisContext.RegisterOperationAction(
                        (OperationAnalysisContext operationAnalysisContext) =>
                    {
                        var invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation;

                        if (rfc2898DeriveBytesTypeSymbol.Equals(invocationOperation.Instance?.Type) &&
                            invocationOperation.TargetMethod.Name == "GetBytes")
                        {
                            lock (rootOperationsNeedingAnalysis)
                            {
                                rootOperationsNeedingAnalysis.Add((invocationOperation.GetRoot(), operationAnalysisContext.ContainingSymbol));
                            }
                        }
                    },
                        OperationKind.Invocation);

                    operationBlockStartAnalysisContext.RegisterOperationAction(
                        (OperationAnalysisContext operationAnalysisContext) =>
                    {
                        var argumentOperation = (IArgumentOperation)operationAnalysisContext.Operation;

                        if (rfc2898DeriveBytesTypeSymbol.Equals(argumentOperation.Parameter.Type))
                        {
                            lock (rootOperationsNeedingAnalysis)
                            {
                                rootOperationsNeedingAnalysis.Add((argumentOperation.GetRoot(), operationAnalysisContext.ContainingSymbol));
                            }
                        }
                    },
                        OperationKind.Argument);
                });

                compilationStartAnalysisContext.RegisterCompilationEndAction(
                    (CompilationAnalysisContext compilationAnalysisContext) =>
                {
                    PooledDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null;

                    try
                    {
                        lock (rootOperationsNeedingAnalysis)
                        {
                            if (!rootOperationsNeedingAnalysis.Any())
                            {
                                return;
                            }

                            allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages(
                                compilationAnalysisContext.Compilation,
                                rootOperationsNeedingAnalysis,
                                compilationAnalysisContext.Options,
                                WellKnownTypeNames.SystemSecurityCryptographyRfc2898DeriveBytes,
                                constructorMapper,
                                propertyMappers,
                                hazardousUsageEvaluators,
                                InterproceduralAnalysisConfiguration.Create(
                                    compilationAnalysisContext.Options,
                                    SupportedDiagnostics,
                                    defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive,
                                    cancellationToken: cancellationToken));
                        }

                        if (allResults == null)
                        {
                            return;
                        }

                        foreach (KeyValuePair <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> kvp
                                 in allResults)
                        {
                            DiagnosticDescriptor descriptor;
                            switch (kvp.Value)
                            {
                            case HazardousUsageEvaluationResult.Flagged:
                                descriptor = DefinitelyUseWeakKDFInsufficientIterationCountRule;
                                break;

                            case HazardousUsageEvaluationResult.MaybeFlagged:
                                descriptor = MaybeUseWeakKDFInsufficientIterationCountRule;
                                break;

                            default:
                                Debug.Fail($"Unhandled result value {kvp.Value}");
                                continue;
                            }

                            compilationAnalysisContext.ReportDiagnostic(
                                Diagnostic.Create(
                                    descriptor,
                                    kvp.Key.Location,
                                    sufficientIterationCount));
                        }
                    }
                    finally
                    {
                        rootOperationsNeedingAnalysis.Free();
                        allResults?.Free();
                    }
                });
            });
        }