Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
thisdir = tools/mono-configuration-crypto
SUBDIRS = lib cli
include ../../build/rules.make
all-local:
install-local:
dist-local: dist-default
clean-local:

View File

@@ -0,0 +1,14 @@
thisdir = tools/mono-configuration-crypto/cli
SUBDIRS =
include ../../../build/rules.make
LOCAL_MCS_FLAGS = -r:Mono.Security.dll \
-r:System.Security.dll \
-r:System.Configuration.dll \
-r:System.dll \
-r:$(topdir)/class/lib/$(PROFILE)/Mono.Configuration.Crypto.dll
PROGRAM = mono-configuration-crypto.exe
PROGRAM_INSTALL_DIR = $(mono_libdir)/mono/mono-configuration-crypto/$(FRAMEWORK_VERSION)
include ../../../build/executable.make

View File

@@ -0,0 +1,65 @@
using System;
namespace MonoConfigurationCrypto
{
sealed class Config
{
public const string DefaultContainerName = "MonoFrameworkConfigurationKey";
public const uint DefaultKeySize = 1024;
public const string DefaultApplicationPhysicalPath = ".";
public const string DefaultConfigFileName = "Web.config";
public string ApplicationPhysicalPath {
get;
set;
}
public string ConfigSectionName {
get;
set;
}
public string ConfigFileName {
get;
set;
}
public string FileName {
get;
set;
}
public bool UseMachinePath {
get;
set;
}
public bool ShowHelp {
get;
set;
}
public string ContainerName {
get;
set;
}
public uint KeySize {
get;
set;
}
public bool Verbose {
get;
set;
}
public Config ()
{
ApplicationPhysicalPath = DefaultApplicationPhysicalPath;
ContainerName = DefaultContainerName;
ConfigFileName = DefaultContainerName;
KeySize = DefaultKeySize;
}
}
}

View File

@@ -0,0 +1,360 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Mono.Options;
using Mono.Configuration.Crypto;
[assembly: AssemblyTitle ("mono-configuration-crypto")]
[assembly: AssemblyDescription ("Mono configuration utility to manage encryption keys and encrypt/decrypt config file sections")]
[assembly: AssemblyCompany (Consts.MonoCompany)]
[assembly: AssemblyProduct ("Mono Configuration Cryptography Tools")]
[assembly: AssemblyCopyright ("Copyright (c) 2010 Novell, Inc (http://novell.com, http://mono-project.com/)")]
[assembly: AssemblyVersion (Consts.FxVersion)]
namespace MonoConfigurationCrypto
{
class MonoConfigurationCrypto
{
void Success ()
{
Console.WriteLine ("Success.");
}
void Failure (Exception ex, Config cfg)
{
Failure (ex, cfg, null);
}
void Failure (Config cfg, string message, params object[] parms)
{
Failure (null, cfg, message, parms);
}
void Failure (Exception ex, Config cfg, string message, params object[] parms)
{
if (!String.IsNullOrEmpty (message)) {
if (parms == null || parms.Length == 0)
Console.Error.WriteLine (message);
else
Console.Error.WriteLine (message, parms);
}
if (ex != null) {
if (cfg.Verbose)
Console.Error.WriteLine (ex.ToString ());
else
Console.Error.WriteLine (ex.Message);
}
Console.Error.WriteLine ("Failure.");
}
bool ListContainers (Config cfg)
{
try {
var kc = new KeyContainerCollection (cfg.UseMachinePath);
int count;
foreach (KeyContainer c in kc) {
count = c.Count;
Console.WriteLine ("{0} container '{1}' ({2} key{3})", c.Local ? "Local" : "Global", c.Name, count,
count == 1 ? String.Empty : "s");
}
} catch (Exception ex) {
Failure (ex, cfg);
}
return true;
}
string FindConfigFile (string path, string configFileName)
{
if (!Directory.Exists (path))
return null;
string fileName = null;
foreach (var s in Directory.GetFiles (path, "*.*", SearchOption.TopDirectoryOnly)) {
string fn = Path.GetFileName (s);
if (String.Compare (fn, configFileName, StringComparison.OrdinalIgnoreCase) == 0) {
fileName = fn;
break;
}
}
if (fileName == null)
return null;
return Path.Combine (path, fileName);
}
bool EncryptSection (Config cfg)
{
string configSection = cfg.ConfigSectionName;
string containerName = cfg.ContainerName;
string configFile = FindConfigFile (cfg.ApplicationPhysicalPath, cfg.ConfigFileName);
Console.WriteLine ("Encrypting section '{0}' in config file '{1}' using key container '{2}'...", configSection, configFile, containerName);
if (String.IsNullOrEmpty (configFile)) {
Failure (cfg, "No config file found in directory '{0}'", cfg.ApplicationPhysicalPath);
return true;
}
if (String.IsNullOrEmpty (configSection)) {
Failure (cfg, "No config section name specified.");
return true;
}
try {
var cs = new ConfigSection ();
cs.Encrypt (configFile, configSection, containerName, cfg.UseMachinePath);
Console.WriteLine ("Success.");
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
bool DecryptSection (Config cfg)
{
string configSection = cfg.ConfigSectionName;
string containerName = cfg.ContainerName;
string configFile = FindConfigFile (cfg.ApplicationPhysicalPath, cfg.ConfigFileName);
Console.WriteLine ("Decrypting section '{0}' in config file '{1}' using key container '{2}'...", configSection, configFile, containerName);
if (String.IsNullOrEmpty (configFile)) {
Failure (cfg, "No config file found in directory '{0}'", cfg.ApplicationPhysicalPath);
return true;
}
if (String.IsNullOrEmpty (configSection)) {
Failure (cfg, "No config section name specified.");
return true;
}
try {
var cs = new ConfigSection ();
cs.Decrypt (configFile, configSection, containerName, cfg.UseMachinePath);
Console.WriteLine ("Success.");
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
bool CreateKey (Config cfg)
{
string name = cfg.ContainerName;
KeyContainerCollection kc;
Console.WriteLine ("Creating RSA key container '{0}'...", name);
try {
kc = new KeyContainerCollection (cfg.UseMachinePath);
if (kc.Contains (name)) {
Failure (cfg, "The RSA container already exists.");
return true;
}
var k = new Key (name, cfg.KeySize, cfg.UseMachinePath);
if (!k.IsValid) {
Failure (cfg, "Failed to generate RSA key pair.");
return true;
}
k.Save ();
Success ();
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
bool ImportKey (Config cfg)
{
string containerName = cfg.ContainerName;
string fileName = cfg.FileName;
Console.WriteLine ("Importing an RSA key from file '{0}' into the container '{1}'...", fileName, containerName);
if (String.IsNullOrEmpty (containerName)) {
Failure (cfg, "Unspecified container name.");
return true;
}
if (String.IsNullOrEmpty (fileName)) {
Failure (cfg, "Unspecified file name.");
return true;
}
if (!File.Exists (fileName)) {
Failure (cfg, "Key file '{0}' does not exist.", fileName);
return true;
}
KeyContainerCollection kcc;
Key key;
KeyContainer kc;
try {
kcc = new KeyContainerCollection (cfg.UseMachinePath);
kc = kcc [containerName];
if (kc != null)
key = kc [0];
else
key = null;
// No validation is performed on the key - this is left for the
// encryption algorithm implementation to do.
string keyvalue = File.ReadAllText (fileName);
if (key == null)
key = new Key (containerName, keyvalue, cfg.UseMachinePath);
else {
key.KeyValue = keyvalue;
key.ContainerName = containerName;
}
key.Save ();
Console.WriteLine ("Success.");
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
bool ExportKey (Config cfg)
{
string containerName = cfg.ContainerName;
string fileName = cfg.FileName;
Console.WriteLine ("Exporting an RSA key from container '{0}' to file '{1}'...", containerName, fileName);
if (String.IsNullOrEmpty (containerName)) {
Failure (cfg, "Unspecified container name.");
return true;
}
if (String.IsNullOrEmpty (fileName)) {
Failure (cfg, "Unspecified file name.");
return true;
}
KeyContainerCollection kcc;
Key key;
KeyContainer kc;
try {
kcc = new KeyContainerCollection (cfg.UseMachinePath);
kc = kcc [containerName];
if (kc != null)
key = kc [0];
else {
Failure (cfg, "Container '{0}' does not exist.", containerName);
return true;
}
if (key == null) {
Failure (cfg, "Container '{0}' exists but it does not contain any keys.", containerName);
return true;
}
File.WriteAllText (fileName, key.KeyValue);
Console.WriteLine ("Success.");
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
bool RemoveContainer (Config cfg)
{
string containerName = cfg.ContainerName;
Console.WriteLine ("Removing container '{0}'...", containerName);
if (String.IsNullOrEmpty (containerName)) {
Failure (cfg, "Unspecified container name.");
return true;
}
try {
KeyContainer.RemoveFromDisk (containerName, cfg.UseMachinePath);
Console.WriteLine ("Success.");
} catch (Exception ex) {
Failure (ex, cfg);
return true;
}
return false;
}
void ShowHeader ()
{
string title = String.Empty, version = String.Empty, description = String.Empty, copyright = String.Empty;
Assembly asm = Assembly.GetExecutingAssembly ();
foreach (object o in asm.GetCustomAttributes (false)) {
if (o is AssemblyTitleAttribute)
title = ((AssemblyTitleAttribute)o).Title;
else if (o is AssemblyCopyrightAttribute)
copyright = ((AssemblyCopyrightAttribute)o).Copyright;
else if (o is AssemblyDescriptionAttribute)
description = ((AssemblyDescriptionAttribute)o).Description;
}
version = asm.GetName ().Version.ToString ();
Console.WriteLine ("{1} - version {2}{0}{3}{0}{4}{0}",
Environment.NewLine,
title,
version,
description,
copyright);
}
void Run (string[] args)
{
var cfg = new Config ();
var actions = new List <Func <Config, bool>> ();
var options = new OptionSet () {
{ "h|?|help", "Show usage information", v => cfg.ShowHelp = true },
{ "v|verbose", "Show verbose information (including exception stacktraces)", v => cfg.Verbose = true },
{ "m|machine|global", "Use machine (global) store for all the key actions", v => cfg.UseMachinePath = true },
{ "u|user|local", "Use local (user) store for all the key actions [*]", v => cfg.UseMachinePath = false },
{ "l|list", "List all the key container names in the store", v => actions.Add (ListContainers) },
{ "c|create", "Creates an RSA public/private key pair", v => actions.Add (CreateKey) },
{ "i|import", "Import key to a container", v => actions.Add (ImportKey) },
{ "x|export", "Export key from a container", v => actions.Add (ExportKey) },
{ "r|remove", "Remove a container", v => actions.Add (RemoveContainer) },
{ "f=|file=", "File name for import or export operations", (string s) => cfg.FileName = s },
{ "cf=|config-file=", String.Format ("Config file name (not path) [{0}]", Config.DefaultConfigFileName), (string s) => cfg.ConfigFileName = s },
{ "n=|name=", String.Format ("Container name [{0}]", Config.DefaultContainerName), (string s) => cfg.ContainerName = s },
{ "s=|size=", String.Format ("Key size [{0}]", Config.DefaultKeySize), (uint s) => cfg.KeySize = s },
{ "p=|path=", String.Format ("Application physical path [{0}]", Config.DefaultApplicationPhysicalPath), (string s) => cfg.ApplicationPhysicalPath = s },
{ "d=|dec=|decrypt=", "Decrypt configuration section", (string s) => { cfg.ConfigSectionName = s; actions.Add (DecryptSection);} },
{ "e=|enc=|encrypt=", "Encrypt configuration section", (string s) => { cfg.ConfigSectionName = s; actions.Add (EncryptSection);} },
};
options.Parse (args);
if (cfg.ShowHelp) {
ShowHeader ();
options.WriteOptionDescriptions (Console.Out);
return;
}
foreach (var action in actions)
if (action (cfg))
Environment.Exit (0);
}
static void Main (string[] args)
{
new MonoConfigurationCrypto ().Run (args);
}
}
}

View File

@@ -0,0 +1,4 @@
../../../build/common/Consts.cs
../../../class/Mono.Options/Mono.Options/Options.cs
main.cs
config.cs

View File

@@ -0,0 +1,59 @@
//
// AssemblyInfo.cs
//
// Authors:
// Marek Safar (marek.safar@gmail.com)
//
// Copyright (C) 2010 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Reflection;
using System.Resources;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about the System.Core assembly
[assembly: AssemblyTitle ("Mono.Configuration.Crypto.dll")]
[assembly: AssemblyDescription ("Mono configuration encryption utilities.")]
[assembly: AssemblyDefaultAlias ("Mono.Configuration.Crypto.dll")]
[assembly: AssemblyCompany (Consts.MonoCompany)]
[assembly: AssemblyProduct (Consts.MonoProduct)]
[assembly: AssemblyCopyright (Consts.MonoCopyright)]
[assembly: AssemblyVersion (Consts.FxVersion)]
[assembly: SatelliteContractVersion (Consts.FxVersion)]
[assembly: AssemblyInformationalVersion (Consts.FxFileVersion)]
[assembly: AssemblyFileVersion (Consts.FxFileVersion)]
[assembly: NeutralResourcesLanguage ("en-US")]
[assembly: AssemblyDelaySign (true)]
[assembly: AssemblyKeyFile ("../../mono.pub")]
[assembly: AllowPartiallyTrustedCallers]
[assembly: DefaultDependency (LoadHint.Always)]
[assembly: ComVisible (false)]

View File

@@ -0,0 +1,9 @@
thisdir = tools/mono-configuration-crypto/lib
SUBDIRS =
include ../../../build/rules.make
LOCAL_MCS_FLAGS = -r:System.dll -r:Mono.Security.dll -r:System.Security.dll -r:System.Configuration.dll -r:System.Xml.dll
LIBRARY = Mono.Configuration.Crypto.dll
LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/mono-configuration-crypto/$(FRAMEWORK_VERSION)
include ../../../build/library.make

View File

@@ -0,0 +1,6 @@
../../../build/common/Consts.cs
Assembly/AssemblyInfo.cs
Mono.Configuration.Crypto/ConfigSection.cs
Mono.Configuration.Crypto/Key.cs
Mono.Configuration.Crypto/KeyContainer.cs
Mono.Configuration.Crypto/KeyContainerCollection.cs

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.Configuration.Crypto
{
public class ConfigSection
{
static readonly char[] sectionSplitChars = { '/' };
ProtectedConfigurationProvider GetProvider (string providerName, string containerName, bool useMachineStore)
{
if (String.IsNullOrEmpty (providerName))
providerName = ProtectedConfiguration.DefaultProvider;
ProtectedConfigurationProvider prov = ProtectedConfiguration.Providers [providerName];
if (prov == null)
throw new InvalidOperationException (String.Format ("Provider '{0}' is unknown.", providerName));
// We need to create a new instance in order to be able to pass our own
// parameters to the provider
var ret = Activator.CreateInstance (prov.GetType ()) as ProtectedConfigurationProvider;
ret.Initialize (providerName, new NameValueCollection {
{"keyContainerName", containerName},
{"useMachineContainer", useMachineStore.ToString ()},
}
);
return ret;
}
string BuildXPathExpression (string configSection)
{
var sb = new StringBuilder ("//config:configuration");
string[] parts = configSection.Split (sectionSplitChars);
foreach (string s in parts)
sb.Append ("/config:" + s);
return sb.ToString ();
}
bool IsValidSection (string configFile, string configSection)
{
var exeMap = new ExeConfigurationFileMap ();
exeMap.ExeConfigFilename = configFile;
global::System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration (exeMap, ConfigurationUserLevel.None);
if (config == null)
return false;
try {
var cs = config.GetSection (configSection) as ConfigurationSection;
if (cs == null)
return false;
} catch (CryptographicException) {
// Ignore - it's ok, since we only want to know if the section is
// valid and this exception is thrown when an attempt to decrypt a
// section is made and the protection provider for some reason
// didn't do the job (e.g. we encrypted the section with local store
// key container and the provider wants to access a global store one
// and cannot find it)
}
return true;
}
string LoadSection (string configFile, string configSection, string containerName, bool useMachineStore,
out XmlDocument doc, out XmlNode section, out ProtectedConfigurationProvider provider)
{
if (!IsValidSection (configFile, configSection))
throw new InvalidOperationException (String.Format ("Section '{0}' is not a valid section in file '{1}'", configSection, configFile));
// This should be done using Configuration, but currently the Mono
// System.Configuration saves configuration files without preserving
// non-significant whitespace which gives a very ugly result.
doc = new XmlDocument ();
doc.PreserveWhitespace = true;
doc.Load (configFile);
XmlNamespaceManager nsmgr = null;
XmlElement root = doc.DocumentElement;
string ns = null;
if (root.HasAttributes) {
ns = root.GetAttribute ("xmlns");
if (!String.IsNullOrEmpty (ns)) {
nsmgr = new XmlNamespaceManager (doc.NameTable);
nsmgr.AddNamespace ("config", ns);
}
}
section = doc.DocumentElement.SelectSingleNode (BuildXPathExpression (configSection), nsmgr);
// This check is necessary even though IsValidSection returned true - it's
// because the section might have been found in files other than the one
// we're processing.
if (section == null)
throw new InvalidOperationException (String.Format ("Section '{0}' not found in config file '{1}'", configSection, configFile));
XmlAttribute attr = section.Attributes ["configProtectionProvider"];
string configProtectionProvider = attr == null ? null : attr.Value;
provider = GetProvider (configProtectionProvider, containerName, useMachineStore);
return ns;
}
void SaveWithBackup (string configFile, XmlDocument doc)
{
string backupFile = configFile + ".save";
bool copied = false;
try {
File.Copy (configFile, backupFile, true);
copied = true;
using (var fs = File.Open (configFile, FileMode.Truncate, FileAccess.Write, FileShare.None)) {
doc.Save (fs);
fs.Flush ();
}
} catch {
if (copied)
File.Copy (backupFile, configFile);
} finally {
if (copied)
File.Delete (backupFile);
}
}
public void Encrypt (string configFile, string configSection, string containerName, bool useMachineStore)
{
if (String.IsNullOrEmpty (configFile))
throw new ArgumentNullException ("configFile");
if (String.IsNullOrEmpty (configSection))
throw new ArgumentNullException ("configSection");
if (String.IsNullOrEmpty (containerName))
throw new ArgumentNullException ("containerName");
XmlNode section;
XmlDocument doc;
ProtectedConfigurationProvider provider;
string ns = LoadSection (configFile, configSection, containerName, useMachineStore, out doc, out section, out provider);
XmlNode encrypted = provider.Encrypt (section);
if (encrypted == null)
throw new InvalidOperationException (String.Format ("Failed to encrypt '{0}' section in config file '{1}'", configSection, configFile));
XmlNode newSection = doc.CreateElement (section.Name, ns);
XmlAttribute attr = doc.CreateAttribute ("configProtectionProvider");
attr.Value = provider.Name;
newSection.InnerXml = encrypted.OuterXml;
newSection.Attributes.Append (attr);
section.ParentNode.ReplaceChild (newSection, section);
SaveWithBackup (configFile, doc);
}
public void Decrypt (string configFile, string configSection, string containerName, bool useMachineStore)
{
if (String.IsNullOrEmpty (configFile))
throw new ArgumentNullException ("configFile");
if (String.IsNullOrEmpty (configSection))
throw new ArgumentNullException ("configSection");
if (String.IsNullOrEmpty (containerName))
throw new ArgumentNullException ("containerName");
XmlNode section;
XmlDocument doc;
ProtectedConfigurationProvider provider;
LoadSection (configFile, configSection, containerName, useMachineStore, out doc, out section, out provider);
XmlNode decrypted = provider.Decrypt (section);
XmlNode newNode = doc.ImportNode (decrypted.FirstChild, true);
XmlAttribute attr = newNode.Attributes ["xmlns"];
if (attr != null)
newNode.Attributes.Remove (attr);
section.ParentNode.ReplaceChild (newNode, section);
SaveWithBackup (configFile, doc);
}
}
}

View File

@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
using Mono.Xml;
namespace Mono.Configuration.Crypto
{
public class Key
{
static readonly char[] splitChars = {']'};
string file;
KeyPairPersistence keypair;
bool machineStore;
uint keySize;
public bool IsValid {
get;
private set;
}
public string KeyValue {
get;
set;
}
public bool Local {
get { return !machineStore; }
}
public string ContainerName {
get;
set;
}
public int ProviderType {
get;
set;
}
public Key (string file, bool machineStore)
{
if (String.IsNullOrEmpty (file))
throw new ArgumentNullException ("file");
this.file = file;
this.machineStore = machineStore;
this.keySize = 0;
ReadFile ();
}
public Key (string containerName, string keyValue, bool machineStore)
{
if (String.IsNullOrEmpty (containerName))
throw new ArgumentNullException ("containerName");
if (String.IsNullOrEmpty (keyValue))
throw new ArgumentNullException ("keyValue");
this.file = null;
this.machineStore = machineStore;
this.keySize = 0;
this.KeyValue = keyValue;
this.IsValid = true;
if (keyValue.StartsWith ("RSAKeyValue", StringComparison.Ordinal))
this.ProviderType = 1;
else if (keyValue.StartsWith ("DSAKeyValue", StringComparison.Ordinal))
this.ProviderType = 13;
else
this.ProviderType = -1;
}
public Key (string containerName, uint keySize, bool machineStore)
{
if (String.IsNullOrEmpty (containerName))
throw new ArgumentNullException ("containerName");
this.ContainerName = containerName;
this.machineStore = machineStore;
this.keySize = keySize;
this.ProviderType = 1;
GenerateKeyPair ();
}
public void Save ()
{
var csp = new CspParameters (1);
if (machineStore)
csp.Flags |= CspProviderFlags.UseMachineKeyStore;
csp.ProviderName = String.Empty;
csp.KeyContainerName = ContainerName;
var kpp = new KeyPairPersistence (csp, KeyValue);
kpp.Save ();
}
void GenerateKeyPair ()
{
var rsa = new RSAManaged ((int)keySize);
KeyValue = rsa.ToXmlString (true);
IsValid = true;
}
void ReadFile ()
{
var sp = new SecurityParser ();
sp.LoadXml (File.ReadAllText (file));
SecurityElement root = sp.ToXml ();
if (root.Tag == "KeyPair") {
SecurityElement keyvalue = root.SearchForChildByTag ("KeyValue");
if (keyvalue.Children.Count == 0)
return;
KeyValue = keyvalue.Children [0].ToString ();
SecurityElement properties = root.SearchForChildByTag ("Properties");
if (properties.Children.Count == 0)
return;
SecurityElement property;
string containerName = null, attribute;
int providerType = -1;
foreach (object o in properties.Children) {
property = o as SecurityElement;
if (property == null)
continue;
switch (property.Tag) {
case "Provider":
attribute = property.Attribute ("Type");
if (String.IsNullOrEmpty (attribute))
return;
if (!Int32.TryParse (attribute, out providerType))
return;
break;
case "Container":
attribute = property.Attribute ("Name");
if (String.IsNullOrEmpty (attribute))
return;
containerName = attribute;
break;
}
}
if (String.IsNullOrEmpty (containerName) || providerType == -1)
return;
ContainerName = containerName;
ProviderType = providerType;
IsValid = true;
}
}
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Configuration.Crypto
{
public class KeyContainer : IEnumerable <Key>
{
List <Key> keys;
List <Key> Keys {
get {
if (keys == null)
keys = new List <Key> ();
return keys;
}
}
public int Count {
get {
if (keys == null)
return 0;
return keys.Count;
}
}
public bool Local {
get;
set;
}
public string Name {
get;
set;
}
public Key this [int index] {
get {
int count = Count;
if (count == 0)
return null;
if (index < 0 || index >= count)
throw new ArgumentOutOfRangeException ("index");
return keys [index];
}
}
public KeyContainer (string name, bool machineStore)
{
Name = name;
Local = !machineStore;
}
public static void RemoveFromDisk (string containerName, bool machineStore)
{
var csp = new CspParameters ();
if (machineStore)
csp.Flags |= CspProviderFlags.UseMachineKeyStore;
csp.ProviderName = String.Empty;
csp.KeyContainerName = containerName;
var kpp = new KeyPairPersistence (csp, String.Empty);
if (!File.Exists (kpp.Filename))
return;
File.Delete (kpp.Filename);
}
public void Add (Key key)
{
if (key == null)
return;
Keys.Add (key);
}
public IEnumerator <Key> GetEnumerator ()
{
return Keys.GetEnumerator ();
}
#region IEnumerable
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
#endregion
#region IEnumerable <T>
IEnumerator <Key> IEnumerable <Key>.GetEnumerator ()
{
return GetEnumerator ();
}
#endregion
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Mono.Security.Cryptography;
namespace Mono.Configuration.Crypto
{
public class KeyContainerCollection : ICollection <KeyContainer>
{
bool machineStore;
SortedDictionary <string, KeyContainer> containers;
SortedDictionary <string, KeyContainer> Containers {
get {
if (containers == null)
containers = new SortedDictionary <string, KeyContainer> ();
return containers;
}
}
public KeyContainer this [string name] {
get { return GetContainer (name); }
}
public KeyContainerCollection (bool machineStore)
{
string topPath;
if (machineStore)
topPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData), ".mono");
else
topPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), ".mono");
topPath = Path.Combine (topPath, "keypairs");
this.machineStore = machineStore;
if (Directory.Exists (topPath))
LoadKeys (topPath);
}
public bool Contains (string name)
{
if (String.IsNullOrEmpty (name) || Count == 0)
return false;
KeyContainer c = GetContainer (name);
if (c == null || c.Count == 0)
return false;
return true;
}
public IEnumerator <KeyContainer> GetEnumerator ()
{
foreach (var de in Containers)
yield return de.Value;
}
KeyContainer GetContainer (string name)
{
KeyContainer c;
if (Containers.TryGetValue (name, out c))
return c;
var md5 = MD5.Create ();
byte[] result = md5.ComputeHash (Encoding.UTF8.GetBytes (name));
string hashed = new Guid (result).ToString ();
if (Containers.TryGetValue (hashed, out c))
return c;
return null;
}
void LoadKeys (string path)
{
string[] files = Directory.GetFiles (path, "*.xml");
if (files == null || files.Length == 0)
return;
SortedDictionary <string, KeyContainer> containers = Containers;
KeyContainer keyContainer;
Key key;
string containerName;
foreach (string file in files) {
key = new Key (file, machineStore);
if (!key.IsValid)
continue;
containerName = key.ContainerName;
if (!containers.TryGetValue (containerName, out keyContainer)) {
keyContainer = new KeyContainer (containerName, machineStore);
containers.Add (containerName, keyContainer);
}
keyContainer.Add (key);
}
}
#region IEnumerable
IEnumerator <KeyContainer> IEnumerable <KeyContainer>.GetEnumerator ()
{
return GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
#endregion
#region ICollection
public int Count {
get {
if (containers == null)
return 0;
return containers.Count;
}
}
public bool IsReadOnly {
get { return false; }
}
public void Add (KeyContainer item)
{
if (item == null)
return;
SortedDictionary <string, KeyContainer> containers = Containers;
string name = item.Name;
if (containers.ContainsKey (name))
containers [name] = item;
else
containers.Add (name, item);
}
public void Clear ()
{
if (containers == null)
return;
containers.Clear ();
}
public bool Contains (KeyContainer item)
{
if (Count == 0 || item == null)
return false;
return containers.ContainsKey (item.Name);
}
public void CopyTo (KeyContainer[] array, int arrayIndex)
{
if (Count == 0)
return;
containers.Values.CopyTo (array, arrayIndex);
}
public bool Remove (KeyContainer item)
{
if (Count == 0 || item == null)
return false;
return containers.Remove (item.Name);
}
#endregion
}
}