Imported Upstream version 3.12.1

Former-commit-id: ce565ca85f5d5abe367a12026a5712944dbf6319
This commit is contained in:
Jo Shields
2015-03-06 18:47:20 +00:00
parent 181b81b4a4
commit 283343f570
73 changed files with 244 additions and 13424 deletions

View File

@ -116,14 +116,14 @@ namespace Mono.Security.Protocol.Tls
scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, true, 8, 8, 56, 8, 8);
// Supported exportable ciphers
scs.Add((0x00 << 0x08) | 0x03, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 5, 16, 40, 0, 0);
scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 16, 40, 8, 8);
scs.Add((0x00 << 0x08) | 0x08, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 8, 40, 8, 8);
scs.Add((0x00 << 0x08) | 0x60, "TLS_RSA_EXPORT_WITH_RC4_56_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
scs.Add((0x00 << 0x08) | 0x61, "TLS_RSA_EXPORT_WITH_RC2_CBC_56_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 7, 16, 56, 8, 8);
// scs.Add((0x00 << 0x08) | 0x03, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 5, 16, 40, 0, 0);
// scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 16, 40, 8, 8);
// scs.Add((0x00 << 0x08) | 0x08, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 8, 40, 8, 8);
// scs.Add((0x00 << 0x08) | 0x60, "TLS_RSA_EXPORT_WITH_RC4_56_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// scs.Add((0x00 << 0x08) | 0x61, "TLS_RSA_EXPORT_WITH_RC2_CBC_56_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 7, 16, 56, 8, 8);
// 56 bits but we use 64 bits because of parity (DES is really 56 bits)
scs.Add((0x00 << 0x08) | 0x62, "TLS_RSA_EXPORT_WITH_DES_CBC_56_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 8, 8, 64, 8, 8);
scs.Add((0x00 << 0x08) | 0x64, "TLS_RSA_EXPORT_WITH_RC4_56_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// scs.Add((0x00 << 0x08) | 0x62, "TLS_RSA_EXPORT_WITH_DES_CBC_56_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 8, 8, 64, 8, 8);
// scs.Add((0x00 << 0x08) | 0x64, "TLS_RSA_EXPORT_WITH_RC4_56_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// Default CipherSuite
// scs.Add(0, "TLS_NULL_WITH_NULL_NULL", CipherAlgorithmType.None, HashAlgorithmType.None, ExchangeAlgorithmType.None, true, false, 0, 0, 0, 0, 0);
@ -195,14 +195,14 @@ namespace Mono.Security.Protocol.Tls
scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, true, 8, 8, 56, 8, 8);
// Supported exportable ciphers
scs.Add((0x00 << 0x08) | 0x03, "SSL_RSA_EXPORT_WITH_RC4_40_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 5, 16, 40, 0, 0);
scs.Add((0x00 << 0x08) | 0x06, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 16, 40, 8, 8);
scs.Add((0x00 << 0x08) | 0x08, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 8, 40, 8, 8);
scs.Add((0x00 << 0x08) | 0x60, "SSL_RSA_EXPORT_WITH_RC4_56_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
scs.Add((0x00 << 0x08) | 0x61, "SSL_RSA_EXPORT_WITH_RC2_CBC_56_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 7, 16, 56, 8, 8);
// scs.Add((0x00 << 0x08) | 0x03, "SSL_RSA_EXPORT_WITH_RC4_40_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 5, 16, 40, 0, 0);
// scs.Add((0x00 << 0x08) | 0x06, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 16, 40, 8, 8);
// scs.Add((0x00 << 0x08) | 0x08, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 5, 8, 40, 8, 8);
// scs.Add((0x00 << 0x08) | 0x60, "SSL_RSA_EXPORT_WITH_RC4_56_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// scs.Add((0x00 << 0x08) | 0x61, "SSL_RSA_EXPORT_WITH_RC2_CBC_56_MD5", CipherAlgorithmType.Rc2, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, true, true, 7, 16, 56, 8, 8);
// 56 bits but we use 64 bits because of parity (DES is really 56 bits)
scs.Add((0x00 << 0x08) | 0x62, "SSL_RSA_EXPORT_WITH_DES_CBC_56_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 8, 8, 64, 8, 8);
scs.Add((0x00 << 0x08) | 0x64, "SSL_RSA_EXPORT_WITH_RC4_56_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// scs.Add((0x00 << 0x08) | 0x62, "SSL_RSA_EXPORT_WITH_DES_CBC_56_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, true, 8, 8, 64, 8, 8);
// scs.Add((0x00 << 0x08) | 0x64, "SSL_RSA_EXPORT_WITH_RC4_56_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, true, false, 7, 16, 56, 0, 0);
// Default CipherSuite
// scs.Add(0, "SSL_NULL_WITH_NULL_NULL", CipherAlgorithmType.None, HashAlgorithmType.None, true, false, 0, 0, 0, 0, 0);

View File

@ -129,6 +129,7 @@ namespace Mono.Security.Protocol.Tls
HandshakeType type, byte[] buffer)
{
ClientContext context = (ClientContext)this.context;
var last = context.LastHandshakeMsg;
switch (type)
{
@ -148,23 +149,37 @@ namespace Mono.Security.Protocol.Tls
return null;
case HandshakeType.ServerHello:
if (last != HandshakeType.HelloRequest)
break;
return new TlsServerHello(this.context, buffer);
// Optional
case HandshakeType.Certificate:
if (last != HandshakeType.ServerHello)
break;
return new TlsServerCertificate(this.context, buffer);
case HandshakeType.ServerKeyExchange:
return new TlsServerKeyExchange(this.context, buffer);
// Optional
case HandshakeType.CertificateRequest:
return new TlsServerCertificateRequest(this.context, buffer);
if (last == HandshakeType.ServerKeyExchange || last == HandshakeType.Certificate)
return new TlsServerCertificateRequest(this.context, buffer);
break;
case HandshakeType.ServerHelloDone:
return new TlsServerHelloDone(this.context, buffer);
if (last == HandshakeType.CertificateRequest || last == HandshakeType.Certificate || last == HandshakeType.ServerHello)
return new TlsServerHelloDone(this.context, buffer);
break;
case HandshakeType.Finished:
return new TlsServerFinished(this.context, buffer);
// depends if a full (ServerHelloDone) or an abbreviated handshake (ServerHello) is being done
bool check = context.AbbreviatedHandshake ? (last == HandshakeType.ServerHello) : (last == HandshakeType.ServerHelloDone);
// ChangeCipherSpecDone is not an handshake message (it's a content type) but still needs to be happens before finished
if (check && context.ChangeCipherSpecDone) {
context.ChangeCipherSpecDone = false;
return new TlsServerFinished (this.context, buffer);
}
break;
default:
throw new TlsException(
AlertDescription.UnexpectedMessage,
@ -172,6 +187,7 @@ namespace Mono.Security.Protocol.Tls
"Unknown server handshake message received ({0})",
type.ToString()));
}
throw new TlsException (AlertDescription.HandshakeFailiure, String.Format ("Protocol error, unexpected protocol transition from {0} to {1}", last, type));
}
#endregion

View File

@ -122,6 +122,8 @@ namespace Mono.Security.Protocol.Tls
set { this.protocolNegotiated = value; }
}
public bool ChangeCipherSpecDone { get; set; }
public SecurityProtocolType SecurityProtocol
{
get

View File

@ -88,6 +88,8 @@ namespace Mono.Security.Protocol.Tls
} else {
ctx.StartSwitchingSecurityParameters (false);
}
ctx.ChangeCipherSpecDone = true;
}
public virtual HandshakeMessage GetMessage(HandshakeType type)
@ -348,9 +350,6 @@ namespace Mono.Security.Protocol.Tls
// Try to read the Record Content Type
int type = internalResult.InitialBuffer[0];
// Set last handshake message received to None
this.context.LastHandshakeMsg = HandshakeType.ClientHello;
ContentType contentType = (ContentType)type;
byte[] buffer = this.ReadRecordBuffer(type, record);
if (buffer == null)
@ -458,9 +457,6 @@ namespace Mono.Security.Protocol.Tls
// Try to read the Record Content Type
int type = recordTypeBuffer[0];
// Set last handshake message received to None
this.context.LastHandshakeMsg = HandshakeType.ClientHello;
ContentType contentType = (ContentType)type;
byte[] buffer = this.ReadRecordBuffer(type, record);
if (buffer == null)
@ -523,87 +519,11 @@ namespace Mono.Security.Protocol.Tls
private byte[] ReadRecordBuffer (int contentType, Stream record)
{
switch (contentType)
{
case 0x80:
return this.ReadClientHelloV2(record);
default:
if (!Enum.IsDefined(typeof(ContentType), (ContentType)contentType))
{
throw new TlsException(AlertDescription.DecodeError);
}
return this.ReadStandardRecordBuffer(record);
}
}
private byte[] ReadClientHelloV2 (Stream record)
{
int msgLength = record.ReadByte ();
// process further only if the whole record is available
if (record.CanSeek && (msgLength + 1 > record.Length))
{
return null;
}
byte[] message = new byte[msgLength];
record.Read (message, 0, msgLength);
int msgType = message [0];
if (msgType != 1)
{
throw new TlsException(AlertDescription.DecodeError);
}
int protocol = (message [1] << 8 | message [2]);
int cipherSpecLength = (message [3] << 8 | message [4]);
int sessionIdLength = (message [5] << 8 | message [6]);
int challengeLength = (message [7] << 8 | message [8]);
int length = (challengeLength > 32) ? 32 : challengeLength;
// Read CipherSpecs
byte[] cipherSpecV2 = new byte[cipherSpecLength];
Buffer.BlockCopy (message, 9, cipherSpecV2, 0, cipherSpecLength);
// Read session ID
byte[] sessionId = new byte[sessionIdLength];
Buffer.BlockCopy (message, 9 + cipherSpecLength, sessionId, 0, sessionIdLength);
// Read challenge ID
byte[] challenge = new byte[challengeLength];
Buffer.BlockCopy (message, 9 + cipherSpecLength + sessionIdLength, challenge, 0, challengeLength);
if (challengeLength < 16 || cipherSpecLength == 0 || (cipherSpecLength % 3) != 0)
if (!Enum.IsDefined(typeof(ContentType), (ContentType)contentType))
{
throw new TlsException(AlertDescription.DecodeError);
}
// Updated the Session ID
if (sessionId.Length > 0)
{
this.context.SessionId = sessionId;
}
// Update the protocol version
this.Context.ChangeProtocol((short)protocol);
// Select the Cipher suite
this.ProcessCipherSpecV2Buffer(this.Context.SecurityProtocol, cipherSpecV2);
// Updated the Client Random
this.context.ClientRandom = new byte [32]; // Always 32
// 1. if challenge is bigger than 32 bytes only use the last 32 bytes
// 2. right justify (0) challenge in ClientRandom if less than 32
Buffer.BlockCopy (challenge, challenge.Length - length, this.context.ClientRandom, 32 - length, length);
// Set
this.context.LastHandshakeMsg = HandshakeType.ClientHello;
this.context.ProtocolNegotiated = true;
return message;
}
private byte[] ReadStandardRecordBuffer (Stream record)
{
byte[] header = new byte[4];
if (record.Read (header, 0, 4) != 4)
throw new TlsException ("buffer underrun");
@ -1031,96 +951,5 @@ namespace Mono.Security.Protocol.Tls
}
#endregion
#region CipherSpecV2 processing
private void ProcessCipherSpecV2Buffer (SecurityProtocolType protocol, byte[] buffer)
{
TlsStream codes = new TlsStream(buffer);
string prefix = (protocol == SecurityProtocolType.Ssl3) ? "SSL_" : "TLS_";
while (codes.Position < codes.Length)
{
byte check = codes.ReadByte();
if (check == 0)
{
// SSL/TLS cipher spec
short code = codes.ReadInt16();
int index = this.Context.SupportedCiphers.IndexOf(code);
if (index != -1)
{
this.Context.Negotiating.Cipher = this.Context.SupportedCiphers[index];
break;
}
}
else
{
byte[] tmp = new byte[2];
codes.Read(tmp, 0, tmp.Length);
int tmpCode = ((check & 0xff) << 16) | ((tmp[0] & 0xff) << 8) | (tmp[1] & 0xff);
CipherSuite cipher = this.MapV2CipherCode(prefix, tmpCode);
if (cipher != null)
{
this.Context.Negotiating.Cipher = cipher;
break;
}
}
}
if (this.Context.Negotiating == null)
{
throw new TlsException(AlertDescription.InsuficientSecurity, "Insuficient Security");
}
}
private CipherSuite MapV2CipherCode(string prefix, int code)
{
try
{
switch (code)
{
case 65664:
// TLS_RC4_128_WITH_MD5
return this.Context.SupportedCiphers[prefix + "RSA_WITH_RC4_128_MD5"];
case 131200:
// TLS_RC4_128_EXPORT40_WITH_MD5
return this.Context.SupportedCiphers[prefix + "RSA_EXPORT_WITH_RC4_40_MD5"];
case 196736:
// TLS_RC2_CBC_128_CBC_WITH_MD5
return this.Context.SupportedCiphers[prefix + "RSA_EXPORT_WITH_RC2_CBC_40_MD5"];
case 262272:
// TLS_RC2_CBC_128_CBC_EXPORT40_WITH_MD5
return this.Context.SupportedCiphers[prefix + "RSA_EXPORT_WITH_RC2_CBC_40_MD5"];
case 327808:
// TLS_IDEA_128_CBC_WITH_MD5
return null;
case 393280:
// TLS_DES_64_CBC_WITH_MD5
return null;
case 458944:
// TLS_DES_192_EDE3_CBC_WITH_MD5
return null;
default:
return null;
}
}
catch
{
return null;
}
}
#endregion
}
}

View File

@ -33,6 +33,8 @@ namespace Mono.Security.Protocol.Tls
{
internal class ServerRecordProtocol : RecordProtocol
{
TlsClientCertificate cert;
#region Constructors
public ServerRecordProtocol(
@ -93,30 +95,45 @@ namespace Mono.Security.Protocol.Tls
private HandshakeMessage createClientHandshakeMessage(
HandshakeType type, byte[] buffer)
{
var last = context.LastHandshakeMsg;
switch (type)
{
case HandshakeType.ClientHello:
return new TlsClientHello(this.context, buffer);
case HandshakeType.Certificate:
return new TlsClientCertificate(this.context, buffer);
if (last != HandshakeType.ClientHello)
break;
cert = new TlsClientCertificate(this.context, buffer);
return cert;
case HandshakeType.ClientKeyExchange:
return new TlsClientKeyExchange(this.context, buffer);
if (last == HandshakeType.ClientHello || last == HandshakeType.Certificate)
return new TlsClientKeyExchange(this.context, buffer);
break;
case HandshakeType.CertificateVerify:
return new TlsClientCertificateVerify(this.context, buffer);
if (last == HandshakeType.ClientKeyExchange && cert != null)
return new TlsClientCertificateVerify(this.context, buffer);
break;
case HandshakeType.Finished:
return new TlsClientFinished(this.context, buffer);
// Certificates are optional, but if provided, they should send a CertificateVerify
bool check = (cert == null) ? (last == HandshakeType.ClientKeyExchange) : (last == HandshakeType.CertificateVerify);
// ChangeCipherSpecDone is not an handshake message (it's a content type) but still needs to be happens before finished
if (check && context.ChangeCipherSpecDone) {
context.ChangeCipherSpecDone = false;
return new TlsClientFinished(this.context, buffer);
}
break;
default:
throw new TlsException(
AlertDescription.UnexpectedMessage,
String.Format(CultureInfo.CurrentUICulture,
"Unknown server handshake message received ({0})",
type.ToString()));
throw new TlsException(AlertDescription.UnexpectedMessage, String.Format(CultureInfo.CurrentUICulture,
"Unknown server handshake message received ({0})",
type.ToString()));
break;
}
throw new TlsException (AlertDescription.HandshakeFailiure, String.Format ("Protocol error, unexpected protocol transition from {0} to {1}", last, type));
}
private HandshakeMessage createServerHandshakeMessage(

View File

@ -190,59 +190,15 @@ namespace Mono.Security.Protocol.Tls
this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
if (!this.IsExportable)
if (this.IvSize != 0)
{
if (this.IvSize != 0)
{
this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
}
else
{
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
}
else
{
HashAlgorithm md5 = MD5.Create();
int keySize = (md5.HashSize >> 3); //in bytes not bits
byte[] temp = new byte [keySize];
// Generate final write keys
md5.TransformBlock(this.Context.ClientWriteKey, 0, this.Context.ClientWriteKey.Length, temp, 0);
md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length);
byte[] finalClientWriteKey = new byte[this.ExpandedKeyMaterialSize];
Buffer.BlockCopy(md5.Hash, 0, finalClientWriteKey, 0, this.ExpandedKeyMaterialSize);
md5.Initialize();
md5.TransformBlock(this.Context.ServerWriteKey, 0, this.Context.ServerWriteKey.Length, temp, 0);
md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length);
byte[] finalServerWriteKey = new byte[this.ExpandedKeyMaterialSize];
Buffer.BlockCopy(md5.Hash, 0, finalServerWriteKey, 0, this.ExpandedKeyMaterialSize);
this.Context.ClientWriteKey = finalClientWriteKey;
this.Context.ServerWriteKey = finalServerWriteKey;
// Generate IV keys
if (this.IvSize > 0)
{
md5.Initialize();
temp = md5.ComputeHash(this.Context.RandomCS, 0, this.Context.RandomCS.Length);
this.Context.ClientWriteIV = new byte[this.IvSize];
Buffer.BlockCopy(temp, 0, this.Context.ClientWriteIV, 0, this.IvSize);
md5.Initialize();
temp = md5.ComputeHash(this.Context.RandomSC, 0, this.Context.RandomSC.Length);
this.Context.ServerWriteIV = new byte[this.IvSize];
Buffer.BlockCopy(temp, 0, this.Context.ServerWriteIV, 0, this.IvSize);
}
else
{
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
DebugHelper.WriteLine(">>>> KeyBlock", keyBlock.ToArray());

View File

@ -588,14 +588,20 @@ namespace Mono.Security.Protocol.Tls
}
catch (TlsException ex)
{
// FIXME: should the send alert also be done asynchronously here and below?
this.protocol.SendAlert(ex.Alert);
negotiate.SetComplete (new IOException("The authentication or decryption has failed.", ex));
try {
Exception e = ex;
this.protocol.SendAlert(ex.Alert != null ? ex.Alert : new Alert (AlertDescription.InternalError));
} catch {
}
negotiate.SetComplete(new IOException("The authentication or decryption has failed.", ex));
}
catch (Exception ex)
{
this.protocol.SendAlert(AlertDescription.InternalError);
negotiate.SetComplete (new IOException("The authentication or decryption has failed.", ex));
try {
this.protocol.SendAlert(AlertDescription.InternalError);
} catch {
}
negotiate.SetComplete(new IOException("The authentication or decryption has failed.", ex));
}
}

View File

@ -233,16 +233,8 @@ namespace Mono.Security.Protocol.Tls
// Send ServerCertificate message
this.protocol.SendRecord(HandshakeType.Certificate);
// If the negotiated cipher is a KeyEx cipher send ServerKeyExchange
if (this.context.Negotiating.Cipher.IsExportable)
{
this.protocol.SendRecord(HandshakeType.ServerKeyExchange);
}
// 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 ||
// If the client certificate is required send the CertificateRequest message
if (((ServerContext)this.context).ClientCertificateRequired ||
((ServerContext)this.context).RequestClientCertificate)
{
this.protocol.SendRecord(HandshakeType.CertificateRequest);

View File

@ -123,45 +123,15 @@ namespace Mono.Security.Protocol.Tls
this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize);
if (!this.IsExportable)
if (this.IvSize != 0)
{
if (this.IvSize != 0)
{
this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
}
else
{
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize);
this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize);
}
else
{
// Generate final write keys
byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);
byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.ExpandedKeyMaterialSize);
this.Context.ClientWriteKey = finalClientWriteKey;
this.Context.ServerWriteKey = finalServerWriteKey;
if (this.IvSize > 0)
{
// Generate IV block
byte[] ivBlock = PRF(CipherSuite.EmptyArray, "IV block", this.Context.RandomCS, this.IvSize*2);
// Generate IV keys
this.Context.ClientWriteIV = new byte[this.IvSize];
Buffer.BlockCopy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length);
this.Context.ServerWriteIV = new byte[this.IvSize];
Buffer.BlockCopy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length);
}
else
{
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
this.Context.ClientWriteIV = CipherSuite.EmptyArray;
this.Context.ServerWriteIV = CipherSuite.EmptyArray;
}
DebugHelper.WriteLine(">>>> KeyBlock", keyBlock.ToArray());

View File

@ -12,6 +12,7 @@
// Copyright 2003 Ximian, Inc. (http://www.ximian.com)
// Copyright 2006, 2010 Novell, Inc. (http://www.novell.com)
// Copyright 2012 Xamarin Inc. (http://www.xamarin.com)
// Copyright 2014 Microsoft Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
@ -553,6 +554,21 @@ namespace System.Net
}
}
// From the Microsoft reference source
string MapToDefaultMethod(Uri address) {
Uri uri;
if (!address.IsAbsoluteUri && baseAddress != null) {
uri = new Uri(baseAddress, address);
} else {
uri = address;
}
if (uri.Scheme.ToLower(System.Globalization.CultureInfo.InvariantCulture) == "ftp") {
return WebRequestMethods.Ftp.UploadFile;
} else {
return "POST";
}
}
byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
{
string fileCType = Headers ["Content-Type"];
@ -565,7 +581,10 @@ namespace System.Net
fileCType = "application/octet-stream";
}
bool needs_boundary = (method != "PUT"); // only verified case so far
if (method == null)
method = MapToDefaultMethod (address);
bool needs_boundary = (method != "PUT" && method != WebRequestMethods.Ftp.UploadFile); // only verified case so far
string boundary = null;
if (needs_boundary) {
boundary = "------------" + DateTime.Now.Ticks.ToString ("x");

View File

@ -10,6 +10,7 @@
#if NET_2_0
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
@ -23,6 +24,31 @@ namespace MonoTests.System.Net
{
FtpWebRequest defaultRequest;
private string _tempDirectory;
private string _tempFile;
[SetUp]
public void SetUp ()
{
_tempDirectory = Path.Combine (Path.GetTempPath (), "MonoTests.System.Net.FileWebRequestTest");
_tempFile = Path.Combine (_tempDirectory, "FtpWebRequestTest.tmp");
if (!Directory.Exists (_tempDirectory)) {
Directory.CreateDirectory (_tempDirectory);
} else {
// ensure no files are left over from previous runs
string [] files = Directory.GetFiles (_tempDirectory, "*");
foreach (string file in files)
File.Delete (file);
}
}
[TearDown]
public void TearDown ()
{
if (Directory.Exists (_tempDirectory))
Directory.Delete (_tempDirectory, true);
}
[TestFixtureSetUp]
public void Init ()
{
@ -183,13 +209,15 @@ namespace MonoTests.System.Net
ftp.KeepAlive = false;
ftp.Timeout = 5000;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
ftp.ContentLength = 1;
ftp.ContentLength = 10;
ftp.UseBinary = true;
Stream stream = ftp.GetRequestStream ();
stream.WriteByte (0);
for (int i = 0; i < 10; i++)
stream.WriteByte ((byte)i);
stream.Close ();
FtpWebResponse response = (FtpWebResponse) ftp.GetResponse ();
Assert.IsTrue ((int) response.StatusCode >= 200 && (int) response.StatusCode < 300, "UP#01");
Assert.AreEqual (10, sp.result.Count, "UP#02");
response.Close ();
} catch (Exception) {
if (!String.IsNullOrEmpty (sp.Where))
@ -200,6 +228,24 @@ namespace MonoTests.System.Net
}
}
[Test]
public void UploadFile_WebClient ()
{
ServerPut sp = new ServerPut ();
File.WriteAllText (_tempFile, "0123456789");
sp.Start ();
using (WebClient m_WebClient = new WebClient())
{
string uri = String.Format ("ftp://{0}:{1}/uploads/file.txt", sp.IPAddress, sp.Port);
m_WebClient.UploadFile(uri, _tempFile);
}
Assert.AreEqual (10, sp.result.Count, "WebClient/Ftp#01");
sp.Stop ();
}
[Test]
public void DownloadFile1 ()
{
@ -464,6 +510,8 @@ namespace MonoTests.System.Net
}
class ServerPut : FtpServer {
public List<byte> result = new List<byte> ();
protected override void Run ()
{
Socket client = control.Accept ();
@ -511,8 +559,12 @@ namespace MonoTests.System.Net
writer.Flush ();
Socket data_cnc = data.Accept ();
byte [] dontcare = new byte [1];
data_cnc.Receive (dontcare, 1, SocketFlags.None);
var datastr = new NetworkStream (data_cnc, false);
int ch;
while ((ch = datastr.ReadByte ()) != -1){
result.Add ((byte)ch);
}
data_cnc.Close ();
writer.WriteLine ("226 File received Ok");
writer.Flush ();

View File

@ -1 +1 @@
9ba190dcc3688e2a5c13d7497222758bd633e940
bb677a1b285adc8f63d91bb2490e7a11bd6d78ec

View File

@ -1 +1 @@
e4a2800a0dcd404b2c1b5b83674c10e1fbbfc422
46fe7a67471e0c277afe9e9843b2cd6fa7223d9e

View File

@ -1 +1 @@
8d3febc3bcc1a68179e2254527f999c81709567e
aab470c977a75d50f8af904c5b6301c59dcaa9d9

View File

@ -1 +1 @@
de746eb848148a6d8d547c4fe4957549830f4100
f80a3e921d07f9ca6ddfd6a6c76778b94052f139

View File

@ -1 +1 @@
388c79223d2c9dfd31370959baa8e0732bf2c782
02cad6d9661f4105e52673659d24ddc3bf57c868

View File

@ -1 +1 @@
954b224e92c0ca40db3ed841324c99ac14419a15
6859fa37972a78123015546fb7abd102201ab436

View File

@ -1 +1 @@
7eb420e04eb9641a8be30dbe4ad33d7591466e00
d32723643e0a5a8ae25fa35ac6c829036082b6be

View File

@ -1 +1 @@
289dd62af9a9073a05a3d659b08b4bdb0fe1db4a
f51ac490d60278d0e9f1a5258727bfd7492007ec