Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement our own network code If we want to encrypt the traffic with the server, we need to be able to work with the socket. SDL_net provides a nice interface, but in the process abstracts away most of the details we need to be able to use SSL. So implement our own socket type. Furthermore, split off the networking part of the message handling from multiplayer.c, into a separate file, and use the new TCPSocket. In time we may get rid of other uses of SDL_net in the code too. This is early code. * Initial version of encrypted connections Encrypt connection using TLS (or the highest encryption scheme both client and server support). This requires server support to function, so it does not yet work. Lightly tested with a toy server. * Move IPAddress struct to separate file * If encryption is used, encrypt directly from the start, don't wait for invitation from the server * Add peek() method to socket, to check incoming network data without removing it. * Verify server certificates * Add function to set blocking mode of sockets, make client sockets blocking by default * Add (optiona;) encryption field to servers.lst Add an optional Encryption column to the servers.lst file between the Port and Description fields that determines whether the connection should be encrypted. If the columns contains "crypt", "encrypt", or "encrypted", the connection should be encrypted, if it contains "plain" or "clear", or is left empty, the connection is not encrypted. The match is case-insensitive. Please note that the field is optional, so any other value than the 5 listed above will be parsed as part of the description. Conversely, server descriptions should not start with any of the five reserved words unless the encryption column is explicitly set. Since the field is optional, existing servers,lst files should still work. Note that the new field is only parsed when the client is compiled with USE_SSL defined. Otherwise, any contents of the encryption column will be added to the description. * Fix parsing over servers.lst when USE_SSL is off. * Fix for parsing servers.lst The field width for strings in a sscanf() format string does not include the terminating NULL byte. Leave room for that. Found by address sanitizer. * Encrypted connection fixes: *) Make connecting and setting up encryption a single operation. Otherwise, on reconnect, the reader thread will start reading after the connection is made, butbefore encryption is set up, wreaking havoc on the TLS handshake. *) Get rid of the mutex on incoming data. It does not protect anything, as only the reader thread accesses the incoming data buffer. *) Set a flag on login, so that on reconnect the login information is automatically sent again *) Properly close the SSL session before closing the socket, if possible *) Protect the SSL object by a mutex to prevent simultaneous reads and writes which OpenSSL cannot handle * Documentation updates * Add C++ abstraction for windows Add a C++ Window class that wraps the C window_info struct, and can automatically register event handlers and handle capturing lambdas as callbacks. This class does not yet expose the full set of window and widget capabilties, and will probably evolve further. But it is a base to start from. * Add text popup Add a new class for text popups that can display a text message and a set of buttons with various callbacks underneath. This is heavily inspired by the serverpopup window, but adds the ability to add multiple buttons. The server popup could be trivially reimplemented in terms of this class. * Show a warning popup when certificate check fails If the certificate sent by the server over an encrypted connection cannot be verified, show a popup dialog to the user with a warning emssage, and options to either disconnect, or continue accepting the risks. * Clean up connection before exit. Welcome to the wonderful world of global statics. The destructor of the Connection singleton may be called after the context menu container singleton. This is a problem since the Connection can contain a (popup) window, that will try to clean up its (non-existant) context menu upon destruction, and tries to look itself up in the destroyed container. Ensure the popup is destroyed before the program finsihes. * Add CMake support for building with SSL * Load certificates from game directories Load SSL certificates from both the game data directory, and the user's configuration directory instead of the current working directory. * Open servers.lst in binary mode Although servers.lst is a text file, open it in binary mode as otherwise the check on the number of bytes read will fail on Windows (or other platforms that use multiple characters to specify end of line). * Changes to make the new network code compile on Windows * Make connection actually work on windows Fixes to make connections actually work on windows: initialize the winsock library and fix an invalid check on the file descriptor leading to the socket not actually calling connect(). * More network initialization/deinitialization Clean up after the last socket is destroyed. Initialize in the constructor, not on connect, and don't throw an exception on failure to initialize. We might be able to catch it, but if the initialization fails, we will refuse to connect anyway. * Proper cleanup after socket Actually clean up when the last socket is destroyed, and properly serialize access to the shared network state. * Make unverified certificate warning translatable * Don't expand unverified signature popup to full screen width. The popup window becomes very wide with the current warning message, limit it to ~80 characters of text. * Let's not destroy the invalid certificate warning window in one of its event handlers. Although it might work in this case, that's asking for trouble. Simply hide the window when a button is clicked, but keep it alive. * Include fix for FreeBSD. Apparently these are pulled in somehow on Linux, but not FreeBSD * The disconnected variable is only used when USE_SSL is not defined, move it inside #ifdef guard * Add hostname verification for encrypted connections * More translatable strings * Log the TLS version used to set up the encryption on the channel * Log the encryption cipher used for encrypted connections * Generate password keys more securely. When using SSL, generate the key for the password file using a cyptographically secure random number generator. Otherwise, on non-Windows systems, try to seed the random number generator with a truly random seed. Doing the same on Windows is a bit problematic: rand_s() is not supported by gcc on MSYS, using RtlGenRandom() directly is a pain, and pulling in the full crypto system (either the old and deprecated one or the new one) feel like overkill if we already have OpenSSL support. So for now, the situation on Windows remain unchanged when USE_SSL is not enabled. This only affects the generation of new password keys. Also the key format hasn't changed, so existing clients can decode newly generated keys.
- Loading branch information