This commit is contained in:
xinchen 2018-06-13 17:25:17 -07:00
Родитель 51eb827180
Коммит 31a5327af5
8 изменённых файлов: 1 добавлений и 979 удалений

Просмотреть файл

@ -1,6 +1,6 @@
# AMQP.Net Lite
AMQP.Net Lite is a lightweight AMQP 1.0 library for the .Net Micro Framework, .Net Compact Framework, .Net Framework, .Net Core, Windows Runtime platforms, and Mono. The library includes both a client and listener to enable peer to peer and broker based messaging.
AMQP.Net Lite is a lightweight AMQP 1.0 library for the .Net Micro Framework, .Net Framework, .Net Core, Windows Runtime platforms, and Mono. The library includes both a client and listener to enable peer to peer and broker based messaging.
[Documentation](http://azure.github.io/amqpnetlite/)
[![Build status](https://ci.appveyor.com/api/projects/status/dph11pp7doubyw7t/branch/master?svg=true)](https://ci.appveyor.com/project/xinchen10/amqpnetlite/branch/master)
@ -30,7 +30,6 @@ The following table shows what features are supported on each platform/framework
|net40 |+|+|+|+<sup>3</sup>|+|+| |+|
|net35 |+|+| | |+| | | |
|netmf   |+<sup>1</sup>|+| | | | | | |
|netcf   |+|+| | | | | | |
|uap10|+|+| |+| | | | |
|netcore451|+|+| |+| | | | |
|wpa81 |+|+| |+| | | | |

Просмотреть файл

@ -1,7 +1,6 @@
# Prerequisites
* Visual Studio 2013. [Community Edition](https://www.visualstudio.com/en-us/news/vs2013-community-vs.aspx) works.
* NETMF SDK (4.2 and 4.3) and Visual Studio project system. You can build fro [sources](https://github.com/NETMF/netmf-interpreter) or download them from the old [netmf web site](https://netmf.codeplex.com).
* Application Builder for Windows Embedded Compact 2013. To build .Net Compact Framework projects, you need to download [Application Builder for Windows Embedded Compact 2013](http://www.microsoft.com/en-us/download/details.aspx?id=38819)
* NuGet tools if you want to build the NuGet package.
# Build the projects
@ -13,7 +12,6 @@
* The solution has a test broker which can be used to run tests. It can be started by running the following command. Note that the value of the "/cert" option is the subject name or the thumbprint of the service certificate that is already installed on the machine.
`TestAmqpBroker.exe amqp://localhost:5672 amqps://localhost:5671 ws://localhost:80 /creds:guest:guest /cert:localhost`
* NETMF tests are in project Test.Amqp.NetMF42/43. It is a NETMF application that runs in the emulator or a real device. It executes all methods whose names begin with "TestMethod_".
* Test.Amqp.NetCF39 project can be run in a .Net Compact Framework environment. You can try it on a VirtualPC virtual machine created using Platform Builder also with the related SDK. If you have a real device, you need an SDK for it too.
# Start building applications
* First take a look at the example projects under the Examples directory. The examples are working code against the Azure Service Bus service or other AMQP 1.0 compliant brokers.

Просмотреть файл

@ -1,61 +0,0 @@
// ------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------
namespace Amqp
{
using System.Diagnostics;
using System.Threading;
/// <summary>
/// Provides framework specific routines.
/// </summary>
public static class Fx
{
/// <summary>
/// Asserts a condition is true.
/// </summary>
/// <param name="condition">A boolean value indicating the condition.</param>
/// <param name="message">The error message if condition is not met.</param>
[Conditional("DEBUG")]
public static void Assert(bool condition, string message)
{
Debug.Assert(condition, message);
}
/// <summary>
/// Formats a string from a format and an array of arguments.
/// </summary>
/// <param name="format">The format string.</param>
/// <param name="args">The arguments.</param>
/// <returns></returns>
public static string Format(string format, params object[] args)
{
return string.Format(format, args);
}
/// <summary>
/// Starts a new thread.
/// </summary>
/// <param name="threadStart">The thread start callback.</param>
public static void StartThread(ThreadStart threadStart)
{
ThreadPool.QueueUserWorkItem(
o => { ((ThreadStart)o)(); },
threadStart);
}
}
}

245
src/NetCF39/SRAmqp.Designer.cs сгенерированный
Просмотреть файл

@ -1,245 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Amqp {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SRAmqp {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SRAmqp() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Amqp.SRAmqp", typeof(SRAmqp).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The session channel &apos;{0}&apos; cannot be found..
/// </summary>
internal static string AmqpChannelNotFound {
get {
return ResourceManager.GetString("AmqpChannelNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot allocate more handles. The maximum number of handles is {0}..
/// </summary>
internal static string AmqpHandleExceeded {
get {
return ResourceManager.GetString("AmqpHandleExceeded", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The handle &apos;{0}&apos; is already allocated for &apos;{1}&apos;..
/// </summary>
internal static string AmqpHandleInUse
{
get
{
return ResourceManager.GetString("AmqpHandleInUse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The link handle &apos;{0}&apos; cannot be found in session &apos;{1}&apos;..
/// </summary>
internal static string AmqpHandleNotFound {
get {
return ResourceManager.GetString("AmqpHandleNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Operation &apos;{0}&apos; is not valid under state: {1}..
/// </summary>
internal static string AmqpIllegalOperationState {
get {
return ResourceManager.GetString("AmqpIllegalOperationState", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The format code &apos;{0}&apos; at frame buffer offset &apos;{1}&apos; is invalid (expected: {2})..
/// </summary>
internal static string AmqpInvalidFormatCode {
get {
return ResourceManager.GetString("AmqpInvalidFormatCode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} is not supported over AMQP..
/// </summary>
internal static string AmqpOperationNotSupported {
get {
return ResourceManager.GetString("AmqpOperationNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The operation {0} did not complete within the allocated time {1} for object {2}..
/// </summary>
internal static string AmqpTimeout {
get {
return ResourceManager.GetString("AmqpTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The descriptor {0} is unknown..
/// </summary>
internal static string AmqpUnknownDescriptor {
get {
return ResourceManager.GetString("AmqpUnknownDescriptor", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to There is no credit to accept a new delivery (id={0}) on the link..
/// </summary>
internal static string DeliveryLimitExceeded {
get {
return ResourceManager.GetString("DeliveryLimitExceeded", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The type &apos;{0}&apos; is not a valid AMQP type and cannot be encoded..
/// </summary>
internal static string EncodingTypeNotSupported {
get {
return ResourceManager.GetString("EncodingTypeNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The address is not correctly formatted..
/// </summary>
internal static string InvalidAddressFormat {
get {
return ResourceManager.GetString("InvalidAddressFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to transfer.delivery-id {0} is invalid (expect: {1}).
/// </summary>
internal static string InvalidDeliveryIdOnTransfer {
get {
return ResourceManager.GetString("InvalidDeliveryIdOnTransfer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid frame size:{0}, maximum frame size:{1}..
/// </summary>
internal static string InvalidFrameSize {
get {
return ResourceManager.GetString("InvalidFrameSize", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The map count {0} is invalid. It must be an even number..
/// </summary>
internal static string InvalidMapCount {
get {
return ResourceManager.GetString("InvalidMapCount", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The key type {0} is invalid. The map key is restricted to {1}..
/// </summary>
internal static string InvalidMapKeyType {
get {
return ResourceManager.GetString("InvalidMapKeyType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Comparison of {0} and {1} is invalid because the result is undefined..
/// </summary>
internal static string InvalidSequenceNumberComparison {
get {
return ResourceManager.GetString("InvalidSequenceNumberComparison", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The link name {0} in the received attach cannot be found..
/// </summary>
internal static string LinkNotFound {
get {
return ResourceManager.GetString("LinkNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sasl negotiation failed with code {0}..
/// </summary>
internal static string SaslNegoFailed {
get {
return ResourceManager.GetString("SaslNegoFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to There is no window to accept an incoming transfer (incoming-id={0})..
/// </summary>
internal static string WindowViolation {
get {
return ResourceManager.GetString("WindowViolation", resourceCulture);
}
}
}
}

Просмотреть файл

@ -1,413 +0,0 @@
// ------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------
using System;
using System.Globalization;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
namespace Amqp
{
/// <summary>
/// Delagate for user certificate validatin callback
/// </summary>
/// <param name="sender">Object sender (SslSocket instance)</param>
/// <param name="certificate">X509 certificate</param>
/// <param name="sslPolicyErrors">Internal validation error</param>
/// <returns>Certificate status (valid or not)</returns>
public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, SslPolicyErrors sslPolicyErrors);
class SslSocket : ITransport, IDisposable
{
#region P/Invoke constants define ...
// reference : winsock2.h in the SDK
// in/out parameter for ioctlsocket() -> WSAIoctl() in winsock
private const uint IOC_VOID = 0x20000000; // no parameters
private const uint IOC_OUT = 0x40000000; // copy out parameters
private const uint IOC_IN = 0x80000000; // copy in parameters
private const uint IOC_INOUT = (IOC_IN | IOC_OUT);
// reference : sslsock.h in the SDK
// options and option values for creating a secure socket
private const ushort SO_SECURE = 0x2001; // add security to socket
private const ushort SO_SEC_NONE = 0x2002; // security not used on socket
private const ushort SO_SEC_SSL = 0x2004; // use unified SSL/PCT for security
// SSL WSAIoctl control code tags
// NOTE : in managed code we have related Socket.IOControl() method
private const int SO_SSL_FAMILY = 0x00730000;
private const int SO_SSL_FAMILY_MASK = 0x07ff0000;
private const long _SO_SSL = ((2L << 27) | SO_SSL_FAMILY);
// base SSL WSAIoctl tags
private const int _SO_SSL_CAPABILITIES = 0x01;
private const int _SO_SSL_FLAGS = 0x02;
private const int _SO_SSL_PROTOCOLS = 0x03;
private const int _SO_SSL_CIPHERS = 0x04;
private const int _SO_SSL_CLIENT_OPTS = 0x05;
private const int _SO_SSL_SERVER_OPTS = 0x06;
private const int _SO_SSL_CLIENT_AUTH_OPTS = 0x07;
private const int _SO_SSL_VALIDATE_CERT_HOOK = 0x08;
private const int _SO_SSL_AUTH_REQUEST_HOOK = 0x09;
private const int _SO_SSL_KEY_EXCH_HOOK = 0x0a;
private const int _SO_SSL_SIGNATURE_HOOK = 0x0b;
private const int _SO_SSL_PERFORM_HANDSHAKE = 0x0d;
private const int _SO_SSL_CONNECTION_INFO = 0x0e;
private const int _SO_SSL_PEERNAME = 0x0f;
// actual SSL WSAIoctl commands
private const long SO_SSL_GET_CAPABILITIES = (IOC_OUT | _SO_SSL | _SO_SSL_CAPABILITIES);
private const long SO_SSL_SET_FLAGS = (IOC_IN | _SO_SSL | _SO_SSL_FLAGS);
private const long SO_SSL_GET_FLAGS = (IOC_OUT | _SO_SSL | _SO_SSL_FLAGS);
private const long SO_SSL_SET_PROTOCOLS = (IOC_IN | _SO_SSL | _SO_SSL_PROTOCOLS);
private const long SO_SSL_GET_PROTOCOLS = (IOC_OUT | _SO_SSL | _SO_SSL_PROTOCOLS);
private const long SO_SSL_SET_CIPHERS = (IOC_IN | _SO_SSL | _SO_SSL_CIPHERS);
private const long SO_SSL_GET_CIPHERS = (IOC_OUT | IOC_IN | _SO_SSL | _SO_SSL_CIPHERS);
private const long SO_SSL_SET_CLIENT_OPTS = (IOC_IN | _SO_SSL | _SO_SSL_CLIENT_OPTS);
private const long SO_SSL_GET_CLIENT_OPTS = (IOC_OUT | _SO_SSL | _SO_SSL_CLIENT_OPTS);
private const long SO_SSL_SET_SERVER_OPTS = (IOC_IN | _SO_SSL | _SO_SSL_SERVER_OPTS);
private const long SO_SSL_GET_SERVER_OPTS = (IOC_OUT | _SO_SSL | _SO_SSL_SERVER_OPTS);
private const long SO_SSL_SET_CLIENT_AUTH_OPTS = (IOC_IN | _SO_SSL | _SO_SSL_CLIENT_AUTH_OPTS);
private const long SO_SSL_GET_CLIENT_AUTH_OPTS = (IOC_OUT | _SO_SSL | _SO_SSL_CLIENT_AUTH_OPTS);
private const long SO_SSL_SET_VALIDATE_CERT_HOOK = (IOC_IN | _SO_SSL | _SO_SSL_VALIDATE_CERT_HOOK);
private const long SO_SSL_GET_VALIDATE_CERT_HOOK = (IOC_OUT | _SO_SSL | _SO_SSL_VALIDATE_CERT_HOOK);
private const long SO_SSL_SET_AUTH_REQUEST_HOOK = (IOC_IN | _SO_SSL | _SO_SSL_AUTH_REQUEST_HOOK);
private const long SO_SSL_GET_AUTH_REQUEST_HOOK = (IOC_OUT | _SO_SSL | _SO_SSL_AUTH_REQUEST_HOOK);
private const long SO_SSL_SET_KEY_EXCH_HOOK = (IOC_IN | _SO_SSL | _SO_SSL_KEY_EXCH_HOOK);
private const long SO_SSL_GET_KEY_EXCH_HOOK = (IOC_OUT | _SO_SSL | _SO_SSL_KEY_EXCH_HOOK);
private const long SO_SSL_SET_SIGNATURE_HOOK = (IOC_IN | _SO_SSL | _SO_SSL_SIGNATURE_HOOK);
private const long SO_SSL_GET_SIGNATURE_HOOK = (IOC_OUT | _SO_SSL | _SO_SSL_SIGNATURE_HOOK);
private const long SO_SSL_PERFORM_HANDSHAKE = ( _SO_SSL | _SO_SSL_PERFORM_HANDSHAKE);
private const long SO_SSL_GET_CONNECTION_INFO = (IOC_OUT | _SO_SSL | _SO_SSL_CONNECTION_INFO);
private const long SO_SSL_SET_PEERNAME = (IOC_OUT | _SO_SSL | _SO_SSL_PEERNAME);
// error codes to be returned by the hook functions.
private const int SSL_ERR_OKAY = 0;
private const int SSL_ERR_FAILED = 2;
private const int SSL_ERR_BAD_LEN = 3;
private const int SSL_ERR_BAD_TYPE = 4;
private const int SSL_ERR_BAD_DATA = 5;
private const int SSL_ERR_NO_CERT = 6;
private const int SSL_ERR_BAD_SIG = 7;
private const int SSL_ERR_CERT_EXPIRED = 8;
private const int SSL_ERR_CERT_REVOKED = 9;
private const int SSL_ERR_CERT_UNKNOWN = 10;
private const int SSL_ERR_SIGNATURE = 11;
// declarations for _SO_SSL_VALIDATE_CERT_HOOK
private const int SSL_CERT_X509 = 0x0001;
private const int SSL_CERT_FLAG_ISSUER_UNKNOWN = 0x0001;
#endregion
#region P/Invoke declarations ...
// sslsock.h : callback (function pointer) for validate certificate
private delegate int SSLVALIDATECERTFUNC(uint dwType, IntPtr pvArg, uint dwChainLen, IntPtr pCertChain, uint dwFlags);
// pointer to host name for certificate validation
private IntPtr ptrHost;
// pointer to hook function for certificate validation
private IntPtr ptrValidateCertHook;
#endregion
// reference to underlying socket;
private Socket socket;
// callback to user certificate validation
private RemoteCertificateValidationCallback userCertificateValidationCallback;
/// <summary>
/// Constructor
/// </summary>
/// <param name="socket">Underlying socket</param>
/// <param name="host">Remote host name</param>
/// <param name="userCertificateValidationCallback">Callback to user certificate validation</param>
public SslSocket(Socket socket, string host, RemoteCertificateValidationCallback userCertificateValidationCallback)
{
this.socket = socket;
// allocate buffer for the host name a copy string
this.ptrHost = Marshal.StringToBSTR(host);
this.userCertificateValidationCallback = userCertificateValidationCallback;
// set SSL (security) as option at socket level
// NOTE : the SocketOptionName enum doesn't contain an option for security but we can cast SO_SECURE
this.socket.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)SO_SECURE, SO_SEC_SSL);
// need to execute IOControl on socket (WSAIoctl in native) to seet the hook to validate function
// IOCTL command = SO_SSL_SET_VALIDATE_CERT_HOOK;
// IOCTL in = pointer to hook function and parameters
// IOCTL out = nothing (null);
// get a pointer to delegate for validate certificate function
this.ptrValidateCertHook = Marshal.GetFunctionPointerForDelegate(new SSLVALIDATECERTFUNC(ValidateCertificate));
// prepare buffer IOCTL in
// 4 bytes : pointer to hook function
// 4 bytes : pointer to paramaters
byte[] optionInValue = new byte[8];
// copy pointer to hook function into buffer
byte[] validateCertHookBytes = BitConverter.GetBytes(ptrValidateCertHook.ToInt32());
byte[] hostPtrBytes = BitConverter.GetBytes(ptrHost.ToInt32());
Array.Copy(validateCertHookBytes, optionInValue, validateCertHookBytes.Length);
Array.Copy(hostPtrBytes, 0, optionInValue, validateCertHookBytes.Length, hostPtrBytes.Length);
unchecked
{
// set hook to validate certificate function
this.socket.IOControl((int)SO_SSL_SET_VALIDATE_CERT_HOOK, optionInValue, null);
}
}
void ITransport.Send(ByteBuffer buffer)
{
// SSL socket on WEC aren't full duplex : send/receive operations must be exclusive
lock (this)
{
this.socket.Send(buffer.Buffer, buffer.Offset, buffer.Length, SocketFlags.None);
}
}
int ITransport.Receive(byte[] buffer, int offset, int count)
{
int read = 0;
do
{
// wait for incoming data
if (this.socket.Poll(Timeout.Infinite, SelectMode.SelectRead))
{
// SSL socket on WEC aren't full duplex : send/receive operations must be exclusive
lock (this)
{
read = this.socket.Receive(buffer, offset, count, SocketFlags.None);
}
}
} while (read == 0);
return read;
}
public void Close()
{
this.Dispose();
}
/// <summary>
/// Validate certificate method as callback to the socket
/// </summary>
/// <param name="dwType">Data type pointed to by pCertChain (SSL_CERT_X.509 if X509 certs chain)</param>
/// <param name="pvArg">Pointer to application-defined context (passed by the SSLVALIDATECERTHOOK structure)</param>
/// <param name="dwChainLen">Number of certificates pointed to by pCertChain (It will always be equal to one)</param>
/// <param name="pCertChain">Pointer to the root certificate</param>
/// <param name="dwFlags">Will contain SSL_CERT_FLAG_ISSUER_UNKNOWN if the root issuer of the certificate could not be found in the CA database</param>
/// <returns>Result</returns>
private int ValidateCertificate(uint dwType, IntPtr pvArg, uint dwChainLen, IntPtr pCertChain, uint dwFlags)
{
bool userResult = false;
X509Certificate2 certificate = null;
// execute internal certificate validation
int result = ValidateCertificateInternal(dwType, pvArg, dwChainLen, pCertChain, dwFlags, out certificate);
// execute user validation callback if available
if (this.userCertificateValidationCallback != null)
userResult = this.userCertificateValidationCallback(this, certificate, (SslPolicyErrors)result);
result = userResult ? SSL_ERR_OKAY : SSL_ERR_FAILED;
return result;
}
/// <summary>
/// Validate certificate method as callback to the socket
/// </summary>
/// <param name="dwType">Data type pointed to by pCertChain (SSL_CERT_X.509 if X509 certs chain)</param>
/// <param name="pvArg">Pointer to application-defined context (passed by the SSLVALIDATECERTHOOK structure)</param>
/// <param name="dwChainLen">Number of certificates pointed to by pCertChain (It will always be equal to one)</param>
/// <param name="pCertChain">Pointer to the root certificate</param>
/// <param name="dwFlags">Will contain SSL_CERT_FLAG_ISSUER_UNKNOWN if the root issuer of the certificate could not be found in the CA database</param>
/// <param name="certificate">X509 certificate</param>
/// <returns>Result</returns>
private int ValidateCertificateInternal(uint dwType, IntPtr pvArg, uint dwChainLen, IntPtr pCertChain, uint dwFlags, out X509Certificate2 certificate)
{
certificate = null;
// check if it is a valid X509 certificate
if (dwType != SSL_CERT_X509)
return SSL_ERR_BAD_TYPE;
// in debug mode accept self-signed certificates
#if !DEBUG
// check if issuer is unknown
if ((dwFlags & SSL_CERT_FLAG_ISSUER_UNKNOWN) != 0)
return SSL_ERR_CERT_UNKNOWN;
#endif
// sslsock.h : pCertChain is a pointer to BLOB structure
// - first 4 bytes are the certificate size
// - following bytes are the certificate itself
// read certificate size
int certSize = Marshal.ReadInt32(pCertChain);
// pointer to start of certificate data
IntPtr pCertData = Marshal.ReadIntPtr(new IntPtr(pCertChain.ToInt32() + sizeof(int)));
byte[] certData = new byte[certSize];
// read certificate data bytes
for (int i = 0; i < certSize; i++)
certData[i] = Marshal.ReadByte(pCertData, (int)i);
// create X509 certificate from raw bytes
try
{
certificate = new X509Certificate2(certData);
}
catch (ArgumentException) { return SSL_ERR_BAD_DATA; }
catch (CryptographicException) { return SSL_ERR_BAD_DATA; }
// check expiration date
if (DateTime.Now > DateTime.Parse(certificate.GetExpirationDateString(), CultureInfo.CurrentCulture))
return SSL_ERR_CERT_EXPIRED;
// check the effective date
if (DateTime.Now < DateTime.Parse(certificate.GetEffectiveDateString(), CultureInfo.CurrentCulture))
return SSL_ERR_FAILED;
// validate the certificate CN with provided host name
string host = Marshal.PtrToStringBSTR(pvArg);
if (!certificate.GetName().Contains("CN=" + host))
return SSL_ERR_FAILED;
return SSL_ERR_OKAY;
}
#region IDisposable ...
/// <summary>
/// Destructor
/// </summary>
~SslSocket()
{
// the object went out of scope and finalized is called
// call dispose ("false" param) to release unmanaged resources
// NOTE : the managed resources will anyways be released when GC
// runs the next time.
Dispose(false);
}
public void Dispose()
{
// method called from user that wants to release all resources (managed and not)
Dispose(true);
// we have already cleaned up so the finalizer is useless
// (tell the GC not to call it later)
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose object resources
/// </summary>
/// <param name="disposing">Dispose managed resources or not</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// we want explicitily clean up resources (managed)
this.ReleaseManagedResources();
}
else
{
// disposing "false" means that object went out of scope
// finalizer is called and GC will release resources on next run
}
// release unmanaged resource because they will not be released by GC
this.ReleaseUnmangedResources();
}
/// <summary>
/// Release unmanaged resources
/// </summary>
private void ReleaseUnmangedResources()
{
// free memory of remote host name
if (this.ptrHost != IntPtr.Zero)
{
Marshal.FreeBSTR(this.ptrHost);
this.ptrHost = IntPtr.Zero;
}
}
/// <summary>
/// Release managed resources
/// </summary>
private void ReleaseManagedResources()
{
// close underlying socket
if (this.socket != null)
this.socket.Close();
}
#endregion
}
/// <summary>
/// Errors related to internal validation
/// </summary>
public enum SslPolicyErrors
{
/// <summary>
/// No SSL validation error.
/// </summary>
SslErrOkay = 0,
/// <summary>
/// SSL validation failed.
/// </summary>
SslErrFailed = 2,
/// <summary>
/// The remote certificate is not an X509 certificate.
/// </summary>
SslErrBadType = 4,
/// <summary>
/// An X509 certificate cannot be created from the received data.
/// </summary>
SslErrBadData = 5,
/// <summary>
/// The certificate has expired.
/// </summary>
SslErrCertExpired = 8,
/// <summary>
/// The certificate issuer is unknown.
/// </summary>
SslErrCertUnknown = 10,
}
}

Просмотреть файл

@ -1,141 +0,0 @@
// ------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------
namespace Amqp
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
sealed class TcpTransport : ITransport
{
ITransport socketTransport;
public void Connect(Connection connection, Address address, bool noVerification)
{
var ipHostEntry = Dns.GetHostEntry(address.Host);
Exception exception = null;
TcpSocket socket = null;
// reference to SSL socket, wrapper for above TCP socket
SslSocket sslSocket = null;
foreach (var ipAddress in ipHostEntry.AddressList)
{
if (ipAddress == null)
{
continue;
}
try
{
socket = new TcpSocket();
// SSL connection requested with an SSL host
if (address.UseSsl)
{
// wrap TCP socket to SSL socket
sslSocket = new SslSocket(socket, address.Host, ValidateCertificate);
}
socket.Connect(new IPEndPoint(ipAddress, address.Port));
exception = null;
break;
}
catch (SocketException socketException)
{
if (address.UseSsl)
{
if (sslSocket != null)
{
sslSocket.Close();
sslSocket = null;
}
}
if (socket != null)
{
socket.Close();
socket = null;
}
exception = socketException;
}
}
if (exception != null)
{
throw exception;
}
if (address.UseSsl)
{
this.socketTransport = sslSocket;
}
else
{
this.socketTransport = socket;
}
}
public void Close()
{
this.socketTransport.Close();
}
public void Send(ByteBuffer buffer)
{
this.socketTransport.Send(buffer);
}
public int Receive(byte[] buffer, int offset, int count)
{
return this.socketTransport.Receive(buffer, offset, count);
}
class TcpSocket : Socket, ITransport
{
public TcpSocket()
: base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
}
void ITransport.Send(ByteBuffer buffer)
{
base.Send(buffer.Buffer, buffer.Offset, buffer.Length, SocketFlags.None);
}
int ITransport.Receive(byte[] buffer, int offset, int count)
{
return base.Receive(buffer, offset, count, SocketFlags.None);
}
void ITransport.Close()
{
base.Close();
}
}
private bool ValidateCertificate(object sender, X509Certificate certificate, SslPolicyErrors sslPolicyErrors)
{
#if DEBUG
return true;
#else
// return verification result or add your logic here to validate certificate
return (sslPolicyErrors == SslPolicyErrors.SslErrOkay);
#endif
}
}
}

Просмотреть файл

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Amqp 1.0")]
[assembly: AssemblyDescription("AMQP 1.0 .Net Library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Amqp")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c97ceedd-db9e-42eb-800a-f2cb10071b6b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{187E608C-FBF4-4517-B61F-A85AFF5BCA75}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Test.Amqp.NetCF39</RootNamespace>
<AssemblyName>Test.Amqp.NetCF39</AssemblyName>
<ProjectTypeGuids>{6AFDAB0D-95EF-424D-8A49-099ECD40B0FF};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<TargetFrameworkIdentifier>WindowsEmbeddedCompact</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v3.9</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<IntermediateOutputPath>..\..\obj\$(Configuration)\$(MSBuildProjectName)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\bin\$(Configuration)\$(MSBuildProjectName)\</OutputPath>
<DefineConstants>TRACE;DEBUG;COMPACT_FRAMEWORK</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\$(Configuration)\$(MSBuildProjectName)\</OutputPath>
<DefineConstants>TRACE;COMPACT_FRAMEWORK</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Common\Assert.cs">
<Link>Assert.cs</Link>
</Compile>
<Compile Include="..\Common\LinkTests.cs">
<Link>LinkTests.cs</Link>
</Compile>
<Compile Include="..\Common\TestRunner.cs">
<Link>TestRunner.cs</Link>
</Compile>
<Compile Include="..\Common\TestTarget.cs">
<Link>TestTarget.cs</Link>
</Compile>
<Compile Include="..\Common\UtilityTests.cs">
<Link>UtilityTests.cs</Link>
</Compile>
<Compile Include="..\Test.Amqp.NetMF\Program.cs">
<Link>Program.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Amqp.NetCF39.csproj">
<Project>{994D25B3-A2C4-4A27-A0E8-3203E954BF58}</Project>
<Name>Amqp.NetCF39</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\v8.0\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>