private IEnumerable <ValidationResult> ValidateAgainstWhitelist(Whitelist whitelist, MethodDefinition method,
                                                                        TypeReference type, string member = null)
        {
            // Allow own defined types
            if (type is TypeDefinition)
            {
                yield break;
            }

            // Filter in the whitelist whether there is any rule
            var result = Search(whitelist, type, member);

            // Return a validation result if search result is negative (any of the denied results)
            switch (result)
            {
            case WhitelistSearchResult.DeniedNamespace:
                var ns = string.IsNullOrWhiteSpace(type.Namespace) ? @"""" : type.Namespace;
                yield return(new WhitelistValidationResult($"{ns} is not allowed.")
                             .WithInfo(method.Name, type.Namespace, type.Name, member));

                break;

            case WhitelistSearchResult.DeniedType:
                yield return(new WhitelistValidationResult($"{type.Name} in {type.Namespace} is not allowed.")
                             .WithInfo(method.Name, type.Namespace, type.Name, member));

                break;

            case WhitelistSearchResult.DeniedMember:
                yield return(new WhitelistValidationResult($"{member} in {type.FullName} is not allowed.")
                             .WithInfo(method.Name, type.Namespace, type.Name, member));

                break;
            }
        }
        private IEnumerable <ValidationResult> Validate(Whitelist whitelist, MethodDefinition method,
                                                        Instruction instruction)
        {
            if (!(instruction.Operand is MemberReference reference))
            {
                return(Enumerable.Empty <ValidationResult>());
            }

            if (reference is MethodReference methodReference)
            {
                var results = new List <ValidationResult>();
                results.AddRange(ValidateReference(whitelist, method, methodReference.DeclaringType,
                                                   methodReference.Name));
                results.AddRange(ValidateReference(whitelist, method, methodReference.ReturnType));
                return(results);
            }

            if (reference is FieldReference fieldReference)
            {
                var results = new List <ValidationResult>();
                results.AddRange(
                    ValidateReference(whitelist, method, fieldReference.DeclaringType, fieldReference.Name));
                results.AddRange(ValidateReference(whitelist, method, fieldReference.FieldType));
                return(results);
            }

            if (reference is TypeReference typeReference)
            {
                return(ValidateReference(whitelist, method, typeReference));
            }

            return(Enumerable.Empty <ValidationResult>());
        }
Пример #3
0
 private void WhitelistAElfTypes(Whitelist whitelist)
 {
     whitelist
     // Selectively allowed types and members
     .Namespace("AElf.Cryptography.SecretSharing", Permission.Denied, type => type
                .Type(typeof(SecretSharingHelper), Permission.Denied, member => member
                      .Member(nameof(SecretSharingHelper.DecodeSecret), Permission.Allowed)));
 }
        private WhitelistSearchResult Search(Whitelist whitelist, TypeReference type, string member = null)
        {
            var typeNs = GetNameSpace(type);

            // Fail if there is no rule for the namespace
            if (!whitelist.TryGetNamespaceRule(typeNs, out var namespaceRule))
            {
                // If no exact match for namespace, check for wildcard matching
                if (whitelist.ContainsWildcardMatchedNamespaceRule(typeNs))
                {
                    return(WhitelistSearchResult.Allowed);
                }

                return(WhitelistSearchResult.DeniedNamespace);
            }

            // Fail if the type is not allowed in the namespace
            if (!namespaceRule.Types.TryGetValue(type.Name, out var typeRule) ||
                typeRule.Permission == Permission.Denied && !typeRule.Members.Any())
            {
                return(namespaceRule.Permission == Permission.Allowed
                    ? WhitelistSearchResult.Allowed
                    : WhitelistSearchResult.DeniedType);
            }

            if (typeRule.Permission == Permission.Denied && !typeRule.Members.Any())
            {
                return(WhitelistSearchResult.DeniedType);
            }

            if (member == null)
            {
                return(WhitelistSearchResult.Allowed);
            }

            if (!typeRule.Members.TryGetValue(member, out var memberRule))
            {
                if (!member.StartsWith("get_") && !member.StartsWith("set_"))
                {
                    return(typeRule.Permission == Permission.Allowed
                        ? WhitelistSearchResult.Allowed
                        : WhitelistSearchResult.DeniedMember);
                }

                // Check without the prefix as well
                member = member.Split(new[] { '_' }, 2)[1];
                if (!typeRule.Members.TryGetValue(member, out memberRule))
                {
                    return(typeRule.Permission == Permission.Allowed
                        ? WhitelistSearchResult.Allowed
                        : WhitelistSearchResult.DeniedMember);
                }
            }

            return(memberRule.Permission == Permission.Allowed
                ? WhitelistSearchResult.Allowed
                : WhitelistSearchResult.DeniedMember);
        }
Пример #5
0
 public Whitelist GetWhitelist()
 {
     if (_whitelist != null)
     {
         return(_whitelist);
     }
     _whitelist = CreateWhitelist();
     return(_whitelist);
 }
Пример #6
0
 private void WhitelistLinqAndCollections(Whitelist whitelist)
 {
     whitelist
     .Namespace("System.Linq", Permission.Allowed)
     .Namespace("System.Collections", Permission.Allowed)
     .Namespace("System.Collections.Generic", Permission.Allowed)
     .Namespace("System.Collections.ObjectModel", Permission.Allowed)
     ;
 }
Пример #7
0
        private Whitelist CreateWhitelist()
        {
            var whitelist = new Whitelist();

            WhitelistAssemblies(whitelist);
            WhitelistSystemTypes(whitelist);
            WhitelistReflectionTypes(whitelist);
            WhitelistLinqAndCollections(whitelist);
            WhitelistOthers(whitelist);
            return(whitelist);
        }
Пример #8
0
 private void WhitelistReflectionTypes(Whitelist whitelist)
 {
     whitelist
     // Used by protobuf generated code
     .Namespace("System.Reflection", Permission.Denied, type => type
                .Type(nameof(AssemblyCompanyAttribute), Permission.Allowed)
                .Type(nameof(AssemblyConfigurationAttribute), Permission.Allowed)
                .Type(nameof(AssemblyFileVersionAttribute), Permission.Allowed)
                .Type(nameof(AssemblyInformationalVersionAttribute), Permission.Allowed)
                .Type(nameof(AssemblyProductAttribute), Permission.Allowed)
                .Type(nameof(AssemblyTitleAttribute), Permission.Allowed))
     ;
 }
        private IEnumerable <ValidationResult> ValidateReference(Whitelist whitelist, MethodDefinition method,
                                                                 TypeReference type,
                                                                 string member = null)
        {
            var results = new List <ValidationResult>();

            // If the type is a generic parameter, stop going deeper
            if (type.IsGenericParameter)
            {
                return(results);
            }

            // If referred type is from a fully trusted assembly, stop going deeper
            if (whitelist.CheckAssemblyFullyTrusted(type.Resolve()?.Module.Assembly.Name))
            {
                return(results);
            }

            // Dig deeper by calling ValidateReference until reaching base type
            if (type.IsByReference)
            {
                results.AddRange(ValidateReference(whitelist, method, type.GetElementType()));
                return(results);
            }

            if (type is GenericInstanceType generic)
            {
                results.AddRange(ValidateReference(whitelist, method, generic.ElementType));

                foreach (var argument in generic.GenericArguments)
                {
                    results.AddRange(ValidateReference(whitelist, method, argument));
                }

                return(results);
            }

            // If the type is an array, then validate the element type of the array
            if (type.IsArray)
            {
                results.AddRange(ValidateReference(whitelist, method, type.GetElementType()));
                return(results);
            }

            // Reached the most base type, now we can validate against the whitelist
            results.AddRange(ValidateAgainstWhitelist(whitelist, method, type, member));

            return(results);
        }
Пример #10
0
 private void WhitelistSystemTypes(Whitelist whitelist)
 {
     whitelist
     // Selectively allowed types and members
     .Namespace("System", Permission.Denied, type => type
                .Type(typeof(Array), Permission.Denied, member => member
                      .Member(nameof(Array.AsReadOnly), Permission.Allowed))
                .Type("Func`1", Permission.Allowed)     // Required for protobuf generated code
                .Type("Func`2", Permission.Allowed)     // Required for protobuf generated code
                .Type("Func`3", Permission.Allowed)     // Required for protobuf generated code
                .Type("Nullable`1", Permission.Allowed) // Required for protobuf generated code
                .Type(typeof(BitConverter), Permission.Denied, member => member
                      .Member(nameof(BitConverter.GetBytes), Permission.Allowed))
                .Type(typeof(Uri), Permission.Denied, member => member
                      .Member(nameof(Uri.TryCreate), Permission.Allowed)
                      .Member(nameof(Uri.Scheme), Permission.Allowed)
                      .Member(nameof(Uri.UriSchemeHttp), Permission.Allowed)
                      .Member(nameof(Uri.UriSchemeHttps), Permission.Allowed))
                .Type(typeof(NotImplementedException),
                      Permission.Allowed)                                      // Required for protobuf generated code
                .Type(typeof(NotSupportedException), Permission.Allowed)       // Required for protobuf generated code
                .Type(typeof(ArgumentOutOfRangeException), Permission.Allowed) // From AEDPoS
                .Type(nameof(DateTime), Permission.Allowed, member => member
                      .Member(nameof(DateTime.Now), Permission.Denied)
                      .Member(nameof(DateTime.UtcNow), Permission.Denied)
                      .Member(nameof(DateTime.Today), Permission.Denied))
                .Type(typeof(void).Name, Permission.Allowed)
                .Type(nameof(Object), Permission.Allowed)
                .Type(nameof(Type), Permission.Allowed)
                .Type(nameof(IDisposable), Permission.Allowed)
                .Type(nameof(Convert), Permission.Allowed)
                .Type(nameof(Math), Permission.Allowed)
                // Primitive types
                .Type(nameof(Boolean), Permission.Allowed)
                .Type(nameof(Byte), Permission.Allowed)
                .Type(nameof(SByte), Permission.Allowed)
                .Type(nameof(Char), Permission.Allowed)
                .Type(nameof(Int32), Permission.Allowed)
                .Type(nameof(UInt32), Permission.Allowed)
                .Type(nameof(Int64), Permission.Allowed)
                .Type(nameof(UInt64), Permission.Allowed)
                .Type(nameof(Decimal), Permission.Allowed)
                .Type(nameof(String), Permission.Allowed, member => member
                      .Constructor(Permission.Denied))
                .Type(typeof(Byte[]).Name, Permission.Allowed)
                );
 }
Пример #11
0
 private void WhitelistAssemblies(Whitelist whitelist)
 {
     whitelist
     .Assembly(System.Reflection.Assembly.Load("netstandard"), Trust.Partial)
     .Assembly(System.Reflection.Assembly.Load("System.Runtime"), Trust.Partial)
     .Assembly(System.Reflection.Assembly.Load("System.Runtime.Extensions"), Trust.Partial)
     .Assembly(System.Reflection.Assembly.Load("System.Private.CoreLib"), Trust.Partial)
     .Assembly(System.Reflection.Assembly.Load("System.ObjectModel"), Trust.Partial)
     .Assembly(System.Reflection.Assembly.Load("System.Linq"), Trust.Full)
     .Assembly(System.Reflection.Assembly.Load("System.Collections"), Trust.Full)
     .Assembly(System.Reflection.Assembly.Load("Google.Protobuf"), Trust.Full)
     .Assembly(typeof(CSharpSmartContract).Assembly, Trust.Full)         // AElf.Sdk.CSharp
     .Assembly(typeof(Address).Assembly, Trust.Full)                     // AElf.Types
     .Assembly(typeof(IMethod).Assembly, Trust.Full)                     // AElf.CSharp.Core
     .Assembly(typeof(SecretSharingHelper).Assembly, Trust.Partial)      // AElf.Cryptography
     .Assembly(typeof(ISmartContractBridgeContext).Assembly, Trust.Full) // AElf.Kernel.SmartContract.Shared
     ;
 }
Пример #12
0
        private void WhitelistOthers(Whitelist whitelist)
        {
            whitelist
            // Used for converting numbers to strings
            .Namespace("System.Globalization", Permission.Denied, type => type
                       .Type(nameof(CultureInfo), Permission.Denied, m => m
                             .Member(nameof(CultureInfo.InvariantCulture), Permission.Allowed)))

            // Used for initializing large arrays hardcoded in the code, array validator will take care of the size
            .Namespace("System.Runtime.CompilerServices", Permission.Denied, type => type
                       .Type(nameof(RuntimeHelpers), Permission.Denied, member => member
                             .Member(nameof(RuntimeHelpers.InitializeArray), Permission.Allowed)))
            .Namespace("System.Text", Permission.Denied, type => type
                       .Type(nameof(Encoding), Permission.Denied, member => member
                             .Member(nameof(Encoding.UTF8), Permission.Allowed)
                             .Member(nameof(Encoding.UTF8.GetByteCount), Permission.Allowed)))
            ;
        }
        private IEnumerable <ValidationResult> Validate(Whitelist whitelist, TypeDefinition type, CancellationToken ct)
        {
            var results = new List <ValidationResult>();

            foreach (var method in type.Methods)
            {
                if (ct.IsCancellationRequested)
                {
                    throw new ContractAuditTimeoutException();
                }

                if (!method.HasBody)
                {
                    continue;
                }

                foreach (var instruction in method.Body.Instructions)
                {
                    results.AddRange(Validate(whitelist, method, instruction));
                }
            }

            return(results);
        }