/// <summary>3b) Receive a Confirm, verify the entire stack and send a Confirm
/// 4a)Receive a Confirm, verify the entire stack and all set to go</summary>
/// <param name="sa">A security association that we wish to perform the
/// specified control operation on.</param>
/// <param name="scm">The received SecurityControlMessage.</param>
/// <param name="scm_reply">A prepared reply message (with headers and such.</param>
/// <param name="return_path">Where to send the result.</param>
/// <param name="low_level_sender">We expect the return_path to not be an edge or
/// some other type of "low level" sender, so this contains the parsed out value.</param>
protected void HandleControlConfirm(SecurityAssociation sa,
SecurityControlMessage scm, SecurityControlMessage scm_reply,
ISender return_path, ISender low_level_sender)
{
ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Confirm from: " + low_level_sender);
if (sa == null)
{
throw new Exception("No valid SA!");
}
HashAlgorithm sha1 = new SHA1CryptoServiceProvider();
scm.Verify((RSACryptoServiceProvider)sa.RemoteCertificate.Value.RSA, sha1);
if (return_path == low_level_sender)
{
sa.VerifyResponse(scm.Hash);
}
else
{
sa.VerifyRequest(scm.Hash);
scm_reply.LocalCookie = scm.RemoteCookie;
scm_reply.RemoteCookie = scm.LocalCookie;
scm_reply.Hash = sa.DHEWithCertificateAndCAsInHash.Value;
scm_reply.Type = SecurityControlMessage.MessageType.Confirm;
lock (_private_key_lock) {
scm_reply.Sign(_private_key, sha1);
}
ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet);
return_path.Send(to_send);
}
if (Verify(sa))
{
sa.Enable();
}
else
{
sa.Close("Unable to verify the SA as being valid!");
}
ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Confirm from: " + low_level_sender);
}