protected bool GetSecureSender(Connection con, out SecurityAssociation sa) { sa = _so.CreateSecurityAssociation(con.State.Edge); bool ready = false; lock (_address_to_sender) { if (!_registered.ContainsKey(sa)) { _registered[sa] = true; sa.StateChangeEvent += SAStateChange; } if (sa.State == SecurityAssociation.States.Active || sa.State == SecurityAssociation.States.Updating) { Address addr = con.Address; if (_address_to_sender.ContainsKey(addr)) { SecurityAssociation to_fixup = _address_to_sender[addr] as SecurityAssociation; if (to_fixup != null && to_fixup != sa) { to_fixup.StateChangeEvent -= SAStateChange; _registered.Remove(to_fixup); } } AddConnection(con.Address, sa); ready = true; } } return(ready); }
AuthorizationAgentsState <SipMessageWriter> IAuthorizationAgent <SipMessageReader, SipMessageWriter, AuthSchemes> .IsAuthorized(IAuthorizationSheduler <SipMessageReader, SipMessageWriter, AuthSchemes> sheduler, AuthorizationShedulerState <SipMessageReader> state) { //int opaque; //bool proxy; //ArraySegment<byte> token; //var error = Authorize(state.Message.Reader, scheme, out token, out opaque, out proxy); //AuthorizationError error1; //switch (error) //{ // case ErrorCodes.Ok: // error1 = AuthorizationError.Success; // break; // case ErrorCodes.Continue: // error1 = AuthorizationError.Continue; // break; // case ErrorCodes.NoResponse: // error1 = AuthorizationError.None; // break; // default: // error1 = AuthorizationError.Failed; // break; //} var realm1 = "officesip.local"; var error = ErrorCodes.NoResponse; if (state.Reader.Count.AuthorizationCount > 0) { //if (credentials.AuthScheme != AuthSchemes.Digest) // var credentials = state.Message.Reader.GetCredentialsByRealm(AuthSchemes.Digest, new ByteArrayPart(realm1)); } ArraySegment <byte> outToken; if (sa == null) { sa = new SecurityAssociation(); sa.Authentication(credHandle, state.Reader.Method, Encoding.ASCII.GetBytes(realm1), null, out outToken); } var response = sheduler.GetCommand(state, AuthSchemes.Digest, AuthorizationError.Failed); //error1); //if (response.Command == AuthorizationCommands.TryAgain) //{ // response.Writer.WriteAuthenticateMs(proxy, scheme, targetname, realm, opaque); // response.Writer.WriteXErrorDetails(GetError(error)); // response.Writer.WriteDate(DateTime.UtcNow); //} //else if (response.Command == AuthorizationCommands.Continue) //{ // response.Writer.WriteAuthenticateMs(proxy, scheme, targetname, realm, opaque, token); // response.Writer.WriteDate(DateTime.UtcNow); //} //else if (response.Command == AuthorizationCommands.Cancel) //{ // response.Writer.WriteXErrorDetails(GetError(error)); //} return(new AuthorizationAgentsState <SipMessageWriter>(response)); }
public void TestWithPreExchangedKeys() { Timer t = new Timer(Timeout, null, 0, 500); int spi = 123333; new SecurityPolicy(spi, "Rijndael", "SHA1", true); PeerSecOverlord so0 = CreateValidSO("valid0"); PeerSecOverlord so1 = CreateValidSO("valid1"); MockSender ms0 = new MockSender(null, null, so1, 0); MockSender ms1 = new MockSender(ms0, null, so0, 0); ms0.ReturnPath = ms1; SecurityAssociation sa0 = so0.CreateSecurityAssociation(ms0, spi); Assert.IsFalse((sa0 as PeerSecAssociation).Start(), "Cannot start SA again"); SecurityAssociation sa1 = so1.CreateSecurityAssociation(ms1, spi); Assert.AreEqual(sa0.State, SecurityAssociation.States.Active, "sa0 should be active!"); Assert.AreEqual(sa1.State, SecurityAssociation.States.Active, "sa1 should be active!"); Assert.AreEqual(so0.SACount, 1, "so0 should contain just one!"); Assert.AreEqual(so1.SACount, 1, "so1 should contain just one!"); t.Dispose(); }
protected void SAStateChange(SecurityAssociation sa, SecurityAssociation.States state) { Address addr = SenderToAddress(sa); if (addr == null) { return; } if (state == SecurityAssociation.States.Active) { AddConnection(addr, sa); } else if (state == SecurityAssociation.States.Closed) { lock (_address_to_sender) { _registered.Remove(sa); if (_address_to_sender.ContainsKey(addr) && _address_to_sender[addr] == sa) { RemoveConnection(addr); } } } }
// Provides an Exact AH Secure Sender using the default SPI given an address public SecurityAssociation GetSecureSender(Address target) { SecurityAssociation sa = null; bool new_sa = false; lock (_sync) { if (_address_to_sa.ContainsKey(target)) { sa = _address_to_sa[target]; } else { AHSender sender = new AHExactSender(_node, target); sa = base.CreateSecurityAssociation(sender, SecurityPolicy.DefaultSPI); _address_to_sa[target] = sa; _sa_to_address[sa] = target; new_sa = true; } } if (new_sa) { StartSA(sa); } return(sa); }
public Address GetAddress(SecurityAssociation sa) { lock(_sync) { if(_sa_to_address.ContainsKey(sa)) { return _sa_to_address[sa]; } } return null; }
/// <summary>Overridden because we know the Brunet address.</summary> protected override bool Verify(SecurityAssociation sa) { lock (_sync) { if (_sa_to_address.ContainsKey(sa)) { return(sa.VerifyCertificateBySubjectAltName(_sa_to_address[sa].ToString())); } } return(base.Verify(sa)); }
public Address GetAddress(SecurityAssociation sa) { lock (_sync) { if (_sa_to_address.ContainsKey(sa)) { return(_sa_to_address[sa]); } } return(null); }
override protected Address SenderToAddress(ISender sender) { SecurityAssociation sa = sender as SecurityAssociation; if (sa == null) { return(null); } return(base.SenderToAddress(sa.Sender)); }
///<summary>Makes the SecurityOverlord listen to the edge and instantiates ///a new SecurityAssociation for the insecure edge. CreateSecurityAssociation ///is idempotent.</summary> protected override void WrapEdge(Edge edge) { edge.Subscribe(_so, null); SecurityAssociation sa = _so.CreateSecurityAssociation(edge, DefaultEdgeSPI, !edge.IsInbound); if (edge.IsClosed) { sa.Close("Edge closed too quickly."); } }
override public void HandleData(MemBlock data, ISender return_path, object state) { SecurityAssociation sa = return_path as SecurityAssociation; if (sa == null) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, String.Format( "Insecure sender {0} sent ptype {1}", return_path, _ptype)); return; } base.HandleData(data, return_path, state); }
/// <summary>Removes the specified SA from our database.</summary> override protected void RemoveSA(SecurityAssociation sa) { lock (_sync) { AHSender sender = sa.Sender as AHSender; if (sender != null) { _address_to_sa.Remove(sender.Destination); _sa_to_address.Remove(sa); } base.RemoveSA(sa); } }
override protected void RemoveSA(SecurityAssociation sa) { DtlsAssociation dsa = sa as DtlsAssociation; if (dsa == null) { throw new Exception("SecurityAssociation is not a DtlsAssociation: " + sa); } _rwl.AcquireWriterLock(Timeout.Infinite); _sender_to_sa.Remove(dsa.Sender); _rwl.ReleaseWriterLock(); _it.Remove(dsa.LocalID); }
protected bool RemoveFromDictionary(Edge edge, out SecurityAssociation sa) { bool found = false; lock(_sync) { if(_edge_to_sa.TryGetValue(edge, out sa)) { _edge_to_sa.Remove(edge); found = true; } else if(_edge_to_inbound.ContainsKey(edge)) { _edge_to_inbound.Remove(edge); found = true; } } return found; }
/// <summary>Removes the specified SA from our database.</summary> override protected void RemoveSA(SecurityAssociation sa) { PeerSecAssociation psa = sa as PeerSecAssociation; if (psa == null) { throw new Exception("Invalid PeerSecAssociation: " + sa); } lock (_sync) { if (_spi.ContainsKey(psa.SPI)) { _spi[psa.SPI].Remove(psa.Sender); } } }
// Provides a method for local apps to add certificates to Brunet without // being loaded with Brunet. public void HandleRpc(ISender caller, string method, IList args, object rs) { object result = null; try { if (method.Equals("AddCertificate")) { ReqrepManager.ReplyState rqrs = caller as ReqrepManager.ReplyState; if (rqrs == null || !(rqrs.ReturnPath is Node)) { throw new Exception("Call must be made locally for security reasons!"); } string path = (string)args[0]; result = _ch.AddCertificate(path); } else if (method.Equals("GetState")) { if (args.Count != 1) { throw new Exception("Not enough arguments"); } else if (!(args[0] is string)) { throw new Exception("Argument should be a string"); } Address addr = AddressParser.Parse(args[0] as string); SecurityAssociation sa = CheckForSecureSender(addr); if (sa == null) { result = "No SA"; } else { result = sa.ToString(); } } else { result = new Exception("Invalid method"); } } catch (Exception e) { result = e; } _node.Rpc.SendResult(rs, result); }
protected void HandleEdgeClose(object edge, EventArgs ea) { Edge e = edge as Edge; if (e == null) { throw new Exception("Should be Edge"); } SecurityAssociation sa = null; RemoveFromDictionary(e, out sa); if (sa != null) { sa.Close("Edge closed early."); } }
protected bool RemoveFromDictionary(Edge edge, out SecurityAssociation sa) { bool found = false; lock (_sync) { if (_edge_to_sa.TryGetValue(edge, out sa)) { _edge_to_sa.Remove(edge); found = true; } else if (_edge_to_inbound.ContainsKey(edge)) { _edge_to_inbound.Remove(edge); found = true; } } return(found); }
override protected bool TryGetSender(Address dst, out ISender sender) { sender = null; var edge = GetConnection(dst); if (edge == null) { return(false); } SecurityAssociation sa = null; if (GetSecureSender(edge, out sa)) { sender = sa; return(true); } return(false); }
override protected void ValidDisconnection(Connection con) { ISender sender; if (!_address_to_sender.TryGetValue(con.Address, out sender)) { sender = _so.CheckForSecurityAssociation(con.State.Edge); if (sender == null) { return; } } SecurityAssociation sa = sender as SecurityAssociation; if (sa != null) { sa.Close("Connection closed..."); } }
///<summary>When a SecurityAssociation changes amongst inactive, active, ///or closed this gets notified.</summary> protected void AnnounceSA(SecurityAssociation sa, SecurityAssociation.States state) { Edge e = sa.Sender as Edge; // if e is an edge, let's see if he's creating a SE // or maybe it isn't our edge! if (e == null) { return; } else if (e.TAType != this.TAType) { return; } if (state == SecurityAssociation.States.Active) { SecurityAssociation stored_sa = null; if (!RemoveFromDictionary(e, out stored_sa)) { // May have already been here return; } else if (stored_sa != null && stored_sa != sa) { throw new Exception("Cannot have the same edge used in multiple SAs"); } SecureEdge se = new SecureEdge(e, sa); sa.Subscribe(se, null); try { Finalize(se); } catch { se.Close(); } } else if (state == SecurityAssociation.States.Closed) { e.Close(); } }
public void TestRemoteRestart() { Timer t = new Timer(Timeout, null, 0, 500); int spi = 123333; new SecurityPolicy(spi, "Rijndael", "SHA1", true); PeerSecOverlord so0 = CreateValidSO("valid0"); PeerSecOverlord so1 = CreateValidSO("valid1"); MockSender ms0 = new MockSender(null, null, so1, 0); MockSender ms1 = new MockSender(ms0, null, so0, 0); ms0.ReturnPath = ms1; SecurityAssociation sa0 = so0.CreateSecurityAssociation(ms0, spi); SecurityAssociation sa1 = so1.CreateSecurityAssociation(ms1, spi); Assert.AreEqual(sa0.State, SecurityAssociation.States.Active, "sa0 should be active!"); Assert.AreEqual(sa1.State, SecurityAssociation.States.Active, "sa1 should be active!"); sa0.CheckState(); sa1.CheckState(); sa1.Send(MemBlock.Reference(new byte[] { 0, 1, 2, 3 })); Assert.AreEqual(so0.SACount, 1, "so0 should contain just one! 0"); Assert.AreEqual(so1.SACount, 1, "so1 should contain just one! 0"); sa0.CheckState(); sa0.CheckState(); sa1.CheckState(); Assert.AreEqual(so0.SACount, 0, "so0 should contain just zero!"); Assert.AreEqual(so1.SACount, 1, "so1 should contain just one! 1"); sa1.Send(MemBlock.Reference(new byte[] { 0, 1, 2, 3 })); Assert.AreEqual(so0.SACount, 1, "so0 should contain just one! 2"); Assert.AreEqual(so1.SACount, 1, "so1 should contain just one! 1"); t.Dispose(); }
///<summary>When a SecurityAssociation changes amongst inactive, active, ///or closed this gets notified.</summary> protected void AnnounceSA(object o, EventArgs ea) { SecurityAssociation sa = o as SecurityAssociation; if (sa == null) { throw new Exception("Needs to be a SecurityAssociation"); } Edge e = sa.Sender as Edge; // if e is an edge, let's see if he's creating a SE // or maybe it isn't our edge! if (e == null) { return; } else if (e.TAType != this.TAType) { return; } if (sa.Active) { SecureEdge se = new SecureEdge(e, sa); sa.Subscribe(se, null); try { Finalize(se); } catch { se.Close(); } } else { e.Close(); } }
///<summary>Makes the SecurityOverlord listen to the edge and instantiates ///a new SecurityAssociation for the insecure edge. CreateSecurityAssociation ///is idempotent.</summary> protected override void WrapEdge(Edge edge) { edge.Subscribe(_so, null); if (edge.IsInbound) { lock (_sync) { _edge_to_inbound.Add(edge, true); } } else { SecurityAssociation sa = _so.CreateSecurityAssociation(edge); lock (_sync) { _edge_to_sa.Add(edge, sa); } } try { edge.CloseEvent += HandleEdgeClose; } catch { HandleEdgeClose(edge, EventArgs.Empty); } }
// We override the underlying method so that we can properly wrap incoming AHSenders protected override SecurityAssociation CreateSecurityAssociation(ISender sender, int spi) { SecurityAssociation sa = null; lock (_sync) { sa = base.CreateSecurityAssociation(sender, spi); AHSender ahsender = sender as AHSender; if (ahsender != null) { Address target = ahsender.Destination; if (_address_to_sa.ContainsKey(target)) { sa = _address_to_sa[target]; } else { sa = base.CreateSecurityAssociation(sender, spi); _address_to_sa[target] = sa; _sa_to_address[sa] = target; } } } return(sa); }
/// <summary>1a) Send a Cookie</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> protected void HandleControlNoSuchSA(SecurityAssociation sa) { if(sa == null) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " NoSuchSA received, but we have no SA either!"); } else { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " NoSuchSA received, handling..."); StartSA(sa); } }
protected bool GetSecureSender(Connection con, out SecurityAssociation sa) { sa = _so.GetSecureSender(con.Address); bool ready = false; lock(_address_to_sender) { if(!_registered.ContainsKey(sa)) { _registered[sa] = true; sa.StateChangeEvent += SAStateChange; } if(sa.State == SecurityAssociation.States.Active || sa.State == SecurityAssociation.States.Updating) { AddConnection(con.Address, sa); ready = true; } } return ready; }
public void Test() { Timer t = new Timer(Timeout, null, 0, 500); PeerSecOverlord so0 = CreateValidSO("valid0"); PeerSecOverlord so1 = CreateValidSO("valid1"); //Test block one { MockSender ms0 = new MockSender(null, null, so1, 0); MockSender ms1 = new MockSender(ms0, null, so0, 0); ms0.ReturnPath = ms1; SecurityAssociation sa0 = so0.CreateSecurityAssociation(ms0); SecurityAssociation sa1 = so1.CreateSecurityAssociation(ms1); Assert.AreEqual(sa0.State, SecurityAssociation.States.Active, "sa0 should be active!"); Assert.AreEqual(sa1.State, SecurityAssociation.States.Active, "sa1 should be active!"); Assert.AreEqual(so0.SACount, 1, "so0 should contain just one!"); Assert.AreEqual(so1.SACount, 1, "so1 should contain just one!"); Random rand = new Random(); byte[] b = new byte[128]; rand.NextBytes(b); MemBlock mb = MemBlock.Reference(b); sa1.Send(mb); new SecurityPolicy(12345, "DES", "MD5"); sa0 = so0.CreateSecurityAssociation(ms0, 12345); Assert.AreEqual(sa0.State, SecurityAssociation.States.Active, "sa0 should be active!"); Assert.AreEqual(so0.SACount, 2, "so0 should contain just one!"); Assert.AreEqual(so1.SACount, 2, "so1 should contain just one!"); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sa0.Send(mb); } // create ~250 valid SAs for one guy... for (int i = 2; i < 250; i++) { PeerSecOverlord so = CreateValidSO("valid" + i); MockSender msa = new MockSender(null, null, so, 0); MockSender msb = new MockSender(msa, null, so0, 0); msa.ReturnPath = msb; SecurityAssociation sab = so.CreateSecurityAssociation(msb); Assert.AreEqual(sab.State, SecurityAssociation.States.Active, "sab should be active! " + i); SecurityAssociation saa = so0.CreateSecurityAssociation(msa); Assert.AreEqual(saa.State, SecurityAssociation.States.Active, "saa should be active! " + i); MockDataHandler mdha = new MockDataHandler(); saa.Subscribe(mdha, null); MockDataHandler mdhb = new MockDataHandler(); sab.Subscribe(mdhb, null); Random rand = new Random(); byte[] b = new byte[128]; rand.NextBytes(b); MemBlock mb = MemBlock.Reference(b); sab.Send(mb); Assert.IsTrue(mdha.Contains(mb), "mdhb Contains " + i); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sab.Send(mb); Assert.IsTrue(mdha.Contains(mb), "mdha Contains " + i); } for (int i = 250; i < 500; i++) { int ij = (250 % 3) + 1; PeerSecOverlord so = CreateInvalidSO("valid" + i, ij); MockSender msa = new MockSender(null, null, so, 0); MockSender msb = new MockSender(msa, null, so0, 0); msa.ReturnPath = msb; SecurityAssociation sab = so.CreateSecurityAssociation(msb); SecurityAssociation saa = so0.CreateSecurityAssociation(msa); Assert.AreEqual(sab.State, SecurityAssociation.States.Waiting, "sab should be waiting! " + i); Assert.AreEqual(saa.State, SecurityAssociation.States.Waiting, "saa should be waiting! " + i); } // create ~250 valid SAs for one guy... for (int i = 500; i < 750; i++) { PeerSecOverlord so = CreateValidSO("valid" + i); MockSender msa = new MockSender(null, null, so, 0); MockSender msb = new MockSender(msa, null, so0, 0); msa.ReturnPath = msb; SecurityAssociation sab = so.CreateSecurityAssociation(msb); Assert.AreEqual(sab.State, SecurityAssociation.States.Active, "sab should be active! " + i); SecurityAssociation saa = so0.CreateSecurityAssociation(msa); Assert.AreEqual(saa.State, SecurityAssociation.States.Active, "saa should be active! " + i); MockDataHandler mdha = new MockDataHandler(); saa.Subscribe(mdha, null); MockDataHandler mdhb = new MockDataHandler(); sab.Subscribe(mdhb, null); Random rand = new Random(); byte[] b = new byte[128]; rand.NextBytes(b); MemBlock mb = MemBlock.Reference(b); sab.Send(mb); Assert.IsTrue(mdha.Contains(mb), "mdhb Contains " + i); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sab.Send(mb); Assert.IsTrue(mdha.Contains(mb), "mdha Contains " + i); } Random randr = new Random(); byte[] br = new byte[128]; randr.NextBytes(br); MemBlock mbr = MemBlock.Reference(br); // New logic requires that we call this first, to set all SAs to not // running, the following for loop sets all "Active" SAs back to _running // Thus keeping the original intent of this test. The new logic only // affects testing paths. so0.CheckSAs(DateTime.UtcNow); foreach (Dictionary <ISender, PeerSecAssociation> sender_to_sa in so0.SPI.Values) { foreach (SecurityAssociation sa in sender_to_sa.Values) { if (sa.State == SecurityAssociation.States.Active) { sa.Send(mbr); } } } so0.CheckSAs(DateTime.UtcNow); Assert.AreEqual(500, so0.SACount, "Count!"); so0.CheckSAs(DateTime.UtcNow); Assert.AreEqual(0, so0.SACount, "Count!"); t.Dispose(); }
/// <summary>This begins the SecurityAssociation exchange protocol over the /// specified SecurityAssociation.</summary> protected void StartSA(SecurityAssociation sa) { SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = sa.SPI; scm_reply.Type = SecurityControlMessage.MessageType.Cookie; scm_reply.LocalCookie = CalculateCookie(sa.Sender); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(sa.Sender, ReqrepManager.ReqrepType.Request, to_send, this, sa); }
protected void SAStateChange(SecurityAssociation sa, SecurityAssociation.States state) { Address addr = _so.GetAddress(sa); if(addr == null) { return; } if(state == SecurityAssociation.States.Active) { AddConnection(addr, sa); } else if(state == SecurityAssociation.States.Closed) { lock(_address_to_sender) { RemoveConnection(addr, sa); _registered.Remove(sa); } } }
protected void AnnounceSA(SecurityAssociation sa, SecurityAssociation.States state) { // PeerSecAssociation sa = o as PeerSecAssociation; }
protected void SAStateChange(SecurityAssociation sa, SecurityAssociation.States state) { Address addr = SenderToAddress(sa); if(addr == null) { return; } if(state == SecurityAssociation.States.Active) { AddConnection(addr, sa); } else if(state == SecurityAssociation.States.Closed) { lock(_address_to_sender) { _registered.Remove(sa); if(_address_to_sender.ContainsKey(addr) && _address_to_sender[addr] == sa) { RemoveConnection(addr); } } } }
/// <summary>Whenever an SA changes amongst inactive, active, and closed /// this is called.</summary> /// <param name="o">The SA whose state changes.</summary> protected void SAStateChange(SecurityAssociation sa, SecurityAssociation.States state) { if(state == SecurityAssociation.States.Active) { if(_sub != null) { sa.Subscribe(_sub.Handler, null); } else { sa.Subscribe(this, null); } } else if(state == SecurityAssociation.States.Updating) { sa.Subscribe(this, null); } else if(sa.Closed) { RemoveSA(sa); } if(AnnounceSA != null) { AnnounceSA(sa, state); } }
/// <summary>Removes the specified SA from our database.</summary> override protected void RemoveSA(SecurityAssociation sa) { lock(_sync) { AHSender sender = sa.Sender as AHSender; if(sender != null) { _address_to_sa.Remove(sender.Destination); _sa_to_address.Remove(sa); } base.RemoveSA(sa); } }
/// <summary>Higher level SOs may have a better way to verify these SAs /// then we do. They can override this and do as they please.</summary> protected virtual bool Verify(SecurityAssociation sa) { #if BRUNET_NUNIT return true; #else return sa.Sender is Edge; #endif }
/// <summary>1b) Receive a Cookie which responds with a CookieResponse</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="calc_cookie">Cookie value for the association sender.</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 HandleControlCookie(SecurityAssociation sa, MemBlock calc_cookie, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Cookie from: " + low_level_sender); scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.LocalCookie = calc_cookie; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Cookie from: " + low_level_sender); }
/// <summary>2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs.</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 HandleControlCookieResponse(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received CookieResponse from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } // This seems like unnecessary code scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.RemoteCookie.Value = scm.LocalCookie; sa.LocalCertificate.Value = lcert; scm_reply.Certificate = lcert.RawData; scm_reply.DHE = sa.LDHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificateAndCAs; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateAndCAsOutHash.Value = sha1.ComputeHash((byte[]) scm_reply.Packet); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful CookieResponse from: " + low_level_sender); }
/// <summary>2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate</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 HandleControlDHEWithCertificateAndCAs(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificateAndCAs from: " + low_level_sender); if(sa == null) { sa = CreateSecurityAssociation(low_level_sender, scm.SPI, false); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); _ch.Verify(rcert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.LocalCertificate.Value = lcert; sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; sa.DHEWithCertificateAndCAsInHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.DHE = sa.LDHE; scm_reply.Certificate = MemBlock.Reference(lcert.RawData); scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificate; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm_reply.Packet)); ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificateAndCAs from: " + low_level_sender); }
/// <summary>3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system.</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 HandleControlDHEWithCertificates(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificate from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); _ch.Verify(rcert); sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificate from: " + low_level_sender); }
/// <summary>Removes the specified SA from our database.</summary> protected virtual void RemoveSA(SecurityAssociation sa) { lock(_sync) { if(_spi.ContainsKey(sa.SPI)) { _spi[sa.SPI].Remove(sa.Sender); } } }
public void Test() { int spi = SecurityPolicy.DefaultSPI; MockSender sender1 = new MockSender(null, null, null, 2); MockSender sender2 = new MockSender(null, null, null, 2); SecurityAssociation sa1 = new SecurityAssociation(sender1, spi); sa1.StateChange += StateChange; sender2.Receiver = sa1; MockDataHandler mdh1 = new MockDataHandler(); sa1.Subscribe(mdh1, null); SecurityAssociation sa2 = new SecurityAssociation(sender2, spi); sender1.Receiver = sa2; MockDataHandler mdh2 = new MockDataHandler(); sa2.Subscribe(mdh2, null); byte[] b = null; Random rand = new Random(); MemBlock mb = null; int current_epoch = sa1.CurrentEpoch; for(int i = 0; i < 5; i++) { Thread.Sleep(SecurityAssociation.TIMEOUT * 2 + 5); Setup(ref sa1, ref sa2); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sa1.Send(mb); Assert.IsTrue(mdh2.Contains(mb), "Contains" + i); Assert.AreEqual(state, sa1.State, "State == Active" + i); Assert.IsFalse(current_epoch == sa1.CurrentEpoch, "Current epoch " + i); current_epoch = sa1.CurrentEpoch; } sa1.GarbageCollect(); sa1.GarbageCollect(); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); try { sa1.Send(mb); } catch {} Assert.IsTrue(!mdh2.Contains(mb), "Failed!"); Assert.AreEqual(state, sa1.State, "State == Failed"); }
/// <summary></summary> abstract protected void RemoveSA(SecurityAssociation sa);
protected void Setup(ref SecurityAssociation sa1, ref SecurityAssociation sa2) { sa1.Reset(); sa2.Reset(); sa1.RDHE.Value = sa2.LDHE; sa2.RDHE.Value = sa1.LDHE; Random rand = new Random(); byte[] b = new byte[128]; rand.NextBytes(b); MemBlock mb = MemBlock.Reference(b); sa1.DHEWithCertificateAndCAsOutHash.Value = mb; sa1.VerifyResponse(mb); b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sa2.DHEWithCertificateHash.Value = mb; sa2.VerifyRequest(mb); sa1.Enable(); sa2.Enable(); // This is just for kicks sa1.Enable(); }
/// <summary>This (idempotently) returns a new SecurityAssociation for the /// specified sender using the specified SA.</summary> virtual protected SecurityAssociation CreateSecurityAssociation(ISender Sender, int SPI) { if(!SecurityPolicy.Supports(SPI)) { throw new Exception("Unsupported SPI"); } SecurityAssociation sa = null; int count = 0; lock(_sync) { Dictionary<ISender, SecurityAssociation> sender_to_sa = null; if(_spi.ContainsKey(SPI)) { sender_to_sa = _spi[SPI]; } else { sender_to_sa = new Dictionary<ISender, SecurityAssociation>(); _spi[SPI] = sender_to_sa; } if(sender_to_sa.ContainsKey(Sender)) { sa = sender_to_sa[Sender]; } else { sa = new SecurityAssociation(Sender, SPI); sa.Subscribe(this, null); sa.StateChange += SAStateChange; sa.RequestUpdate += SARequestUpdate; sender_to_sa[Sender] = sa; } } return sa; }
/// <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); }
public SecureEdge(Edge edge, SecurityAssociation sa): base(edge, false) { SA = sa; _closed = 0; }
public void StateChange(SecurityAssociation sa, SecurityAssociation.States st) { state = st; }
public void SHUpdateTest() { callback_count = 0; int spi = SecurityPolicy.DefaultSPI; MockSender sender1 = new MockSender(null, null, null, 2); MockSender sender2 = new MockSender(null, null, null, 2); SecurityAssociation sa1 = new SecurityAssociation(sender1, spi); sa1.StateChange += StateChange; sender2.Receiver = sa1; MockDataHandler mdh1 = new MockDataHandler(); sa1.Subscribe(mdh1, null); SecurityAssociation sa2 = new SecurityAssociation(sender2, spi); sender1.Receiver = sa2; MockDataHandler mdh2 = new MockDataHandler(); sa2.Subscribe(mdh2, null); Setup(ref sa1, ref sa2); sa1.RequestUpdate += Callback; sa2.RequestUpdate += Callback; byte[] b = null; Random rand = new Random(); MemBlock mb = null; int current_epoch = sa1.CurrentEpoch; for(int i = 0; i < 80; i++) { b = new byte[128]; rand.NextBytes(b); mb = MemBlock.Reference(b); sa1.Send(mb); Assert.IsTrue(mdh2.Contains(mb), "Contains" + i); if(i % 20 == 0 && i != 0) { Assert.AreEqual(callback_count, 1, "Callback count " + i); callback_count = 0; Thread.Sleep(SecurityAssociation.TIMEOUT * 2 + 5); Setup(ref sa1, ref sa2); } else { if(i % 20 == 1 && i != 1) { Assert.IsFalse(current_epoch == sa1.CurrentEpoch, "Current epoch " + i); current_epoch = sa1.CurrentEpoch; } Assert.AreEqual(current_epoch, sa1.CurrentEpoch, "Current epoch " + i); } } }
///<summary>When a SecurityAssociation changes amongst inactive, active, ///or closed this gets notified.</summary> protected void AnnounceSA(SecurityAssociation sa, SecurityAssociation.States state) { Edge e = sa.Sender as Edge; // if e is an edge, let's see if he's creating a SE // or maybe it isn't our edge! if(e == null) { return; } else if(e.TAType != this.TAType) { return; } if(state == SecurityAssociation.States.Active) { SecurityAssociation stored_sa = null; if(!RemoveFromDictionary(e, out stored_sa)) { // May have already been here return; } else if(stored_sa != null && stored_sa != sa) { throw new Exception("Cannot have the same edge used in multiple SAs"); } SecureEdge se = new SecureEdge(e, sa); sa.Subscribe(se, null); try { Finalize(se); } catch { se.Close(); } } else if(state == SecurityAssociation.States.Closed) { e.Close(); } }
public SecureEdge(Edge edge, SecurityAssociation sa) : base(edge, false) { SA = sa; _closed = 0; }
protected bool GetSecureSender(Connection con, out SecurityAssociation sa) { sa = _so.CreateSecurityAssociation(con.State.Edge); bool ready = false; lock(_address_to_sender) { if(!_registered.ContainsKey(sa)) { _registered[sa] = true; sa.StateChangeEvent += SAStateChange; } if(sa.State == SecurityAssociation.States.Active || sa.State == SecurityAssociation.States.Updating) { Address addr = con.Address; if(_address_to_sender.ContainsKey(addr)) { SecurityAssociation to_fixup = _address_to_sender[addr] as SecurityAssociation; if(to_fixup != null && to_fixup != sa) { to_fixup.StateChangeEvent -= SAStateChange; _registered.Remove(to_fixup); } } AddConnection(con.Address, sa); ready = true; } } return ready; }