/// <summary> /// Creates and sends an <see cref="AuthenticatePacket"/>. /// </summary> /// <param name="sessionId">Session ID</param> /// <param name="credential">Credentials</param> private void sendAuthenticatePacket(string sessionId, Credential credential) { RaiseLogEntry(new LogEventArgs("Sending AuthenticatePacket", LogLevel.DEBUG)); // Create and populate an authentication packet AuthenticatePacket authPacket = new AuthenticatePacket { AuthType = credential.AuthType, SessionId = sessionId, Username = credential.Username, Password = credential.Password }; // Pack it into an Any for transmission Any packedAuthPacket = ProtobufPacketHelper.Pack(authPacket); // Send it on its way netClient.Send(MODULE_NAME, packedAuthPacket.ToByteArray()); }
/// <summary> /// Handles incoming <see cref="AuthenticatePacket"/>s from clients trying to authenticate. /// </summary> /// <param name="connectionId">Original connection ID</param> /// <param name="packet">Incoming packet</param> private void authenticatePacketHandler(string connectionId, AuthenticatePacket packet) { // Check the supplied credentials are of the appropriate type if (packet.AuthType != authType) { // Fail the authentication attempt due to mismatched credential type sendFailedAuthResponsePacket(connectionId, AuthFailureReason.AuthType, string.Format("Wrong type of credentials supplied. The server only accepts \"{0}\" credentials.", authType.ToString())); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0}: Wrong credential type", connectionId.Highlight(HighlightType.ConnectionID)), LogLevel.DEBUG)); // Stop here return; } lock (sessionsLock) { // Check whether a session exists for this connection or the supplied session ID is assigned to this connection if (!sessions.ContainsKey(connectionId) || sessions[connectionId].SessionId != packet.SessionId) { // Fail the authentication attempt due to invalid session ID sendFailedAuthResponsePacket(connectionId, AuthFailureReason.SessionId, "Could not find session for your connection. It may have expired. Try logging in again."); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0}: No session found for this connection", connectionId.Highlight(HighlightType.ConnectionID)), LogLevel.DEBUG)); // Stop here return; } // Get an alias of the session for simplicity Session session = sessions[connectionId]; // Check if the session has expired if (session.Expiry.CompareTo(DateTime.UtcNow) <= 0) { // Fail the authentication attempt due to expired session sendFailedAuthResponsePacket(connectionId, AuthFailureReason.SessionId, "Session has expired. Try logging in again."); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0} (SessID: {1}): Session expired", connectionId.Highlight(HighlightType.ConnectionID), session.SessionId.Highlight(HighlightType.SessionID)), LogLevel.DEBUG)); // Stop here return; } lock (credentialStoreLock) { // Check if user does not have an existing credential if (!credentialStore.Credentials.ContainsKey(packet.Username)) { // Exception for PhiKey, it should be a 'zero-configuration' solution if (authType == AuthTypes.ClientKey) { // Create a new credential and add it to the credential store Credential newCredential = new Credential { AuthType = AuthTypes.ClientKey, Username = packet.Username, Password = packet.Password }; credentialStore.Credentials.Add(newCredential.Username, newCredential); } else { // Fail the authentication attempt due to missing credential sendFailedAuthResponsePacket(connectionId, AuthFailureReason.Credentials, string.Format("No credential found for the username \"{0}\".", packet.Username.Highlight(HighlightType.Username))); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0} (SessID: {1}): No credentials found for {2}", connectionId.Highlight(HighlightType.ConnectionID), session.SessionId.Highlight(HighlightType.SessionID), packet.Username.Highlight(HighlightType.Username)), LogLevel.DEBUG)); // Stop here return; } } // Add username to the session session.Username = packet.Username; // Get an alias of the user's credential for simplicity Credential credential = credentialStore.Credentials[session.Username]; // Check if the credential is not for our current auth type if (credential.AuthType != authType) { // Delete the offending credential credentialStore.Credentials.Remove(session.Username); // Fail the authentication attempt due to invalid stored credential sendFailedAuthResponsePacket(connectionId, AuthFailureReason.InternalServerError, "Server's stored credential did not match its accepted authentication type. Try logging in again."); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0} (SessID: {1}): Stored credentials for {2} are of wrong type ({3})", connectionId.Highlight(HighlightType.ConnectionID), session.SessionId.Highlight(HighlightType.SessionID), packet.Username.Highlight(HighlightType.Username), credential.AuthType.ToString()), LogLevel.DEBUG)); // Stop here return; } // Check if the password does not match the stored credential // This check is ignored if the auth type is 'ClientKey' as the password does not matter if (authType == AuthTypes.ClientKey && packet.Password != credential.Password) { // Fail the authentication attempt due to mismatching password sendFailedAuthResponsePacket(connectionId, AuthFailureReason.Credentials, "Invalid password provided."); RaiseLogEntry(new LogEventArgs(string.Format("Auth failure for {0} (SessID: {1}): Wrong password provided for {2}", connectionId.Highlight(HighlightType.ConnectionID), session.SessionId.Highlight(HighlightType.SessionID), packet.Username.Highlight(HighlightType.Username)), LogLevel.DEBUG)); // Stop here return; } // Auth attempt made it through the gauntlet, time to accept it as a valid request // Mark the session as authenticated session.Authenticated = true; // Extend their session by 30 minutes TimeSpan expiresIn = TimeSpan.FromMinutes(30); session.Expiry = DateTime.UtcNow + expiresIn; // Approve the authentication attempt sendSuccessfulAuthResponsePacket(connectionId, session.SessionId, (int)expiresIn.TotalMilliseconds); // Log this momentous occasion RaiseLogEntry(new LogEventArgs(string.Format("User \"{0}\" (ConnID: {1}, SessID: {2}) successfully authenticated", session.Username.Highlight(HighlightType.Username), session.ConnectionId.Highlight(HighlightType.ConnectionID), session.SessionId.Highlight(HighlightType.SessionID)))); } } }