Ignore:
Timestamp:
11/14/2008 2:14:26 PM (4 years ago)
Author:
lowjoel
Message:

Tighten the plugin loading criteria:
-Plugins are first loaded reflection-only, checking for the presence of the IPlugin interface being implemented. If it is not implemented, the DLL is skipped.
-The plugins are then checked for a public key. If the public key is different from the executing assembly, it is not trusted and therefore is foreign.
-Foreign plugins must be approved by the user explicitly before they are loaded.

The SettingsPanel? and the ManagerSettings? classes have therefore been updated.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/Manager/Plugins.cs

    r564 r569  
    2626using System.Reflection; 
    2727using System.Windows.Forms; 
     28using System.Runtime.InteropServices; 
    2829 
    2930namespace Eraser.Manager.Plugin 
     
    106107        public override void Load() 
    107108        { 
    108             AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolve); 
     109            AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; 
     110            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveReflectionDependency; 
    109111            string pluginsFolder = Path.Combine( 
    110112                Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), //Assembly location 
     
    116118                FileInfo file = new FileInfo(fileName); 
    117119                if (file.Extension.Equals(".dll")) 
    118                     LoadPlugin(file.FullName); 
     120                    try 
     121                    { 
     122                        LoadPlugin(file.FullName); 
     123                    } 
     124                    catch (BadImageFormatException) 
     125                    { 
     126                    } 
     127                    catch (FileLoadException) 
     128                    { 
     129                    } 
    119130            } 
    120131        } 
     
    140151        public override void LoadPlugin(string filePath) 
    141152        { 
    142             //Load the plugin 
    143             Assembly assembly = Assembly.LoadFrom(filePath); 
     153            //Create the PluginInstance structure 
     154            Assembly reflectAssembly = Assembly.ReflectionOnlyLoadFrom(filePath); 
     155            PluginInstance instance = new PluginInstance(reflectAssembly, null); 
     156            Type typePlugin = null; 
    144157 
    145158            //Iterate over every exported type, checking if it implements IPlugin 
    146             foreach (Type type in assembly.GetTypes()) 
    147             { 
    148                 if (!type.IsPublic || type.IsAbstract) 
    149                     //Not interesting. 
    150                     continue; 
    151  
     159            foreach (Type type in instance.Assembly.GetExportedTypes()) 
     160            { 
    152161                //Check for an implementation of IPlugin 
    153162                Type typeInterface = type.GetInterface("Eraser.Manager.Plugin.IPlugin", true); 
    154163                if (typeInterface != null) 
    155164                { 
    156                     //Create the PluginInstance structure 
    157                     PluginInstance instance = new PluginInstance(assembly, filePath, null); 
    158  
    159                     //Add the plugin to the list of loaded plugins 
    160                     lock (plugins) 
    161                         plugins.Add(instance); 
    162  
    163                     //Initialize the plugin 
    164                     IPlugin pluginInterface = (IPlugin)Activator.CreateInstance( 
    165                         assembly.GetType(type.ToString())); 
    166                     pluginInterface.Initialize(this); 
    167                     instance.Plugin = pluginInterface; 
    168  
    169                     //And broadcast the plugin load event 
    170                     OnPluginLoaded(instance); 
     165                    typePlugin = type; 
     166                    break; 
    171167                } 
    172168            } 
     169 
     170            //If the typePlugin type is empty the assembly doesn't implement IPlugin; we 
     171            //aren't interested. 
     172            if (typePlugin == null) 
     173                return; 
     174 
     175            //OK this assembly is a plugin 
     176            lock (plugins) 
     177                plugins.Add(instance); 
     178 
     179            //First check the plugin for the presence of a signature. 
     180            if (reflectAssembly.GetName().GetPublicKey().Length == 0) 
     181            { 
     182                //If the user did not allow the plug-in to load, don't load it. 
     183                if (ManagerLibrary.Instance.Settings.ApprovedPlugins. 
     184                    IndexOf(instance.AssemblyInfo.GUID) == -1) 
     185                { 
     186                    return; 
     187                } 
     188            } 
     189 
     190            //Load the plugin 
     191            instance.Assembly = Assembly.LoadFrom(filePath); 
     192 
     193            //Initialize the plugin 
     194            IPlugin pluginInterface = (IPlugin)Activator.CreateInstance( 
     195                instance.Assembly.GetType(typePlugin.ToString())); 
     196            pluginInterface.Initialize(this); 
     197            instance.Plugin = pluginInterface; 
     198 
     199            //And broadcast the plugin load event 
     200            OnPluginLoaded(instance); 
    173201        } 
    174202 
     
    182210        } 
    183211 
     212        Assembly ResolveReflectionDependency(object sender, ResolveEventArgs args) 
     213        { 
     214            return Assembly.ReflectionOnlyLoad(args.Name); 
     215        } 
     216 
    184217        private List<PluginInstance> plugins = new List<PluginInstance>(); 
    185218    } 
     
    190223    public class PluginInstance 
    191224    { 
    192         internal PluginInstance(Assembly assembly, string path, IPlugin plugin) 
     225        /// <summary> 
     226        /// Constructor 
     227        /// </summary> 
     228        /// <param name="assembly">The assembly representing this plugin.</param> 
     229        /// <param name="path">The path to the ass</param> 
     230        /// <param name="plugin"></param> 
     231        internal PluginInstance(Assembly assembly, IPlugin plugin) 
    193232        { 
    194233            Assembly = assembly; 
    195             Path = path; 
    196234            Plugin = plugin; 
    197235        } 
    198236 
    199         public Assembly Assembly; 
    200         public string Path; 
    201         public IPlugin Plugin; 
     237        /// <summary> 
     238        /// Gets the Assembly this plugin instance came from. 
     239        /// </summary> 
     240        public Assembly Assembly 
     241        { 
     242            get 
     243            { 
     244                return assembly; 
     245            } 
     246            internal set 
     247            { 
     248                assembly = value; 
     249 
     250                assemblyInfo.Version = assembly.GetName().Version; 
     251                IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(assembly); 
     252                foreach (CustomAttributeData attr in attributes) 
     253                    if (attr.Constructor.DeclaringType == typeof(GuidAttribute)) 
     254                        assemblyInfo.GUID = new Guid((string)attr.ConstructorArguments[0].Value); 
     255                    else if (attr.Constructor.DeclaringType == typeof(AssemblyCompanyAttribute)) 
     256                        assemblyInfo.Author = (string)attr.ConstructorArguments[0].Value; 
     257            } 
     258        } 
     259 
     260        /// <summary> 
     261        /// Gets the attributes of the assembly, loading from reflection-only sources. 
     262        /// </summary> 
     263        public AssemblyInfo AssemblyInfo 
     264        { 
     265            get 
     266            { 
     267                return assemblyInfo; 
     268            } 
     269            internal set 
     270            { 
     271                assemblyInfo = value; 
     272            } 
     273        } 
     274 
     275        /// <summary> 
     276        /// Gets the IPlugin interface which the plugin exposed. 
     277        /// </summary> 
     278        public IPlugin Plugin 
     279        { 
     280            get 
     281            { 
     282                return plugin; 
     283            } 
     284            internal set 
     285            { 
     286                plugin = value; 
     287            } 
     288        } 
     289 
     290        private Assembly assembly; 
     291        private AssemblyInfo assemblyInfo; 
     292        private IPlugin plugin; 
     293    } 
     294 
     295    /// <summary> 
     296    /// Reflection-only information retrieved from the assembly. 
     297    /// </summary> 
     298    public struct AssemblyInfo 
     299    { 
     300        /// <summary> 
     301        /// The GUID of the assembly. 
     302        /// </summary> 
     303        public Guid GUID; 
     304 
     305        /// <summary> 
     306        /// The publisher of the assembly. 
     307        /// </summary> 
     308        public string Author; 
     309 
     310        /// <summary> 
     311        /// The version of the assembly. 
     312        /// </summary> 
     313        public Version Version; 
    202314    } 
    203315 
Note: See TracChangeset for help on using the changeset viewer.