private void GrantPermissions(CtpNetStream stream, CtpAccount account, string loginName, List <string> grantedRoles, List <string> deniedRoles) { stream.LoginName = loginName; stream.AccountName = account.Name; stream.GrantedRoles.UnionWith(account.ImplicitRoles); stream.GrantedRoles.UnionWith(account.ExplicitRoles.Union(grantedRoles)); stream.GrantedRoles.ExceptWith(deniedRoles); }
public bool IsCertificateTrusted(CtpNetStream stream, ClientDone clientDone) { if (!TryFindCertificate(stream.RemoteCertificate.GetCertHashString(), out var cert, out var account)) { return(false); } if (!account.IsIPAllowed(stream.RemoteEndpoint.Address)) { return(false); } GrantPermissions(stream, account, clientDone.LoginName, clientDone.GrantedRoles, clientDone.DeniedRoles); return(true); }
public bool IsCertificateTrusted(CtpNetStream stream, CertificateProof proof) { var eph = new EphemeralCertificate(proof.EphemeralCertificate); if (!TryFindCertificate(HexToString(eph.TrustedCertThumbprint), out var signingCert, out var account)) { return(false); } if (!eph.ValidateSignature(signingCert)) { return(false); } if (!account.IsIPAllowed(stream.RemoteEndpoint.Address)) { return(false); } GrantPermissions(stream, account, eph.LoginName, eph.GrantedRoles, eph.DeniedRoles); return(true); }
public CtpNetStream Connect() { Log.Publish(MessageLevel.Info, "Attempting Connection"); var socket = new TcpClient(); socket.SendTimeout = 3000; socket.ReceiveTimeout = 3000; var connect = socket.BeginConnect(m_remoteEndpoint.Address, m_remoteEndpoint.Port, null, null); var success = connect.AsyncWaitHandle.WaitOne(3000); if (!success) { socket.Close(); throw new TimeoutException("Failed to connect"); } socket.EndConnect(connect); var netStream = socket.GetStream(); SslStream sslStream = null; using (var handshake = m_authentication.StartHandshake()) { if (handshake.UseSSL) { sslStream = new SslStream(netStream, false, ValidateCertificate, null, EncryptionPolicy.RequireEncryption); sslStream.AuthenticateAsClient(string.Empty, handshake.GetCertificateCollection(), SslProtocols.Tls12, false); var session = new CtpNetStream(socket, netStream, sslStream); var cmd = session.Read(); if (cmd.CommandName == "ServerDone") { if (!handshake.IsCertificateTrusted(sslStream.RemoteCertificate, (ServerDone)cmd)) { m_authentication.AuthenticationFailed(); session.Send(new AuthFailure("Negotiated Certificate is not trusted: " + sslStream.RemoteCertificate.ToString())); session.Dispose(); throw new Exception("Certificate is not trusted"); } } else if (cmd.CommandName == "CertificateProof") { if (!handshake.IsCertificateTrusted(sslStream.RemoteCertificate, (CertificateProof)cmd)) { m_authentication.AuthenticationFailed(); session.Send(new AuthFailure("Negotiated Certificate is not trusted: " + sslStream.RemoteCertificate.ToString())); session.Dispose(); throw new Exception("Certificate is not trusted"); } } else { m_authentication.AuthenticationFailed(); session.Send(new AuthFailure("Unrecognized Auth Command: " + cmd.CommandName)); session.Dispose(); throw new Exception("Unrecognized Auth Command: " + cmd.CommandName); } if (handshake.IsEphemeralCertificate) { session.Send(handshake.GetCertificateProof()); } else { session.Send(handshake.GetClientDone()); } cmd = session.Read(); if (cmd.CommandName != "AuthSuccess") { m_authentication.AuthenticationFailed(); session.Send(new AuthFailure("Expecting AuthSuccess, received: " + cmd.CommandName)); session.Dispose(); throw new Exception("Expecting AuthSuccess, received: " + cmd.CommandName); } Log.Publish(MessageLevel.Info, "SSL Session Completed"); return(session); } else { var session = new CtpNetStream(socket, netStream, null); Log.Publish(MessageLevel.Info, "Non SSL Session Completed"); return(session); } } }
private void Process() { try { TcpClient socket = m_client; NetworkStream netStream = socket.GetStream(); IServerHandshake config = m_server.m_config.StartHandshake(); CtpNetStream session; if (config.UseSSL) { var ssl = new SslStream(netStream, false, UserCertificateValidationCallback, null, EncryptionPolicy.RequireEncryption); ssl.AuthenticateAsServer(config.GetCertificate(), true, SslProtocols.Tls12, false); session = new CtpNetStream(socket, netStream, ssl); if (config.IsEphemeralCertificate) { session.Send(config.GetCertificateProof()); } else { session.Send(config.GetServerDone()); } var cmd = session.Read(); if (cmd.CommandName == "ClientDone") { if (!config.IsCertificateTrusted(session, (ClientDone)cmd)) { session.Send(new AuthFailure("Negotiated Certificate is not trusted: " + ssl.RemoteCertificate.ToString())); session.Dispose(); throw new Exception("Certificate is not trusted"); } } else if (cmd.CommandName == "CertificateProof") { if (!config.IsCertificateTrusted(session, (CertificateProof)cmd)) { session.Send(new AuthFailure("Negotiated Certificate is not trusted: " + ssl.RemoteCertificate.ToString())); session.Dispose(); throw new Exception("Certificate is not trusted"); } } else { session.Send(new AuthFailure("Unrecognized Auth Command: " + cmd.CommandName)); session.Dispose(); throw new Exception("Unrecognized Auth Command: " + cmd.CommandName); } session.Send(new AuthSuccess()); } else { session = new CtpNetStream(socket, netStream, null); } m_server.OnSessionCompleted(session); } catch (Exception e) { Logger.SwallowException(e, "Failed to authenticate client, Safely Disconnecting"); //Swallow the exception since a failed connection attempt can safely be ignored by the server. } }
protected virtual void OnSessionCompleted(CtpNetStream token) { SessionCompleted?.Invoke(token); }