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,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
}
}