public RealTimeWebSocketBridgeWorker( ILogger <RealTimeWebSocketBridgeWorker> logger, IRpcConnection rpcConnection, IRtConnector connector) { this.logger = logger; this.rpcConnection = rpcConnection; this.connector = connector; }
public Rpc(IRpcConnection connection, IDispatcher dispatcher = null, ILogger logger = null, int timeoutMs = 30000) { this.Connection = connection; this.Dispatcher = dispatcher ?? new RpcDispatcher(); this.logger = logger; TimeoutMs = timeoutMs; this.Connection.OnReceive += OnConnectionReceive; }
/// <summary> /// Creates a new channel with the given information, already established connection, /// and optionally the given backlog. /// </summary> public static async Task <RpcChannel> Create(RpcPeerInfo remoteInfo, IRpcConnection connection, IRpcMethodExecutor executor, IRpcBacklog?backlog = null) { var ret = new RpcChannel(remoteInfo, connection, executor); ret.callsQueue = await RpcQueue.Create(remoteInfo.PeerID, backlog); return(ret); }
public WorkerService( ILogger <WorkerService> logger, IRpcConnection rpcConnection, IRtConnector connector, RpcHistoryService historyService, Rpc rpc) { this.logger = logger; this.rpcConnection = rpcConnection; this.connector = connector; this.historyService = historyService; this.rpc = rpc; }
internal SessionOpenedEventArgs(RpcSession session, IRpcConnection connection) { if (session == null) { throw new ArgumentNullException(nameof(session)); } if (connection == null) { throw new ArgumentNullException(nameof(connection)); } this.Session = session; this.Connection = connection; }
protected override Task SendMessage(WireMessage message, IRpcConnection conn) { try { ThrowIfDisposed(); conn.Send(message); return(Completed); } catch (Exception e) { return(Task.FromException(e)); } }
public RpcSession(RpcSessionContext sessionContext) { if (sessionContext.Serializer == null) { throw new ArgumentNullException(nameof(sessionContext.Serializer)); } if (sessionContext.Connection == null) { throw new ArgumentNullException(nameof(sessionContext.Connection)); } if (sessionContext.LogManager == null) { throw new ArgumentNullException(nameof(sessionContext.LogManager)); } if (sessionContext.TaskScheduler == null) { throw new ArgumentNullException(nameof(sessionContext.TaskScheduler)); } this.requests = new ConcurrentDictionary <uint, RemotingRequest>(); this.rpcSerializer = sessionContext.Serializer; this.orderedExecution = sessionContext.OrderedExecution; this.orderedExecutionTask = Task.CompletedTask; this.orderedExecutionMaxQueue = sessionContext.OrderedExecutionMaxQueue; this.remotingObjectConfiguration = sessionContext.RemotingObjectConfiguration; this.taskScheduler = sessionContext.TaskScheduler; this.Connection = sessionContext.Connection; this.defaultExecutionTimeout = sessionContext.DefaultExecutionTimeout; this.logger = sessionContext.LogManager.GetLogger(nameof(RpcSession)); this.logger.Meta["kind"] = this.GetType().Name; this.logger.Meta["connection_id"] = this.Connection.Id; this.logger.Meta["connection_endpoint"] = new RefLogLabel <IRpcConnection>(this.Connection, s => s.RemoteEndpoint); this.logger.Meta["closed"] = new RefLogLabel <RpcSession>(this, s => s.closed); this.logger.Meta["tag"] = new RefLogLabel <RpcSession>(this, s => s.Tag); this.logger.Meta["latency"] = new RefLogLabel <RpcSession>(this, s => { var lat = s.Connection.Latency; if (lat.HasValue) { return(lat.Value); } else { return(""); } }); this.logger.Debug($"{sessionContext.Connection} created {this}"); }
/// <summary> /// Add a sign check. /// </summary> /// <param name="signedSignCheck">Signed sign check.</param> public void AddSignatureRequestSignCheck( IRpcConnection connection, Signed<SignatureRequestSignCheck> signedSignCheck) { if (!signedSignCheck.Verify(CertificateStorage)) { if (signedSignCheck.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Server id {1} (unverified) tried to add a sign check, but his certificate status was {2}.", connection.Id, signedSignCheck.Certificate.Id.ToString(), signedSignCheck.Certificate.Validate(CertificateStorage).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Server id {1} (unverified) tried to add a sign check, but the signature was invalid.", connection.Id, signedSignCheck.Certificate.Id.ToString()); } throw new PiSecurityException(ExceptionCode.InvalidSignature, "Signature on sign check invalid."); } if (!(signedSignCheck.Certificate is ServerCertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Server id {1} (verified) tried to add a sign check, but he is not a server.", connection.Id, signedSignCheck.Certificate.Id.ToString()); throw new PiSecurityException(ExceptionCode.SignCheckNotFromServer, "Signature on sign check not from server."); } var signCheck = signedSignCheck.Value; Signed<SignatureResponse> signatureResponse = null; var status = GetSignatureResponseStatus(signCheck.Certificate.Id, out signatureResponse); if (status != SignatureResponseStatus.Pending) { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to a sign check to id {2}, but its status was {3}.", connection.Id, signCheck.Cookie.Certificate.Id.ToString(), signCheck.Certificate.Id.ToString(), status.ToString()); throw new PiException(ExceptionCode.SignCheckResponseStateMismatch, "Signature response status mismatch."); } if (!signCheck.Cookie.Verify(CertificateStorage)) { if (signCheck.Cookie.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to a sign check to id {2}, but his certificate status was {3}.", connection.Id, signCheck.Cookie.Certificate.Id.ToString(), signCheck.Certificate.Id.ToString(), signCheck.Cookie.Certificate.Validate(CertificateStorage).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to a sign check to id {2}, but the signature was invalid.", connection.Id, signCheck.Cookie.Certificate.Id.ToString(), signCheck.Certificate.Id.ToString()); } throw new PiSecurityException(ExceptionCode.SignCheckCookieSignatureInvalid, "Signature on sign check cookie invalid."); } if (!(signCheck.Cookie.Certificate is AuthorityCertificate || signCheck.Cookie.Certificate is NotaryCertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to a sign check to id {2}, but he is not an authority or notary.", connection.Id, signCheck.Cookie.Certificate.Id.ToString(), signCheck.Certificate.Id.ToString()); throw new PiSecurityException(ExceptionCode.SignCheckCookieNotFromNotary, "Signature on sign check cookie not from notary."); } Signed<SignCheckCookie> dbCookie = null; var reader = DbConnection.ExecuteReader( "SELECT Cookie FROM signcheckcookie WHERE NotaryId = @NotaryId", "@NotaryId", signCheck.Cookie.Certificate.Id.ToByteArray()); if (reader.Read()) { dbCookie = Serializable.FromBinary<Signed<SignCheckCookie>>(reader.GetBlob(0)); reader.Close(); } else { reader.Close(); throw new PiSecurityException(ExceptionCode.SignCheckCookieNotFound, "Sign check cookie not found."); } if (dbCookie.Certificate.Fingerprint != signCheck.Cookie.Certificate.Fingerprint) throw new PiSecurityException(ExceptionCode.SignCheckCookieFingerprintMismatch, "Fingerprint on sign check cookie does not match."); if (!dbCookie.Value.Randomness.Equal(signCheck.Cookie.Value.Randomness)) throw new PiSecurityException(ExceptionCode.SignCheckCookieRandomnessMismatch, "Randomness of sign check cookie does not match."); MySqlCommand insertCommand = new MySqlCommand("INSERT INTO signcheck (CertificateId, Value) VALUES (@CertificateId, @Value)", DbConnection); insertCommand.Parameters.AddWithValue("@CertificateId", signedSignCheck.Value.Certificate.Id.ToByteArray()); insertCommand.Parameters.AddWithValue("@Value", signedSignCheck.ToBinary()); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Notary {1}, {2} has signed signature request {3}", connection.Id, signCheck.Cookie.Certificate.Id.ToString(), signCheck.Cookie.Certificate.FullName, signCheck.Certificate.Id.ToString()); }
/// <summary> /// Add a certificate storage to the server's data. /// </summary> /// <remarks> /// Used to add new CRLs. /// </remarks> /// <param name="certificateStorage">Certificate storage to add.</param> public void AddCertificateStorage( IRpcConnection connection, CertificateStorage certificateStorage) { if (!certificateStorage.SignedRevocationLists.All(crl => crl.Certificate is CACertificate && crl.Value.IssuerId.Equals(crl.Certificate.Id) && crl.Verify(CertificateStorage))) { Logger.Log(LogLevel.Warning, "Connection {0}: Add certificate storage failed; Signature on CRL or issuer not valid.", connection.Id); throw new PiSecurityException(ExceptionCode.InvalidSignature, "Signature on CRL or issuer not valid."); } CertificateStorage.Add(certificateStorage.SignedRevocationLists); var validCertificates = certificateStorage.Certificates .Where(certificate => certificate.Validate(CertificateStorage) == CertificateValidationResult.Valid && certificate.AllSignaturesValid(CertificateStorage)); CertificateStorage.Add(validCertificates); Logger.Log(LogLevel.Info, "Connection {0}: Certificate storage added.", connection.Id); }
public byte[] SetSignCheckCookie( IRpcConnection connection, Signed<SignCheckCookie> signedCookie) { if (!signedCookie.Verify(CertificateStorage)) { if (signedCookie.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to set his sign check cookie, but his certificate status was {2}.", connection.Id, signedCookie.Certificate.Id.ToString(), signedCookie.Certificate.Validate(CertificateStorage).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to set his sign check cookie, but the signature was invalid.", connection.Id, signedCookie.Certificate.Id.ToString()); } throw new PiSecurityException(ExceptionCode.InvalidSignature, "Invalid signature."); } if (!(signedCookie.Certificate is AuthorityCertificate || signedCookie.Certificate is NotaryCertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {0} (verified) tried to set his sign check cookie, but he is no authority or notary.", connection.Id, signedCookie.Certificate.Id.ToString()); throw new PiSecurityException(ExceptionCode.SignCheckCookieNotFromNotary, "Not from proper authority or notary."); } this.DbConnection.ExecuteNonQuery( "DELETE FROM signcheckcookie WHERE NotaryId = @NotaryId", "@NotaryId", signedCookie.Certificate.Id.ToByteArray()); var rng = RandomNumberGenerator.Create(); byte[] code = new byte[32]; rng.GetBytes(code); byte[] encryptedCode = signedCookie.Certificate.Encrypt(code); MySqlCommand insertCommand = new MySqlCommand( "INSERT INTO signcheckcookie (NotaryId, Cookie, Code, Expires) VALUES (@NotaryId, @Cookie, @Code, @Expires)", this.DbConnection); insertCommand.Parameters.AddWithValue("@NotaryId", signedCookie.Certificate.Id.ToByteArray()); insertCommand.Parameters.AddWithValue("@Cookie", signedCookie.ToBinary()); insertCommand.Parameters.AddWithValue("@Code", code); insertCommand.Parameters.AddWithValue("@Expires", DateTime.Now.AddMinutes(15).ToString("yyyy-MM-dd HH:mm:ss")); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Notary id {1} (verified) has set his sign check cookie with code {2}.", connection.Id, signedCookie.Certificate.Id.ToString(), code.ToHexString()); return encryptedCode; }
/// <summary> /// Sets a signature response. /// </summary> /// <param name="signatureRequestId">Id of the corresponding request.</param> /// <param name="signedSignatureResponse">Signed signature response.</param> public void SetSignatureResponse( IRpcConnection connection, Signed<SignatureResponse> signedSignatureResponse) { if (!signedSignatureResponse.Verify(CertificateStorage)) { if (signedSignatureResponse.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: CA id {1} (unverified) tried to set a signature response, but his certificate status was {2}.", connection.Id, signedSignatureResponse.Certificate.Id.ToString(), signedSignatureResponse.Certificate.Validate(CertificateStorage).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: CA id {1} (unverified) tried to set a signature response, but the signature was invalid.", connection.Id, signedSignatureResponse.Certificate.Id.ToString()); } throw new PiSecurityException(ExceptionCode.InvalidSignature, "Signature response has invalid signature."); } if (!(signedSignatureResponse.Certificate is CACertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: CA id {1} (unverified) tried to set a signature response, but it's not a CA.", connection.Id, signedSignatureResponse.Certificate.Id.ToString()); throw new PiSecurityException(ExceptionCode.SignatureResponseNotFromCA, "Signature response not from proper CA."); } SignatureResponse signatureResponse = signedSignatureResponse.Value; MySqlCommand replaceCommand = new MySqlCommand("REPLACE INTO signatureresponse (Id, Value) VALUES (@Id, @Value)", DbConnection); replaceCommand.Parameters.AddWithValue("@Id", signatureResponse.SubjectId.ToByteArray()); replaceCommand.Parameters.AddWithValue("@Value", signedSignatureResponse.ToBinary()); replaceCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Signature response for certificate id {1} stored on behalf of CA id {2}.", connection.Id, signatureResponse.SubjectId.ToString(), signedSignatureResponse.Certificate.Id.ToString()); if (signatureResponse.Status == SignatureResponseStatus.Accepted) { if (CertificateStorage.Has(signatureResponse.SubjectId)) { Certificate certificate = CertificateStorage.Get(signatureResponse.SubjectId); certificate.AddSignature(signatureResponse.Signature); CertificateStorage.Add(certificate); } Secure<SignatureRequestInfo> secureSignatureRequestInfo = GetSignatureRequestInfo(signatureResponse.SubjectId); SignatureRequestInfo signatureRequestInfo = secureSignatureRequestInfo.Value.Decrypt(this.serverCertificate); if (!signatureRequestInfo.EmailAddress.IsNullOrEmpty()) { SendMail( signatureRequestInfo.EmailAddress, MailType.VoterRequestApproved, signatureRequestInfo.EmailAddress, secureSignatureRequestInfo.Certificate.Id.ToString(), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.English), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.German), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.French)); } } else { Secure<SignatureRequestInfo> secureSignatureRequestInfo = GetSignatureRequestInfo(signatureResponse.SubjectId); SignatureRequestInfo signatureRequestInfo = secureSignatureRequestInfo.Value.Decrypt(this.serverCertificate); if (!signatureRequestInfo.EmailAddress.IsNullOrEmpty()) { SendMail( signatureRequestInfo.EmailAddress, MailType.VoterRequestDeclined, signatureRequestInfo.EmailAddress, secureSignatureRequestInfo.Certificate.Id.ToString(), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.English), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.German), CertificateTypeText(secureSignatureRequestInfo.Certificate, Language.French), signatureResponse.Reason); } } }
/// <summary> /// Deposit a ballot. /// </summary> /// <param name="ballot">Ballot in signed envleope.</param> /// <returns>Vote receipt signed by the server.</returns> public Signed<VoteReceipt> Vote( IRpcConnection connection, Signed<Envelope> signedEnvelope) { if (signedEnvelope == null) throw new ArgumentNullException("ballot"); if (Status != VotingStatus.Voting) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (unverified) tried to vote, but status was {2}.", connection.Id, signedEnvelope.Certificate.Id.ToString(), Status.ToString()); throw new PiArgumentException(ExceptionCode.WrongStatusForOperation, "Wrong status for operation."); } if (!signedEnvelope.Verify(this.certificateStorage)) { if (signedEnvelope.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (unverified) tried to vote, but his certificate had state {2}.", connection.Id, signedEnvelope.Certificate.Id.ToString(), signedEnvelope.Certificate.Validate(this.certificateStorage).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (unverified) tried to vote, but the signature on envelope was invalid.", connection.Id, signedEnvelope.Certificate.Id.ToString()); } throw new PiArgumentException(ExceptionCode.VoteSignatureNotValid, "Vote signature not valid."); } if (!(signedEnvelope.Certificate is VoterCertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but his certificate was not a voter certificate.", connection.Id, signedEnvelope.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.NoVoterCertificate, "Not a voter certificate."); } if (Parameters.GroupId != ((VoterCertificate)signedEnvelope.Certificate).GroupId) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but his group id was {2} when it should have been {3}.", connection.Id, signedEnvelope.Certificate.Id.ToString(), ((VoterCertificate)signedEnvelope.Certificate).GroupId, Parameters.GroupId); throw new PiArgumentException(ExceptionCode.BadGroupIdInCertificate, "Wrong group id in certificate."); } var envelope = signedEnvelope.Value; if (envelope.Date.Subtract(DateTime.Now).TotalHours < -1d || envelope.Date.Subtract(DateTime.Now).TotalHours > 1d) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but the envelope was created at {2} and pushed at {3}.", connection.Id, signedEnvelope.Certificate.Id.ToString(), envelope.Date.ToString(), DateTime.Now.ToString()); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadDateTime, "Invalid envelope. Date out of range."); } if (envelope.VoterId != signedEnvelope.Certificate.Id) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but the envelope voter id did not match his certificate.", connection.Id, signedEnvelope.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadVoterId, "Invalid envelope. Voter id does not match."); } if (envelope.Ballots.Count != Parameters.Questions.Count()) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but there were {2} ballots in the envelope for {3} questions.", connection.Id, signedEnvelope.Certificate.Id.ToString(), envelope.Ballots.Count, Parameters.Questions.Count()); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadBallotCount, "Invalid envelope. Ballot count does not match."); } for (int questionIndex = 0; questionIndex < parameters.Questions.Count(); questionIndex++) { var ballot = envelope.Ballots[questionIndex]; var question = parameters.Questions.ElementAt(questionIndex); if (ballot.SumProves.Count != parameters.ProofCount) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but there were {2} sum proofs present where there sould have been {3}.", connection.Id, signedEnvelope.Certificate.Id.ToString(), ballot.SumProves.Count, parameters.ProofCount); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadProofCount, "Invalid envelope. Number of sum prooves does not match."); } if (ballot.Votes.Count != question.Options.Count()) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but there were {2} votes present for {3} options.", connection.Id, signedEnvelope.Certificate.Id.ToString(), ballot.Votes.Count, question.Options.Count()); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadVoteCount, "Invalid envelope. Vote count does not match."); } if (ballot.Votes.Any(vote => vote.RangeProves.Count != parameters.ProofCount)) { Logger.Log(LogLevel.Warning, "Connection {0}: Voter id {1} (verified) tried to vote, but there was the wrong number of range proofs on a vote.", connection.Id, signedEnvelope.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.InvalidEnvelopeBadProofCount, "Invalid envelope. Number of range prooves does not match."); } } bool hasVoted = DbConnection.ExecuteHasRows( "SELECT count(*) FROM envelope WHERE VotingId = @VotingId AND VoterId = @VoterId", "@VotingId", Id.ToByteArray(), "@VoterId", signedEnvelope.Certificate.Id.ToByteArray()); if (hasVoted) throw new PiArgumentException(ExceptionCode.AlreadyVoted, "Voter has already voted."); MySqlTransaction transaction = DbConnection.BeginTransaction(); MySqlCommand indexCommand = new MySqlCommand( "SELECT max(EnvelopeIndex) + 1 FROM envelope WHERE VotingId = @VotingId", DbConnection, transaction); indexCommand.Add("@VotingId", Id.ToByteArray()); object indexObject = indexCommand.ExecuteScalar(); int envelopeIndex = indexObject == DBNull.Value ? 1 : Convert.ToInt32(indexObject); MySqlCommand insertCommand = new MySqlCommand( "INSERT INTO envelope (VotingId, EnvelopeIndex, VoterId, Value) VALUES (@VotingId, @EnvelopeIndex, @VoterId, @Value)", DbConnection, transaction); insertCommand.Add("@VotingId", Id.ToByteArray()); insertCommand.Add("@VoterId", signedEnvelope.Certificate.Id.ToByteArray()); insertCommand.Add("@Value", signedEnvelope.ToBinary()); insertCommand.Add("@EnvelopeIndex", envelopeIndex); insertCommand.ExecuteNonQuery(); transaction.Commit(); Logger.Log(LogLevel.Info, "Connection {0}: Envelope for certificate id {1} on voting id {2} stored.", connection.Id, signedEnvelope.Certificate.Id.ToString(), Id.ToString()); VoteReceipt voteReceipt = new VoteReceipt(Parameters, signedEnvelope); return new Signed<VoteReceipt>(voteReceipt, this.serverCertificate); }
protected abstract Task HandleMessage(RemoteMessage message, IRpcConnection rpcConnection);
public Signed<SignCheckCookie> GetSignCheckCookie( IRpcConnection connection, Guid notaryId, byte[] code) { var reader = this.DbConnection.ExecuteReader( "SELECT Cookie, Code, Expires FROM signcheckcookie WHERE NotaryId = @NotaryId", "@NotaryId", notaryId.ToByteArray()); if (reader.Read()) { if (DateTime.Now <= reader.GetDateTime(2)) { if (reader.GetBlob(1).Equal(code)) { var signedCookie = Serializable.FromBinary<Signed<SignCheckCookie>>(reader.GetBlob(0)); reader.Close(); Logger.Log(LogLevel.Info, "Connection {0}: Notary id {1} (unverified) got his sign check cookie.", connection.Id, notaryId.ToString()); return signedCookie; } else { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to get his sign check cookie, but the code was invalid.", connection.Id, notaryId.ToString()); reader.Close(); throw new PiSecurityException(ExceptionCode.SignCheckCookieCodeWrong, "Sign check cookie code wrong."); } } else { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to get his sign check cookie, the this had already run out.", connection.Id, notaryId.ToString()); reader.Close(); throw new PiSecurityException(ExceptionCode.SignCheckCookieCodeExpired, "Sign check cookie code has expired."); } } else { Logger.Log(LogLevel.Warning, "Connection {0}: Notary id {1} (unverified) tried to get his sign check cookie, but it was not found.", connection.Id, notaryId.ToString()); throw new PiException(ExceptionCode.SignCheckCookieNotFound, "Sign check cookie not found."); } }
/// <summary> /// Add an authority. /// </summary> /// <param name="certificate">Authority to be added.</param> /// <returns>Index of the authority.</returns> public int AddAuthority( IRpcConnection connection, Certificate certificate) { if (certificate == null) throw new ArgumentNullException("certificate"); if (certificate.Validate(this.certificateStorage) != CertificateValidationResult.Valid) throw new PiSecurityException(ExceptionCode.InvalidCertificate, "Authority certificate not valid."); if (!(certificate is AuthorityCertificate)) throw new PiSecurityException(ExceptionCode.NoAuthorizedAuthority, "No an authority certificate."); MySqlTransaction transaction = DbConnection.BeginTransaction(); MySqlCommand countCommand = new MySqlCommand("SELECT count(*) FROM authority WHERE VotingId = @VotingId", DbConnection, transaction); countCommand.Add("@VotingId", this.parameters.VotingId.ToByteArray()); if ((long)countCommand.ExecuteScalar() >= this.parameters.AuthorityCount) throw new PiArgumentException(ExceptionCode.AlreadyEnoughAuthorities, "Already enough authorities."); MySqlCommand addedCommand = new MySqlCommand("SELECT count(*) FROM authority WHERE VotingId = @VotingId AND AuthorityId = @AuthorityId", DbConnection, transaction); addedCommand.Add("@VotingId", this.parameters.VotingId.ToByteArray()); addedCommand.Add("@AuthorityId", certificate.Id.ToByteArray()); if (addedCommand.ExecuteHasRows()) throw new PiArgumentException(ExceptionCode.AuthorityAlreadyInVoting, "Already an authority of the voting."); MySqlCommand indexCommand = new MySqlCommand("SELECT max(AuthorityIndex) + 1 FROM authority WHERE VotingId = @VotingId", DbConnection, transaction); indexCommand.Add("@VotingId", this.parameters.VotingId.ToByteArray()); object authorityIndexNull = indexCommand.ExecuteScalar(); int authorityIndex = authorityIndexNull == DBNull.Value ? 1 : Convert.ToInt32((long)authorityIndexNull); MySqlCommand insertCommand = new MySqlCommand("INSERT INTO authority (VotingId, AuthorityIndex, AuthorityId, Certificate) VALUES (@VotingId, @AuthorityIndex, @AuthorityId, @Certificate)", DbConnection, transaction); insertCommand.Parameters.AddWithValue("@VotingId", this.parameters.VotingId.ToByteArray()); insertCommand.Parameters.AddWithValue("@AuthorityIndex", authorityIndex); insertCommand.Parameters.AddWithValue("@AuthorityId", certificate.Id.ToByteArray()); insertCommand.Parameters.AddWithValue("@Certificate", certificate.ToBinary()); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Authority id {1} added to voting id {2}", connection.Id, certificate.Id.ToString(), Id.ToString()); transaction.Commit(); return authorityIndex; }
/// <summary> /// Use <see cref="Create"/> for creating new instances. /// </summary> private RpcChannel(RpcPeerInfo remotePeer, IRpcConnection connection, IRpcMethodExecutor executor) { RemotePeer = remotePeer; this.connection = connection; this.executor = executor; }
protected override Task HandleMessage(RemoteMessage message, IRpcConnection rpcConnection) { ThrowIfDisposed(); var iMessage = message.Message; if (iMessage == null) { throw new Exception(RpcErrors.InvalidMessage); } var to = message.To; if (to != null && to != Aid.Unknown) { var actorSystem = to.ActorSystem?.Trim(); if (!String.IsNullOrEmpty(actorSystem) && TryGetBindedSystem(actorSystem, out ActorSystem bindedSystem) && bindedSystem.TryGetInternal(to.Actor, out Pid pid) && pid != null && pid != Aid.Unknown) { var request = iMessage as FutureMessage; if (request is null) { return(pid.Tell(iMessage)); } var response = pid.Request(request); if (response == null) { throw new Exception(RpcErrors.InvalidMessageResponse); } return(response.ContinueWith((previousTask) => { var faulted = previousTask.IsFaulted; if (faulted || previousTask.IsCanceled) { var state = WireMessageState.Empty; state |= faulted ? WireMessageState.Faulted : WireMessageState.Canceled; var wireMessage = new WireMessage { From = to, To = iMessage.From, Exception = faulted ? previousTask.Exception : null, MessageType = faulted ? MessageType.FutureError : MessageType.FutureResponse, Id = message.MessageId ?? WireMessageId.Empty, State = state }; SendMessage(wireMessage, rpcConnection); return; } if (previousTask.IsCompleted) { SendMessage(previousTask.Result.ToWireMessage(iMessage.From, message.MessageId), rpcConnection); } })); } } throw new Exception(RpcErrors.InvalidMessageReceiver); }
public DummyMessageWriter(Stream stream, IRpcConnection conn, string serializerKey) : base(conn, serializerKey) { _stream = stream; }
public RpcMessageWriter(IRpcConnection conn, string serializerKey) { _connnection = conn; InitializeSerializer(serializerKey); }
/// <summary> /// Creates a new voting. /// </summary> /// <param name="votingParameters">Parameters for the voting.</param> /// <param name="authorities">List of authorities to oversee the voting.</param> public void CreateVoting( IRpcConnection connection, Signed<VotingParameters> signedVotingParameters, IEnumerable<AuthorityCertificate> authorities) { if (signedVotingParameters == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "Voting parameters cannot be null."); if (authorities == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "Authority list cannot be null."); VotingParameters votingParameters = signedVotingParameters.Value; if (!signedVotingParameters.Verify(CertificateStorage, votingParameters.VotingBeginDate)) { if (!signedVotingParameters.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Admin {1} (unverified) tried to create voting {2} title {3} but the signature was wrong.", connection.Id, signedVotingParameters.Certificate.Id.ToString(), votingParameters.VotingId.ToString(), votingParameters.Title.Text); } else if (signedVotingParameters.Certificate.Validate(CertificateStorage, votingParameters.VotingBeginDate) != CertificateValidationResult.Valid) { Logger.Log(LogLevel.Warning, "Connection {0}: Admin {1} (unverified) tried to create voting {2} title {3} but his certificate status was {4}.", connection.Id, signedVotingParameters.Certificate.Id.ToString(), votingParameters.VotingId.ToString(), votingParameters.Title.Text, signedVotingParameters.Certificate.Validate(CertificateStorage, votingParameters.VotingBeginDate).ToString()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Admin {1} (unverified) tried to create voting {2} title {3} but his signature was invalid.", connection.Id, signedVotingParameters.Certificate.Id.ToString(), votingParameters.VotingId.ToString(), votingParameters.Title.Text); } throw new PiSecurityException(ExceptionCode.InvalidSignature, "Invalid signature of voting authority."); } if (!(signedVotingParameters.Certificate is AdminCertificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Admin {1} (verified) tried to create voting {2} title {3} but he is a {4}.", connection.Id, signedVotingParameters.Certificate.Id.ToString(), votingParameters.VotingId.ToString(), votingParameters.Title.Text, signedVotingParameters.Certificate.TypeText); throw new PiSecurityException(ExceptionCode.NoAuthorizedAdmin, "No authorized admin."); } if (!CertificateStorage.SignedRevocationLists .Any(signedCrl => signedCrl.Verify(CertificateStorage) && votingParameters.VotingBeginDate >= signedCrl.Value.ValidFrom && votingParameters.VotingBeginDate <= signedCrl.Value.ValidUntil)) { Logger.Log(LogLevel.Info, "Connection {0}: Admin id {1} name {2} tried to create voting {3} title {4} but the voting begin date {5} was not covered by any CRL.", connection.Id, signedVotingParameters.Certificate.Id.ToString(), ((AdminCertificate)signedVotingParameters.Certificate).FullName, votingParameters.VotingId.ToString(), votingParameters.Title.Text, votingParameters.VotingBeginDate.ToString()); throw new PiSecurityException(ExceptionCode.InvalidSignature, "Voting begin date not covered by CRL."); } if (votingParameters.P == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "P cannot be null."); if (votingParameters.Q == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "Q cannot be null."); if (votingParameters.F == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "F cannot be null."); if (votingParameters.G == null) throw new PiArgumentException(ExceptionCode.ArgumentNull, "G cannot be null."); if (!Prime.HasSufficientLength(votingParameters.P, BaseParameters.PrimeBits)) throw new PiException(ExceptionCode.ArgumentNull, "P is not long enough"); if (!Prime.HasSufficientLength(votingParameters.Q, BaseParameters.PrimeBits)) throw new PiException(ExceptionCode.ArgumentNull, "Q is not long enough"); if (!Prime.IsPrimeUnsure(votingParameters.P)) throw new PiArgumentException(ExceptionCode.PIsNoPrime, "P is not prime."); if (!Prime.IsPrimeUnsure((votingParameters.P - 1) / 2)) throw new PiArgumentException(ExceptionCode.PIsNoSafePrime, "P is no safe prime."); if (!Prime.IsPrimeUnsure(votingParameters.Q)) throw new PiArgumentException(ExceptionCode.QIsNoPrime, "Q is not prime."); if (!votingParameters.AuthorityCount.InRange(3, 23)) throw new PiArgumentException(ExceptionCode.AuthorityCountOutOfRange, "Authority count out of range."); if (!votingParameters.Thereshold.InRange(1, votingParameters.AuthorityCount - 1)) throw new PiArgumentException(ExceptionCode.TheresholdOutOfRange, "Thereshold out of range."); foreach (Question question in votingParameters.Questions) { if (question.Options.Count() < 2) throw new PiArgumentException(ExceptionCode.OptionCountOutOfRange, "Option count out of range."); if (!question.MaxVota.InRange(1, question.Options.Count())) throw new PiArgumentException(ExceptionCode.MaxVotaOutOfRange, "Maximum vota out of range."); } if (votingParameters.AuthorityCount != authorities.Count()) throw new PiArgumentException(ExceptionCode.AuthorityCountMismatch, "Authority count does not match number of provided authorities."); if (!authorities.All(authority => authority.Validate(CertificateStorage, votingParameters.VotingBeginDate) == CertificateValidationResult.Valid)) throw new PiArgumentException(ExceptionCode.AuthorityInvalid, "Authority certificate invalid or not recognized."); MySqlCommand insertCommand = new MySqlCommand("INSERT INTO voting (Id, Parameters, Status) VALUES (@Id, @Parameters, @Status)", DbConnection); insertCommand.Parameters.AddWithValue("@Id", votingParameters.VotingId.ToByteArray()); insertCommand.Parameters.AddWithValue("@Parameters", signedVotingParameters.ToBinary()); insertCommand.Parameters.AddWithValue("@Status", (int)VotingStatus.New); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Voting id {1} title {2} is created.", connection.Id, votingParameters.VotingId.ToString(), votingParameters.Title.Text); VotingServerEntity voting = new VotingServerEntity(this, signedVotingParameters, CertificateStorage, this.serverCertificate); authorities.Foreach(authority => voting.AddAuthority(connection, authority)); this.votings.Add(voting.Id, voting); voting.SendAuthorityActionRequiredMail(MailType.AuthorityCreateSharesGreen); }
/// <summary> /// Deposit partial deciphers from an authority. /// </summary> /// <param name="signedPartialDecipherList">Partial decipher list.</param> public void DepositPartialDecipher( IRpcConnection connection, Signed<PartialDecipherList> signedPartialDecipherList) { if (signedPartialDecipherList == null) throw new ArgumentNullException("partialDecipherContainer"); if (Status != VotingStatus.Deciphering) { Logger.Log(LogLevel.Warning, "Authority id {0} (unverified) tried to deposit his partial decipher, but the status was {1}.", signedPartialDecipherList.Certificate.Id.ToString(), Status.ToString()); throw new InvalidOperationException("Wrong status for operation."); } PartialDecipherList partialDecipherList = signedPartialDecipherList.Value; Certificate certificate = GetAuthority(partialDecipherList.AuthorityIndex); if (!signedPartialDecipherList.Verify(this.certificateStorage, Parameters.VotingBeginDate)) { if (signedPartialDecipherList.VerifySimple()) { Logger.Log(LogLevel.Warning, "Authority id {0} (unverified) tried to deposit his partial decipher, but his certificate had state {1}.", signedPartialDecipherList.Certificate.Id.ToString(), signedPartialDecipherList.Certificate.Validate(this.certificateStorage, Parameters.VotingBeginDate).Text()); } else { Logger.Log(LogLevel.Warning, "Authority id {0} (unverified) tried to deposit his partial decipher, but the signature was invalid.", signedPartialDecipherList.Certificate.Id.ToString()); } throw new PiArgumentException(ExceptionCode.InvalidSignature, "Bad signature."); } if (!signedPartialDecipherList.Certificate.IsIdentic(certificate)) { Logger.Log(LogLevel.Warning, "Authority id {0} (verified) tried to deposit his partial decipher, but his certificate did not match id {1} for authority index {2}.", signedPartialDecipherList.Certificate.Id.ToString(), certificate.Id.ToString(), partialDecipherList.AuthorityIndex); throw new PiArgumentException(ExceptionCode.AuthorityInvalid, "Not signed by proper authority."); } if (partialDecipherList.PartialDeciphers.Count < 4) { Logger.Log(LogLevel.Warning, "Authority id {0} (verified) tried to deposit his partial decipher, but there were only {1} parts instead of 4.", signedPartialDecipherList.Certificate.Id.ToString(), partialDecipherList.PartialDeciphers.Count); throw new PiArgumentException(ExceptionCode.AuthorityCountMismatch, "Your Pi-Vote client is outdated."); } bool exists = DbConnection.ExecuteHasRows( "SELECT count(*) FROM deciphers WHERE VotingId = @VotingId AND AuthorityIndex = @AuthorityIndex", "@VotingId", Id.ToByteArray(), "@AuthorityIndex", partialDecipherList.AuthorityIndex); if (exists) throw new ArgumentException("Authority has already deposited shares."); MySqlCommand insertCommand = new MySqlCommand("INSERT INTO deciphers (VotingId, AuthorityIndex, Value) VALUES (@VotingId, @AuthorityIndex, @Value)", DbConnection); insertCommand.Add("@VotingId", Id.ToByteArray()); insertCommand.Add("@AuthorityIndex", partialDecipherList.AuthorityIndex); insertCommand.Add("@Value", signedPartialDecipherList.ToBinary()); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Partical deciphers for certificate id {1} on voting id {2} stored.", connection.Id, signedPartialDecipherList.Certificate.Id.ToString(), Id.ToString()); long depositedShareResponseCount = (long)DbConnection.ExecuteScalar( "SELECT count(*) FROM deciphers WHERE VotingId = @VotingId", "@VotingId", Id.ToByteArray()); SendAdminAuthorityActivityMail(certificate, "deposited partial deciphers"); if (depositedShareResponseCount == this.parameters.Thereshold + 1) { Status = VotingStatus.Finished; } }
/// <summary> /// Delete a voting. /// </summary> /// <param name="votingId">Id of voting to delete.</param> public void DeleteVoting(IRpcConnection connection, Guid votingId) { VotingServerEntity voting = GetVoting(votingId); switch (voting.Status) { case VotingStatus.New: case VotingStatus.Sharing: case VotingStatus.Ready: voting.Delete(); Logger.Log(LogLevel.Info, "Connection {0}: Voting id {1} title {2} is deleted.", connection.Id, voting.Parameters.VotingId.ToString(), voting.Parameters.Title.Text); this.votings.Remove(votingId); break; default: Logger.Log(LogLevel.Warning, "Connection {0}: Tried to delete voting id {1} title {2} but it was in state {3}.", connection.Id, voting.Parameters.VotingId.ToString(), voting.Parameters.Title.Text, voting.Status.ToString()); throw new PiException(ExceptionCode.CommandNotAllowedInStatus, "Deletion of voting is not allowed in current status."); } }
/// <summary> /// Deposit a share part from authorities. /// </summary> /// <param name="signedSharePart">Share part.</param> public void DepositShares( IRpcConnection connection, Signed<SharePart> signedSharePart) { if (signedSharePart == null) throw new ArgumentNullException("shares"); if (Status != VotingStatus.New) { Logger.Log(LogLevel.Warning, "Connection {0}: Authority id {1} (unverified) tried to deposit shares, but the status was {2}.", connection.Id, signedSharePart.Certificate.Id.ToString(), Status.ToString()); throw new PiArgumentException(ExceptionCode.WrongStatusForOperation, "Wrong status for operation."); } SharePart sharePart = signedSharePart.Value; Certificate certificate = GetAuthority(sharePart.AuthorityIndex); if (!signedSharePart.Verify(this.certificateStorage, Parameters.VotingBeginDate)) { if (signedSharePart.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Authority id {1} (unverified) tried to deposit shares, but his certificate had state {2}.", connection.Id, signedSharePart.Certificate.Id.ToString(), signedSharePart.Certificate.Validate(this.certificateStorage, Parameters.VotingBeginDate).Text()); } else { Logger.Log(LogLevel.Warning, "Connection {0}: Authority id {1} (unverified) tried to deposit shares, but the signature was invalid.", connection.Id, signedSharePart.Certificate.Id.ToString()); } throw new PiSecurityException(ExceptionCode.InvalidSignature, "Bad signature."); } if (!signedSharePart.Certificate.IsIdentic(certificate)) { Logger.Log(LogLevel.Warning, "Connection {0}: Authority id {1} (verified) tried to deposit shares, but his certificate did not match id {2} for authority index {3}.", connection.Id, signedSharePart.Certificate.Id.ToString(), certificate.Id.ToString(), sharePart.AuthorityIndex); throw new PiSecurityException(ExceptionCode.NoAuthorizedAuthority, "Not signed by proper authority."); } bool exists = DbConnection.ExecuteHasRows( "SELECT count(*) FROM sharepart WHERE VotingId = @VotingId AND AuthorityIndex = @AuthorityIndex", "@VotingId", Id.ToByteArray(), "@AuthorityIndex", sharePart.AuthorityIndex); if (exists) { Logger.Log(LogLevel.Warning, "Connection {0}: uthority id {1} (verified) tried to deposit shares, these were already present.", connection.Id, signedSharePart.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.AuthorityHasAlreadyDeposited, "Authority has already deposited shares."); } MySqlCommand insertCommand = new MySqlCommand("INSERT INTO sharepart (VotingId, AuthorityIndex, Value) VALUES (@VotingId, @AuthorityIndex, @Value)", DbConnection); insertCommand.Add("@VotingId", Id.ToByteArray()); insertCommand.Add("@AuthorityIndex", sharePart.AuthorityIndex); insertCommand.Add("@Value", signedSharePart.ToBinary()); insertCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Shares for certificate id {1} on voting id {2} stored.", connection.Id, signedSharePart.Certificate.Id.ToString(), Id.ToString()); long depositedSharePartCount = (long)DbConnection.ExecuteScalar( "SELECT count(*) FROM sharepart WHERE VotingId = @VotingId", "@VotingId", Id.ToByteArray()); SendAdminAuthorityActivityMail(certificate, "deposited shares"); if (depositedSharePartCount == this.parameters.AuthorityCount) { Status = VotingStatus.Sharing; } }
/// <summary> /// Set a signature request. /// </summary> /// <remarks> /// Add or replaces a signature request. /// </remarks> /// <param name="signatureRequest">Signed signature request.</param> public void SetSignatureRequest( IRpcConnection connection, Secure<SignatureRequest> signatureRequest, Secure<SignatureRequestInfo> signatureRequestInfo) { Guid id = signatureRequest.Certificate.Id; if (signatureRequest.Certificate.Id != signatureRequestInfo.Certificate.Id) { Logger.Log(LogLevel.Warning, "Connection {0}: Certificate id {1} (unverified) tried to set a signature request, but the certificate id on the request info was {2}.", connection.Id, signatureRequest.Certificate.Id.ToString(), signatureRequestInfo.Certificate.Id); throw new PiArgumentException(ExceptionCode.SignatureRequestInvalid, "Signature request invalid."); } if (!signatureRequest.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Certificate id {1} (unverified) tried to set a signature request, but the signature on the request was invalid.", connection.Id, signatureRequest.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.SignatureRequestInvalid, "Signature request invalid."); } if (!signatureRequestInfo.VerifySimple()) { Logger.Log(LogLevel.Warning, "Connection {0}: Certificate id {1} (unverified) tried to set a signature request, but the signature on the request info was invalid.", connection.Id, signatureRequest.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.SignatureRequestInvalid, "Signature request invalid."); } SignatureRequestInfo requestInfo = signatureRequestInfo.Value.Decrypt(this.serverCertificate); if (!requestInfo.Valid) { Logger.Log(LogLevel.Warning, "Connection {0}: Certificate id {1} (unverified) tried to set a signature request, but the request data was invalid.", connection.Id, signatureRequest.Certificate.Id.ToString()); throw new PiArgumentException(ExceptionCode.InvalidSignatureRequest, "Signature request data not valid."); } MySqlCommand replaceCommand = new MySqlCommand("REPLACE INTO signaturerequest (Id, Value, Info) VALUES (@Id, @Value, @Info)", DbConnection); replaceCommand.Parameters.AddWithValue("@Id", id.ToByteArray()); replaceCommand.Parameters.AddWithValue("@Value", signatureRequest.ToBinary()); replaceCommand.Parameters.AddWithValue("@Info", signatureRequestInfo.ToBinary()); replaceCommand.ExecuteNonQuery(); Logger.Log(LogLevel.Info, "Connection {0}: Signature request for certificate id {1} stored.", connection.Id, signatureRequest.Certificate.Id.ToString()); MySqlCommand deleteCommand = new MySqlCommand("DELETE FROM signatureresponse WHERE Id = @Id", DbConnection); deleteCommand.Parameters.AddWithValue("@Id", id.ToByteArray()); deleteCommand.ExecuteNonQuery(); if (signatureRequest.Certificate is AuthorityCertificate) { CertificateStorage.Add(signatureRequest.Certificate); } if (!requestInfo.EmailAddress.IsNullOrEmpty()) { SendMail( requestInfo.EmailAddress, MailType.VoterRequestDeposited, requestInfo.EmailAddress, signatureRequest.Certificate.Id.ToString(), CertificateTypeText(signatureRequest.Certificate, Language.English), CertificateTypeText(signatureRequest.Certificate, Language.German), CertificateTypeText(signatureRequest.Certificate, Language.French)); } SendMail( this.serverConfig.MailAdminAddress, MailType.AdminNewRequest, requestInfo.EmailAddress.IsNullOrEmpty() ? "?@?.?" : requestInfo.EmailAddress, signatureRequest.Certificate.Id.ToString(), signatureRequest.Certificate.TypeText); }
protected abstract Task SendMessage(WireMessage message, IRpcConnection rpcConnection);