Merge branch 'upstream'

Former-commit-id: 70340005d173498c8871669ddb9867e171cbb3e1
This commit is contained in:
Xamarin Public Jenkins 2016-04-12 13:22:08 -04:00
commit 1ffecf6eb5
118 changed files with 4121 additions and 1632 deletions

View File

@ -84,8 +84,8 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(srcdir)/config.h.in mkinstalldirs \
$(srcdir)/mono-uninstalled.pc.in COPYING.LIB ChangeLog NEWS \
compile config.guess config.rpath config.sub depcomp \
install-sh missing ltmain.sh
compile config.guess config.rpath config.sub install-sh \
missing ltmain.sh
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \

View File

@ -75,6 +75,7 @@ namespace System.Web.Services.Configuration
try {
var hack = this.EvaluationContext;
} catch (ConfigurationErrorsException) {
this.actualPath = GetConfigurationDirectory();
return;
}
#endif
@ -127,6 +128,7 @@ namespace System.Web.Services.Configuration
var hack = this.EvaluationContext;
} catch (ConfigurationErrorsException) {
base.Reset(parentElement);
this.actualPath = GetConfigurationDirectory();
return;
}
#endif

View File

@ -43,7 +43,7 @@ namespace System.Runtime.InteropServices {
// Should not have been instantiable - here for binary compatibility in V4.
}
#endif
#if !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.Machine)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
@ -58,8 +58,8 @@ namespace System.Runtime.InteropServices {
[ResourceExposure(ResourceScope.Machine)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern String GetHostBindingFile();
#if !FEATURE_CORECLR
#endif
#if !FEATURE_CORECLR && !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
@ -78,7 +78,7 @@ namespace System.Runtime.InteropServices {
[MethodImpl (MethodImplOptions.NoInlining)]
public static String GetSystemVersion()
{
#if FEATURE_CORECLR
#if FEATURE_CORECLR || MONO
return Assembly.GetExecutingAssembly().ImageRuntimeVersion;
@ -97,15 +97,36 @@ namespace System.Runtime.InteropServices {
[ResourceConsumption(ResourceScope.Machine)]
public static String GetRuntimeDirectory()
{
#if !MOBILE
//
// Workaround for csc hardcoded behaviour where executing mscorlib
// location is always the first path to search for references unless
// they have full path. Mono build is using simple assembly names for
// references and -lib for path which is by default csc dehaviour never
// used
//
var sdk = Environment.GetEnvironmentVariable ("CSC_SDK_PATH_DISABLED");
if (sdk != null)
return null;
#endif
String dir = GetRuntimeDirectoryImpl();
#if !DISABLE_CAS_USE
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dir).Demand();
#endif
return dir;
}
#if MONO
static String GetRuntimeDirectoryImpl()
{
return Path.GetDirectoryName (typeof (object).Assembly.Location);
}
#else
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.Machine)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern String GetRuntimeDirectoryImpl();
#endif
// Returns the system ConfigurationFile
public static String SystemConfigurationFile {
@ -113,19 +134,24 @@ namespace System.Runtime.InteropServices {
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
get {
#if MONO
String path = Environment.GetMachineConfigPath ();
#else
StringBuilder sb = new StringBuilder(Path.MAX_PATH);
sb.Append(GetRuntimeDirectory());
sb.Append(AppDomainSetup.RuntimeConfigurationFile);
String path = sb.ToString();
#endif
#if !DISABLE_CAS_USE
// Do security check
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
#endif
return path;
}
}
#if FEATURE_COMINTEROP
#if FEATURE_COMINTEROP && !MONO
[System.Security.SecurityCritical]
[ResourceExposure(ResourceScope.Process)]
[ResourceConsumption(ResourceScope.Process)]

View File

@ -1 +1 @@
f0d95f2e3a9502289ad1dba49a96fc174998e83f
7f83cf34517d801b0428a702ae9dd6fa9d28a79b

View File

@ -233,10 +233,8 @@ AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue)
AC_MSG_CHECKING(for __sync_bool_compare_and_swap)
AC_TRY_COMPILE([],[
volatile unsigned int foo = 0;
int main(int argc, char** argv) {
unsigned int r1 = __sync_bool_compare_and_swap(&foo, 0, 1);
return 0;
}
unsigned int r1 = __sync_bool_compare_and_swap(&foo, 0, 1);
return 0;
], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAS___SYNC_BOOL_COMPARE_AND_SWAP)

View File

@ -41,6 +41,8 @@ namespace Microsoft.Build.Tasks {
ITaskItem[] assignedProjects;
string solutionConfigurationContents;
ITaskItem[] unassignedProjects;
Dictionary<Guid, string> guidToConfigPlatform;
Dictionary<string, string> absolutePathToConfigPlatform;
public AssignProjectConfiguration ()
{
@ -53,10 +55,10 @@ namespace Microsoft.Build.Tasks {
return true;
XmlReader xr = null;
Dictionary<Guid, string> guidToConfigPlatform = null;
guidToConfigPlatform = new Dictionary<Guid, string> ();
absolutePathToConfigPlatform = new Dictionary<string, string> ();
try {
xr = XmlReader.Create (new StringReader (solutionConfigurationContents));
guidToConfigPlatform = new Dictionary<Guid, string> ();
xr.Read ();
while (!xr.EOF) {
@ -65,12 +67,20 @@ namespace Microsoft.Build.Tasks {
continue;
string guid_str = xr.GetAttribute ("Project");
string abs_path = xr.GetAttribute ("AbsolutePath");
string config_str = xr.ReadString ();
if (String.IsNullOrEmpty (config_str))
continue;
Guid guid;
if (!String.IsNullOrEmpty (guid_str) && !String.IsNullOrEmpty (config_str) &&
TryParseGuid (guid_str, out guid))
if (TryParseGuid (guid_str, out guid))
guidToConfigPlatform [guid] = config_str;
if (!String.IsNullOrEmpty (abs_path)) {
abs_path = Path.GetFullPath (abs_path);
absolutePathToConfigPlatform [abs_path] = config_str;
}
}
} catch (XmlException xe) {
Log.LogError ("XmlException while parsing SolutionConfigurationContents: {0}",
@ -84,32 +94,22 @@ namespace Microsoft.Build.Tasks {
List<ITaskItem> tempAssignedProjects = new List<ITaskItem> ();
List<ITaskItem> tempUnassignedProjects = new List<ITaskItem> ();
foreach (ITaskItem item in ProjectReferences) {
string config;
string config = GetConfigPlatformFromProjectReference (item);
string guid_str = item.GetMetadata ("Project");
Guid guid = Guid.Empty;
if (!string.IsNullOrEmpty(guid_str) && !TryParseGuid (guid_str, out guid)) {
Log.LogError ("Project reference '{0}' has invalid or missing guid for metadata 'Project'.",
item.ItemSpec);
return false;
}
if (guid != Guid.Empty && guidToConfigPlatform.TryGetValue (guid, out config)) {
string [] parts = config.Split (new char [] {'|'}, 2);
ITaskItem new_item = new TaskItem (item);
new_item.SetMetadata ("SetConfiguration", "Configuration=" + parts [0]);
new_item.SetMetadata ("SetPlatform", "Platform=" +
((parts.Length > 1) ? parts [1] : String.Empty));
tempAssignedProjects.Add (new_item);
} else {
Log.LogWarning ("Project reference '{0}' could not be resolved.",
item.ItemSpec);
if (String.IsNullOrEmpty (config)) {
tempUnassignedProjects.Add (item);
continue;
}
string [] parts = config.Split (new char [] {'|'}, 2);
ITaskItem new_item = new TaskItem (item);
new_item.SetMetadata ("SetConfiguration", "Configuration=" + parts [0]);
new_item.SetMetadata ("SetPlatform", "Platform=" +
((parts.Length > 1) ? parts [1] : String.Empty));
tempAssignedProjects.Add (new_item);
}
assignedProjects = tempAssignedProjects.ToArray ();
@ -118,9 +118,29 @@ namespace Microsoft.Build.Tasks {
return true;
}
string GetConfigPlatformFromProjectReference (ITaskItem item)
{
string guid_str = item.GetMetadata ("Project");
string proj_full_path = item.GetMetadata ("FullPath");
string config;
Guid guid = Guid.Empty;
if (TryParseGuid (guid_str, out guid) && guidToConfigPlatform.TryGetValue (guid, out config))
return config;
string abs_path = item.GetMetadata ("FullPath");
if (absolutePathToConfigPlatform.TryGetValue (abs_path, out config))
return config;
return null;
}
bool TryParseGuid (string guid_str, out Guid guid)
{
guid = Guid.Empty;
if (String.IsNullOrEmpty (guid_str))
return false;
try {
guid = new Guid (guid_str);
} catch (ArgumentNullException) {

View File

@ -32,6 +32,7 @@ using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using NUnit.Framework;
using System.IO;
using System.Text;
namespace MonoTests.Microsoft.Build.Tasks
@ -58,22 +59,73 @@ namespace MonoTests.Microsoft.Build.Tasks
"{DAE34193-B5C7-4488-A911-29EE15C84CBE}"
};
CreateAndCheckProject (guids, project_ref_guids, new string[] {
"AssignedProjects : foo0.csproj;foo1.csproj;foo2.csproj;foo3.csproj: SetConfig: Configuration=Release",
CreateAndCheckProject (guids, new bool[] {true, true, true, true, true, true},
project_ref_guids, new string[] {
"AssignedProjects : foo0.csproj;foo1.csproj;foo2.csproj;foo3.csproj;foo4.csproj: SetConfig: Configuration=Release",
"AssignedProjects : foo0.csproj: SetPlatform: Platform=AnyCPU0",
"AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU1",
"AssignedProjects : foo2.csproj: SetPlatform: Platform=AnyCPU2",
"AssignedProjects : foo3.csproj: SetPlatform: Platform=AnyCPU3",
"UnassignedProjects : foo4.csproj"},
"AssignedProjects : foo4.csproj: SetPlatform: Platform=AnyCPU4",
"UnassignedProjects : "},
true,
"A1#");
}
[Test]
public void TestInvalidProjectGuid ()
public void TestNoGuidAndNoAbsolutePathFound()
{
string[] guids = new string[] {
"asd"
};
string[] project_ref_guids = new string[] {
"{DAE34193-B5C7-4488-A911-29EE15C84CB8}",
"invalid guid",
""
};
CreateAndCheckProject (guids, new bool[]{false},
project_ref_guids,
new string[] {
"AssignedProjects : : SetConfig: ",
"AssignedProjects : : SetPlatform: ",
"UnassignedProjects : foo0.csproj;foo1.csproj;foo2.csproj"
},
true, "A1#");
}
[Test]
public void TestInvalidProjectGuidWithAbsolutePath ()
{
string[] guids = new string[] {
null, // no AbsPath
"another invalid guid", // has AbsPath
};
string[] project_ref_guids = new string[] {
"1234zxc", // this won't match because no AbsPath
"xzxoiu", // match with the second project, foo1.csproj
"{23F291D9-78DF-4133-8CF2-78CE104DDE63}",
"badref" // no corresponding project at all
};
CreateAndCheckProject (guids, new bool[]{false, true},
project_ref_guids,
new string[] {
"AssignedProjects : foo1.csproj: SetConfig: Configuration=Release",
"AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU1",
"UnassignedProjects : foo0.csproj;foo2.csproj;foo3.csproj"
},
true, "A1#");
}
[Test]
public void TestNoGuidWithAbsolutePath ()
{
string[] guids = new string[] {
"",
null
};
string[] project_ref_guids = new string[] {
@ -82,7 +134,14 @@ namespace MonoTests.Microsoft.Build.Tasks
"invalid guid"
};
CreateAndCheckProject (guids, project_ref_guids, null, false, "A1#");
CreateAndCheckProject (guids, new bool[]{true, false},
project_ref_guids,
new string[] {
"AssignedProjects : foo0.csproj: SetConfig: Configuration=Release",
"AssignedProjects : foo0.csproj: SetPlatform: Platform=AnyCPU0",
"UnassignedProjects : foo1.csproj;foo2.csproj"
},
true, "A1#");
}
[Test]
@ -97,7 +156,8 @@ namespace MonoTests.Microsoft.Build.Tasks
"{23F291D9-78DF-4133-8CF2-78CE104DDE63}"
};
CreateAndCheckProject (guids, project_ref_guids,
CreateAndCheckProject (guids, new bool[]{false, true},
project_ref_guids,
new string [] {
"AssignedProjects : foo1.csproj: SetConfig: Configuration=Release",
"AssignedProjects : foo1.csproj: SetPlatform: Platform=AnyCPU0",
@ -106,14 +166,14 @@ namespace MonoTests.Microsoft.Build.Tasks
}
void CreateAndCheckProject (string[] guids, string[] project_ref_guids, string[] messages, bool build_result, string prefix)
void CreateAndCheckProject (string[] guids, bool[] set_project_paths, string[] project_ref_guids, string[] messages, bool build_result, string prefix)
{
Engine engine = new Engine (Consts.BinPath);
Project project = engine.CreateNewProject ();
TestMessageLogger testLogger = new TestMessageLogger ();
engine.RegisterLogger (testLogger);
string projectString = CreateProject (guids, project_ref_guids);
string projectString = CreateProject (guids, set_project_paths, project_ref_guids);
project.LoadXml (projectString);
try {
@ -131,12 +191,12 @@ namespace MonoTests.Microsoft.Build.Tasks
}
}
string CreateProject (string[] guids, string[] project_ref_guids)
string CreateProject (string[] guids, bool[] set_project_paths, string[] project_ref_guids)
{
StringBuilder sb = new StringBuilder ();
sb.Append (@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
sb.Append ("\n" + GetUsingTask ("AssignProjectConfiguration"));
sb.AppendFormat (@"<PropertyGroup>{0}</PropertyGroup>", CreateSolutionConfigurationProperty (guids, "Release|AnyCPU"));
sb.AppendFormat (@"<PropertyGroup>{0}</PropertyGroup>", CreateSolutionConfigurationProperty (guids, set_project_paths, "Release|AnyCPU"));
sb.Append (CreateProjectReferencesItemGroup (project_ref_guids));
sb.Append ("\n\t<Target Name=\"1\">\n");
@ -154,13 +214,19 @@ namespace MonoTests.Microsoft.Build.Tasks
return sb.ToString ();
}
string CreateSolutionConfigurationProperty (string[] guids, string config_str)
string CreateSolutionConfigurationProperty (string[] guids, bool[] set_project_paths, string config_str)
{
string abs_proj_path_prefix = Path.GetFullPath ("foo");
StringBuilder sb = new StringBuilder ();
sb.Append ("\n<CurrentSolutionConfigurationContents>\n");
sb.Append ("\t<foo xmlns=\"\">\n");
for (int i = 0; i < guids.Length; i++) {
sb.AppendFormat ("\t\t<bar Project=\"{0}\">{1}{2}</bar>\n",
sb.Append ("\t\t<bar");
if (guids[i] != null)
sb.AppendFormat (" Project=\"{0}\"", guids[i]);
if (set_project_paths[i])
sb.AppendFormat (" AbsolutePath=\"{0}{1}.csproj\" ", abs_proj_path_prefix, i);
sb.AppendFormat (">{1}{2}</bar>\n",
guids[i], config_str, i);
}
sb.Append ("\t</foo>\n");
@ -173,8 +239,12 @@ namespace MonoTests.Microsoft.Build.Tasks
{
StringBuilder sb = new StringBuilder ();
sb.Append ("\n<ItemGroup>\n");
for (int i = 0; i < guids.Length; i ++)
sb.AppendFormat ("\t<ProjectReference Include=\"foo{1}.csproj\"><Project>{0}</Project></ProjectReference>\n", guids [i], i);
for (int i = 0; i < guids.Length; i ++) {
sb.AppendFormat ("\t<ProjectReference Include=\"foo{0}.csproj\">", i);
if (guids[i] != null)
sb.AppendFormat ("<Project>{0}</Project>", guids[i]);
sb.Append ("</ProjectReference>\n");
}
sb.Append ("</ItemGroup>\n");
return sb.ToString ();
}

View File

@ -145,13 +145,6 @@ namespace MonoTests.Microsoft.Build.Tasks {
Assert.AreEqual (0, testLogger.CheckHead ("Text", "HelpKeyword", "Code"), "A1");
}
[Test]
public void TestExecute1 ()
{
Error error = new Error ();
Assert.AreEqual (false, error.Execute (), "A1");
}
}
}

View File

@ -197,6 +197,19 @@ namespace MonoTests.Microsoft.Build.Tasks
return 0;
}
public int CheckFullLog (string text)
{
for (int i = 0; i < all_messages.Count; i ++) {
BuildEventArgs arg = all_messages [i];
if (text == arg.Message) {
all_messages.RemoveAt (i);
return 0;
}
}
return 1;
}
public void DumpMessages ()
{
foreach (BuildEventArgs arg in all_messages)

View File

@ -16,7 +16,18 @@ LIB_MCS_FLAGS = \
/r:System.Xml.dll \
/r:$(XBUILD_FRAMEWORK)
TEST_MCS_FLAGS = /r:$(XBUILD_ENGINE) /r:$(XBUILD_FRAMEWORK) -r:System.dll -r:System.Core.dll
TEST_RESX_RESOURCES = Test/Microsoft.Build.Utilities/Strings.resources
TEST_MCS_FLAGS = /r:$(XBUILD_ENGINE) /r:$(XBUILD_FRAMEWORK) -r:System.dll -r:System.Core.dll $(TEST_RESX_RESOURCES:%=-resource:%)
include $(XBUILD_DIR)/xbuild_test.make
include ../../build/library.make
EXTRA_DISTFILES = $(TEST_RESX_RESOURCES:.resources=.resx)
CLEAN_FILES += $(TEST_RESX_RESOURCES)
$(TEST_RESX_RESOURCES): %.resources: %.resx
$(RESGEN) $< || cp $@.prebuilt $@
$(test_lib): $(TEST_RESX_RESOURCES)

View File

@ -38,7 +38,6 @@ namespace Microsoft.Build.Utilities
string helpKeywordPrefix;
ITaskHost hostObject;
TaskLoggingHelper log;
ResourceManager taskResources;
protected Task()
: this (null, null)
@ -53,7 +52,8 @@ namespace Microsoft.Build.Utilities
protected Task(ResourceManager taskResources,
string helpKeywordPrefix)
{
this.taskResources = taskResources;
log = new TaskLoggingHelper (this);
log.TaskResources = taskResources;
this.helpKeywordPrefix = helpKeywordPrefix;
}
@ -65,7 +65,6 @@ namespace Microsoft.Build.Utilities
}
set {
buildEngine = value;
log = new TaskLoggingHelper (this);
}
}
@ -99,10 +98,10 @@ namespace Microsoft.Build.Utilities
protected ResourceManager TaskResources {
get {
return taskResources;
return log.TaskResources;
}
set {
taskResources = value;
log.TaskResources = value;
}
}
}

View File

@ -41,11 +41,14 @@ namespace Microsoft.Build.Utilities
string helpKeywordPrefix;
string taskName;
ResourceManager taskResources;
ITask taskInstance;
public TaskLoggingHelper (ITask taskInstance)
{
if (taskInstance != null)
this.buildEngine = taskInstance.BuildEngine;
if (taskInstance == null)
throw new ArgumentNullException ("taskInstance");
this.taskInstance = taskInstance;
taskName = null;
}
@ -67,7 +70,14 @@ namespace Microsoft.Build.Utilities
if (resourceName == null)
throw new ArgumentNullException ("resourceName");
return null;
if (taskResources == null)
throw new InvalidOperationException ("Task did not register any task resources");
string resourceString = taskResources.GetString (resourceName);
if (resourceString == null)
throw new ArgumentException ($"No resource string found for resource named {resourceName}");
return FormatString (resourceString, args);
}
[MonoTODO]
@ -100,10 +110,12 @@ namespace Microsoft.Build.Utilities
if (message == null)
throw new ArgumentNullException ("message");
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
BuildErrorEventArgs beea = new BuildErrorEventArgs (
null, null, buildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, FormatString (message, messageArgs),
null, null, BuildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, FormatString (message, messageArgs),
helpKeywordPrefix, null);
buildEngine.LogErrorEvent (beea);
BuildEngine.LogErrorEvent (beea);
hasLoggedErrors = true;
}
@ -117,12 +129,14 @@ namespace Microsoft.Build.Utilities
if (message == null)
throw new ArgumentNullException ("message");
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
BuildErrorEventArgs beea = new BuildErrorEventArgs (
subcategory, errorCode, file, lineNumber,
columnNumber, endLineNumber, endColumnNumber,
FormatString (message, messageArgs), helpKeyword /*it's helpKeyword*/,
null /*it's senderName*/);
buildEngine.LogErrorEvent (beea);
BuildEngine.LogErrorEvent (beea);
hasLoggedErrors = true;
}
@ -144,14 +158,16 @@ namespace Microsoft.Build.Utilities
if (exception == null)
throw new ArgumentNullException ("exception");
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
StringBuilder sb = new StringBuilder ();
sb.Append (exception.Message);
if (showStackTrace == true)
sb.Append (exception.StackTrace);
BuildErrorEventArgs beea = new BuildErrorEventArgs (
null, null, buildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, sb.ToString (),
null, null, BuildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, sb.ToString (),
exception.HelpLink, exception.Source);
buildEngine.LogErrorEvent (beea);
BuildEngine.LogErrorEvent (beea);
hasLoggedErrors = true;
}
@ -159,7 +175,7 @@ namespace Microsoft.Build.Utilities
params object[] messageArgs)
{
LogErrorFromResources (null, null, null, null, 0, 0, 0,
0, messageResourceName, null);
0, messageResourceName, messageArgs);
}
public void LogErrorFromResources (string subcategoryResourceName,
@ -172,13 +188,22 @@ namespace Microsoft.Build.Utilities
string messageResourceName,
params object[] messageArgs)
{
if (messageResourceName == null)
throw new ArgumentNullException ("messageResourceName");
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
string subcategory = null;
if (!String.IsNullOrEmpty (subcategoryResourceName))
subcategory = taskResources.GetString (subcategoryResourceName);
BuildErrorEventArgs beea = new BuildErrorEventArgs (
taskResources.GetString (subcategoryResourceName),
subcategory,
errorCode, file, lineNumber, columnNumber,
endLineNumber, endColumnNumber,
taskResources.GetString (messageResourceName),
FormatResourceString (messageResourceName, messageArgs),
helpKeyword, null );
buildEngine.LogErrorEvent (beea);
BuildEngine.LogErrorEvent (beea);
hasLoggedErrors = true;
}
@ -226,16 +251,17 @@ namespace Microsoft.Build.Utilities
public void LogMessageFromResources (string messageResourceName,
params object[] messageArgs)
{
LogMessage (taskResources.GetString (messageResourceName),
messageArgs);
LogMessageFromResources (MessageImportance.Normal, messageResourceName, messageArgs);
}
public void LogMessageFromResources (MessageImportance importance,
string messageResourceName,
params object[] messageArgs)
{
LogMessage (importance, taskResources.GetString (
messageResourceName), messageArgs);
if (messageResourceName == null)
throw new ArgumentNullException ("messageResourceName");
LogMessage (importance, FormatResourceString (messageResourceName, messageArgs));
}
public bool LogMessagesFromFile (string fileName)
@ -280,10 +306,12 @@ namespace Microsoft.Build.Utilities
if (lineOfText == null)
throw new ArgumentNullException ("lineOfText");
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
BuildMessageEventArgs bmea = new BuildMessageEventArgs (
lineOfText, helpKeywordPrefix,
null, messageImportance);
buildEngine.LogMessageEvent (bmea);
BuildEngine.LogMessageEvent (bmea);
return true;
}
@ -291,11 +319,13 @@ namespace Microsoft.Build.Utilities
public void LogWarning (string message,
params object[] messageArgs)
{
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
// FIXME: what about all the parameters?
BuildWarningEventArgs bwea = new BuildWarningEventArgs (
null, null, buildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, FormatString (message, messageArgs),
null, null, BuildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, FormatString (message, messageArgs),
helpKeywordPrefix, null);
buildEngine.LogWarningEvent (bwea);
BuildEngine.LogWarningEvent (bwea);
}
public void LogWarning (string subcategory, string warningCode,
@ -305,11 +335,13 @@ namespace Microsoft.Build.Utilities
string message,
params object[] messageArgs)
{
ThrowInvalidOperationIf (BuildEngine == null, "Task is attempting to log before it was initialized");
BuildWarningEventArgs bwea = new BuildWarningEventArgs (
subcategory, warningCode, file, lineNumber,
columnNumber, endLineNumber, endColumnNumber,
FormatString (message, messageArgs), helpKeyword, null);
buildEngine.LogWarningEvent (bwea);
BuildEngine.LogWarningEvent (bwea);
}
public void LogWarningFromException (Exception exception)
@ -331,8 +363,10 @@ namespace Microsoft.Build.Utilities
public void LogWarningFromResources (string messageResourceName,
params object[] messageArgs)
{
LogWarning (taskResources.GetString (messageResourceName),
messageArgs);
if (messageResourceName == null)
throw new ArgumentNullException ("messageResourceName");
LogWarningFromResources (null, null, null, null, 0, 0, 0, 0, messageResourceName, messageArgs);
}
public void LogWarningFromResources (string subcategoryResourceName,
@ -346,11 +380,17 @@ namespace Microsoft.Build.Utilities
string messageResourceName,
params object[] messageArgs)
{
LogWarning (taskResources.GetString (subcategoryResourceName),
if (messageResourceName == null)
throw new ArgumentNullException ("messageResourceName");
string subcategory = null;
if (!String.IsNullOrEmpty (subcategoryResourceName))
subcategory = taskResources.GetString (subcategoryResourceName);
LogWarning (subcategory,
warningCode, helpKeyword, file, lineNumber,
columnNumber, endLineNumber, endColumnNumber,
taskResources.GetString (messageResourceName),
messageArgs);
FormatResourceString (messageResourceName, messageArgs));
}
public void LogWarningWithCodeFromResources (string messageResourceName,
@ -391,9 +431,15 @@ namespace Microsoft.Build.Utilities
{
}
void ThrowInvalidOperationIf (bool condition, string message)
{
if (condition)
throw new InvalidOperationException (message);
}
protected IBuildEngine BuildEngine {
get {
return buildEngine;
return taskInstance?.BuildEngine;
}
}

View File

@ -4,3 +4,5 @@ Microsoft.Build.Utilities/TaskItemTest.cs
Microsoft.Build.Utilities/TaskLoggingHelperTest.cs
Microsoft.Build.Utilities/ToolLocationHelperTest.cs
Microsoft.Build.Utilities/ToolTaskTest.cs
../../Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/TestMessageLogger.cs
../../Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/Consts.cs

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MessageResource1">
<value>Message from resources with arg '{0}'</value>
</data>
</root>

View File

@ -3,8 +3,10 @@
//
// Author:
// Marek Sieradzki (marek.sieradzki@gmail.com)
// Ankit Jain (ankit.jain@xamarin.com)
//
// (C) 2005 Marek Sieradzki
// (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@ -27,15 +29,27 @@
using System;
using System.Collections;
using System.Reflection;
using System.Resources;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Build.BuildEngine;
using NUnit.Framework;
using MonoTests.Microsoft.Build.Tasks;
namespace MonoTests.Microsoft.Build.Utilities {
class TestTask : Task {
public static Action<TaskLoggingHelper> action = null;
public TestTask ()
: base (new ResourceManager("Strings", typeof(TestTask).GetTypeInfo().Assembly))
{
}
public override bool Execute ()
{
action (Log);
return true;
}
}
@ -46,6 +60,11 @@ namespace MonoTests.Microsoft.Build.Utilities {
TaskLoggingHelper tlh;
TestTask task;
public TaskLoggingHelperTest ()
{
task = new TestTask ();
}
[Test]
public void TestAssignment ()
{
@ -77,6 +96,218 @@ namespace MonoTests.Microsoft.Build.Utilities {
string output;
tlh.ExtractMessageCode (null, out output);
}
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogErrorFromResourcesNullMessage ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogErrorFromResources (null);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogErrorFromResourcesNullMessage2 ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogErrorFromResources (null, null, null, null, 0, 0, 0, 0, null);
}
[Test]
public void TestLogErrorFromResources1 ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogErrorFromResources ("MessageResource1", "foo"),
(l) => Assert.IsTrue (l.CheckFullLog ("Message from resources with arg 'foo'") == 0, "Message not found")
);
}
[Test]
public void TestLogErrorFromResourcesNonExistantResourceName ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogErrorFromResources ("NonExistantResourceName", "foo"),
null,
(p, l) => {
Assert.IsFalse (p.Build (), "Build should have failed");
Assert.IsTrue (l.CheckFullLog (
"Error executing task TestTask: No resource string found for resource named NonExistantResourceName") == 0,
"Error not found in the log");
}
);
}
[Test]
public void TestLogErrorFromResourcesNullSubcategoryResourceName ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogErrorFromResources (null, null, null, null, 0, 0, 0, 0, "MessageResource1", "foo"),
(l) => Assert.IsTrue (l.CheckFullLog ("Message from resources with arg 'foo'") == 0, "Message not found")
);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogWarningFromResourcesNullMessage ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogWarningFromResources (null);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogWarningFromResourcesNullMessage2 ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogWarningFromResources (null, null, null, null, 0, 0, 0, 0, null);
}
[Test]
public void TestLogWarningFromResourcesNullSubcategoryResourceName ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogWarningFromResources (null, null, null, null, 0, 0, 0, 0, "MessageResource1", "foo"),
(l) => Assert.IsTrue (l.CheckFullLog ("Message from resources with arg 'foo'") == 0, "Message not found")
);
}
[Test]
public void TestLogWarningFromResources1 ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogWarningFromResources ("MessageResource1", "foo"),
(l) => Assert.IsTrue (l.CheckFullLog ("Message from resources with arg 'foo'") == 0, "Message not found")
);
}
[Test]
public void TestLogWarningFromResourcesNonExistantResourceName ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogWarningFromResources ("NonExistantResourceName", "foo"),
null,
(p, l) => {
if (p.Build ()) { l.DumpMessages (); Assert.Fail ("Build should have failed"); }
Assert.IsTrue (l.CheckFullLog (
"Error executing task TestTask: No resource string found for resource named NonExistantResourceName") == 0,
"Error not found in the log");
}
);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogMessageFromResourcesNullMessage ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogMessageFromResources (null);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestLogMessageFromResourcesNullMessage2 ()
{
tlh = new TaskLoggingHelper (task);
tlh.LogMessageFromResources (MessageImportance.Low, null);
}
[Test]
public void TestLogMessageFromResources1 ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogMessageFromResources ("MessageResource1", "foo"),
(l) => Assert.IsTrue (l.CheckFullLog ("Message from resources with arg 'foo'") == 0, "Message not found")
);
}
[Test]
public void TestLogMessageFromResourcesNonExistantResourceName ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.LogMessageFromResources ("NonExistantResourceName", "foo"),
null,
(p, l) => {
if (p.Build ()) { l.DumpMessages (); Assert.Fail ("Build should have failed"); }
l.DumpMessages ();
Assert.IsTrue (l.CheckFullLog (
"Error executing task TestTask: No resource string found for resource named NonExistantResourceName") == 0,
"Error not found in the log");
}
);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void TestFormatResourceString1 ()
{
tlh = new TaskLoggingHelper (task);
tlh.FormatResourceString (null);
}
[Test]
[ExpectedException (typeof (InvalidOperationException))]
public void TestFormatResourceString2 ()
{
tlh = new TaskLoggingHelper (task);
tlh.FormatResourceString ("MessageResource1");
}
[Test]
public void TestFormatResourceString3 ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => tlh.FormatResourceString ("NonExistantResourceName"),
null,
(p, l) => {
if (p.Build ()) { l.DumpMessages (); Assert.Fail ("Build should have failed"); }
l.DumpMessages ();
Assert.IsTrue (l.CheckFullLog (
"Error executing task TestTask: No resource string found for resource named NonExistantResourceName") == 0,
"Error not found in the log");
}
);
}
[Test]
public void TestFormatResourceString4 ()
{
RunAndCheckTaskLoggingHelper (
(tlh) => Assert.AreEqual (
tlh.FormatResourceString ("MessageResource1", "foo"),
"Message from resources with arg 'foo'"),
null
);
}
void RunAndCheckTaskLoggingHelper (Action<TaskLoggingHelper> taskAction, Action<TestMessageLogger> loggerAction, Action<Project, TestMessageLogger> projectBuildAction = null)
{
string asmLocation = typeof (TaskLoggingHelperTest).Assembly.Location;
string project_xml = @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<UsingTask TaskName='MonoTests.Microsoft.Build.Utilities.TestTask' AssemblyFile='" + asmLocation + @"' />
<Target Name=""1"">
<TestTask />
</Target>
</Project>";
Engine engine = new Engine (Consts.BinPath);
Project proj = engine.CreateNewProject ();
proj.LoadXml (project_xml);
TestMessageLogger logger = new TestMessageLogger ();
engine.RegisterLogger (logger);
TestTask.action = taskAction;
if (projectBuildAction == null) {
if (!proj.Build ("1")) {
logger.DumpMessages ();
Assert.Fail ("Build failed");
}
} else
projectBuildAction (proj, logger);
if (loggerAction != null)
loggerAction (logger);
}
}
}

View File

@ -70,3 +70,4 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo ("Mono.Security.Providers.OldTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Mono.Security.Providers.DotNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewSystemSource, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")]

View File

@ -21,5 +21,5 @@ EXTRA_DISTFILES = Mono.Security.Interface/README.md
#
# Update this comment to trigger a build in System
# +2
# +3
#

View File

@ -95,6 +95,14 @@ namespace Mono.Security.Interface
* If @serverMode is true, then we're a server and want to validate a certificate that we received from a client.
*/
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509CertificateCollection certificates);
}
internal interface ICertificateValidator2 : ICertificateValidator
{
/*
* Internal use only.
*/
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain);
/*
* On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built.
@ -137,25 +145,20 @@ namespace Mono.Security.Interface
get { return supportsTrustAnchors; }
}
static ICertificateValidator GetDefaultValidator (MonoTlsProvider provider, MonoTlsSettings settings)
{
return (ICertificateValidator)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings);
}
/*
* Internal API, intended to be used by MonoTlsProvider implementations.
*/
public static ICertificateValidator GetValidator (MonoTlsProvider provider, MonoTlsSettings settings)
internal static ICertificateValidator2 GetDefaultValidator (MonoTlsSettings settings, MonoTlsProvider provider)
{
return GetDefaultValidator (provider, settings);
return (ICertificateValidator2)NoReflectionHelper.GetDefaultCertificateValidator (provider, settings);
}
/*
* Use this overloaded version in user code.
*/
public static ICertificateValidator GetValidator (MonoTlsSettings settings)
public static ICertificateValidator GetValidator (MonoTlsSettings settings, MonoTlsProvider provider = null)
{
return GetDefaultValidator (null, settings);
return GetDefaultValidator (settings, provider);
}
}
}

View File

@ -124,12 +124,32 @@ namespace Mono.Security.Interface
#endregion
#region Native Certificate Implementation
internal virtual bool HasNativeCertificates {
get { return false; }
}
internal virtual X509Certificate2Impl GetNativeCertificate (
byte[] data, string password, X509KeyStorageFlags flags)
{
throw new InvalidOperationException ();
}
internal virtual X509Certificate2Impl GetNativeCertificate (
X509Certificate certificate)
{
throw new InvalidOperationException ();
}
#endregion
#region Certificate Validation
/*
* Allows a TLS provider to provide a custom system certificiate validator.
*/
public virtual bool HasCustomSystemCertificateValidator {
internal virtual bool HasCustomSystemCertificateValidator {
get { return false; }
}
@ -142,13 +162,12 @@ namespace Mono.Security.Interface
* Returns `true` if certificate validation has been performed and `false` to invoke the
* default system validator.
*/
public virtual bool InvokeSystemCertificateValidator (
ICertificateValidator validator, string targetHost, bool serverMode,
X509CertificateCollection certificates, X509Chain chain, out bool success,
ref MonoSslPolicyErrors errors, ref int status11)
internal virtual bool InvokeSystemCertificateValidator (
ICertificateValidator2 validator, string targetHost, bool serverMode,
X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain,
out bool success, ref MonoSslPolicyErrors errors, ref int status11)
{
success = false;
return false;
throw new InvalidOperationException ();
}
#endregion

View File

@ -313,6 +313,20 @@ namespace System.Net.Http.Headers
start = pos - 1;
while (pos < s.Length) {
ch = s [pos++];
//
// The backslash character ("\") MAY be used as a single-character
// quoting mechanism only within quoted-string
//
if (ch == '\\') {
if (pos + 1 < s.Length) {
++pos;
continue;
}
break;
}
if (ch == '"') {
ttype = Token.Type.QuotedString;
break;

View File

@ -74,6 +74,12 @@ namespace MonoTests.System.Net.Http.Headers
Assert.AreEqual ("\"mm\"", res.Tag, "#11");
Assert.IsTrue (res.IsWeak, "#12");
Assert.AreEqual ("W/\"mm\"", res.ToString (), "#13");
res = EntityTagHeaderValue.Parse ("\"\\\"123\\\"\"");
Assert.AreEqual ("\"\\\"123\\\"\"", res.Tag, "#21");
Assert.IsFalse (res.IsWeak, "#22");
Assert.AreEqual ("\"\\\"123\\\"\"", res.ToString (), "#23");
}
[Test]

View File

@ -152,15 +152,16 @@ namespace MonoTests.System.Net.Http
const int WaitTimeout = 5000;
string port, TestHost, LocalServer;
string TestHost, LocalServer;
int port;
[SetUp]
public void SetupFixture ()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
port = "810";
port = 810;
} else {
port = "8810";
port = 8810;
}
TestHost = "localhost:" + port;
@ -1060,9 +1061,20 @@ namespace MonoTests.System.Net.Http
var response = l.Response;
response.StatusCode = (int)HttpStatusCode.Moved;
response.RedirectLocation = "http://xamarin.com/";
response.RedirectLocation = "http://localhost:8811/";
});
var listener2 = CreateListener (l => {
var response = l.Response;
response.StatusCode = (int)HttpStatusCode.OK;
response.OutputStream.WriteByte (0x68);
response.OutputStream.WriteByte (0x65);
response.OutputStream.WriteByte (0x6c);
response.OutputStream.WriteByte (0x6c);
response.OutputStream.WriteByte (0x6f);
}, 8811);
try {
var chandler = new HttpClientHandler ();
chandler.AllowAutoRedirect = true;
@ -1071,10 +1083,13 @@ namespace MonoTests.System.Net.Http
var r = client.GetAsync (LocalServer);
Assert.IsTrue (r.Wait (WaitTimeout), "#1");
var resp = r.Result;
Assert.AreEqual ("http://xamarin.com/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
Assert.AreEqual ("http://localhost:8811/", resp.RequestMessage.RequestUri.AbsoluteUri, "#2");
Assert.AreEqual ("hello", resp.Content.ReadAsStringAsync ().Result, "#3");
} finally {
listener.Abort ();
listener.Close ();
listener2.Abort ();
listener2.Close ();
}
}
@ -1131,6 +1146,11 @@ namespace MonoTests.System.Net.Http
}
HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
{
return CreateListener (contextAssert, port);
}
HttpListener CreateListener (Action<HttpListenerContext> contextAssert, int port)
{
var l = new HttpListener ();
l.Prefixes.Add (string.Format ("http://+:{0}/", port));

View File

@ -4,9 +4,13 @@ include ../../build/rules.make
LIBRARY = System.Runtime.Remoting.dll
LIB_REFS = System System.Web System.Xml System.Runtime.Serialization.Formatters.Soap
LIB_REFS = System System.Xml System.Runtime.Serialization.Formatters.Soap
LIB_MCS_FLAGS = /r:$(corlib)
ifndef NO_SYSTEM_WEB_DEPENDENCY
LIB_REFS += System.Web
endif
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS) -nowarn:618 /r:System.Runtime.Remoting.dll
TEST_MONO_PATH = .

View File

@ -0,0 +1,56 @@
Assembly/AssemblyInfo.cs
../../build/common/Consts.cs
../../build/common/Locale.cs
../../build/common/MonoTODOAttribute.cs
System.Runtime.Remoting.Channels/BinaryClientFormatterSink.cs
System.Runtime.Remoting.Channels/BinaryClientFormatterSinkProvider.cs
System.Runtime.Remoting.Channels/BinaryCore.cs
System.Runtime.Remoting.Channels/BinaryServerFormatterSink.cs
System.Runtime.Remoting.Channels/BinaryServerFormatterSinkProvider.cs
System.Runtime.Remoting.Channels/ChannelCore.cs
System.Runtime.Remoting.Channels/CommonTransportKeys.cs
System.Runtime.Remoting.Channels/IAuthorizeRemotingConnection.cs
System.Runtime.Remoting.Channels/RemotingThreadPool.cs
System.Runtime.Remoting.Channels/SoapClientFormatterSink.cs
System.Runtime.Remoting.Channels/SoapCore.cs
System.Runtime.Remoting.Channels/SoapServerFormatterSink.cs
System.Runtime.Remoting.Channels/SoapClientFormatterSinkProvider.cs
System.Runtime.Remoting.Channels/SoapServerFormatterSinkProvider.cs
System.Runtime.Remoting.Channels/SoapMessageFormatter.cs
System.Runtime.Remoting.Channels/SocketCachePolicy.cs
System.Runtime.Remoting.Channels.Ipc/IpcChannel.cs
System.Runtime.Remoting.Channels.Ipc/IpcClientChannel.cs
System.Runtime.Remoting.Channels.Ipc/IpcServerChannel.cs
System.Runtime.Remoting.Channels.Ipc.Win32/IpcTransport.cs
System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannel.cs
System.Runtime.Remoting.Channels.Ipc.Win32/IpcChannelHelper.cs
System.Runtime.Remoting.Channels.Ipc.Win32/IpcClientChannel.cs
System.Runtime.Remoting.Channels.Ipc.Win32/IpcServerChannel.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeClient.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeException.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs
System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeStream.cs
System.Runtime.Remoting.Channels.Ipc.Unix/IpcChannel.cs
System.Runtime.Remoting.Channels.Ipc.Unix/IpcClientChannel.cs
System.Runtime.Remoting.Channels.Ipc.Unix/IpcServerChannel.cs
System.Runtime.Remoting.Channels.Ipc.Unix/UnixChannelLoader.cs
System.Runtime.Remoting.Channels.Tcp/TcpChannel.cs
System.Runtime.Remoting.Channels.Tcp/TcpClientChannel.cs
System.Runtime.Remoting.Channels.Tcp/TcpMessageIO.cs
System.Runtime.Remoting.Channels.Tcp/TcpServerChannel.cs
System.Runtime.Remoting.Channels.Tcp/TcpServerTransportSink.cs
System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSinkProvider.cs
System.Runtime.Remoting.Channels.Tcp/TcpClientTransportSink.cs
System.Runtime.Remoting.Channels.Tcp/TcpConnectionPool.cs
System.Runtime.Remoting.MetadataServices/MetaData.cs
System.Runtime.Remoting.MetadataServices/MetaDataExporter.cs
System.Runtime.Remoting.MetadataServices/MetaDataCodeGenerator.cs
System.Runtime.Remoting.MetadataServices/SdlChannelSinkProvider.cs
System.Runtime.Remoting.MetadataServices/ServiceType.cs
System.Runtime.Remoting.MetadataServices/SUDSParserException.cs
System.Runtime.Remoting.MetadataServices/SdlChannelSink.cs
System.Runtime.Remoting.MetadataServices/SdlType.cs
System.Runtime.Remoting.MetadataServices/SUDSGeneratorException.cs
System.Runtime.Remoting.Services/RemotingClientProxy.cs

View File

@ -65,7 +65,6 @@ namespace System.ServiceModel
return new EndpointAddress10 (address);
}
#if !NET_2_1
public static XmlQualifiedName GetSchema (XmlSchemaSet xmlSchemaSet)
{
if (xmlSchemaSet == null)
@ -73,7 +72,6 @@ namespace System.ServiceModel
xmlSchemaSet.Add (XmlSchema.Read (typeof (EndpointAddress10).Assembly.GetManifestResourceStream ("ws-addr.xsd"), null));
return new XmlQualifiedName ("EndpointReferenceType", AddressingVersion.WSAddressing10.Namespace);
}
#endif
public EndpointAddress ToEndpointAddress ()
{

View File

@ -166,6 +166,7 @@ System.ServiceModel.Security/SupportingTokenParametersTest.cs
System.ServiceModel.Security/TransportSecurityBindingElementTest.cs
System.ServiceModel.Security/WSSecurityTokenSerializerTest.cs
System.ServiceModel/BasicHttpBindingTest.cs
System.ServiceModel/Bug36080Test.cs
System.ServiceModel/CallbackBehaviorAttributeTest.cs
System.ServiceModel/ChannelFactoryTest.cs
System.ServiceModel/ChannelFactory_1Test.cs

View File

@ -0,0 +1,585 @@
//
// Author:
// Marcos Henrich <marcos.henrich@xamarin.com>
//
// Copyright (c) 2016 Xamarin, Inc.
//
// 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.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
using System.ServiceModel.Channels;
using System.Text;
using NUnit.Framework;
using MonoTests.Helpers;
namespace MonoTests.System.ServiceModel
{
[TestFixture]
public class Bug36080
{
[Test]
public void Bug36080Test ()
{
int port = NetworkHelpers.FindFreePort ();
var url = "http://localhost:" + port + "/HelloWorldService";
TransportBindingElement element = new HttpTransportBindingElement { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
Binding binding = new CustomBinding(new BindingElement[]
{
new TextMessageEncodingBindingElement (MessageVersion.Default, Encoding.UTF8),
element
});
#if !MOBILE
// Init service
ServiceHost serviceHost = new ServiceHost (typeof (HelloWorldServiceImpl), new Uri (url));
serviceHost.AddServiceEndpoint (typeof (IHelloWorldService), binding, string.Empty);
serviceHost.Open ();
#endif
// In Mobile we still run this tests without any server.
// Issue reported in #36080 was occuring before the connections fails.
var wait = new ManualResetEvent (false);
Exception error = null;
string result = null;
try {
var client = new HelloWorldServiceClient (binding, new EndpointAddress(url));
client.SayHelloToCompleted += delegate (object o, SayHelloToCompletedEventArgs e) {
try {
error = e.Error;
result = e.Error == null ? e.Result : null;
} finally {
wait.Set ();
}
};
var str = "Xamarin";
client.SayHelloToAsync(str);
Assert.IsTrue (wait.WaitOne (TimeSpan.FromSeconds (20)), "timeout");
#if MOBILE
if (error.GetType() == typeof(EndpointNotFoundException))
return;
#endif
Assert.IsNull (error, "#1, inner exception: {0}", error);
Assert.AreEqual (str, result, "#2");
} finally {
#if !MOBILE
serviceHost.Close ();
#endif
}
}
}
public class HelloWorldServiceImpl : IHelloWorldService
{
Func<string, string> sayHelloToFunc = SayHelloTo;
static string SayHelloTo (string name)
{
return name;
}
public IAsyncResult BeginSayHelloTo(string name, AsyncCallback callback, object asyncState)
{
return sayHelloToFunc.BeginInvoke (name, callback, asyncState);
}
public string EndSayHelloTo(IAsyncResult result)
{
return sayHelloToFunc.EndInvoke(result);
}
public IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, AsyncCallback callback, object asyncState)
{
return null;
}
public TestXamarin4WCFService.HelloWorldData EndGetHelloData(IAsyncResult result)
{
return null;
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
//
// This code was auto-generated by SlSvcUtil, version 5.0.61118.0
//
namespace TestXamarin4WCFService
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name = "HelloWorldData", Namespace = "http://schemas.datacontract.org/2004/07/TestXamarin4WCFService")]
public partial class HelloWorldData : object
{
private string NameField;
private bool SayHelloField;
[System.Runtime.Serialization.DataMemberAttribute()]
public string Name
{
get
{
return this.NameField;
}
set
{
this.NameField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public bool SayHello
{
get
{
return this.SayHelloField;
}
set
{
this.SayHelloField = value;
}
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IHelloWorldService")]
public interface IHelloWorldService
{
[System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/SayHelloTo", ReplyAction="http://tempuri.org/IHelloWorldService/SayHelloToResponse")]
System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState);
string EndSayHelloTo(System.IAsyncResult result);
[System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://tempuri.org/IHelloWorldService/GetHelloData", ReplyAction="http://tempuri.org/IHelloWorldService/GetHelloDataResponse")]
System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState);
TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IHelloWorldServiceChannel : IHelloWorldService, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class SayHelloToCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
private object[] results;
public SayHelloToCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState)
{
this.results = results;
}
public string Result
{
get
{
base.RaiseExceptionIfNecessary();
return ((string)(this.results[0]));
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class GetHelloDataCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
private object[] results;
public GetHelloDataCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState)
{
this.results = results;
}
public TestXamarin4WCFService.HelloWorldData Result
{
get
{
base.RaiseExceptionIfNecessary();
return ((TestXamarin4WCFService.HelloWorldData)(this.results[0]));
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class HelloWorldServiceClient : System.ServiceModel.ClientBase<IHelloWorldService>, IHelloWorldService
{
private BeginOperationDelegate onBeginSayHelloToDelegate;
private EndOperationDelegate onEndSayHelloToDelegate;
private System.Threading.SendOrPostCallback onSayHelloToCompletedDelegate;
private BeginOperationDelegate onBeginGetHelloDataDelegate;
private EndOperationDelegate onEndGetHelloDataDelegate;
private System.Threading.SendOrPostCallback onGetHelloDataCompletedDelegate;
private BeginOperationDelegate onBeginOpenDelegate;
private EndOperationDelegate onEndOpenDelegate;
private System.Threading.SendOrPostCallback onOpenCompletedDelegate;
private BeginOperationDelegate onBeginCloseDelegate;
private EndOperationDelegate onEndCloseDelegate;
private System.Threading.SendOrPostCallback onCloseCompletedDelegate;
public HelloWorldServiceClient()
{
}
public HelloWorldServiceClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public HelloWorldServiceClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public System.Net.CookieContainer CookieContainer
{
get
{
System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
if ((httpCookieContainerManager != null))
{
return httpCookieContainerManager.CookieContainer;
}
else
{
return null;
}
}
set
{
System.ServiceModel.Channels.IHttpCookieContainerManager httpCookieContainerManager = this.InnerChannel.GetProperty<System.ServiceModel.Channels.IHttpCookieContainerManager>();
if ((httpCookieContainerManager != null))
{
httpCookieContainerManager.CookieContainer = value;
}
else
{
throw new System.InvalidOperationException("Unable to set the CookieContainer. Please make sure the binding contains an HttpC" +
"ookieContainerBindingElement.");
}
}
}
public event System.EventHandler<SayHelloToCompletedEventArgs> SayHelloToCompleted;
public event System.EventHandler<GetHelloDataCompletedEventArgs> GetHelloDataCompleted;
public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> OpenCompleted;
public event System.EventHandler<System.ComponentModel.AsyncCompletedEventArgs> CloseCompleted;
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.IAsyncResult IHelloWorldService.BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
{
return base.Channel.BeginSayHelloTo(name, callback, asyncState);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
string IHelloWorldService.EndSayHelloTo(System.IAsyncResult result)
{
return base.Channel.EndSayHelloTo(result);
}
private System.IAsyncResult OnBeginSayHelloTo(object[] inValues, System.AsyncCallback callback, object asyncState)
{
string name = ((string)(inValues[0]));
return ((IHelloWorldService)(this)).BeginSayHelloTo(name, callback, asyncState);
}
private object[] OnEndSayHelloTo(System.IAsyncResult result)
{
string retVal = ((IHelloWorldService)(this)).EndSayHelloTo(result);
return new object[] {
retVal};
}
private void OnSayHelloToCompleted(object state)
{
if ((this.SayHelloToCompleted != null))
{
InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
this.SayHelloToCompleted(this, new SayHelloToCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
}
}
public void SayHelloToAsync(string name)
{
this.SayHelloToAsync(name, null);
}
public void SayHelloToAsync(string name, object userState)
{
if ((this.onBeginSayHelloToDelegate == null))
{
this.onBeginSayHelloToDelegate = new BeginOperationDelegate(this.OnBeginSayHelloTo);
}
if ((this.onEndSayHelloToDelegate == null))
{
this.onEndSayHelloToDelegate = new EndOperationDelegate(this.OnEndSayHelloTo);
}
if ((this.onSayHelloToCompletedDelegate == null))
{
this.onSayHelloToCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnSayHelloToCompleted);
}
base.InvokeAsync(this.onBeginSayHelloToDelegate, new object[] {
name}, this.onEndSayHelloToDelegate, this.onSayHelloToCompletedDelegate, userState);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.IAsyncResult IHelloWorldService.BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
{
return base.Channel.BeginGetHelloData(helloWorldData, callback, asyncState);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
TestXamarin4WCFService.HelloWorldData IHelloWorldService.EndGetHelloData(System.IAsyncResult result)
{
return base.Channel.EndGetHelloData(result);
}
private System.IAsyncResult OnBeginGetHelloData(object[] inValues, System.AsyncCallback callback, object asyncState)
{
TestXamarin4WCFService.HelloWorldData helloWorldData = ((TestXamarin4WCFService.HelloWorldData)(inValues[0]));
return ((IHelloWorldService)(this)).BeginGetHelloData(helloWorldData, callback, asyncState);
}
private object[] OnEndGetHelloData(System.IAsyncResult result)
{
TestXamarin4WCFService.HelloWorldData retVal = ((IHelloWorldService)(this)).EndGetHelloData(result);
return new object[] {
retVal};
}
private void OnGetHelloDataCompleted(object state)
{
if ((this.GetHelloDataCompleted != null))
{
InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
this.GetHelloDataCompleted(this, new GetHelloDataCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState));
}
}
public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData)
{
this.GetHelloDataAsync(helloWorldData, null);
}
public void GetHelloDataAsync(TestXamarin4WCFService.HelloWorldData helloWorldData, object userState)
{
if ((this.onBeginGetHelloDataDelegate == null))
{
this.onBeginGetHelloDataDelegate = new BeginOperationDelegate(this.OnBeginGetHelloData);
}
if ((this.onEndGetHelloDataDelegate == null))
{
this.onEndGetHelloDataDelegate = new EndOperationDelegate(this.OnEndGetHelloData);
}
if ((this.onGetHelloDataCompletedDelegate == null))
{
this.onGetHelloDataCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnGetHelloDataCompleted);
}
base.InvokeAsync(this.onBeginGetHelloDataDelegate, new object[] {
helloWorldData}, this.onEndGetHelloDataDelegate, this.onGetHelloDataCompletedDelegate, userState);
}
private System.IAsyncResult OnBeginOpen(object[] inValues, System.AsyncCallback callback, object asyncState)
{
return ((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(callback, asyncState);
}
private object[] OnEndOpen(System.IAsyncResult result)
{
((System.ServiceModel.ICommunicationObject)(this)).EndOpen(result);
return null;
}
private void OnOpenCompleted(object state)
{
if ((this.OpenCompleted != null))
{
InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
this.OpenCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
}
}
public void OpenAsync()
{
this.OpenAsync(null);
}
public void OpenAsync(object userState)
{
if ((this.onBeginOpenDelegate == null))
{
this.onBeginOpenDelegate = new BeginOperationDelegate(this.OnBeginOpen);
}
if ((this.onEndOpenDelegate == null))
{
this.onEndOpenDelegate = new EndOperationDelegate(this.OnEndOpen);
}
if ((this.onOpenCompletedDelegate == null))
{
this.onOpenCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnOpenCompleted);
}
base.InvokeAsync(this.onBeginOpenDelegate, null, this.onEndOpenDelegate, this.onOpenCompletedDelegate, userState);
}
private System.IAsyncResult OnBeginClose(object[] inValues, System.AsyncCallback callback, object asyncState)
{
return ((System.ServiceModel.ICommunicationObject)(this)).BeginClose(callback, asyncState);
}
private object[] OnEndClose(System.IAsyncResult result)
{
((System.ServiceModel.ICommunicationObject)(this)).EndClose(result);
return null;
}
private void OnCloseCompleted(object state)
{
if ((this.CloseCompleted != null))
{
InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state));
this.CloseCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(e.Error, e.Cancelled, e.UserState));
}
}
public void CloseAsync()
{
this.CloseAsync(null);
}
public void CloseAsync(object userState)
{
if ((this.onBeginCloseDelegate == null))
{
this.onBeginCloseDelegate = new BeginOperationDelegate(this.OnBeginClose);
}
if ((this.onEndCloseDelegate == null))
{
this.onEndCloseDelegate = new EndOperationDelegate(this.OnEndClose);
}
if ((this.onCloseCompletedDelegate == null))
{
this.onCloseCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnCloseCompleted);
}
base.InvokeAsync(this.onBeginCloseDelegate, null, this.onEndCloseDelegate, this.onCloseCompletedDelegate, userState);
}
protected override IHelloWorldService CreateChannel()
{
return new HelloWorldServiceClientChannel(this);
}
private class HelloWorldServiceClientChannel : ChannelBase<IHelloWorldService>, IHelloWorldService
{
public HelloWorldServiceClientChannel(System.ServiceModel.ClientBase<IHelloWorldService> client) :
base(client)
{
}
public System.IAsyncResult BeginSayHelloTo(string name, System.AsyncCallback callback, object asyncState)
{
object[] _args = new object[1];
_args[0] = name;
System.IAsyncResult _result = base.BeginInvoke("SayHelloTo", _args, callback, asyncState);
return _result;
}
public string EndSayHelloTo(System.IAsyncResult result)
{
object[] _args = new object[0];
string _result = ((string)(base.EndInvoke("SayHelloTo", _args, result)));
return _result;
}
public System.IAsyncResult BeginGetHelloData(TestXamarin4WCFService.HelloWorldData helloWorldData, System.AsyncCallback callback, object asyncState)
{
object[] _args = new object[1];
_args[0] = helloWorldData;
System.IAsyncResult _result = base.BeginInvoke("GetHelloData", _args, callback, asyncState);
return _result;
}
public TestXamarin4WCFService.HelloWorldData EndGetHelloData(System.IAsyncResult result)
{
object[] _args = new object[0];
TestXamarin4WCFService.HelloWorldData _result = ((TestXamarin4WCFService.HelloWorldData)(base.EndInvoke("GetHelloData", _args, result)));
return _result;
}
}
}

View File

@ -83,3 +83,5 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo ("Mono.Security.Providers.NewTls, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Mono.Security.Providers.DotNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Mono.Security, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
[assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")]

View File

@ -74,7 +74,7 @@ namespace Mono.Net.Security
{
internal delegate bool ServerCertValidationCallbackWrapper (ServerCertValidationCallback callback, X509Certificate certificate, X509Chain chain, MonoSslPolicyErrors sslPolicyErrors);
internal class ChainValidationHelper : ICertificateValidator
internal class ChainValidationHelper : ICertificateValidator2
{
readonly object sender;
readonly MonoTlsSettings settings;
@ -228,7 +228,7 @@ namespace Mono.Net.Security
var certs = new XX509CertificateCollection ();
certs.Add (new X509Certificate2 (certificate.GetRawCertData ()));
var result = ValidateChain (string.Empty, true, certs, (SslPolicyErrors)errors);
var result = ValidateChain (string.Empty, true, certificate, null, certs, (SslPolicyErrors)errors);
if (result == null)
return false;
@ -238,7 +238,12 @@ namespace Mono.Net.Security
public ValidationResult ValidateCertificate (string host, bool serverMode, XX509CertificateCollection certs)
{
try {
var result = ValidateChain (host, serverMode, certs, 0);
X509Certificate leaf;
if (certs != null && certs.Count != 0)
leaf = certs [0];
else
leaf = null;
var result = ValidateChain (host, serverMode, leaf, null, certs, 0);
if (tlsStream != null)
tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
return result;
@ -249,7 +254,43 @@ namespace Mono.Net.Security
}
}
ValidationResult ValidateChain (string host, bool server, XX509CertificateCollection certs, SslPolicyErrors errors)
public ValidationResult ValidateCertificate (string host, bool serverMode, X509Certificate leaf, XX509Chain xchain)
{
try {
var chain = (X509Chain)(object)xchain;
var result = ValidateChain (host, serverMode, leaf, chain, null, 0);
if (tlsStream != null)
tlsStream.CertificateValidationFailed = result == null || !result.Trusted || result.UserDenied;
return result;
} catch {
if (tlsStream != null)
tlsStream.CertificateValidationFailed = true;
throw;
}
}
ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
X509Chain chain, XX509CertificateCollection certs,
SslPolicyErrors errors)
{
var oldChain = chain;
var ownsChain = chain == null;
try {
var result = ValidateChain (host, server, leaf, ref chain, certs, errors);
if (chain != oldChain)
ownsChain = true;
return result;
} finally {
// If ValidateChain() changed the chain, then we need to free it.
if (ownsChain && chain != null)
chain.Dispose ();
}
}
ValidationResult ValidateChain (string host, bool server, X509Certificate leaf,
ref X509Chain chain, XX509CertificateCollection certs,
SslPolicyErrors errors)
{
// user_denied is true if the user callback is called and returns false
bool user_denied = false;
@ -257,12 +298,6 @@ namespace Mono.Net.Security
var hasCallback = certValidationCallback != null || callbackWrapper != null;
X509Certificate leaf;
if (certs == null || certs.Count == 0)
leaf = null;
else
leaf = certs [0];
if (tlsStream != null)
request.ServicePoint.UpdateServerCertificate (leaf);
@ -281,7 +316,6 @@ namespace Mono.Net.Security
ICertificatePolicy policy = ServicePointManager.GetLegacyCertificatePolicy ();
int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
X509Chain chain = null;
bool wantsChain = SystemCertificateValidator.NeedsChain (settings);
if (!wantsChain && hasCallback) {
@ -289,18 +323,15 @@ namespace Mono.Net.Security
wantsChain = true;
}
if (wantsChain)
chain = SystemCertificateValidator.CreateX509Chain (certs);
if (wantsChain || SystemCertificateValidator.NeedsChain (settings))
SystemCertificateValidator.BuildX509Chain (certs, chain, ref errors, ref status11);
bool providerValidated = false;
if (provider != null && provider.HasCustomSystemCertificateValidator) {
var xerrors = (MonoSslPolicyErrors)errors;
var xchain = (XX509Chain)(object)chain;
providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, xchain, out result, ref xerrors, ref status11);
providerValidated = provider.InvokeSystemCertificateValidator (this, host, server, certs, wantsChain, ref xchain, out result, ref xerrors, ref status11);
chain = (X509Chain)(object)xchain;
errors = (SslPolicyErrors)xerrors;
} else if (wantsChain) {
chain = SystemCertificateValidator.CreateX509Chain (certs);
}
if (!providerValidated)

View File

@ -69,7 +69,7 @@ namespace Mono.Net.Security
return currentProvider;
try {
defaultProvider = CreateDefaultProvider ();
defaultProvider = GetDefaultProviderInternal ();
} catch (Exception ex) {
throw new NotSupportedException ("TLS Support not available.", ex);
}
@ -174,6 +174,8 @@ namespace Mono.Net.Security
providerRegistration = new Dictionary<string,string> ();
providerRegistration.Add ("newtls", "Mono.Security.Providers.NewTls.NewTlsProvider, Mono.Security.Providers.NewTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
providerRegistration.Add ("oldtls", "Mono.Security.Providers.OldTls.OldTlsProvider, Mono.Security.Providers.OldTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
providerRegistration.Add ("boringtls", "Xamarin.BoringTls.BoringTlsProvider, Xamarin.BoringTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=672c06b0b8f05406");
X509Helper2.Initialize ();
}
}

View File

@ -86,13 +86,13 @@ namespace Mono.Net.Security
return chain;
}
public static bool BuildX509Chain (XX509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
static bool BuildX509Chain (XX509CertificateCollection certs, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
{
#if MOBILE
return true;
return false;
#else
if (is_macosx)
return true;
return false;
var leaf = (X509Certificate2)certs [0];
@ -121,7 +121,9 @@ namespace Mono.Net.Security
static bool CheckUsage (XX509CertificateCollection certs, string host, ref SslPolicyErrors errors, ref int status11)
{
#if !MONOTOUCH
var leaf = (X509Certificate2)certs[0];
var leaf = certs[0] as X509Certificate2;
if (leaf == null)
leaf = new X509Certificate2 (certs[0]);
// for OSX and iOS we're using the native API to check for the SSL server policy and host names
if (!is_macosx) {
if (!CheckCertificateUsage (leaf)) {
@ -130,7 +132,7 @@ namespace Mono.Net.Security
return false;
}
if (host != null && !CheckServerIdentity (leaf, host)) {
if (!string.IsNullOrEmpty (host) && !CheckServerIdentity (leaf, host)) {
errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
return false;
@ -143,7 +145,7 @@ namespace Mono.Net.Security
static bool EvaluateSystem (XX509CertificateCollection certs, XX509CertificateCollection anchors, string host, X509Chain chain, ref SslPolicyErrors errors, ref int status11)
{
var leaf = certs [0];
var result = false;
bool result;
#if MONODROID
result = AndroidPlatform.TrustEvaluateSsl (certs);
@ -166,6 +168,8 @@ namespace Mono.Net.Security
result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
trustResult == OSX509Certificates.SecTrustResult.Unspecified);
} catch {
result = false;
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
// Ignore
}
@ -178,6 +182,8 @@ namespace Mono.Net.Security
status11 = (int)trustResult;
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
}
} else {
result = BuildX509Chain (certs, chain, ref errors, ref status11);
}
#endif
@ -203,6 +209,8 @@ namespace Mono.Net.Security
#if MOBILE
return false;
#else
if (!is_macosx)
return true;
if (!CertificateValidationHelper.SupportsX509Chain)
return false;
if (settings != null)

View File

@ -255,10 +255,10 @@ namespace System.Diagnostics {
WritePrefix ();
}
WriteDebugString (message);
if (Debugger.IsLogging())
Debugger.Log (0, null, message);
else
WriteDebugString (message);
WriteLogFile (message, LogFileName);
}

View File

@ -52,6 +52,7 @@ namespace System.Security.Cryptography.X509Certificates {
X500DistinguishedNameFlags.UseT61Encoding | X500DistinguishedNameFlags.ForceUTF8Encoding;
private string name;
private byte[] canonEncoding;
public X500DistinguishedName (AsnEncodedData encodedDistinguishedName)
@ -122,6 +123,20 @@ namespace System.Security.Cryptography.X509Certificates {
name = distinguishedName.name;
}
internal X500DistinguishedName (byte[] encoded, byte[] canonEncoding, string name)
: this (encoded)
{
this.canonEncoding = canonEncoding;
this.name = name;
Oid = new Oid ();
RawData = encoded;
}
internal byte[] CanonicalEncoding {
get { return canonEncoding; }
}
public string Name {
get { return name; }
@ -215,6 +230,16 @@ namespace System.Security.Cryptography.X509Certificates {
if (name2 == null)
return false;
if (name1.canonEncoding != null && name2.canonEncoding != null) {
if (name1.canonEncoding.Length != name2.canonEncoding.Length)
return false;
for (int i = 0; i < name1.canonEncoding.Length; i++) {
if (name1.canonEncoding[i] != name2.canonEncoding[2])
return false;
}
return true;
}
X500DistinguishedNameFlags flags = X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.DoNotUseQuotes;
string[] split = new string[] { Environment.NewLine };
string[] parts1 = name1.Decode (flags).Split (split, StringSplitOptions.RemoveEmptyEntries);

View File

@ -50,6 +50,7 @@ namespace System.Security.Cryptography.X509Certificates {
[Serializable]
public class X509Certificate2 : X509Certificate {
#if !SECURITY_DEP
// Used in Mono.Security HttpsClientStream
public X509Certificate2 (byte[] rawData)
@ -57,24 +58,20 @@ namespace System.Security.Cryptography.X509Certificates {
}
#endif
#if SECURITY_DEP
private bool _archived;
private X509ExtensionCollection _extensions;
private string _name = String.Empty;
private string _serial;
private PublicKey _publicKey;
private X500DistinguishedName issuer_name;
private X500DistinguishedName subject_name;
private Oid signature_algorithm;
new internal X509Certificate2Impl Impl {
get {
var impl2 = base.Impl as X509Certificate2Impl;
X509Helper2.ThrowIfContextInvalid (impl2);
return impl2;
}
}
private MX.X509Certificate _cert;
private static string empty_error = Locale.GetText ("Certificate instance is empty.");
string friendlyName = string.Empty;
// constructors
public X509Certificate2 ()
{
_cert = null;
}
public X509Certificate2 (byte[] rawData)
@ -129,206 +126,88 @@ namespace System.Security.Cryptography.X509Certificates {
public X509Certificate2 (IntPtr handle) : base (handle)
{
_cert = new MX.X509Certificate (base.GetRawCertData ());
throw new NotImplementedException ();
}
public X509Certificate2 (X509Certificate certificate)
: base (certificate)
: base (X509Helper2.Import (certificate))
{
}
internal X509Certificate2 (X509Certificate2Impl impl)
: base (impl)
{
_cert = new MX.X509Certificate (base.GetRawCertData ());
}
// properties
public bool Archived {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _archived;
}
set {
if (_cert == null)
throw new CryptographicException (empty_error);
_archived = value;
}
get { return Impl.Archived; }
set { Impl.Archived = true; }
}
public X509ExtensionCollection Extensions {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (_extensions == null)
_extensions = new X509ExtensionCollection (_cert);
return _extensions;
}
get { return Impl.Extensions; }
}
public string FriendlyName {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _name;
ThrowIfContextInvalid ();
return friendlyName;
}
set {
if (_cert == null)
throw new CryptographicException (empty_error);
_name = value;
ThrowIfContextInvalid ();
friendlyName = value;
}
}
// FIXME - Could be more efficient
public bool HasPrivateKey {
get { return PrivateKey != null; }
get { return Impl.HasPrivateKey; }
}
public X500DistinguishedName IssuerName {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (issuer_name == null)
issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
return issuer_name;
}
get { return Impl.IssuerName; }
}
public DateTime NotAfter {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _cert.ValidUntil.ToLocalTime ();
}
get { return Impl.GetValidUntil ().ToLocalTime (); }
}
public DateTime NotBefore {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _cert.ValidFrom.ToLocalTime ();
}
get { return Impl.GetValidFrom ().ToLocalTime (); }
}
public AsymmetricAlgorithm PrivateKey {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
try {
if (_cert.RSA != null) {
RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
if (rcsp != null)
return rcsp.PublicOnly ? null : rcsp;
RSAManaged rsam = _cert.RSA as RSAManaged;
if (rsam != null)
return rsam.PublicOnly ? null : rsam;
_cert.RSA.ExportParameters (true);
return _cert.RSA;
} else if (_cert.DSA != null) {
DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
if (dcsp != null)
return dcsp.PublicOnly ? null : dcsp;
_cert.DSA.ExportParameters (true);
return _cert.DSA;
}
}
catch {
}
return null;
}
set {
if (_cert == null)
throw new CryptographicException (empty_error);
// allow NULL so we can "forget" the key associated to the certificate
// e.g. in case we want to export it in another format (see bug #396620)
if (value == null) {
_cert.RSA = null;
_cert.DSA = null;
} else if (value is RSA)
_cert.RSA = (RSA) value;
else if (value is DSA)
_cert.DSA = (DSA) value;
else
throw new NotSupportedException ();
}
get { return Impl.PrivateKey; }
set { Impl.PrivateKey = value; }
}
public PublicKey PublicKey {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (_publicKey == null) {
try {
_publicKey = new PublicKey (_cert);
}
catch (Exception e) {
string msg = Locale.GetText ("Unable to decode public key.");
throw new CryptographicException (msg, e);
}
}
return _publicKey;
}
get { return Impl.PublicKey; }
}
public byte[] RawData {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return base.GetRawCertData ();
}
get { return GetRawCertData (); }
}
public string SerialNumber {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (_serial == null) {
StringBuilder sb = new StringBuilder ();
byte[] serial = _cert.SerialNumber;
for (int i=serial.Length - 1; i >= 0; i--)
sb.Append (serial [i].ToString ("X2"));
_serial = sb.ToString ();
}
return _serial;
}
get { return GetSerialNumberString (); }
}
public Oid SignatureAlgorithm {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (signature_algorithm == null)
signature_algorithm = new Oid (_cert.SignatureAlgorithm);
return signature_algorithm;
}
get { return Impl.SignatureAlgorithm; }
}
public X500DistinguishedName SubjectName {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (subject_name == null)
subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
return subject_name;
}
get { return Impl.SubjectName; }
}
public string Thumbprint {
get { return base.GetCertHashString (); }
get { return GetCertHashString (); }
}
public int Version {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _cert.Version;
}
get { return Impl.Version; }
}
// methods
@ -336,135 +215,7 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
public string GetNameInfo (X509NameType nameType, bool forIssuer)
{
switch (nameType) {
case X509NameType.SimpleName:
if (_cert == null)
throw new CryptographicException (empty_error);
// return CN= or, if missing, the first part of the DN
ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
ASN1 dn = Find (commonName, sn);
if (dn != null)
return GetValueAsString (dn);
if (sn.Count == 0)
return String.Empty;
ASN1 last_entry = sn [sn.Count - 1];
if (last_entry.Count == 0)
return String.Empty;
return GetValueAsString (last_entry [0]);
case X509NameType.EmailName:
// return the E= part of the DN (if present)
ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
if (e != null)
return GetValueAsString (e);
return String.Empty;
case X509NameType.UpnName:
// FIXME - must find/create test case
return String.Empty;
case X509NameType.DnsName:
// return the CN= part of the DN (if present)
ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
if (cn != null)
return GetValueAsString (cn);
return String.Empty;
case X509NameType.DnsFromAlternativeName:
// FIXME - must find/create test case
return String.Empty;
case X509NameType.UrlName:
// FIXME - must find/create test case
return String.Empty;
default:
throw new ArgumentException ("nameType");
}
}
static byte[] commonName = { 0x55, 0x04, 0x03 };
static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
private ASN1 Find (byte[] oid, ASN1 dn)
{
if (dn.Count == 0)
return null;
// process SET
for (int i = 0; i < dn.Count; i++) {
ASN1 set = dn [i];
for (int j = 0; j < set.Count; j++) {
ASN1 pair = set [j];
if (pair.Count != 2)
continue;
ASN1 poid = pair [0];
if (poid == null)
continue;
if (poid.CompareValue (oid))
return pair;
}
}
return null;
}
private string GetValueAsString (ASN1 pair)
{
if (pair.Count != 2)
return String.Empty;
ASN1 value = pair [1];
if ((value.Value == null) || (value.Length == 0))
return String.Empty;
if (value.Tag == 0x1E) {
// BMPSTRING
StringBuilder sb = new StringBuilder ();
for (int j = 1; j < value.Value.Length; j += 2)
sb.Append ((char)value.Value [j]);
return sb.ToString ();
} else {
return Encoding.UTF8.GetString (value.Value);
}
}
private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
{
MX.PKCS12 pfx = null;
if (string.IsNullOrEmpty (password)) {
try {
// Support both unencrypted PKCS#12..
pfx = new MX.PKCS12 (rawData, (string)null);
} catch {
// ..and PKCS#12 encrypted with an empty password
pfx = new MX.PKCS12 (rawData, string.Empty);
}
} else {
pfx = new MX.PKCS12 (rawData, password);
}
if (pfx.Certificates.Count == 0) {
// no certificate was found
return null;
} else if (pfx.Keys.Count == 0) {
// no key were found - pick the first certificate
return pfx.Certificates [0];
} else {
// find the certificate that match the first key
MX.X509Certificate cert = null;
var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
string pubkey = keypair.ToXmlString (false);
foreach (var c in pfx.Certificates) {
if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
cert = c;
break;
}
}
if (cert == null) {
cert = pfx.Certificates [0]; // no match, pick first certificate without keys
} else {
cert.RSA = (keypair as RSA);
cert.DSA = (keypair as DSA);
}
return cert;
}
return Impl.GetNameInfo (nameType, forIssuer);
}
public override void Import (byte[] rawData)
@ -475,37 +226,8 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("missing KeyStorageFlags support")]
public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
{
MX.X509Certificate cert = null;
if (password == null) {
try {
cert = new MX.X509Certificate (rawData);
}
catch (Exception e) {
try {
cert = ImportPkcs12 (rawData, null);
}
catch {
string msg = Locale.GetText ("Unable to decode certificate.");
// inner exception is the original (not second) exception
throw new CryptographicException (msg, e);
}
}
} else {
// try PKCS#12
try {
cert = ImportPkcs12 (rawData, password);
}
catch {
// it's possible to supply a (unrequired/unusued) password
// fix bug #79028
cert = new MX.X509Certificate (rawData);
}
}
// we do not have to fully re-decode the certificate since X509Certificate does not deal with keys
if (cert != null) {
base.Import (cert.RawData, (string) null, keyStorageFlags);
_cert = cert; // becuase base call will call Reset!
}
var impl = X509Helper2.Import (rawData, password, keyStorageFlags);
ImportHandle (impl);
}
[MonoTODO ("SecureString is incomplete")]
@ -537,69 +259,25 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("X509ContentType.SerializedCert is not supported")]
public override byte[] Export (X509ContentType contentType, string password)
{
if (_cert == null)
throw new CryptographicException (empty_error);
switch (contentType) {
case X509ContentType.Cert:
return _cert.RawData;
case X509ContentType.Pfx: // this includes Pkcs12
return ExportPkcs12 (password);
case X509ContentType.SerializedCert:
// TODO
throw new NotSupportedException ();
default:
string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
throw new CryptographicException (msg);
}
}
byte[] ExportPkcs12 (string password)
{
var pfx = new MX.PKCS12 ();
try {
var attrs = new Hashtable ();
var localKeyId = new ArrayList ();
localKeyId.Add (new byte[] { 1, 0, 0, 0 });
attrs.Add (MX.PKCS9.localKeyId, localKeyId);
if (password != null)
pfx.Password = password;
pfx.AddCertificate (_cert, attrs);
var privateKey = PrivateKey;
if (privateKey != null)
pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs);
return pfx.GetBytes ();
} finally {
pfx.Password = null;
}
return Impl.Export (contentType, password);
}
public override void Reset ()
{
_cert = null;
_archived = false;
_extensions = null;
_name = String.Empty;
_serial = null;
_publicKey = null;
issuer_name = null;
subject_name = null;
signature_algorithm = null;
friendlyName = string.Empty;
base.Reset ();
}
public override string ToString ()
{
if (_cert == null)
if (!IsValid)
return "System.Security.Cryptography.X509Certificates.X509Certificate2";
return base.ToString (true);
}
public override string ToString (bool verbose)
{
if (_cert == null)
if (!IsValid)
return "System.Security.Cryptography.X509Certificates.X509Certificate2";
// the non-verbose X509Certificate2 == verbose X509Certificate
@ -649,14 +327,7 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("by default this depends on the incomplete X509Chain")]
public bool Verify ()
{
if (_cert == null)
throw new CryptographicException (empty_error);
X509Chain chain = X509Chain.Create ();
if (!chain.Build (this))
return false;
// TODO - check chain and other stuff ???
return true;
return Impl.Verify (this);
}
// static methods
@ -723,8 +394,14 @@ namespace System.Security.Cryptography.X509Certificates {
// internal stuff because X509Certificate2 isn't complete enough
// (maybe X509Certificate3 will be better?)
[Obsolete ("KILL")]
internal MX.X509Certificate MonoCertificate {
get { return _cert; }
get {
var monoImpl = Impl as X509Certificate2ImplMono;
if (monoImpl == null)
throw new NotSupportedException ();
return monoImpl.MonoCertificate;
}
}
#else

View File

@ -0,0 +1,82 @@
//
// X509Certificate2Impl.cs
//
// Authors:
// Martin Baulig <martin.baulig@xamarin.com>
//
// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.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.
//
namespace System.Security.Cryptography.X509Certificates
{
internal abstract class X509Certificate2Impl : X509CertificateImpl
{
#if SECURITY_DEP
public abstract bool Archived {
get; set;
}
public abstract X509ExtensionCollection Extensions {
get;
}
public abstract bool HasPrivateKey {
get;
}
public abstract X500DistinguishedName IssuerName {
get;
}
public abstract AsymmetricAlgorithm PrivateKey {
get; set;
}
public abstract PublicKey PublicKey {
get;
}
public abstract Oid SignatureAlgorithm {
get;
}
public abstract X500DistinguishedName SubjectName {
get;
}
public abstract int Version {
get;
}
public abstract string GetNameInfo (X509NameType nameType, bool forIssuer);
public abstract void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags);
public abstract byte[] Export (X509ContentType contentType, string password);
public abstract bool Verify (X509Certificate2 thisCertificate);
public abstract void Reset ();
#endif
}
}

View File

@ -0,0 +1,694 @@
//
// X509Certificate2ImplMono
//
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
// Martin Baulig <martin.baulig@xamarin.com>
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
// Copyright (C) 2015-2016 Xamarin, Inc. (http://www.xamarin.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.
//
#if SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MonoSecurity::Mono.Security;
using MonoSecurity::Mono.Security.Cryptography;
using MX = MonoSecurity::Mono.Security.X509;
#else
using Mono.Security;
using Mono.Security.Cryptography;
using MX = Mono.Security.X509;
#endif
using System.IO;
using System.Text;
using System.Collections;
namespace System.Security.Cryptography.X509Certificates
{
internal class X509Certificate2ImplMono : X509Certificate2Impl
{
bool _archived;
X509ExtensionCollection _extensions;
string _serial;
PublicKey _publicKey;
X500DistinguishedName issuer_name;
X500DistinguishedName subject_name;
Oid signature_algorithm;
MX.X509Certificate _cert;
static string empty_error = Locale.GetText ("Certificate instance is empty.");
public override bool IsValid {
get {
return _cert != null;
}
}
public override IntPtr Handle {
get { return IntPtr.Zero; }
}
internal X509Certificate2ImplMono (MX.X509Certificate cert)
{
this._cert = cert;
}
public override X509CertificateImpl Clone ()
{
ThrowIfContextInvalid ();
return new X509Certificate2ImplMono (_cert);
}
#region Implemented X509CertificateImpl members
public override string GetIssuerName (bool legacyV1Mode)
{
ThrowIfContextInvalid ();
if (legacyV1Mode)
return _cert.IssuerName;
else
return MX.X501.ToString (_cert.GetIssuerName (), true, ", ", true);
}
public override string GetSubjectName (bool legacyV1Mode)
{
ThrowIfContextInvalid ();
if (legacyV1Mode)
return _cert.SubjectName;
else
return MX.X501.ToString (_cert.GetSubjectName (), true, ", ", true);
}
public override byte[] GetRawCertData ()
{
ThrowIfContextInvalid ();
return _cert.RawData;
}
protected override byte[] GetCertHash (bool lazy)
{
ThrowIfContextInvalid ();
SHA1 sha = SHA1.Create ();
return sha.ComputeHash (_cert.RawData);
}
public override DateTime GetValidFrom ()
{
ThrowIfContextInvalid ();
return _cert.ValidFrom;
}
public override DateTime GetValidUntil ()
{
ThrowIfContextInvalid ();
return _cert.ValidUntil;
}
public override bool Equals (X509CertificateImpl other, out bool result)
{
// Use default implementation
result = false;
return false;
}
public override string GetKeyAlgorithm ()
{
ThrowIfContextInvalid ();
return _cert.KeyAlgorithm;
}
public override byte[] GetKeyAlgorithmParameters ()
{
ThrowIfContextInvalid ();
return _cert.KeyAlgorithmParameters;
}
public override byte[] GetPublicKey ()
{
ThrowIfContextInvalid ();
return _cert.PublicKey;
}
public override byte[] GetSerialNumber ()
{
ThrowIfContextInvalid ();
return _cert.SerialNumber;
}
public override byte[] Export (X509ContentType contentType, byte[] password)
{
ThrowIfContextInvalid ();
switch (contentType) {
case X509ContentType.Cert:
return GetRawCertData ();
case X509ContentType.Pfx: // this includes Pkcs12
// TODO
throw new NotSupportedException ();
case X509ContentType.SerializedCert:
// TODO
throw new NotSupportedException ();
default:
string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
throw new CryptographicException (msg);
}
}
#endregion
// constructors
public X509Certificate2ImplMono ()
{
_cert = null;
}
// properties
public override bool Archived {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _archived;
}
set {
if (_cert == null)
throw new CryptographicException (empty_error);
_archived = value;
}
}
public override X509ExtensionCollection Extensions {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (_extensions == null)
_extensions = new X509ExtensionCollection (_cert);
return _extensions;
}
}
// FIXME - Could be more efficient
public override bool HasPrivateKey {
get { return PrivateKey != null; }
}
public override X500DistinguishedName IssuerName {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (issuer_name == null)
issuer_name = new X500DistinguishedName (_cert.GetIssuerName ().GetBytes ());
return issuer_name;
}
}
public override AsymmetricAlgorithm PrivateKey {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
try {
if (_cert.RSA != null) {
RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
if (rcsp != null)
return rcsp.PublicOnly ? null : rcsp;
RSAManaged rsam = _cert.RSA as RSAManaged;
if (rsam != null)
return rsam.PublicOnly ? null : rsam;
_cert.RSA.ExportParameters (true);
return _cert.RSA;
} else if (_cert.DSA != null) {
DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
if (dcsp != null)
return dcsp.PublicOnly ? null : dcsp;
_cert.DSA.ExportParameters (true);
return _cert.DSA;
}
}
catch {
}
return null;
}
set {
if (_cert == null)
throw new CryptographicException (empty_error);
// allow NULL so we can "forget" the key associated to the certificate
// e.g. in case we want to export it in another format (see bug #396620)
if (value == null) {
_cert.RSA = null;
_cert.DSA = null;
} else if (value is RSA)
_cert.RSA = (RSA) value;
else if (value is DSA)
_cert.DSA = (DSA) value;
else
throw new NotSupportedException ();
}
}
public override PublicKey PublicKey {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (_publicKey == null) {
try {
_publicKey = new PublicKey (_cert);
}
catch (Exception e) {
string msg = Locale.GetText ("Unable to decode public key.");
throw new CryptographicException (msg, e);
}
}
return _publicKey;
}
}
public override Oid SignatureAlgorithm {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (signature_algorithm == null)
signature_algorithm = new Oid (_cert.SignatureAlgorithm);
return signature_algorithm;
}
}
public override X500DistinguishedName SubjectName {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
if (subject_name == null)
subject_name = new X500DistinguishedName (_cert.GetSubjectName ().GetBytes ());
return subject_name;
}
}
public override int Version {
get {
if (_cert == null)
throw new CryptographicException (empty_error);
return _cert.Version;
}
}
// methods
[MonoTODO ("always return String.Empty for UpnName, DnsFromAlternativeName and UrlName")]
public override string GetNameInfo (X509NameType nameType, bool forIssuer)
{
switch (nameType) {
case X509NameType.SimpleName:
if (_cert == null)
throw new CryptographicException (empty_error);
// return CN= or, if missing, the first part of the DN
ASN1 sn = forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ();
ASN1 dn = Find (commonName, sn);
if (dn != null)
return GetValueAsString (dn);
if (sn.Count == 0)
return String.Empty;
ASN1 last_entry = sn [sn.Count - 1];
if (last_entry.Count == 0)
return String.Empty;
return GetValueAsString (last_entry [0]);
case X509NameType.EmailName:
// return the E= part of the DN (if present)
ASN1 e = Find (email, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
if (e != null)
return GetValueAsString (e);
return String.Empty;
case X509NameType.UpnName:
// FIXME - must find/create test case
return String.Empty;
case X509NameType.DnsName:
// return the CN= part of the DN (if present)
ASN1 cn = Find (commonName, forIssuer ? _cert.GetIssuerName () : _cert.GetSubjectName ());
if (cn != null)
return GetValueAsString (cn);
return String.Empty;
case X509NameType.DnsFromAlternativeName:
// FIXME - must find/create test case
return String.Empty;
case X509NameType.UrlName:
// FIXME - must find/create test case
return String.Empty;
default:
throw new ArgumentException ("nameType");
}
}
static byte[] commonName = { 0x55, 0x04, 0x03 };
static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
private ASN1 Find (byte[] oid, ASN1 dn)
{
if (dn.Count == 0)
return null;
// process SET
for (int i = 0; i < dn.Count; i++) {
ASN1 set = dn [i];
for (int j = 0; j < set.Count; j++) {
ASN1 pair = set [j];
if (pair.Count != 2)
continue;
ASN1 poid = pair [0];
if (poid == null)
continue;
if (poid.CompareValue (oid))
return pair;
}
}
return null;
}
private string GetValueAsString (ASN1 pair)
{
if (pair.Count != 2)
return String.Empty;
ASN1 value = pair [1];
if ((value.Value == null) || (value.Length == 0))
return String.Empty;
if (value.Tag == 0x1E) {
// BMPSTRING
StringBuilder sb = new StringBuilder ();
for (int j = 1; j < value.Value.Length; j += 2)
sb.Append ((char)value.Value [j]);
return sb.ToString ();
} else {
return Encoding.UTF8.GetString (value.Value);
}
}
private MX.X509Certificate ImportPkcs12 (byte[] rawData, string password)
{
MX.PKCS12 pfx = null;
if (string.IsNullOrEmpty (password)) {
try {
// Support both unencrypted PKCS#12..
pfx = new MX.PKCS12 (rawData, (string)null);
} catch {
// ..and PKCS#12 encrypted with an empty password
pfx = new MX.PKCS12 (rawData, string.Empty);
}
} else {
pfx = new MX.PKCS12 (rawData, password);
}
if (pfx.Certificates.Count == 0) {
// no certificate was found
return null;
} else if (pfx.Keys.Count == 0) {
// no key were found - pick the first certificate
return pfx.Certificates [0];
} else {
// find the certificate that match the first key
MX.X509Certificate cert = null;
var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
string pubkey = keypair.ToXmlString (false);
foreach (var c in pfx.Certificates) {
if (((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false))) ||
((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))) {
cert = c;
break;
}
}
if (cert == null) {
cert = pfx.Certificates [0]; // no match, pick first certificate without keys
} else {
cert.RSA = (keypair as RSA);
cert.DSA = (keypair as DSA);
}
return cert;
}
}
[MonoTODO ("missing KeyStorageFlags support")]
public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
{
MX.X509Certificate cert = null;
if (password == null) {
try {
cert = new MX.X509Certificate (rawData);
}
catch (Exception e) {
try {
cert = ImportPkcs12 (rawData, null);
}
catch {
string msg = Locale.GetText ("Unable to decode certificate.");
// inner exception is the original (not second) exception
throw new CryptographicException (msg, e);
}
}
} else {
// try PKCS#12
try {
cert = ImportPkcs12 (rawData, password);
}
catch {
// it's possible to supply a (unrequired/unusued) password
// fix bug #79028
cert = new MX.X509Certificate (rawData);
}
}
_cert = cert;
}
[MonoTODO ("X509ContentType.SerializedCert is not supported")]
public override byte[] Export (X509ContentType contentType, string password)
{
if (_cert == null)
throw new CryptographicException (empty_error);
switch (contentType) {
case X509ContentType.Cert:
return _cert.RawData;
case X509ContentType.Pfx: // this includes Pkcs12
return ExportPkcs12 (password);
case X509ContentType.SerializedCert:
// TODO
throw new NotSupportedException ();
default:
string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
throw new CryptographicException (msg);
}
}
byte[] ExportPkcs12 (string password)
{
var pfx = new MX.PKCS12 ();
try {
var attrs = new Hashtable ();
var localKeyId = new ArrayList ();
localKeyId.Add (new byte[] { 1, 0, 0, 0 });
attrs.Add (MX.PKCS9.localKeyId, localKeyId);
if (password != null)
pfx.Password = password;
pfx.AddCertificate (_cert, attrs);
var privateKey = PrivateKey;
if (privateKey != null)
pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs);
return pfx.GetBytes ();
} finally {
pfx.Password = null;
}
}
public override void Reset ()
{
_cert = null;
_archived = false;
_extensions = null;
_serial = null;
_publicKey = null;
issuer_name = null;
subject_name = null;
signature_algorithm = null;
}
public override string ToString ()
{
if (_cert == null)
return "System.Security.Cryptography.X509Certificates.X509Certificate2";
return ToString (true);
}
public override string ToString (bool verbose)
{
if (_cert == null)
return "System.Security.Cryptography.X509Certificates.X509Certificate2";
string nl = Environment.NewLine;
StringBuilder sb = new StringBuilder ();
// the non-verbose X509Certificate2 == verbose X509Certificate
if (!verbose) {
sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, GetSubjectName (false));
sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, GetIssuerName (false));
sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
sb.Append (nl);
return sb.ToString ();
}
sb.AppendFormat ("[Version]{0} V{1}{0}{0}", nl, Version);
sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, GetSubjectName (false));
sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, GetIssuerName (false));
sb.AppendFormat ("[Serial Number]{0} {1}{0}{0}", nl, GetSerialNumber ());
sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
sb.AppendFormat ("[Signature Algorithm]{0} {1}({2}){0}{0}", nl, SignatureAlgorithm.FriendlyName,
SignatureAlgorithm.Value);
AsymmetricAlgorithm key = PublicKey.Key;
sb.AppendFormat ("[Public Key]{0} Algorithm: ", nl);
if (key is RSA)
sb.Append ("RSA");
else if (key is DSA)
sb.Append ("DSA");
else
sb.Append (key.ToString ());
sb.AppendFormat ("{0} Length: {1}{0} Key Blob: ", nl, key.KeySize);
AppendBuffer (sb, PublicKey.EncodedKeyValue.RawData);
sb.AppendFormat ("{0} Parameters: ", nl);
AppendBuffer (sb, PublicKey.EncodedParameters.RawData);
sb.Append (nl);
return sb.ToString ();
}
private static void AppendBuffer (StringBuilder sb, byte[] buffer)
{
if (buffer == null)
return;
for (int i=0; i < buffer.Length; i++) {
sb.Append (buffer [i].ToString ("x2"));
if (i < buffer.Length - 1)
sb.Append (" ");
}
}
[MonoTODO ("by default this depends on the incomplete X509Chain")]
public override bool Verify (X509Certificate2 thisCertificate)
{
if (_cert == null)
throw new CryptographicException (empty_error);
X509Chain chain = X509Chain.Create ();
if (!chain.Build (thisCertificate))
return false;
// TODO - check chain and other stuff ???
return true;
}
// static methods
private static byte[] signedData = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02 };
[MonoTODO ("Detection limited to Cert, Pfx, Pkcs12, Pkcs7 and Unknown")]
public static X509ContentType GetCertContentType (byte[] rawData)
{
if ((rawData == null) || (rawData.Length == 0))
throw new ArgumentException ("rawData");
X509ContentType type = X509ContentType.Unknown;
try {
ASN1 data = new ASN1 (rawData);
if (data.Tag != 0x30) {
string msg = Locale.GetText ("Unable to decode certificate.");
throw new CryptographicException (msg);
}
if (data.Count == 0)
return type;
if (data.Count == 3) {
switch (data [0].Tag) {
case 0x30:
// SEQUENCE / SEQUENCE / BITSTRING
if ((data [1].Tag == 0x30) && (data [2].Tag == 0x03))
type = X509ContentType.Cert;
break;
case 0x02:
// INTEGER / SEQUENCE / SEQUENCE
if ((data [1].Tag == 0x30) && (data [2].Tag == 0x30))
type = X509ContentType.Pkcs12;
// note: Pfx == Pkcs12
break;
}
}
// check for PKCS#7 (count unknown but greater than 0)
// SEQUENCE / OID (signedData)
if ((data [0].Tag == 0x06) && data [0].CompareValue (signedData))
type = X509ContentType.Pkcs7;
}
catch (Exception e) {
string msg = Locale.GetText ("Unable to decode certificate.");
throw new CryptographicException (msg, e);
}
return type;
}
[MonoTODO ("Detection limited to Cert, Pfx, Pkcs12 and Unknown")]
public static X509ContentType GetCertContentType (string fileName)
{
if (fileName == null)
throw new ArgumentNullException ("fileName");
if (fileName.Length == 0)
throw new ArgumentException ("fileName");
byte[] data = File.ReadAllBytes (fileName);
return GetCertContentType (data);
}
// internal stuff because X509Certificate2 isn't complete enough
// (maybe X509Certificate3 will be better?)
internal MX.X509Certificate MonoCertificate {
get { return _cert; }
}
}
}
#endif

View File

@ -42,23 +42,27 @@ using System.Text;
namespace System.Security.Cryptography.X509Certificates {
public class X509Chain {
public class X509Chain : IDisposable {
private StoreLocation location;
private X509ChainElementCollection elements;
private X509ChainPolicy policy;
private X509ChainStatus[] status;
X509ChainImpl impl;
static X509ChainStatus[] Empty = new X509ChainStatus [0];
// RFC3280 variables
private int max_path_length;
private X500DistinguishedName working_issuer_name;
// private string working_public_key_algorithm;
private AsymmetricAlgorithm working_public_key;
internal X509ChainImpl Impl {
get {
X509Helper2.ThrowIfContextInvalid (impl);
return impl;
}
}
// other flags
private X509ChainElement bce_restriction;
internal bool IsValid {
get { return X509Helper2.IsValid (impl); }
}
internal void ThrowIfContextInvalid ()
{
X509Helper2.ThrowIfContextInvalid (impl);
}
// constructors
@ -69,9 +73,13 @@ namespace System.Security.Cryptography.X509Certificates {
public X509Chain (bool useMachineContext)
{
location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
elements = new X509ChainElementCollection ();
policy = new X509ChainPolicy ();
impl = X509Helper2.CreateChainImpl (useMachineContext);
}
internal X509Chain (X509ChainImpl impl)
{
X509Helper2.ThrowIfContextInvalid (impl);
this.impl = impl;
}
[MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
@ -85,24 +93,24 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("Mono's X509Chain is fully managed. Always returns IntPtr.Zero.")]
public IntPtr ChainContext {
get { return IntPtr.Zero; }
get {
if (impl != null && impl.IsValid)
return impl.Handle;
return IntPtr.Zero;
}
}
public X509ChainElementCollection ChainElements {
get { return elements; }
get { return Impl.ChainElements; }
}
public X509ChainPolicy ChainPolicy {
get { return policy; }
set { policy = value; }
get { return Impl.ChainPolicy; }
set { Impl.ChainPolicy = value; }
}
public X509ChainStatus[] ChainStatus {
get {
if (status == null)
return Empty;
return status;
}
get { return Impl.ChainStatus; }
}
// methods
@ -110,128 +118,12 @@ namespace System.Security.Cryptography.X509Certificates {
[MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
public bool Build (X509Certificate2 certificate)
{
if (certificate == null)
throw new ArgumentException ("certificate");
Reset ();
X509ChainStatusFlags flag;
try {
flag = BuildChainFrom (certificate);
ValidateChain (flag);
}
catch (CryptographicException ce) {
throw new ArgumentException ("certificate", ce);
}
X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
ArrayList list = new ArrayList ();
// build "global" ChainStatus from the ChainStatus of every ChainElements
foreach (X509ChainElement ce in elements) {
foreach (X509ChainStatus cs in ce.ChainElementStatus) {
// we MUST avoid duplicates in the "global" list
if ((total & cs.Status) != cs.Status) {
list.Add (cs);
total |= cs.Status;
}
}
}
// and if required add some
if (flag != X509ChainStatusFlags.NoError) {
list.Insert (0, new X509ChainStatus (flag));
}
status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
// (fast path) this ignore everything we have checked
if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
return true;
bool result = true;
// now check if exclude some verification for the "end result" (boolean)
foreach (X509ChainStatus cs in status) {
switch (cs.Status) {
case X509ChainStatusFlags.UntrustedRoot:
case X509ChainStatusFlags.PartialChain:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
break;
case X509ChainStatusFlags.NotTimeValid:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
break;
// FIXME - from here we needs new test cases for all cases
case X509ChainStatusFlags.NotTimeNested:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
break;
case X509ChainStatusFlags.InvalidBasicConstraints:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
break;
case X509ChainStatusFlags.InvalidPolicyConstraints:
case X509ChainStatusFlags.NoIssuanceChainPolicy:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
break;
case X509ChainStatusFlags.InvalidNameConstraints:
case X509ChainStatusFlags.HasNotSupportedNameConstraint:
case X509ChainStatusFlags.HasNotPermittedNameConstraint:
case X509ChainStatusFlags.HasExcludedNameConstraint:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
break;
case X509ChainStatusFlags.InvalidExtension:
// not sure ?!?
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
break;
//
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
case X509ChainStatusFlags.CtlNotTimeValid:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
break;
case X509ChainStatusFlags.CtlNotSignatureValid:
// ?
break;
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
case X509ChainStatusFlags.CtlNotValidForUsage:
// FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
break;
default:
result = false;
break;
}
// once we have one failure there's no need to check further
if (!result)
return false;
}
// every "problem" was excluded
return true;
return Impl.Build (certificate);
}
public void Reset ()
{
// note: this call doesn't Reset the X509ChainPolicy
if ((status != null) && (status.Length != 0))
status = null;
if (elements.Count > 0)
elements.Clear ();
if (user_root_store != null) {
user_root_store.Close ();
user_root_store = null;
}
if (root_store != null) {
root_store.Close ();
root_store = null;
}
if (user_ca_store != null) {
user_ca_store.Close ();
user_ca_store = null;
}
if (ca_store != null) {
ca_store.Close ();
ca_store = null;
}
roots = null;
cas = null;
collection = null;
bce_restriction = null;
working_public_key = null;
Impl.Reset ();
}
// static methods
@ -245,717 +137,23 @@ namespace System.Security.Cryptography.X509Certificates {
#endif
}
// private stuff
private X509Certificate2Collection roots;
private X509Certificate2Collection cas;
private X509Store root_store;
private X509Store ca_store;
private X509Store user_root_store;
private X509Store user_ca_store;
private X509Certificate2Collection Roots {
get {
if (roots == null) {
X509Certificate2Collection c = new X509Certificate2Collection ();
X509Store store = LMRootStore;
if (location == StoreLocation.CurrentUser)
c.AddRange (UserRootStore.Certificates);
c.AddRange (store.Certificates);
roots = c;
}
return roots;
}
}
private X509Certificate2Collection CertificateAuthorities {
get {
if (cas == null) {
X509Certificate2Collection c = new X509Certificate2Collection ();
X509Store store = LMCAStore;
if (location == StoreLocation.CurrentUser)
c.AddRange (UserCAStore.Certificates);
c.AddRange (store.Certificates);
cas = c;
}
return cas;
}
}
private X509Store LMRootStore {
get {
if (root_store == null) {
root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
try {
root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return root_store;
}
}
private X509Store UserRootStore {
get {
if (user_root_store == null) {
user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
try {
user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return user_root_store;
}
}
private X509Store LMCAStore {
get {
if (ca_store == null) {
ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
try {
ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return ca_store;
}
}
private X509Store UserCAStore {
get {
if (user_ca_store == null) {
user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
try {
user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return user_ca_store;
}
}
// *** certificate chain/path building stuff ***
private X509Certificate2Collection collection;
// we search local user (default) or machine certificate store
// and in the extra certificate supplied in ChainPolicy.ExtraStore
private X509Certificate2Collection CertificateCollection {
get {
if (collection == null) {
collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
collection.AddRange (Roots);
collection.AddRange (CertificateAuthorities);
}
return collection;
}
}
// This is a non-recursive chain/path building algorithm.
//
// At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
// affect the path building (other errors are verification errors).
//
// Note that the order match the one we need to match MS and not the one defined in RFC3280,
// we also include the trusted root certificate (trust anchor in RFC3280) in the list.
// (this isn't an issue, just keep that in mind if you look at the source and the RFC)
private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
public void Dispose ()
{
elements.Add (certificate);
while (!IsChainComplete (certificate)) {
certificate = FindParent (certificate);
if (certificate == null)
return X509ChainStatusFlags.PartialChain;
if (elements.Contains (certificate))
return X509ChainStatusFlags.Cyclic;
elements.Add (certificate);
}
// roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
// trustiness (what a cute word) in the trusted root collection
if (!Roots.Contains (certificate))
elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
return X509ChainStatusFlags.NoError;
Dispose (true);
GC.SuppressFinalize (this);
}
private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
protected virtual void Dispose (bool disposing)
{
switch (c.Count) {
case 0:
return null;
case 1:
return c [0];
default:
// multiple candidate, keep only the ones that are still valid
X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
switch (time_valid.Count) {
case 0:
// that's too restrictive, let's revert and try another thing...
time_valid = c;
break;
case 1:
return time_valid [0];
default:
break;
}
// again multiple candidates, let's find the AKI that match the SKI (if we have one)
string aki = GetAuthorityKeyIdentifier (child);
if (String.IsNullOrEmpty (aki)) {
return time_valid [0]; // FIXME: out of luck, you get the first one
}
foreach (X509Certificate2 parent in time_valid) {
string ski = GetSubjectKeyIdentifier (parent);
// if both id are available then they must match
if (aki == ski)
return parent;
}
return time_valid [0]; // FIXME: out of luck, you get the first one
if (impl != null) {
impl.Dispose ();
impl = null;
}
}
private X509Certificate2 FindParent (X509Certificate2 certificate)
~X509Chain ()
{
X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
string aki = GetAuthorityKeyIdentifier (certificate);
if ((aki != null) && (aki.Length > 0)) {
subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
}
X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
// if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
return certificate.Equals (parent) ? null : parent;
}
private bool IsChainComplete (X509Certificate2 certificate)
{
// the chain is complete if we have a self-signed certificate
if (!IsSelfIssued (certificate))
return false;
// we're very limited to what we can do without certificate extensions
if (certificate.Version < 3)
return true;
// check that Authority Key Identifier == Subject Key Identifier
// e.g. it will be different if a self-signed certificate is part (not the end) of the chain
string ski = GetSubjectKeyIdentifier (certificate);
if (String.IsNullOrEmpty (ski))
return true;
string aki = GetAuthorityKeyIdentifier (certificate);
if (String.IsNullOrEmpty (aki))
return true;
// if both id are available then they must match
return (aki == ski);
}
// check for "self-issued" certificate - without verifying the signature
// note that self-issued doesn't always mean it's a root certificate!
private bool IsSelfIssued (X509Certificate2 certificate)
{
return (certificate.Issuer == certificate.Subject);
}
// *** certificate chain/path validation stuff ***
// Currently a subset of RFC3280 (hopefully a full implementation someday)
private void ValidateChain (X509ChainStatusFlags flag)
{
// 'n' should be the root certificate...
int n = elements.Count - 1;
X509Certificate2 certificate = elements [n].Certificate;
// ... and, if so, must be treated outside the chain...
if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
Process (n);
// deal with the case where the chain == the root certificate
// (which isn't for RFC3280) part of the chain
if (n == 0) {
elements [0].UncompressFlags ();
return;
}
// skip the root certificate when processing the chain (in 6.1.3)
n--;
}
// ... unless the chain is a partial one (then we start with that one)
// 6.1.1 - Inputs
// 6.1.1.a - a prospective certificate path of length n (i.e. elements)
// 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
// 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
// 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
// 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
// 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
// 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
// 6.1.2 - Initialization (incomplete)
// 6.1.2.a-f - policy stuff, some TODO, some not supported
// 6.1.2.g - working public key algorithm
// working_public_key_algorithm = certificate.PublicKey.Oid.Value;
// 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
working_public_key = certificate.PublicKey.Key;
// 6.1.2.j - working issuer name
working_issuer_name = certificate.IssuerName;
// 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
// may be reduced to the value in the path length constraint field
max_path_length = n;
// 6.1.3 - Basic Certificate Processing
// note: loop looks reversed (the list is) but we process this part just like RFC3280 does
for (int i = n; i > 0; i--) {
Process (i);
// 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
PrepareForNextCertificate (i);
}
Process (0);
// 6.1.3.a.3 - revocation checks
CheckRevocationOnChain (flag);
// 6.1.5 - Wrap-up procedure
WrapUp ();
}
private void Process (int n)
{
X509ChainElement element = elements [n];
X509Certificate2 certificate = element.Certificate;
// pre-step: DSA certificates may inherit the parameters of their CA
if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
X509Certificate2 parent = elements [n+1].Certificate;
certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
}
}
bool root = (working_public_key == null);
// 6.1.3.a.1 - check signature (with special case to deal with root certificates)
if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
// another special case where only an end-entity is available and can't be verified.
// In this case we do not report an invalid signature (since this is unknown)
if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
}
}
// 6.1.3.a.2 - check validity period
if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
(ChainPolicy.VerificationTime > certificate.NotAfter)) {
element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
}
// TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
// note: most of them don't apply to the root certificate
if (root) {
return;
}
// 6.1.3.a.3 - revocation check (we're doing at the last stage)
// note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
// 6.1.3.a.4 - check certificate issuer name
if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
// NOTE: this is not the "right" error flag, but it's the closest one defined
element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
}
if (!IsSelfIssued (certificate) && (n != 0)) {
// TODO 6.1.3.b - subject name in the permitted_subtrees ...
// TODO 6.1.3.c - subject name not within excluded_subtrees...
// TODO - check for X509ChainStatusFlags.InvalidNameConstraint
// TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
// TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
// TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
}
// TODO 6.1.3.d - check if certificate policies extension is present
//if (false) {
// TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
// using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
// TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
//} else {
// TODO 6.1.3.e - set valid_policy_tree to NULL
//}
// TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
}
// CTL == Certificate Trust List / NOT SUPPORTED
// TODO - check for X509ChainStatusFlags.CtlNotTimeValid
// TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
// TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
private void PrepareForNextCertificate (int n)
{
X509ChainElement element = elements [n];
X509Certificate2 certificate = element.Certificate;
// TODO 6.1.4.a-b
// 6.1.4.c
working_issuer_name = certificate.SubjectName;
// 6.1.4.d-e - our key includes both the public key and it's parameters
working_public_key = certificate.PublicKey.Key;
// 6.1.4.f
// working_public_key_algorithm = certificate.PublicKey.Oid.Value;
// TODO 6.1.4.g-j
// 6.1.4.k - Verify that the certificate is a CA certificate
X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
if (bce != null) {
if (!bce.CertificateAuthority) {
element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
} else if (certificate.Version >= 3) {
// recent (v3+) CA certificates must include BCE
element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
// 6.1.4.l - if the certificate isn't self-issued...
if (!IsSelfIssued (certificate)) {
// ... verify that max_path_length > 0
if (max_path_length > 0) {
max_path_length--;
} else {
// to match MS the reported status must be against the certificate
// with the BCE and not where the path is too long. It also means
// that this condition has to be reported only once
if (bce_restriction != null) {
bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
}
}
// 6.1.4.m - if pathLengthConstraint is present...
if ((bce != null) && (bce.HasPathLengthConstraint)) {
// ... and is less that max_path_length, set max_path_length to it's value
if (bce.PathLengthConstraint < max_path_length) {
max_path_length = bce.PathLengthConstraint;
bce_restriction = element;
}
}
// 6.1.4.n - if key usage extension is present...
X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
if (kue != null) {
// ... verify keyCertSign is set
X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
if ((kue.KeyUsages & success) != success)
element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
}
// 6.1.4.o - recognize and process other critical extension present in the certificate
ProcessCertificateExtensions (element);
}
private void WrapUp ()
{
X509ChainElement element = elements [0];
X509Certificate2 certificate = element.Certificate;
// 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
if (IsSelfIssued (certificate)) {
// TODO... decrement explicit_policy by 1
}
// 6.1.5.b - TODO
// 6.1.5.c,d,e - not required by the X509Chain implementation
// 6.1.5.f - recognize and process other critical extension present in the certificate
ProcessCertificateExtensions (element);
// 6.1.5.g - TODO
// uncompressed the flags into several elements
for (int i = elements.Count - 1; i >= 0; i--) {
elements [i].UncompressFlags ();
}
}
private void ProcessCertificateExtensions (X509ChainElement element)
{
foreach (X509Extension ext in element.Certificate.Extensions) {
if (ext.Critical) {
switch (ext.Oid.Value) {
case "2.5.29.15": // X509KeyUsageExtension
case "2.5.29.19": // X509BasicConstraintsExtension
// we processed this extension
break;
default:
// note: Under Windows XP MS implementation seems to ignore
// certificate with unknown critical extensions.
element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
break;
}
}
}
}
private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
{
if (pubkey == null)
return false;
// Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
MX.X509Certificate mx = signed.MonoCertificate;
return (mx.VerifySignature (pubkey));
}
private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
{
X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
}
// System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
{
return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
}
// but anyway System.dll v2 doesn't expose CRL in any way so...
static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
{
return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
}
static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
{
if (ext == null)
return String.Empty;
MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
byte[] id = aki.Identifier;
if (id == null)
return String.Empty;
StringBuilder sb = new StringBuilder ();
foreach (byte b in id)
sb.Append (b.ToString ("X02"));
return sb.ToString ();
}
// we check the revocation only once we have built the complete chain
private void CheckRevocationOnChain (X509ChainStatusFlags flag)
{
bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
bool online;
switch (ChainPolicy.RevocationMode) {
case X509RevocationMode.Online:
// default
online = true;
break;
case X509RevocationMode.Offline:
online = false;
break;
case X509RevocationMode.NoCheck:
return;
default:
throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
}
bool unknown = partial;
// from the root down to the end-entity
for (int i = elements.Count - 1; i >= 0; i--) {
bool check = true;
switch (ChainPolicy.RevocationFlag) {
case X509RevocationFlag.EndCertificateOnly:
check = (i == 0);
break;
case X509RevocationFlag.EntireChain:
check = true;
break;
case X509RevocationFlag.ExcludeRoot:
// default
check = (i != (elements.Count - 1));
// anyway, who's gonna sign that the root is invalid ?
break;
}
X509ChainElement element = elements [i];
// we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
if (!unknown)
unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
if (unknown) {
// we can skip the revocation checks as we can't be sure of them anyway
element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
} else if (check && !partial && !IsSelfIssued (element.Certificate)) {
// check for revocation (except for the trusted root and self-issued certs)
element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
// if revoked, then all others following in the chain are unknown...
unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
}
}
}
// This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
{
X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
X509ChainElement element = elements [ca];
X509Certificate2 ca_cert = element.Certificate;
// find the CRL from the "right" CA
while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
// try with this self-issued
result = CheckRevocation (certificate, ca_cert, online);
if (result != X509ChainStatusFlags.RevocationStatusUnknown)
break;
ca++;
element = elements [ca];
ca_cert = element.Certificate;
}
if (result == X509ChainStatusFlags.RevocationStatusUnknown)
result = CheckRevocation (certificate, ca_cert, online);
return result;
}
private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
{
// change this if/when we support OCSP
X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
if (kue != null) {
// ... verify CrlSign is set
X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
if ((kue.KeyUsages & success) != success) {
// FIXME - we should try to find an alternative CA that has the CrlSign bit
return X509ChainStatusFlags.RevocationStatusUnknown;
}
}
MX.X509Crl crl = FindCrl (ca_cert);
if ((crl == null) && online) {
// FIXME - download and install new CRL
// then you get a second chance
// crl = FindCrl (ca_cert, ref valid, ref out_of_date);
// We need to get the subjectAltName and an URI from there (or use OCSP)
// X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
}
if (crl != null) {
// validate the digital signature on the CRL using the CA public key
// note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
// checks and we loose the "why" of the failure
// note #2: we do this before other tests as an invalid signature could be a hacked CRL
// (so anything within can't be trusted)
if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
if (entry != null) {
// We have an entry for this CRL that includes an unknown CRITICAL extension
// See [X.509 7.3] NOTE 4
if (!ProcessCrlEntryExtensions (entry))
return X509ChainStatusFlags.Revoked;
// FIXME - a little more is involved
if (entry.RevocationDate <= ChainPolicy.VerificationTime)
return X509ChainStatusFlags.Revoked;
}
// are we overdue for a CRL update ? if so we can't be sure of any certificate status
if (crl.NextUpdate < ChainPolicy.VerificationTime)
return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
// we have a CRL that includes an unknown CRITICAL extension
// we put this check at the end so we do not "hide" any Revoked flags
if (!ProcessCrlExtensions (crl)) {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
} else {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
return X509ChainStatusFlags.NoError;
}
static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
{
if (store == null)
return null;
var crls = store.Crls;
foreach (MX.X509Crl crl in crls) {
if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
return crl;
}
return null; // No CRL found
}
private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
{
string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
string ski = GetSubjectKeyIdentifier (caCertificate);
// consider that the LocalMachine directories could not exists... and cannot be created by the user
MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
if (result != null)
return result;
if (location == StoreLocation.CurrentUser) {
result = CheckCrls (subject, ski, UserCAStore.Store);
if (result != null)
return result;
}
// consider that the LocalMachine directories could not exists... and cannot be created by the user
result = CheckCrls (subject, ski, LMRootStore.Store);
if (result != null)
return result;
if (location == StoreLocation.CurrentUser) {
result = CheckCrls (subject, ski, UserRootStore.Store);
if (result != null)
return result;
}
return null;
}
private bool ProcessCrlExtensions (MX.X509Crl crl)
{
foreach (MX.X509Extension ext in crl.Extensions) {
if (ext.Critical) {
switch (ext.Oid) {
case "2.5.29.20": // cRLNumber
case "2.5.29.35": // authorityKeyIdentifier
// we processed/know about this extension
break;
default:
return false;
}
}
}
return true;
}
private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
{
foreach (MX.X509Extension ext in entry.Extensions) {
if (ext.Critical) {
switch (ext.Oid) {
case "2.5.29.21": // cRLReason
// we processed/know about this extension
break;
default:
return false;
}
}
}
return true;
Dispose (false);
}
}
}

View File

@ -0,0 +1,81 @@
//
// X509ChainImpl.cs
//
// Authors:
// Martin Baulig <martin.baulig@xamarin.com>
//
// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.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.
//
#if SECURITY_DEP
namespace System.Security.Cryptography.X509Certificates
{
internal abstract class X509ChainImpl : IDisposable
{
public abstract bool IsValid {
get;
}
public abstract IntPtr Handle {
get;
}
protected void ThrowIfContextInvalid ()
{
if (!IsValid)
throw X509Helper2.GetInvalidChainContextException ();
}
public abstract X509ChainElementCollection ChainElements {
get;
}
public abstract X509ChainPolicy ChainPolicy {
get; set;
}
public abstract X509ChainStatus[] ChainStatus {
get;
}
public abstract bool Build (X509Certificate2 certificate);
public abstract void Reset ();
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
}
~X509ChainImpl ()
{
Dispose (false);
}
}
}
#endif

View File

@ -0,0 +1,954 @@
//
// System.Security.Cryptography.X509Certificates.X509ChainImplMono
//
// Author:
// Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
// Copyright (C) 2011 Xamarin Inc. (http://www.xamarin.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.
//
#if SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
using MX = MonoSecurity::Mono.Security.X509;
#else
using MX = Mono.Security.X509;
#endif
using System.Collections;
using System.Text;
namespace System.Security.Cryptography.X509Certificates {
internal class X509ChainImplMono : X509ChainImpl
{
private StoreLocation location;
private X509ChainElementCollection elements;
private X509ChainPolicy policy;
private X509ChainStatus[] status;
static X509ChainStatus[] Empty = new X509ChainStatus [0];
// RFC3280 variables
private int max_path_length;
private X500DistinguishedName working_issuer_name;
// private string working_public_key_algorithm;
private AsymmetricAlgorithm working_public_key;
// other flags
private X509ChainElement bce_restriction;
// constructors
public X509ChainImplMono ()
: this (false)
{
}
public X509ChainImplMono (bool useMachineContext)
{
location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
elements = new X509ChainElementCollection ();
policy = new X509ChainPolicy ();
}
[MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
public X509ChainImplMono (IntPtr chainContext)
{
// CryptoAPI compatibility (unmanaged handle)
throw new NotSupportedException ();
}
public override bool IsValid {
get { return true; }
}
public override IntPtr Handle {
get { return IntPtr.Zero; }
}
// properties
public override X509ChainElementCollection ChainElements {
get { return elements; }
}
public override X509ChainPolicy ChainPolicy {
get { return policy; }
set { policy = value; }
}
public override X509ChainStatus[] ChainStatus {
get {
if (status == null)
return Empty;
return status;
}
}
// methods
[MonoTODO ("Not totally RFC3280 compliant, but neither is MS implementation...")]
public override bool Build (X509Certificate2 certificate)
{
if (certificate == null)
throw new ArgumentException ("certificate");
Reset ();
X509ChainStatusFlags flag;
try {
flag = BuildChainFrom (certificate);
ValidateChain (flag);
}
catch (CryptographicException ce) {
throw new ArgumentException ("certificate", ce);
}
X509ChainStatusFlags total = X509ChainStatusFlags.NoError;
ArrayList list = new ArrayList ();
// build "global" ChainStatus from the ChainStatus of every ChainElements
foreach (X509ChainElement ce in elements) {
foreach (X509ChainStatus cs in ce.ChainElementStatus) {
// we MUST avoid duplicates in the "global" list
if ((total & cs.Status) != cs.Status) {
list.Add (cs);
total |= cs.Status;
}
}
}
// and if required add some
if (flag != X509ChainStatusFlags.NoError) {
list.Insert (0, new X509ChainStatus (flag));
}
status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
// (fast path) this ignore everything we have checked
if ((status.Length == 0) || (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags))
return true;
bool result = true;
// now check if exclude some verification for the "end result" (boolean)
foreach (X509ChainStatus cs in status) {
switch (cs.Status) {
case X509ChainStatusFlags.UntrustedRoot:
case X509ChainStatusFlags.PartialChain:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);
break;
case X509ChainStatusFlags.NotTimeValid:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
break;
// FIXME - from here we needs new test cases for all cases
case X509ChainStatusFlags.NotTimeNested:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);
break;
case X509ChainStatusFlags.InvalidBasicConstraints:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);
break;
case X509ChainStatusFlags.InvalidPolicyConstraints:
case X509ChainStatusFlags.NoIssuanceChainPolicy:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);
break;
case X509ChainStatusFlags.InvalidNameConstraints:
case X509ChainStatusFlags.HasNotSupportedNameConstraint:
case X509ChainStatusFlags.HasNotPermittedNameConstraint:
case X509ChainStatusFlags.HasExcludedNameConstraint:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);
break;
case X509ChainStatusFlags.InvalidExtension:
// not sure ?!?
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
break;
//
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)
case X509ChainStatusFlags.CtlNotTimeValid:
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);
break;
case X509ChainStatusFlags.CtlNotSignatureValid:
// ?
break;
// ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);
case X509ChainStatusFlags.CtlNotValidForUsage:
// FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)
result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);
break;
default:
result = false;
break;
}
// once we have one failure there's no need to check further
if (!result)
return false;
}
// every "problem" was excluded
return true;
}
public override void Reset ()
{
// note: this call doesn't Reset the X509ChainPolicy
if ((status != null) && (status.Length != 0))
status = null;
if (elements.Count > 0)
elements.Clear ();
if (user_root_store != null) {
user_root_store.Close ();
user_root_store = null;
}
if (root_store != null) {
root_store.Close ();
root_store = null;
}
if (user_ca_store != null) {
user_ca_store.Close ();
user_ca_store = null;
}
if (ca_store != null) {
ca_store.Close ();
ca_store = null;
}
roots = null;
cas = null;
collection = null;
bce_restriction = null;
working_public_key = null;
}
// private stuff
private X509Certificate2Collection roots;
private X509Certificate2Collection cas;
private X509Store root_store;
private X509Store ca_store;
private X509Store user_root_store;
private X509Store user_ca_store;
private X509Certificate2Collection Roots {
get {
if (roots == null) {
X509Certificate2Collection c = new X509Certificate2Collection ();
X509Store store = LMRootStore;
if (location == StoreLocation.CurrentUser)
c.AddRange (UserRootStore.Certificates);
c.AddRange (store.Certificates);
roots = c;
}
return roots;
}
}
private X509Certificate2Collection CertificateAuthorities {
get {
if (cas == null) {
X509Certificate2Collection c = new X509Certificate2Collection ();
X509Store store = LMCAStore;
if (location == StoreLocation.CurrentUser)
c.AddRange (UserCAStore.Certificates);
c.AddRange (store.Certificates);
cas = c;
}
return cas;
}
}
private X509Store LMRootStore {
get {
if (root_store == null) {
root_store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
try {
root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return root_store;
}
}
private X509Store UserRootStore {
get {
if (user_root_store == null) {
user_root_store = new X509Store (StoreName.Root, StoreLocation.CurrentUser);
try {
user_root_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return user_root_store;
}
}
private X509Store LMCAStore {
get {
if (ca_store == null) {
ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.LocalMachine);
try {
ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return ca_store;
}
}
private X509Store UserCAStore {
get {
if (user_ca_store == null) {
user_ca_store = new X509Store (StoreName.CertificateAuthority, StoreLocation.CurrentUser);
try {
user_ca_store.Open (OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
} catch {
}
}
return user_ca_store;
}
}
// *** certificate chain/path building stuff ***
private X509Certificate2Collection collection;
// we search local user (default) or machine certificate store
// and in the extra certificate supplied in ChainPolicy.ExtraStore
private X509Certificate2Collection CertificateCollection {
get {
if (collection == null) {
collection = new X509Certificate2Collection (ChainPolicy.ExtraStore);
collection.AddRange (Roots);
collection.AddRange (CertificateAuthorities);
}
return collection;
}
}
// This is a non-recursive chain/path building algorithm.
//
// At this stage we only checks for PartialChain, Cyclic and UntrustedRoot errors are they
// affect the path building (other errors are verification errors).
//
// Note that the order match the one we need to match MS and not the one defined in RFC3280,
// we also include the trusted root certificate (trust anchor in RFC3280) in the list.
// (this isn't an issue, just keep that in mind if you look at the source and the RFC)
private X509ChainStatusFlags BuildChainFrom (X509Certificate2 certificate)
{
elements.Add (certificate);
while (!IsChainComplete (certificate)) {
certificate = FindParent (certificate);
if (certificate == null)
return X509ChainStatusFlags.PartialChain;
if (elements.Contains (certificate))
return X509ChainStatusFlags.Cyclic;
elements.Add (certificate);
}
// roots may be supplied (e.g. in the ExtraStore) so we need to confirm their
// trustiness (what a cute word) in the trusted root collection
if (!Roots.Contains (certificate))
elements [elements.Count - 1].StatusFlags |= X509ChainStatusFlags.UntrustedRoot;
return X509ChainStatusFlags.NoError;
}
private X509Certificate2 SelectBestFromCollection (X509Certificate2 child, X509Certificate2Collection c)
{
switch (c.Count) {
case 0:
return null;
case 1:
return c [0];
default:
// multiple candidate, keep only the ones that are still valid
X509Certificate2Collection time_valid = c.Find (X509FindType.FindByTimeValid, ChainPolicy.VerificationTime, false);
switch (time_valid.Count) {
case 0:
// that's too restrictive, let's revert and try another thing...
time_valid = c;
break;
case 1:
return time_valid [0];
default:
break;
}
// again multiple candidates, let's find the AKI that match the SKI (if we have one)
string aki = GetAuthorityKeyIdentifier (child);
if (String.IsNullOrEmpty (aki)) {
return time_valid [0]; // FIXME: out of luck, you get the first one
}
foreach (X509Certificate2 parent in time_valid) {
string ski = GetSubjectKeyIdentifier (parent);
// if both id are available then they must match
if (aki == ski)
return parent;
}
return time_valid [0]; // FIXME: out of luck, you get the first one
}
}
private X509Certificate2 FindParent (X509Certificate2 certificate)
{
X509Certificate2Collection subset = CertificateCollection.Find (X509FindType.FindBySubjectDistinguishedName, certificate.Issuer, false);
string aki = GetAuthorityKeyIdentifier (certificate);
if ((aki != null) && (aki.Length > 0)) {
subset.AddRange (CertificateCollection.Find (X509FindType.FindBySubjectKeyIdentifier, aki, false));
}
X509Certificate2 parent = SelectBestFromCollection (certificate, subset);
// if parent==certificate we're looping but it's not (probably) a bug and not a true cyclic (over n certs)
return certificate.Equals (parent) ? null : parent;
}
private bool IsChainComplete (X509Certificate2 certificate)
{
// the chain is complete if we have a self-signed certificate
if (!IsSelfIssued (certificate))
return false;
// we're very limited to what we can do without certificate extensions
if (certificate.Version < 3)
return true;
// check that Authority Key Identifier == Subject Key Identifier
// e.g. it will be different if a self-signed certificate is part (not the end) of the chain
string ski = GetSubjectKeyIdentifier (certificate);
if (String.IsNullOrEmpty (ski))
return true;
string aki = GetAuthorityKeyIdentifier (certificate);
if (String.IsNullOrEmpty (aki))
return true;
// if both id are available then they must match
return (aki == ski);
}
// check for "self-issued" certificate - without verifying the signature
// note that self-issued doesn't always mean it's a root certificate!
private bool IsSelfIssued (X509Certificate2 certificate)
{
return (certificate.Issuer == certificate.Subject);
}
// *** certificate chain/path validation stuff ***
// Currently a subset of RFC3280 (hopefully a full implementation someday)
private void ValidateChain (X509ChainStatusFlags flag)
{
// 'n' should be the root certificate...
int n = elements.Count - 1;
X509Certificate2 certificate = elements [n].Certificate;
// ... and, if so, must be treated outside the chain...
if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
Process (n);
// deal with the case where the chain == the root certificate
// (which isn't for RFC3280) part of the chain
if (n == 0) {
elements [0].UncompressFlags ();
return;
}
// skip the root certificate when processing the chain (in 6.1.3)
n--;
}
// ... unless the chain is a partial one (then we start with that one)
// 6.1.1 - Inputs
// 6.1.1.a - a prospective certificate path of length n (i.e. elements)
// 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
// 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
// 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
// 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
// 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
// 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)
// 6.1.2 - Initialization (incomplete)
// 6.1.2.a-f - policy stuff, some TODO, some not supported
// 6.1.2.g - working public key algorithm
// working_public_key_algorithm = certificate.PublicKey.Oid.Value;
// 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
working_public_key = certificate.PublicKey.Key;
// 6.1.2.j - working issuer name
working_issuer_name = certificate.IssuerName;
// 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
// may be reduced to the value in the path length constraint field
max_path_length = n;
// 6.1.3 - Basic Certificate Processing
// note: loop looks reversed (the list is) but we process this part just like RFC3280 does
for (int i = n; i > 0; i--) {
Process (i);
// 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
PrepareForNextCertificate (i);
}
Process (0);
// 6.1.3.a.3 - revocation checks
CheckRevocationOnChain (flag);
// 6.1.5 - Wrap-up procedure
WrapUp ();
}
private void Process (int n)
{
X509ChainElement element = elements [n];
X509Certificate2 certificate = element.Certificate;
// pre-step: DSA certificates may inherit the parameters of their CA
if ((n != elements.Count - 1) && (certificate.MonoCertificate.KeyAlgorithm == "1.2.840.10040.4.1")) {
if (certificate.MonoCertificate.KeyAlgorithmParameters == null) {
X509Certificate2 parent = elements [n+1].Certificate;
certificate.MonoCertificate.KeyAlgorithmParameters = parent.MonoCertificate.KeyAlgorithmParameters;
}
}
bool root = (working_public_key == null);
// 6.1.3.a.1 - check signature (with special case to deal with root certificates)
if (!IsSignedWith (certificate, root ? certificate.PublicKey.Key : working_public_key)) {
// another special case where only an end-entity is available and can't be verified.
// In this case we do not report an invalid signature (since this is unknown)
if (root || (n != elements.Count - 1) || IsSelfIssued (certificate)) {
element.StatusFlags |= X509ChainStatusFlags.NotSignatureValid;
}
}
// 6.1.3.a.2 - check validity period
if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||
(ChainPolicy.VerificationTime > certificate.NotAfter)) {
element.StatusFlags |= X509ChainStatusFlags.NotTimeValid;
}
// TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)
// note: most of them don't apply to the root certificate
if (root) {
return;
}
// 6.1.3.a.3 - revocation check (we're doing at the last stage)
// note: you revoke a trusted root by removing it from your trusted store (i.e. no CRL can do this job)
// 6.1.3.a.4 - check certificate issuer name
if (!X500DistinguishedName.AreEqual (certificate.IssuerName, working_issuer_name)) {
// NOTE: this is not the "right" error flag, but it's the closest one defined
element.StatusFlags |= X509ChainStatusFlags.InvalidNameConstraints;
}
if (!IsSelfIssued (certificate) && (n != 0)) {
// TODO 6.1.3.b - subject name in the permitted_subtrees ...
// TODO 6.1.3.c - subject name not within excluded_subtrees...
// TODO - check for X509ChainStatusFlags.InvalidNameConstraint
// TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
// TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
// TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
}
// TODO 6.1.3.d - check if certificate policies extension is present
//if (false) {
// TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
// using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
// TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
//} else {
// TODO 6.1.3.e - set valid_policy_tree to NULL
//}
// TODO 6.1.3.f - verify explict_policy > 0 if valid_policy_tree != NULL
}
// CTL == Certificate Trust List / NOT SUPPORTED
// TODO - check for X509ChainStatusFlags.CtlNotTimeValid
// TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
// TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
private void PrepareForNextCertificate (int n)
{
X509ChainElement element = elements [n];
X509Certificate2 certificate = element.Certificate;
// TODO 6.1.4.a-b
// 6.1.4.c
working_issuer_name = certificate.SubjectName;
// 6.1.4.d-e - our key includes both the public key and it's parameters
working_public_key = certificate.PublicKey.Key;
// 6.1.4.f
// working_public_key_algorithm = certificate.PublicKey.Oid.Value;
// TODO 6.1.4.g-j
// 6.1.4.k - Verify that the certificate is a CA certificate
X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension);
if (bce != null) {
if (!bce.CertificateAuthority) {
element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
} else if (certificate.Version >= 3) {
// recent (v3+) CA certificates must include BCE
element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
// 6.1.4.l - if the certificate isn't self-issued...
if (!IsSelfIssued (certificate)) {
// ... verify that max_path_length > 0
if (max_path_length > 0) {
max_path_length--;
} else {
// to match MS the reported status must be against the certificate
// with the BCE and not where the path is too long. It also means
// that this condition has to be reported only once
if (bce_restriction != null) {
bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints;
}
}
}
// 6.1.4.m - if pathLengthConstraint is present...
if ((bce != null) && (bce.HasPathLengthConstraint)) {
// ... and is less that max_path_length, set max_path_length to it's value
if (bce.PathLengthConstraint < max_path_length) {
max_path_length = bce.PathLengthConstraint;
bce_restriction = element;
}
}
// 6.1.4.n - if key usage extension is present...
X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension);
if (kue != null) {
// ... verify keyCertSign is set
X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign;
if ((kue.KeyUsages & success) != success)
element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage;
}
// 6.1.4.o - recognize and process other critical extension present in the certificate
ProcessCertificateExtensions (element);
}
private void WrapUp ()
{
X509ChainElement element = elements [0];
X509Certificate2 certificate = element.Certificate;
// 6.1.5.a - TODO if certificate n (our 0) wasn't self issued and explicit_policy != 0
if (IsSelfIssued (certificate)) {
// TODO... decrement explicit_policy by 1
}
// 6.1.5.b - TODO
// 6.1.5.c,d,e - not required by the X509Chain implementation
// 6.1.5.f - recognize and process other critical extension present in the certificate
ProcessCertificateExtensions (element);
// 6.1.5.g - TODO
// uncompressed the flags into several elements
for (int i = elements.Count - 1; i >= 0; i--) {
elements [i].UncompressFlags ();
}
}
private void ProcessCertificateExtensions (X509ChainElement element)
{
foreach (X509Extension ext in element.Certificate.Extensions) {
if (ext.Critical) {
switch (ext.Oid.Value) {
case "2.5.29.15": // X509KeyUsageExtension
case "2.5.29.19": // X509BasicConstraintsExtension
// we processed this extension
break;
default:
// note: Under Windows XP MS implementation seems to ignore
// certificate with unknown critical extensions.
element.StatusFlags |= X509ChainStatusFlags.InvalidExtension;
break;
}
}
}
}
private bool IsSignedWith (X509Certificate2 signed, AsymmetricAlgorithm pubkey)
{
if (pubkey == null)
return false;
// Sadly X509Certificate2 doesn't expose the signature nor the tbs (to be signed) structure
MX.X509Certificate mx = signed.MonoCertificate;
return (mx.VerifySignature (pubkey));
}
private string GetSubjectKeyIdentifier (X509Certificate2 certificate)
{
X509SubjectKeyIdentifierExtension ski = (certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension);
return (ski == null) ? String.Empty : ski.SubjectKeyIdentifier;
}
// System.dll v2 doesn't have a class to deal with the AuthorityKeyIdentifier extension
static string GetAuthorityKeyIdentifier (X509Certificate2 certificate)
{
return GetAuthorityKeyIdentifier (certificate.MonoCertificate.Extensions ["2.5.29.35"]);
}
// but anyway System.dll v2 doesn't expose CRL in any way so...
static string GetAuthorityKeyIdentifier (MX.X509Crl crl)
{
return GetAuthorityKeyIdentifier (crl.Extensions ["2.5.29.35"]);
}
static string GetAuthorityKeyIdentifier (MX.X509Extension ext)
{
if (ext == null)
return String.Empty;
MX.Extensions.AuthorityKeyIdentifierExtension aki = new MX.Extensions.AuthorityKeyIdentifierExtension (ext);
byte[] id = aki.Identifier;
if (id == null)
return String.Empty;
StringBuilder sb = new StringBuilder ();
foreach (byte b in id)
sb.Append (b.ToString ("X02"));
return sb.ToString ();
}
// we check the revocation only once we have built the complete chain
private void CheckRevocationOnChain (X509ChainStatusFlags flag)
{
bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
bool online;
switch (ChainPolicy.RevocationMode) {
case X509RevocationMode.Online:
// default
online = true;
break;
case X509RevocationMode.Offline:
online = false;
break;
case X509RevocationMode.NoCheck:
return;
default:
throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
}
bool unknown = partial;
// from the root down to the end-entity
for (int i = elements.Count - 1; i >= 0; i--) {
bool check = true;
switch (ChainPolicy.RevocationFlag) {
case X509RevocationFlag.EndCertificateOnly:
check = (i == 0);
break;
case X509RevocationFlag.EntireChain:
check = true;
break;
case X509RevocationFlag.ExcludeRoot:
// default
check = (i != (elements.Count - 1));
// anyway, who's gonna sign that the root is invalid ?
break;
}
X509ChainElement element = elements [i];
// we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
if (!unknown)
unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);
if (unknown) {
// we can skip the revocation checks as we can't be sure of them anyway
element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
} else if (check && !partial && !IsSelfIssued (element.Certificate)) {
// check for revocation (except for the trusted root and self-issued certs)
element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
// if revoked, then all others following in the chain are unknown...
unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
}
}
}
// This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, int ca, bool online)
{
X509ChainStatusFlags result = X509ChainStatusFlags.RevocationStatusUnknown;
X509ChainElement element = elements [ca];
X509Certificate2 ca_cert = element.Certificate;
// find the CRL from the "right" CA
while (IsSelfIssued (ca_cert) && (ca < elements.Count - 1)) {
// try with this self-issued
result = CheckRevocation (certificate, ca_cert, online);
if (result != X509ChainStatusFlags.RevocationStatusUnknown)
break;
ca++;
element = elements [ca];
ca_cert = element.Certificate;
}
if (result == X509ChainStatusFlags.RevocationStatusUnknown)
result = CheckRevocation (certificate, ca_cert, online);
return result;
}
private X509ChainStatusFlags CheckRevocation (X509Certificate2 certificate, X509Certificate2 ca_cert, bool online)
{
// change this if/when we support OCSP
X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension);
if (kue != null) {
// ... verify CrlSign is set
X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign;
if ((kue.KeyUsages & success) != success) {
// FIXME - we should try to find an alternative CA that has the CrlSign bit
return X509ChainStatusFlags.RevocationStatusUnknown;
}
}
MX.X509Crl crl = FindCrl (ca_cert);
if ((crl == null) && online) {
// FIXME - download and install new CRL
// then you get a second chance
// crl = FindCrl (ca_cert, ref valid, ref out_of_date);
// We need to get the subjectAltName and an URI from there (or use OCSP)
// X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension);
}
if (crl != null) {
// validate the digital signature on the CRL using the CA public key
// note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates
// checks and we loose the "why" of the failure
// note #2: we do this before other tests as an invalid signature could be a hacked CRL
// (so anything within can't be trusted)
if (!crl.VerifySignature (ca_cert.PublicKey.Key)) {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry (certificate.MonoCertificate);
if (entry != null) {
// We have an entry for this CRL that includes an unknown CRITICAL extension
// See [X.509 7.3] NOTE 4
if (!ProcessCrlEntryExtensions (entry))
return X509ChainStatusFlags.Revoked;
// FIXME - a little more is involved
if (entry.RevocationDate <= ChainPolicy.VerificationTime)
return X509ChainStatusFlags.Revoked;
}
// are we overdue for a CRL update ? if so we can't be sure of any certificate status
if (crl.NextUpdate < ChainPolicy.VerificationTime)
return X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;
// we have a CRL that includes an unknown CRITICAL extension
// we put this check at the end so we do not "hide" any Revoked flags
if (!ProcessCrlExtensions (crl)) {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
} else {
return X509ChainStatusFlags.RevocationStatusUnknown;
}
return X509ChainStatusFlags.NoError;
}
static MX.X509Crl CheckCrls (string subject, string ski, MX.X509Store store)
{
if (store == null)
return null;
var crls = store.Crls;
foreach (MX.X509Crl crl in crls) {
if (crl.IssuerName == subject && (ski.Length == 0 || ski == GetAuthorityKeyIdentifier (crl)))
return crl;
}
return null; // No CRL found
}
private MX.X509Crl FindCrl (X509Certificate2 caCertificate)
{
string subject = caCertificate.SubjectName.Decode (X500DistinguishedNameFlags.None);
string ski = GetSubjectKeyIdentifier (caCertificate);
// consider that the LocalMachine directories could not exists... and cannot be created by the user
MX.X509Crl result = CheckCrls (subject, ski, LMCAStore.Store);
if (result != null)
return result;
if (location == StoreLocation.CurrentUser) {
result = CheckCrls (subject, ski, UserCAStore.Store);
if (result != null)
return result;
}
// consider that the LocalMachine directories could not exists... and cannot be created by the user
result = CheckCrls (subject, ski, LMRootStore.Store);
if (result != null)
return result;
if (location == StoreLocation.CurrentUser) {
result = CheckCrls (subject, ski, UserRootStore.Store);
if (result != null)
return result;
}
return null;
}
private bool ProcessCrlExtensions (MX.X509Crl crl)
{
foreach (MX.X509Extension ext in crl.Extensions) {
if (ext.Critical) {
switch (ext.Oid) {
case "2.5.29.20": // cRLNumber
case "2.5.29.35": // authorityKeyIdentifier
// we processed/know about this extension
break;
default:
return false;
}
}
}
return true;
}
private bool ProcessCrlEntryExtensions (MX.X509Crl.X509CrlEntry entry)
{
foreach (MX.X509Extension ext in entry.Extensions) {
if (ext.Critical) {
switch (ext.Oid) {
case "2.5.29.21": // cRLReason
// we processed/know about this extension
break;
default:
return false;
}
}
}
return true;
}
}
}
#endif

View File

@ -0,0 +1,119 @@
//
// X509Helper2.cs
//
// Authors:
// Martin Baulig <martin.baulig@xamarin.com>
//
// Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.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.
//
#if SECURITY_DEP
#if MONO_SECURITY_ALIAS
extern alias MonoSecurity;
#endif
#if MONO_X509_ALIAS
extern alias PrebuiltSystem;
#endif
#if MONO_SECURITY_ALIAS
using MonoSecurity::Mono.Security.Interface;
#else
using Mono.Security.Interface;
#endif
namespace System.Security.Cryptography.X509Certificates
{
internal static class X509Helper2
{
internal static void Initialize ()
{
X509Helper.InstallNativeHelper (new MyNativeHelper ());
}
internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
{
X509Helper.ThrowIfContextInvalid (impl);
}
internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
{
var provider = MonoTlsProviderFactory.GetProvider ();
if (provider.HasNativeCertificates) {
var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
return (X509Certificate2Impl)(object)impl;
} else {
var impl = new X509Certificate2ImplMono ();
impl.Import (rawData, password, keyStorageFlags);
return impl;
}
}
internal static X509Certificate2Impl Import (X509Certificate cert)
{
var provider = MonoTlsProviderFactory.GetProvider ();
if (provider.HasNativeCertificates) {
var impl = provider.GetNativeCertificate (cert);
return (X509Certificate2Impl)(object)impl;
}
var impl2 = cert.Impl as X509Certificate2Impl;
if (impl2 != null)
return (X509Certificate2Impl)impl2.Clone ();
return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
}
internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
{
return new X509ChainImplMono (useMachineContext);
}
public static bool IsValid (X509ChainImpl impl)
{
return impl != null && impl.IsValid;
}
internal static void ThrowIfContextInvalid (X509ChainImpl impl)
{
if (!IsValid (impl))
throw GetInvalidChainContextException ();
}
internal static Exception GetInvalidChainContextException ()
{
return new CryptographicException (Locale.GetText ("Chain instance is empty."));
}
class MyNativeHelper : INativeCertificateHelper
{
public X509CertificateImpl Import (
byte[] data, string password, X509KeyStorageFlags flags)
{
return X509Helper2.Import (data, password, flags);
}
public X509CertificateImpl Import (X509Certificate cert)
{
return X509Helper2.Import (cert);
}
}
}
}
#endif

View File

@ -536,11 +536,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
System.Security.Cryptography.X509Certificates/X509Certificate2.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
System.Security.Cryptography.X509Certificates/X509Chain.cs
System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
System.Security.Cryptography.X509Certificates/X509ChainElement.cs
System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@ -550,6 +554,7 @@ System.Security.Cryptography.X509Certificates/X509Extension.cs
System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
System.Security.Cryptography.X509Certificates/X509FindType.cs
System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
System.Security.Cryptography.X509Certificates/X509Helper2.cs
System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
System.Security.Cryptography.X509Certificates/X509NameType.cs

View File

@ -1 +1 @@
e642d688f3c59c8d62dd075b49ad48e36176f470
a7e48646d05dcf3b87af070d4ee4cb66ac045634

View File

@ -300,11 +300,15 @@ System.Security.Cryptography.X509Certificates/X509BasicConstraintsExtension.cs
System.Security.Cryptography.X509Certificates/X509Certificate2.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Collection.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Enumerator.cs
System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
System.Security.Cryptography.X509Certificates/X509CertificateCollection.cs
System.Security.Cryptography.X509Certificates/X509Chain.cs
System.Security.Cryptography.X509Certificates/X509ChainElement.cs
System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
System.Security.Cryptography.X509Certificates/X509ChainElementEnumerator.cs
System.Security.Cryptography.X509Certificates/X509ChainImpl.cs
System.Security.Cryptography.X509Certificates/X509ChainImplMono.cs
System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
System.Security.Cryptography.X509Certificates/X509ChainStatus.cs
System.Security.Cryptography.X509Certificates/X509ChainStatusFlags.cs
@ -314,6 +318,7 @@ System.Security.Cryptography.X509Certificates/X509ExtensionCollection.cs
System.Security.Cryptography.X509Certificates/X509ExtensionEnumerator.cs
System.Security.Cryptography.X509Certificates/X509FindType.cs
System.Security.Cryptography.X509Certificates/X509IncludeOption.cs
System.Security.Cryptography.X509Certificates/X509Helper2.cs
System.Security.Cryptography.X509Certificates/X509KeyUsageExtension.cs
System.Security.Cryptography.X509Certificates/X509KeyUsageFlags.cs
System.Security.Cryptography.X509Certificates/X509NameType.cs

View File

@ -98,4 +98,5 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
#endif
[assembly: InternalsVisibleTo ("Xamarin.BoringTls, PublicKey=002400000480000094000000060200000024000052534131000400001100000099dd12eda85767ae6f06023ee28e711c7e5a212462095c83868c29db75eddf6d8e296e03824c14fedd5f55553fed0b6173be3cc985a4b7f9fb7c83ccff8ba3938563b3d1f45a81122f12a1bcb73edcaad61a8456c7595a6da5184b4dd9d10f011b949ef1391fccfeab1ba62aa51c267ef8bd57ef1b6ba5a4c515d0badb81a78f")]
[assembly: Guid ("BED7F4EA-1A96-11D2-8F08-00A0C9A6186D")]

View File

@ -1,74 +0,0 @@
//
// System.Runtime.InteropServices/RuntimeEnvironment.cs
//
// Authors:
// Dominik Fretz (roboto@gmx.net)
// Sebastien Pouliot (sebastien@ximian.com)
//
// (C) 2003 Dominik Fretz
// Copyright (C) 2004-2005 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.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace System.Runtime.InteropServices
{
[ComVisible (true)]
public class RuntimeEnvironment
{
public RuntimeEnvironment ()
{
}
public static string SystemConfigurationFile {
get {
// GetMachineConfigPath is internal and not protected by CAS
string path = Environment.GetMachineConfigPath ();
if (SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand ();
}
return path;
}
}
public static bool FromGlobalAccessCache (Assembly a)
{
// yes, this will throw a NullReferenceException (just like MS, reported as ...)
return a.GlobalAssemblyCache;
}
public static string GetRuntimeDirectory ()
{
return Path.GetDirectoryName (typeof (int).Assembly.Location);
}
[SecuritySafeCritical]
public static string GetSystemVersion ()
{
return "v" + Environment.Version.Major + "." + Environment.Version.Minor + "." + Environment.Version.Build;
}
}
}

View File

@ -0,0 +1,35 @@
//
// INativeCertificateHelper.cs
//
// Author:
// Martin Baulig <martin.baulig@xamarin.com>
//
// Copyright (c) 2016 Xamarin, Inc.
//
// 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.
namespace System.Security.Cryptography.X509Certificates
{
internal interface INativeCertificateHelper
{
X509CertificateImpl Import (byte[] data, string password, X509KeyStorageFlags flags);
X509CertificateImpl Import (X509Certificate cert);
}
}

View File

@ -109,17 +109,44 @@ namespace System.Security.Cryptography.X509Certificates {
impl = X509Helper.InitFromHandle (handle);
}
internal X509Certificate (X509CertificateImpl impl)
{
if (impl == null)
throw new ArgumentNullException ("impl");
this.impl = X509Helper.InitFromCertificate (impl);
}
public X509Certificate (System.Security.Cryptography.X509Certificates.X509Certificate cert)
{
if (cert == null)
throw new ArgumentNullException ("cert");
X509Helper.ThrowIfContextInvalid (cert.impl);
impl = X509Helper.InitFromCertificate (cert.impl);
impl = X509Helper.InitFromCertificate (cert);
hideDates = false;
}
internal void ImportHandle (X509CertificateImpl impl)
{
Reset ();
this.impl = impl;
}
internal X509CertificateImpl Impl {
get {
X509Helper.ThrowIfContextInvalid (impl);
return impl;
}
}
internal bool IsValid {
get { return X509Helper.IsValid (impl); }
}
internal void ThrowIfContextInvalid ()
{
X509Helper.ThrowIfContextInvalid (impl);
}
// public methods
@ -161,7 +188,7 @@ namespace System.Security.Cryptography.X509Certificates {
return null;
X509Helper.ThrowIfContextInvalid (impl);
return impl.GetEffectiveDateString ().ToString ();
return impl.GetValidFrom ().ToLocalTime ().ToString ();
}
// strangly there are no DateTime returning function
@ -171,7 +198,7 @@ namespace System.Security.Cryptography.X509Certificates {
return null;
X509Helper.ThrowIfContextInvalid (impl);
return impl.GetExpirationDateString ().ToString ();
return impl.GetValidUntil ().ToLocalTime ().ToString ();
}
// well maybe someday there'll be support for PGP or SPKI ?

View File

@ -45,17 +45,15 @@ namespace System.Security.Cryptography.X509Certificates
public abstract X509CertificateImpl Clone ();
public abstract string GetSubjectSummary ();
public abstract string GetIssuerName (bool legacyV1Mode);
public abstract string GetSubjectName (bool legacyV1Mode);
public abstract byte[] GetRawCertData ();
public abstract DateTime GetEffectiveDateString ();
public abstract DateTime GetValidFrom ();
public abstract DateTime GetExpirationDateString ();
public abstract DateTime GetValidUntil ();
byte[] cachedCertificateHash;

View File

@ -66,12 +66,6 @@ namespace System.Security.Cryptography.X509Certificates
return MX.X501.ToString (x509.GetIssuerName (), true, ", ", true);
}
public override string GetSubjectSummary ()
{
ThrowIfContextInvalid ();
return x509.SubjectName;
}
public override string GetSubjectName (bool legacyV1Mode)
{
ThrowIfContextInvalid ();
@ -94,16 +88,16 @@ namespace System.Security.Cryptography.X509Certificates
return sha.ComputeHash (x509.RawData);
}
public override DateTime GetEffectiveDateString ()
public override DateTime GetValidFrom ()
{
ThrowIfContextInvalid ();
return x509.ValidFrom.ToLocalTime ();
return x509.ValidFrom;
}
public override DateTime GetExpirationDateString ()
public override DateTime GetValidUntil ()
{
ThrowIfContextInvalid ();
return x509.ValidUntil.ToLocalTime ();
return x509.ValidUntil;
}
public override bool Equals (X509CertificateImpl other, out bool result)
@ -164,8 +158,8 @@ namespace System.Security.Cryptography.X509Certificates
StringBuilder sb = new StringBuilder ();
sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, GetSubjectName (false));
sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, GetIssuerName (false));
sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetEffectiveDateString ());
sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetExpirationDateString ());
sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
sb.Append (nl);
return sb.ToString ();

View File

@ -30,6 +30,7 @@
//
using System;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
#if !NET_2_1
using System.Security.Permissions;
@ -40,6 +41,14 @@ namespace System.Security.Cryptography.X509Certificates
{
static partial class X509Helper
{
static INativeCertificateHelper nativeHelper;
internal static void InstallNativeHelper (INativeCertificateHelper helper)
{
if (nativeHelper == null)
Interlocked.CompareExchange (ref nativeHelper, helper, null);
}
#if !NET_2_1
// typedef struct _CERT_CONTEXT {
// DWORD dwCertEncodingType;
@ -77,6 +86,14 @@ namespace System.Security.Cryptography.X509Certificates
}
#endif
public static X509CertificateImpl InitFromCertificate (X509Certificate cert)
{
if (nativeHelper != null)
return nativeHelper.Import (cert);
return InitFromCertificate (cert.Impl);
}
public static X509CertificateImpl InitFromCertificate (X509CertificateImpl impl)
{
ThrowIfContextInvalid (impl);
@ -134,6 +151,9 @@ namespace System.Security.Cryptography.X509Certificates
#if !MONOTOUCH && !XAMMAC
public static X509CertificateImpl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
{
if (nativeHelper != null)
return nativeHelper.Import (rawData, password, keyStorageFlags);
MX.X509Certificate x509;
if (password == null) {
try {

View File

@ -96,11 +96,6 @@ namespace System
static Console ()
{
#if NET_2_1
Encoding inputEncoding;
Encoding outputEncoding;
#endif
if (Environment.IsRunningOnWindows) {
//
// On Windows, follow the Windows tradition
@ -540,7 +535,6 @@ namespace System
#endif
#if !NET_2_1
// FIXME: Console should use these encodings when changed
static Encoding inputEncoding;
static Encoding outputEncoding;
@ -561,6 +555,7 @@ namespace System
}
}
#if !NET_2_1
public static ConsoleColor BackgroundColor {
get { return ConsoleDriver.BackgroundColor; }
set { ConsoleDriver.BackgroundColor = value; }

View File

@ -218,7 +218,7 @@ namespace System {
if (typeName == null)
throw new ArgumentNullException ("typeName");
TypeSpec res = Parse (typeName, ref pos, false, false);
TypeSpec res = Parse (typeName, ref pos, false, true);
if (pos < typeName.Length)
throw new ArgumentException ("Count not parse the whole type name", "typeName");
return res;
@ -287,7 +287,7 @@ namespace System {
{
Assembly asm = null;
if (assemblyResolver == null && typeResolver == null)
return Type.GetType (name.DisplayName, throwOnError, ignoreCase);
return Type.GetType (DisplayFullName, throwOnError, ignoreCase);
if (assembly_name != null) {
if (assemblyResolver != null)
@ -376,6 +376,12 @@ namespace System {
pos = p;
}
static void BoundCheck (int idx, string s)
{
if (idx >= s.Length)
throw new ArgumentException ("Invalid generic arguments spec", "typeName");
}
static TypeIdentifier ParsedTypeIdentifier (string displayName)
{
return TypeIdentifiers.FromDisplay(displayName);
@ -383,6 +389,17 @@ namespace System {
static TypeSpec Parse (string name, ref int p, bool is_recurse, bool allow_aqn)
{
// Invariants:
// - On exit p, is updated to pos the current unconsumed character.
//
// - The callee peeks at but does not consume delimiters following
// recurisve parse (so for a recursive call like the args of "Foo[P,Q]"
// we'll return with p either on ',' or on ']'. If the name was aqn'd
// "Foo[[P,assmblystuff],Q]" on return p with be on the ']' just
// after the "assmblystuff")
//
// - If allow_aqn is True, assembly qualification is optional.
// If allow_aqn is False, assembly qualification is prohibited.
int pos = p;
int name_start;
bool in_modifiers = false;
@ -450,18 +467,24 @@ namespace System {
data.AddModifier (new PointerSpec(pointer_level));
break;
case ',':
if (is_recurse) {
if (is_recurse && allow_aqn) {
int end = pos;
while (end < name.Length && name [end] != ']')
++end;
if (end >= name.Length)
throw new ArgumentException ("Unmatched ']' while parsing generic argument assembly name");
data.assembly_name = name.Substring (pos + 1, end - pos - 1).Trim ();
p = end + 1;
p = end;
return data;
}
data.assembly_name = name.Substring (pos + 1).Trim ();
pos = name.Length;
if (is_recurse) {
p = pos;
return data;
}
if (allow_aqn) {
data.assembly_name = name.Substring (pos + 1).Trim ();
pos = name.Length;
}
break;
case '[':
if (data.is_byref)
@ -482,11 +505,17 @@ namespace System {
if (aqn)
++pos; //skip '[' to the start of the type
args.Add (Parse (name, ref pos, true, aqn));
if (pos >= name.Length)
throw new ArgumentException ("Invalid generic arguments spec", "typeName");
BoundCheck (pos, name);
if (aqn) {
if (name [pos] == ']')
++pos;
else
throw new ArgumentException ("Unclosed assembly-qualified type name at " + name[pos], "typeName");
BoundCheck (pos, name);
}
if (name [pos] == ']')
break;
break;
if (name [pos] == ',')
++pos; // skip ',' to the start of the next arg
else
@ -523,7 +552,7 @@ namespace System {
break;
case ']':
if (is_recurse) {
p = pos + 1;
p = pos;
return data;
}
throw new ArgumentException ("Unmatched ']'", "typeName");

View File

@ -35,6 +35,7 @@ using System.Diagnostics;
namespace MonoTests.System.Runtime.ExceptionServices
{
[TestFixture]
[Category ("BitcodeNotWorking")]
public class ExceptionDispatchInfoTest
{
[Test]

View File

@ -1 +1 @@
19dbff4804c0ea37f0033f0911c3674f4bf65b90
541acb6afb71ee34f37b1aa52431ed984f0cbca2

View File

@ -403,7 +403,6 @@ System.Runtime.InteropServices/RegistrationConnectionType.cs
System.Runtime.InteropServices/SEHException.cs
System.Runtime.InteropServices/STATSTG.cs
System.Runtime.InteropServices/RegistrationServices.cs
System.Runtime.InteropServices/RuntimeEnvironment.cs
System.Runtime.InteropServices/SafeArrayRankMismatchException.cs
System.Runtime.InteropServices/SafeArrayTypeMismatchException.cs
System.Runtime.InteropServices/SafeBuffer.cs
@ -733,6 +732,7 @@ System.Security.Cryptography/RSAPKCS1SignatureDeformatter.cs
System.Security.Cryptography/RSAPKCS1SignatureFormatter.cs
System.Security.Cryptography/SHA1CryptoServiceProvider.cs
System.Security.Cryptography/TripleDESCryptoServiceProvider.cs
System.Security.Cryptography.X509Certificates/INativeCertificateHelper.cs
System.Security.Cryptography.X509Certificates/X509Certificate.cs
System.Security.Cryptography.X509Certificates/X509Certificate20.cs
System.Security.Cryptography.X509Certificates/X509CertificateImpl.cs
@ -1280,6 +1280,7 @@ ReferenceSources/SecurityContext.cs
../../../external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs
../../../external/referencesource/mscorlib/system/runtime/interopservices/attributes.cs
../../../external/referencesource/mscorlib/system/runtime/interopservices/runtimeenvironment.cs
../../../external/referencesource/mscorlib/system/runtime/interopservices/safehandle.cs
../../../external/referencesource/mscorlib/system/runtime/interopservices/ucomienumconnections.cs

View File

@ -1 +1 @@
362e108c1374bb987f401f2b4d420b050a031231
cda5f1e52d7ff05ac3c67c95adb635880bcd8928

View File

@ -1 +1 @@
42eaf0337c8b492035f2d3bcd22cdbd06a9d1428
28d0cee3d630bf94dfea9611a14d38b8287e32ac

View File

@ -1 +1 @@
2968266af5fb7b1521b79ce929b2fb27097233aa
1123b73866732a094cf1c7bdcf6e3a92e8f34df7

View File

@ -1 +1 @@
24979c09819a656e19fc58fcf19e9b5a16584075
8e64e5a6758d73dbf3d8c6fb3eb48c076357b70d

View File

@ -1 +1 @@
bd4b36083e46dd607da7e0ec9922f22c312cf270
5de7e54e585f6b49306081a2d825a268eae55a8b

View File

@ -1 +1 @@
2caa7c6153cffdaf2f9392820e8c2468e5b287af
7b90f739b90808c54955991f2ee7ade80d218166

View File

@ -2245,7 +2245,7 @@ namespace Mono.CSharp {
return IsLeftResolvedExpressionValid (dmb.Arguments [0].Expr);
}
if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is This)
if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is VariableReference)
return true;
return false;

View File

@ -901,7 +901,7 @@ namespace Mono.CSharp
public override void Emit ()
{
if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.AutoProperty)) == Modifiers.AutoProperty && Parent.PartialContainer.HasExplicitLayout) {
Report.Error (842, Location,
"Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
GetSignatureForError ());

View File

@ -1211,13 +1211,29 @@ namespace Mono.CSharp {
return ParseResult.Success;
// csc options that we don't support
case "/utf8output":
case "/subsystemversion":
case "/analyzer":
case "/appconfig":
case "/baseaddress":
case "/deterministic":
case "/errorendlocation":
case "/errorlog":
case "/features":
case "/highentropyva":
case "/highentropyva+":
case "/highentropyva-":
case "/win32manifest":
case "/link":
case "/moduleassemblyname":
case "/nowin32manifest":
case "/pathmap":
case "/pdb":
case "/preferreduilang":
case "/publicsign":
case "/reportanalyzer":
case "/ruleset":
case "/sqmsessionguid":
case "/subsystemversion":
case "/utf8output":
case "/win32manifest":
return ParseResult.Success;
default:

View File

@ -0,0 +1,17 @@
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Cs0842ExpressionBodyGetterBug
{
[FieldOffset(0)]
public int DummyVariable;
public int MyGetter => 5;
}
class C
{
public static void Main ()
{
}
}

View File

@ -29,6 +29,11 @@ public class MainClass
public static event Action Act = null;
public static dynamic BBB = null;
void ParameterTest (Person ParPerson)
{
Console.WriteLine (nameof (ParPerson.MyCar.Year));
}
public static int Main ()
{
string name;
@ -61,6 +66,11 @@ public class MainClass
if (name != "ToString")
return 7;
Person LocPerson = null;
name = nameof (LocPerson.MyCar.Year);
if (name != "Year")
return 8;
return 0;
}
}

View File

@ -1 +1 @@
55a55a8ce00b5f19846f2a4e0df099c17d0799cd
de9fea39fc570d60a08eeeba6e5eef06352b9197

View File

@ -12,6 +12,7 @@ using System;
using System.Globalization;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Cryptography;
@ -19,6 +20,7 @@ using System.Text;
using System.Configuration.Assemblies;
using Mono.Security.Cryptography;
using IKR = IKVM.Reflection;
namespace Mono.AssemblyLinker
{
@ -591,46 +593,8 @@ namespace Mono.AssemblyLinker
* Emit Manifest
* */
if (isTemplateFile) {
// LAMESPEC: according to MSDN, the template assembly must have a
// strong name but this is not enforced
Assembly assembly = Assembly.LoadFrom (templateFile);
// inherit signing related settings from template, but do not
// override command-line options
object [] attrs = assembly.GetCustomAttributes (true);
foreach (object o in attrs) {
if (o is AssemblyKeyFileAttribute) {
if (keyfile != null)
// ignore if specified on command line
continue;
AssemblyKeyFileAttribute keyFileAttr = (AssemblyKeyFileAttribute) o;
// ignore null or zero-length keyfile
if (keyFileAttr.KeyFile == null || keyFileAttr.KeyFile.Length == 0)
continue;
keyfile = Path.Combine (Path.GetDirectoryName(templateFile),
keyFileAttr.KeyFile);
} else if (o is AssemblyDelaySignAttribute) {
if (delaysign != DelaySign.NotSet)
// ignore if specified on command line
continue;
AssemblyDelaySignAttribute delaySignAttr = (AssemblyDelaySignAttribute) o;
delaysign = delaySignAttr.DelaySign ? DelaySign.Yes :
DelaySign.No;
} else if (o is AssemblyKeyNameAttribute) {
if (keyname != null)
// ignore if specified on command line
continue;
AssemblyKeyNameAttribute keynameAttr = (AssemblyKeyNameAttribute) o;
// ignore null or zero-length keyname
if (keynameAttr.KeyName == null || keynameAttr.KeyName.Length == 0)
continue;
keyname = keynameAttr.KeyName;
}
}
aname.Version = assembly.GetName().Version;
aname.HashAlgorithm = assembly.GetName().HashAlgorithm;
}
if (isTemplateFile)
aname = ReadCustomAttributesFromTemplateFile (templateFile, aname);
SetKeyPair (aname);
@ -765,6 +729,85 @@ namespace Mono.AssemblyLinker
}
}
private AssemblyName ReadCustomAttributesFromTemplateFile (string templateFile, AssemblyName aname)
{
// LAMESPEC: according to MSDN, the template assembly must have a
// strong name but this is not enforced
const IKR.UniverseOptions options = IKR.UniverseOptions.MetadataOnly;
var universe = new IKR.Universe (options);
var asm = universe.LoadFile (templateFile);
// Create missing assemblies, we don't want to load them!
// Code taken from ikdasm
var names = new HashSet<string> ();
IKR.AssemblyName[] assembly_refs = asm.ManifestModule.__GetReferencedAssemblies ();
var resolved_assemblies = new IKR.Assembly [assembly_refs.Length];
for (int i = 0; i < resolved_assemblies.Length; i++) {
string name = assembly_refs [i].Name;
while (names.Contains (name)) {
name = name + "_" + i;
}
names.Add (name);
resolved_assemblies [i] = universe.CreateMissingAssembly (assembly_refs [i].FullName);
}
asm.ManifestModule.__ResolveReferencedAssemblies (resolved_assemblies);
foreach (var attr_data in asm.__GetCustomAttributes (null, false)) {
string asm_name = attr_data.AttributeType.Assembly.GetName ().Name;
if (asm_name != "mscorlib")
continue;
switch (attr_data.AttributeType.FullName) {
case "System.Reflection.AssemblyKeyFileAttribute": {
if (keyfile != null)
// ignore if specified on command line
continue;
// / AssemblyKeyFileAttribute .ctor(string keyFile)
string key_file_value = (string) attr_data.ConstructorArguments [0].Value;
if (!String.IsNullOrEmpty (key_file_value))
keyfile = Path.Combine (Path.GetDirectoryName (templateFile), key_file_value);
}
break;
case "System.Reflection.AssemblyDelaySignAttribute": {
if (delaysign != DelaySign.NotSet)
// ignore if specified on command line
continue;
// AssemblyDelaySignAttribute .ctor(bool delaySign)
bool delay_sign_value = (bool) attr_data.ConstructorArguments [0].Value;
delaysign = delay_sign_value ? DelaySign.Yes : DelaySign.No;
}
break;
case "System.Reflection.AssemblyKeyNameAttribute": {
if (keyname != null)
// ignore if specified on command line
continue;
// AssemblyKeyNameAttribute .ctor(string keyName)
string key_name_value = (string) attr_data.ConstructorArguments [0].Value;
// ignore null or zero-length keyname
if (!String.IsNullOrEmpty (key_name_value))
keyname = key_name_value;
}
break;
}
}
var asm_name_for_template_file = asm.GetName ();
aname.Version = asm_name_for_template_file.Version;
aname.HashAlgorithm = asm_name_for_template_file.HashAlgorithm;
return aname;
}
private void LoadArgs (string file, ArrayList args) {
StreamReader f = null;
string line;

View File

@ -2,7 +2,7 @@ thisdir = tools/al
SUBDIRS =
include ../../build/rules.make
LOCAL_MCS_FLAGS = -r:Mono.Security.dll
LOCAL_MCS_FLAGS = -r:Mono.Security.dll -r:System.Security.dll -r:Mono.CompilerServices.SymbolWriter
PROGRAM = al.exe
CLEAN_FILES = al.exe al.exe.mdb

View File

@ -1,2 +1,9 @@
Al.cs
../../build/common/Consts.cs
../../../external/ikvm/reflect/*.cs
../../../external/ikvm/reflect/Emit/*.cs
../../../external/ikvm/reflect/Metadata/*.cs
../../../external/ikvm/reflect/Reader/*.cs
../../../external/ikvm/reflect/Writer/*.cs
../../../external/ikvm/reflect/Impl/*.cs
../../../external/ikvm/reflect/Properties/*.cs

View File

@ -596,6 +596,7 @@ namespace Mono.Terminal {
if (completions.Length == 1){
InsertTextAtCursor (completions [0]);
HideCompletions ();
} else {
int last = -1;

View File

@ -404,7 +404,7 @@ namespace Mono {
static void EscapeString (TextWriter output, string s)
{
foreach (var c in s){
if (c > 32){
if (c >= 32){
output.Write (c);
continue;
}
@ -416,7 +416,7 @@ namespace Mono {
case '\b':
output.Write ("\\b"); break;
case '\n':
output.Write ("\\n");
output.Write ("\n");
break;
case '\v':
@ -448,7 +448,7 @@ namespace Mono {
output.Write ("'\\''");
return;
}
if (c > 32){
if (c >= 32){
output.Write ("'{0}'", c);
return;
}
@ -482,7 +482,7 @@ namespace Mono {
break;
default:
output.Write ("'\\x{0:x}", (int) c);
output.Write ("'\\x{0:x}'", (int) c);
break;
}
}

View File

@ -510,8 +510,8 @@ namespace Mono.XBuild.CommandLine {
if (solutionTarget.Configuration == targetInfo.Key.Configuration &&
solutionTarget.Platform == targetInfo.Key.Platform) {
solutionConfigurationContents.AppendFormat (
"<ProjectConfiguration Project=\"{0}\">{1}|{2}</ProjectConfiguration>",
guid.ToString ("B").ToUpper (), targetInfo.Value.Configuration, targetInfo.Value.Platform);
"<ProjectConfiguration Project=\"{0}\" AbsolutePath=\"{1}\">{2}|{3}</ProjectConfiguration>",
guid.ToString ("B").ToUpper (), projectInfo.FileName, targetInfo.Value.Configuration, targetInfo.Value.Platform);
}
}
}

View File

@ -49,10 +49,12 @@
#include <mach-o/dyld.h>
#endif
/* AssemblyVersionMap: an assembly name and the assembly version set on which it is based */
/* AssemblyVersionMap: an assembly name, the assembly version set on which it is based, the assembly name it is replaced with and whether only versions lower than the current runtime version should be remapped */
typedef struct {
const char* assembly_name;
guint8 version_set_index;
const char* new_assembly_name;
gboolean only_lower_versions;
} AssemblyVersionMap;
/* the default search path is empty, the first slot is replaced with the computed value */
@ -88,8 +90,12 @@ static const AssemblyVersionMap framework_assemblies [] = {
{"I18N.Other", 0},
{"I18N.Rare", 0},
{"I18N.West", 0},
{"Microsoft.Build.Engine", 2},
{"Microsoft.Build.Framework", 2},
{"Microsoft.Build.Engine", 2, NULL, TRUE},
{"Microsoft.Build.Framework", 2, NULL, TRUE},
{"Microsoft.Build.Tasks", 2, "Microsoft.Build.Tasks.v4.0"},
{"Microsoft.Build.Tasks.v3.5", 2, "Microsoft.Build.Tasks.v4.0"},
{"Microsoft.Build.Utilities", 2, "Microsoft.Build.Utilities.v4.0"},
{"Microsoft.Build.Utilities.v3.5", 2, "Microsoft.Build.Utilities.v4.0"},
{"Microsoft.VisualBasic", 1},
{"Microsoft.VisualC", 1},
{"Mono.Cairo", 0},
@ -1013,6 +1019,9 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
aname->build == vset->build && aname->revision == vset->revision)
return aname;
if (framework_assemblies[pos].only_lower_versions && compare_versions ((AssemblyVersionSet*)vset, aname) < 0)
return aname;
if ((aname->major | aname->minor | aname->build | aname->revision) != 0)
mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
"The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d",
@ -1026,6 +1035,13 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
dest_aname->minor = vset->minor;
dest_aname->build = vset->build;
dest_aname->revision = vset->revision;
if (framework_assemblies[pos].new_assembly_name != NULL) {
dest_aname->name = framework_assemblies[pos].new_assembly_name;
mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
"The assembly name %s was remapped to %s",
aname->name,
dest_aname->name);
}
return dest_aname;
} else if (res < 0) {
last = pos - 1;
@ -2546,8 +2562,9 @@ mono_assembly_load_publisher_policy (MonoAssemblyName *aname)
if (strstr (aname->name, ".dll")) {
len = strlen (aname->name) - 4;
name = (gchar *)g_malloc (len);
name = (gchar *)g_malloc (len + 1);
strncpy (name, aname->name, len);
name[len] = 0;
} else
name = g_strdup (aname->name);
@ -2857,8 +2874,9 @@ mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImag
if (strstr (aname->name, ".dll")) {
len = strlen (filename) - 4;
name = (gchar *)g_malloc (len);
name = (gchar *)g_malloc (len + 1);
strncpy (name, aname->name, len);
name[len] = 0;
} else {
name = g_strdup (aname->name);
}

View File

@ -517,7 +517,6 @@ struct _MonoMethodInflated {
MonoMethod method;
MonoMethodPInvoke pinvoke;
} method;
MonoMethodHeader *header;
MonoMethod *declaring; /* the generic method definition. */
MonoGenericContext context; /* The current instantiation */
MonoImageSet *owner; /* The image set that the inflated method belongs to. */

View File

@ -935,8 +935,8 @@ mono_cleanup (void)
mono_loader_cleanup ();
mono_classes_cleanup ();
mono_assemblies_cleanup ();
mono_images_cleanup ();
mono_debug_cleanup ();
mono_images_cleanup ();
mono_metadata_cleanup ();
mono_native_tls_free (appdomain_thread_id);

View File

@ -1 +1 @@
e48934f8d82dd4794e2fc56288e9dd994bc370a8
6f8827dfb84f99f9c320aaf3b0ab5c9ac82e720e

View File

@ -509,9 +509,19 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
i = ((MonoImageLoader*)image->loader)->load_tables (image);
g_assert (image->heap_guid.data);
g_assert (image->heap_guid.size >= 16);
image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
if (!image->metadata_only) {
g_assert (image->heap_guid.size >= 16);
image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
} else {
/* PPDB files have no guid */
guint8 empty_guid [16];
memset (empty_guid, 0, sizeof (empty_guid));
image->guid = mono_guid_to_string (empty_guid);
}
return i;
}

View File

@ -873,21 +873,25 @@ mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *co
static MonoMethodHeader*
inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
{
MonoMethodHeader *res;
int i;
res = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals);
size_t locals_size = sizeof (gpointer) * header->num_locals;
size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause);
size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size;
MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size);
res->num_locals = header->num_locals;
res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ;
memcpy (res->clauses, header->clauses, clauses_size);
res->code = header->code;
res->code_size = header->code_size;
res->max_stack = header->max_stack;
res->num_clauses = header->num_clauses;
res->init_locals = header->init_locals;
res->num_locals = header->num_locals;
res->clauses = header->clauses;
for (i = 0; i < header->num_locals; ++i)
res->is_transient = TRUE;
for (int i = 0; i < header->num_locals; ++i)
res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
if (res->num_clauses) {
res->clauses = (MonoExceptionClause *)g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses);
for (i = 0; i < header->num_clauses; ++i) {
for (int i = 0; i < header->num_clauses; ++i) {
MonoExceptionClause *clause = &res->clauses [i];
if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE)
continue;
@ -2821,20 +2825,7 @@ mono_method_get_header (MonoMethod *method)
iheader = inflate_generic_header (header, mono_method_get_context (method));
mono_metadata_free_mh (header);
mono_image_lock (img);
if (imethod->header) {
mono_metadata_free_mh (iheader);
mono_image_unlock (img);
return imethod->header;
}
mono_memory_barrier ();
imethod->header = iheader;
mono_image_unlock (img);
return imethod->header;
return iheader;
}
if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {

View File

@ -1 +1 @@
e50ad0288c968135460f054b7e73e34f5406f363
a4ff3a17390cd25aa67e4084019cd0777669b06d

View File

@ -239,6 +239,8 @@ bb_split (MonoSimpleBasicBlock *first, MonoSimpleBasicBlock *hint, MonoSimpleBas
{
MonoSimpleBasicBlock *res, *bb = first;
mono_error_init (error);
if (bb_idx_is_contained (hint, target)) {
first = hint;
} else if (hint->next && bb_idx_is_contained (hint->next, target)) {
@ -335,6 +337,8 @@ bb_formation_il_pass (const unsigned char *start, const unsigned char *end, Mono
MonoSimpleBasicBlock *branch, *next, *current;
const MonoOpcode *opcode;
mono_error_init (error);
current = bb;
while (ip < end) {
@ -463,6 +467,9 @@ bb_formation_eh_pass (MonoMethodHeader *header, MonoSimpleBasicBlock *bb, MonoSi
{
int i;
int end = header->code_size;
mono_error_init (error);
/*We must split at all points to verify for targets in the middle of an instruction*/
for (i = 0; i < header->num_clauses; ++i) {
MonoExceptionClause *clause = header->clauses + i;
@ -514,19 +521,13 @@ mono_basic_block_free (MonoSimpleBasicBlock *bb)
* Return the list of basic blocks of method. Return NULL on failure and set @error.
*/
MonoSimpleBasicBlock*
mono_basic_block_split (MonoMethod *method, MonoError *error)
mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header)
{
MonoSimpleBasicBlock *bb, *root;
const unsigned char *start, *end;
MonoMethodHeader *header = mono_method_get_header (method);
mono_error_init (error);
if (!header) {
mono_error_set_not_verifiable (error, method, "Could not decode header");
return NULL;
}
start = header->code;
end = start + header->code_size;
@ -551,11 +552,9 @@ mono_basic_block_split (MonoMethod *method, MonoError *error)
dump_bb_list (bb, &root, g_strdup_printf("AFTER LIVENESS %s", mono_method_full_name (method, TRUE)));
#endif
mono_metadata_free_mh (header);
return bb;
fail:
mono_metadata_free_mh (header);
mono_basic_block_free (bb);
return NULL;
}

View File

@ -19,7 +19,7 @@ struct _MonoSimpleBasicBlock {
};
MonoSimpleBasicBlock*
mono_basic_block_split (MonoMethod *method, MonoError *error);
mono_basic_block_split (MonoMethod *method, MonoError *error, MonoMethodHeader *header);
void
mono_basic_block_free (MonoSimpleBasicBlock *bb);

View File

@ -285,8 +285,8 @@ dllmap_start (gpointer user_data,
char *result;
result = (char *)g_malloc (libdir_len-strlen("$mono_libdir")+strlen(attribute_values[i])+1);
strncpy (result, attribute_names[i], p-attribute_values[i]);
strcat (result, libdir);
strncpy (result, attribute_values[i], p-attribute_values[i]);
strcpy (result+(p-attribute_values[i]), libdir);
strcat (result, p+strlen("$mono_libdir"));
info->target = result;
} else

View File

@ -867,7 +867,7 @@ gint64 ves_icall_System_Diagnostics_Process_StartTime_internal (HANDLE process)
gint32 ves_icall_System_Diagnostics_Process_ExitCode_internal (HANDLE process)
{
DWORD code;
DWORD code = 0;
GetExitCodeProcess (process, &code);

View File

@ -8,6 +8,9 @@
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-error.h>
MonoType*
mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, mono_bool ignorecase, mono_bool *type_resolve);
MonoObject*
mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error);

View File

@ -1 +1 @@
9765c61de2ebb89a23549f49a6cafb7c0c0ca36d
258308a0a883826613bae9322e5a1463ac1a5a2c

View File

@ -522,7 +522,7 @@ worker_park (void)
if (interrupted)
goto done;
if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next ((void **)rand_handle, 5 * 1000, 60 * 1000)) != 0)
if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next (&rand_handle, 5 * 1000, 60 * 1000)) != 0)
timeout = TRUE;
mono_thread_info_uninstall_interrupt (&interrupted);

View File

@ -1 +1 @@
e9af9516a1b4652f3e43ca9b3dd254addad43a0f
711107ac5200b078d25785ce5854a2ab4ef20e5e

View File

@ -801,7 +801,7 @@ EXTRA_DIST = TestDriver.cs \
Makefile.am.in
version.h: Makefile
echo "#define FULL_VERSION \"Stable 4.4.0.40/f8474c4\"" > version.h
echo "#define FULL_VERSION \"Stable 4.4.0.122/a3fabf1\"" > version.h
# Utility target for patching libtool to speed up linking
patch-libtool:

View File

@ -801,7 +801,7 @@ EXTRA_DIST = TestDriver.cs \
Makefile.am.in
version.h: Makefile
echo "#define FULL_VERSION \"Stable 4.4.0.40/f8474c4\"" > version.h
echo "#define FULL_VERSION \"Stable 4.4.0.122/a3fabf1\"" > version.h
# Utility target for patching libtool to speed up linking
patch-libtool:

View File

@ -1 +1 @@
feaddf3ea0bb6cd34b061a30d89031f0d11d66ec
c30141f67c9a2e03366c40284ff6f85c7ec12f08

View File

@ -1 +1 @@
26979427a0ebbb4e979939dad6a0e766cc2b6917
c40ca98ce5a35a78b5c13a82796c7d90c988d66e

View File

@ -1 +1 @@
26d4d91456e706536c43cb083afe6adde5d651e0
1c829de55ab1a77e98f4eee2f2db9532481d0839

View File

@ -1 +1 @@
a8e6b3920eb370ed43e229f6f4ce9d1317dffe39
02c5187dfa1b7625b82adf66c91c0f619f144302

View File

@ -1176,6 +1176,8 @@ mini_usage_jitdeveloper (void)
" --agent=ASSEMBLY[:ARG] Loads the specific agent assembly and executes its Main method with the given argument before loading the main assembly.\n"
" --no-x86-stack-align Don't align stack on x86\n"
"\n"
"The options supported by MONO_DEBUG can also be passed on the command line.\n"
"\n"
"Other options:\n"
" --graph[=TYPE] METHOD Draws a graph of the specified method:\n");
@ -1425,6 +1427,7 @@ mono_jit_parse_options (int argc, char * argv[])
#else
mono_use_llvm = TRUE;
#endif
} else if (argv [i][0] == '-' && argv [i][1] == '-' && mini_parse_debug_option (argv [i] + 2)) {
} else {
fprintf (stderr, "Unsupported command line option: '%s'\n", argv [i]);
exit (1);
@ -1897,6 +1900,7 @@ mono_main (int argc, char* argv[])
} else if (strcmp (argv [i], "--nacl-null-checks-off") == 0){
nacl_null_checks_off = TRUE;
#endif
} else if (argv [i][0] == '-' && argv [i][1] == '-' && mini_parse_debug_option (argv [i] + 2)) {
} else {
fprintf (stderr, "Unknown command line option: '%s'\n", argv [i]);
return 1;

View File

@ -165,12 +165,13 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_
}
void
mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
{
guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
/* Clear thumb bit */
pc &= ~1;
mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
}
void
@ -245,9 +246,15 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
/* exc is already in place in r0 */
if (corlib) {
/* The caller ip is already in R1 */
if (llvm)
/* Negate the ip adjustment done in mono_arm_throw_exception */
ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
if (llvm) {
/*
* The address passed by llvm might point to before the call,
* thus outside the eh range recorded by llvm. Use the return
* address instead.
* FIXME: Do this on more platforms.
*/
ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
}
} else {
ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
}

View File

@ -1695,6 +1695,23 @@ public class Tests
return 0;
}
interface ISmallArg {
T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
string s9, string s10, string s11, string s12, string s13, T t);
}
class SmallArgClass : ISmallArg {
public T foo<T> (string s1, string s2, string s3, string s4, string s5, string s6, string s7, string s8,
string s9, string s10, string s11, string s12, string s13, T t) {
return t;
}
}
public static int test_1_small_gsharedvt_stack_arg_ios () {
ISmallArg o = new SmallArgClass ();
return o.foo<int> ("", "", "", "", "", "", "", "", "", "", "", "", "", 1);
}
// Passing vtype normal arguments on the stack
public static int test_0_arm64_vtype_stack_args () {
IFoo3<EmptyStruct> o = (IFoo3<EmptyStruct>)Activator.CreateInstance (typeof (Foo3<>).MakeGenericType (new Type [] { typeof (EmptyStruct) }));

View File

@ -1686,6 +1686,9 @@ bin_writer_emit_writeout (MonoImageWriter *acfg)
static void
asm_writer_emit_start (MonoImageWriter *acfg)
{
#if defined(TARGET_ASM_APPLE)
fprintf (acfg->fp, ".subsections_via_symbols\n");
#endif
}
static int

View File

@ -1 +1 @@
1dcf73164eccdc0c7389a06bee320745cebfb29d
56f60c91e1860a8b1b0a68b5453db395488f781c

View File

@ -1 +1 @@
9560b157d9f99e89f4b495f3e0c5995a3b7d44ca
5a157904b92a0c6d2f071e57cdd8ec33eea80842

Some files were not shown because too many files have changed in this diff Show More