Fix for pull request #85

This commit is contained in:
sta
2014-10-30 19:09:12 +09:00
parent 956f16a162
commit 912b1f0d62
11 changed files with 419 additions and 263 deletions

View File

@@ -5,6 +5,7 @@
* The MIT License
*
* Copyright (c) 2014 liryna
* Copyright (c) 2014 sta.blockhead
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +30,7 @@
#region Authors
/*
* Authors:
* - Liryna liryna.stark@gmail.com
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
@@ -38,63 +39,100 @@ using System.Security.Cryptography.X509Certificates;
namespace WebSocketSharp.Net
{
/// <summary>
/// Stores the parameters used in configuring <see cref="System.Net.Security.SslStream"/>
/// as a client.
/// </summary>
public class ClientSslAuthConfiguration
{
#region Public Constructors
/// <summary>
/// Stores the parameters used in configuring <see cref="System.Net.Security.SslStream"/>
/// as a client.
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class with
/// the specified <paramref name="clientCertificates"/>.
/// </summary>
public class ClientSslAuthConfiguration
/// <param name="clientCertificates">
/// A <see cref="X509CertificateCollection"/> that contains client certificates.
/// </param>
public ClientSslAuthConfiguration (X509CertificateCollection clientCertificates)
: this (clientCertificates, SslProtocols.Default, false)
{
/// <summary>
/// Gets or sets the certificate configuration used to authenticate the clients on the secure connection.
/// </summary>
/// <value>
/// A <see cref="X509CertificateCollection"/> that represents the certificate collection used to authenticate
/// the clients.
/// </value>
public X509CertificateCollection clientCertificates { get; set; }
/// <summary>
/// Gets or sets the Ssl protocols type enabled.
/// </summary>
/// <value>
/// The <see cref="SslProtocols"/> value that represents the protocol used for authentication.
/// </value>
public SslProtocols EnabledSslProtocols { get; set; }
/// <summary>
/// Gets or sets the verification of certificate revocation option.
/// </summary>
/// <value>
/// A Boolean value that specifies whether the certificate revocation list is checked during authentication.
/// </value>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class.
/// </summary>
public ClientSslAuthConfiguration(X509CertificateCollection clientCertificates)
: this(clientCertificates, SslProtocols.Default, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class.
/// </summary>
public ClientSslAuthConfiguration(X509CertificateCollection clientCertificates,
SslProtocols enabledSslProtocols)
: this(clientCertificates, enabledSslProtocols, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class.
/// </summary>
public ClientSslAuthConfiguration(X509CertificateCollection clientCertificates,
SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
this.clientCertificates = clientCertificates;
this.EnabledSslProtocols = enabledSslProtocols;
this.CheckCertificateRevocation = checkCertificateRevocation;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class with
/// the specified <paramref name="clientCertificates"/> and
/// <paramref name="enabledSslProtocols"/>.
/// </summary>
/// <param name="clientCertificates">
/// A <see cref="X509CertificateCollection"/> that contains client certificates.
/// </param>
/// <param name="enabledSslProtocols">
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </param>
public ClientSslAuthConfiguration (
X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols)
: this (clientCertificates, enabledSslProtocols, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ClientSslAuthConfiguration"/> class with
/// the specified <paramref name="clientCertificates"/>, <paramref name="enabledSslProtocols"/>,
/// and <paramref name="checkCertificateRevocation"/>.
/// </summary>
/// <param name="clientCertificates">
/// A <see cref="X509CertificateCollection"/> that contains client certificates.
/// </param>
/// <param name="enabledSslProtocols">
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </param>
/// <param name="checkCertificateRevocation">
/// <c>true</c> if the certificate revocation list is checked during authentication;
/// otherwise, <c>false</c>.
/// </param>
public ClientSslAuthConfiguration (
X509CertificateCollection clientCertificates,
SslProtocols enabledSslProtocols,
bool checkCertificateRevocation)
{
ClientCertificates = clientCertificates;
EnabledSslProtocols = enabledSslProtocols;
CheckCertificateRevocation = checkCertificateRevocation;
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets a value indicating whether the certificate revocation list is checked
/// during authentication.
/// </summary>
/// <value>
/// <c>true</c> if the certificate revocation list is checked; otherwise, <c>false</c>.
/// </value>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Gets or sets the collection that contains client certificates.
/// </summary>
/// <value>
/// A <see cref="X509CertificateCollection"/> that contains client certificates.
/// </value>
public X509CertificateCollection ClientCertificates { get; set; }
/// <summary>
/// Gets or sets the SSL protocols used for authentication.
/// </summary>
/// <value>
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </value>
public SslProtocols EnabledSslProtocols { get; set; }
#endregion
}
}

View File

@@ -37,6 +37,13 @@
*/
#endregion
#region Contributors
/*
* Contributors:
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
@@ -54,12 +61,12 @@ namespace WebSocketSharp.Net
#region Private Fields
private List<HttpListenerPrefix> _all; // host == '+'
private ServerSslAuthConfiguration _sslAuthenticationConfig;
private static readonly string _defaultCertFolderPath;
private IPEndPoint _endpoint;
private Dictionary<HttpListenerPrefix, HttpListener> _prefixes;
private bool _secure;
private Socket _socket;
private ServerSslAuthConfiguration _sslConfig;
private List<HttpListenerPrefix> _unhandled; // host == '*'
private Dictionary<HttpConnection, HttpConnection> _unregistered;
private object _unregisteredSync;
@@ -83,14 +90,17 @@ namespace WebSocketSharp.Net
int port,
bool secure,
string certificateFolderPath,
ServerSslAuthConfiguration defaultCertificate,
ServerSslAuthConfiguration sslConfiguration,
bool reuseAddress)
{
if (secure) {
_secure = secure;
_sslAuthenticationConfig = getCertificate(port, certificateFolderPath, defaultCertificate);
if (_sslAuthenticationConfig == null)
var cert = getCertificate (port, certificateFolderPath, sslConfiguration.ServerCertificate);
if (cert == null)
throw new ArgumentException ("No server certificate could be found.");
_secure = secure;
_sslConfig = sslConfiguration;
_sslConfig.ServerCertificate = cert;
}
_prefixes = new Dictionary<HttpListenerPrefix, HttpListener> ();
@@ -116,19 +126,18 @@ namespace WebSocketSharp.Net
#region Public Properties
public ServerSslAuthConfiguration CertificateConfig
{
get {
return _sslAuthenticationConfig;
}
}
public bool IsSecure {
get {
return _secure;
}
}
public ServerSslAuthConfiguration SslConfiguration {
get {
return _sslConfig;
}
}
#endregion
#region Private Methods
@@ -174,8 +183,8 @@ namespace WebSocketSharp.Net
return rsa;
}
private static ServerSslAuthConfiguration getCertificate(
int port, string certificateFolderPath, ServerSslAuthConfiguration defaultCertificate)
private static X509Certificate2 getCertificate (
int port, string certificateFolderPath, X509Certificate2 defaultCertificate)
{
if (certificateFolderPath == null || certificateFolderPath.Length == 0)
certificateFolderPath = _defaultCertFolderPath;
@@ -187,7 +196,7 @@ namespace WebSocketSharp.Net
var cert = new X509Certificate2 (cer);
cert.PrivateKey = createRSAFromFile (key);
return new ServerSslAuthConfiguration(cert);
return cert;
}
}
catch {

View File

@@ -37,6 +37,13 @@
*/
#endregion
#region Contributors
/*
* Contributors:
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
@@ -107,7 +114,7 @@ namespace WebSocketSharp.Net
port,
secure,
httpListener.CertificateFolderPath,
httpListener.DefaultSslAuthenticationConfig,
httpListener.DefaultSslConfiguration,
httpListener.ReuseAddress);
eps[port] = epl;

View File

@@ -37,6 +37,13 @@
*/
#endregion
#region Contributors
/*
* Contributors:
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
using System;
using System.IO;
using System.Net;
@@ -87,10 +94,13 @@ namespace WebSocketSharp.Net
var netStream = new NetworkStream (socket, false);
if (_secure) {
var sslStream = new SslStream (netStream, false);
var certificateConfig = listener.CertificateConfig;
sslStream.AuthenticateAsServer(certificateConfig.ServerCertificate,
certificateConfig.ClientCertificateRequired, certificateConfig.EnabledSslProtocols,
certificateConfig.CheckCertificateRevocation);
var sslConfig = listener.SslConfiguration;
sslStream.AuthenticateAsServer (
sslConfig.ServerCertificate,
sslConfig.ClientCertificateRequired,
sslConfig.EnabledSslProtocols,
sslConfig.CheckCertificateRevocation);
_stream = sslStream;
}
else {

View File

@@ -37,6 +37,13 @@
*/
#endregion
#region Contributors
/*
* Contributors:
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
@@ -64,7 +71,7 @@ namespace WebSocketSharp.Net
private Dictionary<HttpListenerContext, HttpListenerContext> _ctxRegistry;
private object _ctxRegistrySync;
private Func<IIdentity, NetworkCredential> _credFinder;
private ServerSslAuthConfiguration _defaultSslAuthenticationConfig;
private ServerSslAuthConfiguration _defaultSslConfig;
private bool _disposed;
private bool _ignoreWriteExceptions;
private bool _listening;
@@ -213,27 +220,25 @@ namespace WebSocketSharp.Net
}
/// <summary>
/// Gets or sets the default Ssl configuration used to authenticate the server on the secure
/// connection.
/// Gets or sets the default SSL configuration used to authenticate the server and
/// optionally the client on the secure connection.
/// </summary>
/// <value>
/// A <see cref="ServerSslAuthConfiguration"/> used to authenticate the server if the certificate
/// files aren't found in the <see cref="CertificateFolderPath"/>. The default value is
/// <see langword="null"/>.
/// A <see cref="ServerSslAuthConfiguration"/> that represents the SSL configuration used to
/// authenticate the server optionally the client. The default value is <see langword="null"/>.
/// </value>
/// <exception cref="ObjectDisposedException">
/// This listener has been closed.
/// </exception>
public ServerSslAuthConfiguration DefaultSslAuthenticationConfig
{
public ServerSslAuthConfiguration DefaultSslConfiguration {
get {
CheckDisposed ();
return _defaultSslAuthenticationConfig;
return _defaultSslConfig;
}
set {
CheckDisposed ();
_defaultSslAuthenticationConfig = value;
_defaultSslConfig = value;
}
}

View File

@@ -5,6 +5,7 @@
* The MIT License
*
* Copyright (c) 2014 liryna
* Copyright (c) 2014 sta.blockhead
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +30,7 @@
#region Authors
/*
* Authors:
* - Liryna liryna.stark@gmail.com
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
@@ -38,80 +39,145 @@ using System.Security.Cryptography.X509Certificates;
namespace WebSocketSharp.Net
{
/// <summary>
/// Stores the parameters used in configuring <see cref="System.Net.Security.SslStream"/>
/// as a server.
/// </summary>
public class ServerSslAuthConfiguration
{
#region Public Constructors
/// <summary>
/// Stores the parameters used in configuring <see cref="System.Net.Security.SslStream"/>
/// as a server.
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class with
/// the specified <paramref name="serverCertificate"/>.
/// </summary>
public class ServerSslAuthConfiguration
/// <param name="serverCertificate">
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </param>
public ServerSslAuthConfiguration (X509Certificate2 serverCertificate)
: this (serverCertificate, false, SslProtocols.Default, false)
{
/// <summary>
/// Gets or sets the certificate used to authenticate the server on the secure connection.
/// </summary>
/// <value>
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </value>
public X509Certificate2 ServerCertificate { get; set; }
/// <summary>
/// Gets or sets the client certificate request option.
/// </summary>
/// <value>
/// A Boolean value that specifies whether the client must supply a certificate for authentication.
/// </value>
public bool ClientCertificateRequired { get; set; }
/// <summary>
/// Gets or sets the Ssl protocols type enabled.
/// </summary>
/// <value>
/// The <see cref="SslProtocols"/> value that represents the protocol used for authentication.
/// </value>
public SslProtocols EnabledSslProtocols { get; set; }
/// <summary>
/// Gets or sets the verification of certificate revocation option.
/// </summary>
/// <value>
/// A Boolean value that specifies whether the certificate revocation list is checked during authentication.
/// </value>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class.
/// </summary>
public ServerSslAuthConfiguration(X509Certificate2 serverCertificate)
: this(serverCertificate, false, SslProtocols.Default, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class.
/// </summary>
public ServerSslAuthConfiguration(X509Certificate2 serverCertificate, bool clientCertificateRequired)
: this(serverCertificate, clientCertificateRequired, SslProtocols.Default, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class.
/// </summary>
public ServerSslAuthConfiguration(X509Certificate2 serverCertificate, bool clientCertificateRequired,
SslProtocols enabledSslProtocols)
: this(serverCertificate, clientCertificateRequired, enabledSslProtocols, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class.
/// </summary>
public ServerSslAuthConfiguration(X509Certificate2 serverCertificate, bool clientCertificateRequired,
SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
{
this.ServerCertificate = serverCertificate;
this.ClientCertificateRequired = clientCertificateRequired;
this.EnabledSslProtocols = enabledSslProtocols;
this.CheckCertificateRevocation = checkCertificateRevocation;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class with
/// the specified <paramref name="serverCertificate"/> and
/// <paramref name="clientCertificateRequired"/>.
/// </summary>
/// <param name="serverCertificate">
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </param>
/// <param name="clientCertificateRequired">
/// <c>true</c> if the client must supply a certificate for authentication;
/// otherwise, <c>false</c>.
/// </param>
public ServerSslAuthConfiguration (
X509Certificate2 serverCertificate, bool clientCertificateRequired)
: this (serverCertificate, clientCertificateRequired, SslProtocols.Default, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class with
/// the specified <paramref name="serverCertificate"/>,
/// <paramref name="clientCertificateRequired"/>, and <paramref name="enabledSslProtocols"/>.
/// </summary>
/// <param name="serverCertificate">
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </param>
/// <param name="clientCertificateRequired">
/// <c>true</c> if the client must supply a certificate for authentication;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="enabledSslProtocols">
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </param>
public ServerSslAuthConfiguration (
X509Certificate2 serverCertificate,
bool clientCertificateRequired,
SslProtocols enabledSslProtocols)
: this (serverCertificate, clientCertificateRequired, enabledSslProtocols, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ServerSslAuthConfiguration"/> class with
/// the specified <paramref name="serverCertificate"/>,
/// <paramref name="clientCertificateRequired"/>, <paramref name="enabledSslProtocols"/>,
/// and <paramref name="checkCertificateRevocation"/>.
/// </summary>
/// <param name="serverCertificate">
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </param>
/// <param name="clientCertificateRequired">
/// <c>true</c> if the client must supply a certificate for authentication;
/// otherwise, <c>false</c>.
/// </param>
/// <param name="enabledSslProtocols">
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </param>
/// <param name="checkCertificateRevocation">
/// <c>true</c> if the certificate revocation list is checked during authentication;
/// otherwise, <c>false</c>.
/// </param>
public ServerSslAuthConfiguration (
X509Certificate2 serverCertificate,
bool clientCertificateRequired,
SslProtocols enabledSslProtocols,
bool checkCertificateRevocation)
{
ServerCertificate = serverCertificate;
ClientCertificateRequired = clientCertificateRequired;
EnabledSslProtocols = enabledSslProtocols;
CheckCertificateRevocation = checkCertificateRevocation;
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets a value indicating whether the certificate revocation list is checked
/// during authentication.
/// </summary>
/// <value>
/// <c>true</c> if the certificate revocation list is checked; otherwise, <c>false</c>.
/// </value>
public bool CheckCertificateRevocation { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the client must supply a certificate for
/// authentication.
/// </summary>
/// <value>
/// <c>true</c> if the client must supply a certificate; otherwise, <c>false</c>.
/// </value>
public bool ClientCertificateRequired { get; set; }
/// <summary>
/// Gets or sets the SSL protocols used for authentication.
/// </summary>
/// <value>
/// The <see cref="SslProtocols"/> enum value that represents the protocols used for
/// authentication.
/// </value>
public SslProtocols EnabledSslProtocols { get; set; }
/// <summary>
/// Gets or sets the certificate used to authenticate the server on the secure connection.
/// </summary>
/// <value>
/// A <see cref="X509Certificate2"/> that represents the certificate used to authenticate
/// the server.
/// </value>
public X509Certificate2 ServerCertificate { get; set; }
#endregion
}
}

View File

@@ -26,6 +26,13 @@
*/
#endregion
#region Contributors
/*
* Contributors:
* - Liryna <liryna.stark@gmail.com>
*/
#endregion
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
@@ -61,7 +68,11 @@ namespace WebSocketSharp.Net.WebSockets
#region Internal Constructors
internal TcpListenerWebSocketContext (
TcpClient tcpClient, string protocol, bool secure, ServerSslAuthConfiguration certificateConfig, Logger logger)
TcpClient tcpClient,
string protocol,
bool secure,
ServerSslAuthConfiguration sslConfiguration,
Logger logger)
{
_tcpClient = tcpClient;
_secure = secure;
@@ -69,9 +80,12 @@ namespace WebSocketSharp.Net.WebSockets
var netStream = tcpClient.GetStream ();
if (secure) {
var sslStream = new SslStream (netStream, false);
sslStream.AuthenticateAsServer(certificateConfig.ServerCertificate,
certificateConfig.ClientCertificateRequired, certificateConfig.EnabledSslProtocols,
certificateConfig.CheckCertificateRevocation);
sslStream.AuthenticateAsServer (
sslConfiguration.ServerCertificate,
sslConfiguration.ClientCertificateRequired,
sslConfiguration.EnabledSslProtocols,
sslConfiguration.CheckCertificateRevocation);
_stream = sslStream;
}
else {