From 03415c261dea93417ed19dfcc1f92c4b5b4666b8 Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Wed, 14 Dec 2016 22:18:24 -0500 Subject: [PATCH] Added netplay spectator password separate from play password --- command.c | 3 ++- configuration.c | 1 + configuration.h | 3 ++- network/netplay/netplay.h | 6 ++++-- network/netplay/netplay_frontend.c | 7 +++--- network/netplay/netplay_handshake.c | 33 +++++++++++++++++++++++------ network/netplay/netplay_init.c | 12 ++++++----- network/netplay/netplay_io.c | 3 +++ network/netplay/netplay_private.h | 23 +++++++++++++------- 9 files changed, 64 insertions(+), 27 deletions(-) diff --git a/command.c b/command.c index 304e13ffca..510b3c5ab2 100644 --- a/command.c +++ b/command.c @@ -2364,7 +2364,8 @@ bool command_event(enum event_command cmd, void *data) if (!init_netplay( data, settings->netplay.server, settings->netplay.port, - settings->netplay.password)) + settings->netplay.password, + settings->netplay.spectate_password)) return false; #endif break; diff --git a/configuration.c b/configuration.c index 8d3c52aaef..33d65f2a7c 100644 --- a/configuration.c +++ b/configuration.c @@ -608,6 +608,7 @@ static int populate_settings_path(settings_t *settings, struct config_path_setti #ifdef HAVE_NETWORKING SETTING_PATH("netplay_ip_address", settings->netplay.server, false, NULL, true); SETTING_PATH("netplay_password", settings->netplay.password, false, NULL, true); + SETTING_PATH("netplay_spectate_password", settings->netplay.spectate_password, false, NULL, true); #endif SETTING_PATH("recording_output_directory", global->record.output_dir, false, NULL, true); diff --git a/configuration.h b/configuration.h index 993a987968..ade5ac6815 100644 --- a/configuration.h +++ b/configuration.h @@ -405,7 +405,8 @@ typedef struct settings unsigned check_frames; bool swap_input; bool nat_traversal; - char password[127]; + char password[128]; + char spectate_password[128]; } netplay; #endif diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h index ea377ccc65..3d87d620da 100644 --- a/network/netplay/netplay.h +++ b/network/netplay/netplay.h @@ -62,7 +62,8 @@ size_t audio_sample_batch_net(const int16_t *data, size_t frames); * @direct_host : Host to connect to directly, if applicable (client only) * @server : server address to connect to (client only) * @port : TCP port to host on/connect to - * @password : Password required to connect (server only) + * @play_password : Password required to play (server only) + * @spectate_password : Password required to connect (server only) * * Initializes netplay. * @@ -70,7 +71,8 @@ size_t audio_sample_batch_net(const int16_t *data, size_t frames); * * Returns: true (1) if successful, otherwise false (0). **/ -bool init_netplay(void *direct_host, const char *server, unsigned port, const char *password); +bool init_netplay(void *direct_host, const char *server, unsigned port, + const char *play_password, const char *spectate_password); void deinit_netplay(void); diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index f69695a368..73754c8672 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -824,7 +824,8 @@ void deinit_netplay(void) * @direct_host : Host to connect to directly, if applicable (client only) * @server : server address to connect to (client only) * @port : TCP port to host on/connect to - * @password : Password required to connect (server only) + * @play_password : Password required to play (server only) + * @spectate_password : Password required to connect (server only) * * Initializes netplay. * @@ -833,7 +834,7 @@ void deinit_netplay(void) * Returns: true (1) if successful, otherwise false (0). **/ bool init_netplay(void *direct_host, const char *server, unsigned port, - const char *password) + const char *play_password, const char *spectate_password) { struct retro_callbacks cbs = {0}; settings_t *settings = config_get_ptr(); @@ -889,7 +890,7 @@ bool init_netplay(void *direct_host, const char *server, unsigned port, netplay_is_client ? direct_host : NULL, netplay_is_client ? server : NULL, port ? port : RARCH_DEFAULT_PORT, - password, + play_password, spectate_password, settings->netplay.delay_frames, settings->netplay.check_frames, &cbs, settings->netplay.nat_traversal, settings->username, quirks); diff --git a/network/netplay/netplay_handshake.c b/network/netplay/netplay_handshake.c index 86a0791c7a..90e6cc7996 100644 --- a/network/netplay/netplay_handshake.c +++ b/network/netplay/netplay_handshake.c @@ -240,7 +240,7 @@ bool netplay_handshake_init_send(netplay_t *netplay, struct netplay_connection * header[1] = htonl(*content_crc_ptr); header[2] = htonl(netplay_platform_magic()); header[3] = htonl(NETPLAY_COMPRESSION_SUPPORTED); - if (netplay->is_server && netplay->password[0]) + if (netplay->is_server && (netplay->play_password[0] || netplay->spectate_password[0])) { /* Demand a password */ if (simple_rand_next == 1) @@ -542,13 +542,14 @@ bool netplay_handshake_pre_nick(netplay_t *netplay, struct netplay_connection *c if (netplay->is_server) { - if (netplay->password[0]) + if (netplay->play_password[0] || netplay->spectate_password[0]) { /* There's a password, so just put them in PRE_PASSWORD mode */ connection->mode = NETPLAY_CONNECTION_PRE_PASSWORD; } else { + connection->can_play = true; if (!netplay_handshake_sync(netplay, connection)) return false; } @@ -572,6 +573,7 @@ bool netplay_handshake_pre_password(netplay_t *netplay, struct netplay_connectio char password[8+NETPLAY_PASS_LEN]; /* 8 for salt */ ssize_t recvd; char msg[512]; + bool correct; msg[0] = '\0'; @@ -594,15 +596,32 @@ bool netplay_handshake_pre_password(netplay_t *netplay, struct netplay_connectio return false; } - /* Calculate the correct password */ + /* Calculate the correct password hash(es) and compare */ + correct = false; snprintf(password, sizeof(password), "%08X", connection->salt); - strlcpy(password + 8, netplay->password, sizeof(password)-8); - sha256_hash(corr_password_buf.password, (uint8_t *) password, strlen(password)); + if (netplay->play_password[0]) + { + strlcpy(password + 8, netplay->play_password, sizeof(password)-8); + sha256_hash(corr_password_buf.password, (uint8_t *) password, strlen(password)); + if (!memcmp(password_buf.password, corr_password_buf.password, sizeof(password_buf.password))) + { + correct = true; + connection->can_play = true; + } + } + if (netplay->spectate_password[0]) + { + strlcpy(password + 8, netplay->spectate_password, sizeof(password)-8); + sha256_hash(corr_password_buf.password, (uint8_t *) password, strlen(password)); + if (!memcmp(password_buf.password, corr_password_buf.password, sizeof(password_buf.password))) + correct = true; + } - /* Compare them */ - if (memcmp(password_buf.password, corr_password_buf.password, sizeof(password_buf.password))) + /* Just disconnect if it was wrong */ + if (!correct) return false; + /* Otherwise, we're ready! */ if (!netplay_handshake_sync(netplay, connection)) return false; diff --git a/network/netplay/netplay_init.c b/network/netplay/netplay_init.c index ec6fd26d83..dcbd2e71cb 100644 --- a/network/netplay/netplay_init.c +++ b/network/netplay/netplay_init.c @@ -388,7 +388,8 @@ static bool netplay_init_buffers(netplay_t *netplay, unsigned frames) * @direct_host : Netplay host discovered from scanning. * @server : IP address of server. * @port : Port of server. - * @password : Password required to connect. + * @play_password : Password required to play. + * @spectate_password : Password required to connect. * @delay_frames : Amount of delay frames. * @check_frames : Frequency with which to check CRCs. * @cb : Libretro callbacks. @@ -402,9 +403,9 @@ static bool netplay_init_buffers(netplay_t *netplay, unsigned frames) * Returns: new netplay handle. **/ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, - const char *password, unsigned delay_frames, unsigned check_frames, - const struct retro_callbacks *cb, bool nat_traversal, const char *nick, - uint64_t quirks) + const char *play_password, const char *spectate_password, + unsigned delay_frames, unsigned check_frames, const struct retro_callbacks + *cb, bool nat_traversal, const char *nick, uint64_t quirks) { netplay_t *netplay = (netplay_t*)calloc(1, sizeof(*netplay)); if (!netplay) @@ -437,7 +438,8 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, } strlcpy(netplay->nick, nick[0] ? nick : RARCH_DEFAULT_NICK, sizeof(netplay->nick)); - strlcpy(netplay->password, password ? password : "", sizeof(netplay->password)); + strlcpy(netplay->play_password, play_password ? play_password : "", sizeof(netplay->play_password)); + strlcpy(netplay->spectate_password, spectate_password ? spectate_password : "", sizeof(netplay->spectate_password)); if (!init_socket(netplay, direct_host, server, port)) { diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index cc4ef274ea..ab603ed386 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -566,6 +566,9 @@ static bool netplay_get_cmd(netplay_t *netplay, if (!netplay->is_server) return netplay_cmd_nak(netplay, connection); + if (!connection->can_play) + break; + /* Find an available player slot */ for (player = 0; player <= netplay->player_max; player++) { diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 42c6e80695..81c4a2fb05 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -260,6 +260,9 @@ struct netplay_connection /* Salt associated with password transaction */ uint32_t salt; + /* Is this connection allowed to play (server only)? */ + bool can_play; + /* Buffers for sending and receiving data */ struct socket_buffer send_packet_buffer, recv_packet_buffer; @@ -288,8 +291,11 @@ struct netplay /* TCP connection for listening (server only) */ int listen_fd; + /* Password required to play (server only) */ + char play_password[NETPLAY_PASS_LEN]; + /* Password required to connect (server only) */ - char password[NETPLAY_PASS_LEN]; + char spectate_password[NETPLAY_PASS_LEN]; /* Our player number */ uint32_t self_player; @@ -420,23 +426,24 @@ void input_poll_net(void); * @direct_host : Netplay host discovered from scanning. * @server : IP address of server. * @port : Port of server. - * @password : Password required to connect. + * @play_password : Password required to play. + * @spectate_password : Password required to connect. * @delay_frames : Amount of delay frames. * @check_frames : Frequency with which to check CRCs. * @cb : Libretro callbacks. * @nat_traversal : If true, attempt NAT traversal. * @nick : Nickname of user. - * @quirks : Netplay quirks. + * @quirks : Netplay quirks required for this session. * - * Creates a new netplay handle. A NULL host means we're + * Creates a new netplay handle. A NULL host means we're * hosting (user 1). * * Returns: new netplay handle. **/ -netplay_t *netplay_new(void *direct_host, const char *server, - uint16_t port, const char *password, unsigned delay_frames, - unsigned check_frames, const struct retro_callbacks *cb, - bool nat_traversal, const char *nick, uint64_t quirks); +netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, + const char *play_password, const char *spectate_password, + unsigned delay_frames, unsigned check_frames, const struct retro_callbacks + *cb, bool nat_traversal, const char *nick, uint64_t quirks); /** * netplay_free: