namespace Mono.Security.Protocol.Tls
{
- public class SslServerStream : SslStreamBase
+#if INSIDE_SYSTEM
+ internal
+#else
+ public
+#endif
+ class SslServerStream : SslStreamBase
{
#region Internal Events
#endregion
+ public event CertificateValidationCallback2 ClientCertValidation2;
#region Constructors
public SslServerStream(
{
}
+ public SslServerStream(
+ Stream stream,
+ X509Certificate serverCertificate,
+ bool clientCertificateRequired,
+ bool requestClientCertificate,
+ bool ownsStream)
+ : this (stream, serverCertificate, clientCertificateRequired, requestClientCertificate, ownsStream, SecurityProtocolType.Default)
+ {
+ }
+
public SslServerStream(
Stream stream,
X509Certificate serverCertificate,
bool clientCertificateRequired,
bool ownsStream,
SecurityProtocolType securityProtocolType)
+ : this (stream, serverCertificate, clientCertificateRequired, false, ownsStream, securityProtocolType)
+ {
+ }
+
+ public SslServerStream(
+ Stream stream,
+ X509Certificate serverCertificate,
+ bool clientCertificateRequired,
+ bool requestClientCertificate,
+ bool ownsStream,
+ SecurityProtocolType securityProtocolType)
: base(stream, ownsStream)
{
this.context = new ServerContext(
this,
securityProtocolType,
serverCertificate,
- clientCertificateRequired);
+ clientCertificateRequired,
+ requestClientCertificate);
this.protocol = new ServerRecordProtocol(innerStream, (ServerContext)this.context);
}
Fig. 1 - Message flow for a full handshake
*/
- internal override IAsyncResult OnBeginNegotiateHandshake(AsyncCallback callback, object state)
+ internal override IAsyncResult BeginNegotiateHandshake(AsyncCallback callback, object state)
{
// Reset the context if needed
if (this.context.HandshakeState != HandshakeState.None)
}
- internal override void OnNegotiateHandshakeCallback(IAsyncResult asyncResult)
+ internal override void EndNegotiateHandshake(IAsyncResult asyncResult)
{
// Receive Client Hello message and ignore it
this.protocol.EndReceiveRecord(asyncResult);
this.protocol.SendRecord(HandshakeType.ServerKeyExchange);
}
- bool certRequested = false;
-
// If the negotiated cipher is a KeyEx cipher or
// the client certificate is required send the CertificateRequest message
if (this.context.Negotiating.Cipher.IsExportable ||
- ((ServerContext)this.context).ClientCertificateRequired)
+ ((ServerContext)this.context).ClientCertificateRequired ||
+ ((ServerContext)this.context).RequestClientCertificate)
{
this.protocol.SendRecord(HandshakeType.CertificateRequest);
- certRequested = true;
}
// Send ServerHelloDone message
}
}
- if (certRequested && (this.context.ClientSettings.ClientCertificate == null))
- {
- // we asked for a certificate but didn't receive one
- // e.g. wget for SSL3
- if (!RaiseClientCertificateValidation(null, new int[0]))
- {
- throw new TlsException(
- AlertDescription.BadCertificate,
- "No certificate received from client.");
- }
- }
-
// Send ChangeCipherSpec and ServerFinished messages
this.protocol.SendChangeCipherSpec();
this.protocol.SendRecord (HandshakeType.Finished);
return (errors != null && errors.Length == 0);
}
+ internal override bool HaveRemoteValidation2Callback {
+ get { return ClientCertValidation2 != null; }
+ }
+
+ internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
+ {
+ CertificateValidationCallback2 cb = ClientCertValidation2;
+ if (cb != null)
+ return cb (collection);
+ return null;
+ }
+
internal bool RaiseClientCertificateValidation(
X509Certificate certificate,
int[] certificateErrors)