Permalink
Browse files

CVars for Secure RCon

  • Loading branch information...
mbasaglia committed Nov 13, 2015
1 parent 6fe5601 commit 1c11a0a354fc940db8a3e563405f3d4188f989a1
View
@@ -137,6 +137,8 @@ set(SERVERLIST
${ENGINE_DIR}/server/sv_snapshot.cpp
${ENGINE_DIR}/server/Crypto.cpp
${ENGINE_DIR}/server/Crypto.h
${ENGINE_DIR}/server/CryptoChallenge.cpp
${ENGINE_DIR}/server/CryptoChallenge.h
)
set(ENGINELIST
@@ -0,0 +1,140 @@
/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2015, Daemon Developers
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Daemon developers nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#include "CryptoChallenge.h"
static Cvar::Cvar<int> cvar_server_challenge_timeout(
"server.rcon.challenge.timeout",
"Timeout (in seconds) of a rcon challenge",
Cvar::NONE,
5
);
static Cvar::Cvar<int> cvar_server_challenge_length(
"server.rcon.challenge.length",
"Length in bytes of the challenge data (The hexadecimal representation will be twice as long",
Cvar::NONE,
8
);
static Cvar::Cvar<int> cvar_server_challenge_count(
"server.rcon.challenge.count",
"Maximum number of active challenges kept in memory",
Cvar::NONE,
1024
);
Challenge::Duration Challenge::Timeout()
{
return std::chrono::duration_cast<Duration>( std::chrono::seconds(
cvar_server_challenge_timeout.Get()
) );
}
std::size_t Challenge::Bytes()
{
return cvar_server_challenge_length.Get();
}
std::string Challenge::GenerateString()
{
std::vector<uint8_t> data( Bytes() );
Sys::GenRandomBytes(data.data(), data.size());
std::ostringstream stream;
stream.setf(std::ios::hex, std::ios::basefield);
stream.fill('0');
for ( auto ch : data )
{
stream.width(2);
stream << int( ch );
}
return stream.str();
}
std::size_t ChallengeManager::MaxChallenges() const
{
return cvar_server_challenge_count.Get();
}
std::string ChallengeManager::GenerateChallenge( const netadr_t& source )
{
auto challenge = Challenge( source );
Push( challenge );
return challenge.String();
}
void ChallengeManager::Push( const Challenge& challenge )
{
auto lock = Lock();
Cleanup();
if ( challenges.size() >= MaxChallenges() )
{
challenges.pop_front();
}
challenges.push_back( challenge );
}
bool ChallengeManager::Match( const Challenge& challenge )
{
auto lock = Lock();
Cleanup();
auto it = std::find_if( challenges.begin(), challenges.end(),
[&challenge]( const Challenge& ch ) {
return ch.Matches( challenge );
} );
if ( it != challenges.end() )
{
challenges.erase( it );
return true;
}
return false;
}
void ChallengeManager::Cleanup()
{
auto now = Challenge::Clock::now();
challenges.erase(
std::remove_if( challenges.begin(), challenges.end(),
[&now]( const Challenge& challenge ) {
return !challenge.ValidAt( now );
}
),
challenges.end()
);
}
@@ -44,20 +44,12 @@ class Challenge
/*
* Time duration a challenge will be valid for
*/
static Duration Timeout()
{
// TODO Read this from a cvar
return std::chrono::duration_cast<Duration>( std::chrono::seconds( 5 ) );
}
static Duration Timeout();
/*
* Size of the raw challenge data
*/
static std::size_t Bytes()
{
// TODO Read this from a cvar
return 8;
}
static std::size_t Bytes();
Challenge( const netadr_t& source, const Crypto::Data& challenge )
: valid_until( Clock::now() + Timeout() ),
@@ -112,20 +104,7 @@ class Challenge
/*
* Generates a random challenge
*/
std::string GenerateString()
{
std::vector<uint8_t> data( Bytes() );
Sys::GenRandomBytes(data.data(), data.size());
std::ostringstream stream;
stream.setf(std::ios::hex, std::ios::basefield);
stream.fill('0');
for ( auto ch : data )
{
stream.width(2);
stream << int( ch );
}
return stream.str();
}
std::string GenerateString();
TimePoint valid_until;
Crypto::Data challenge;
@@ -142,62 +121,23 @@ class ChallengeManager
return singleton;
}
std::size_t MaxChallenges() const
{
// TODO Read this from a cvar
return 1024;
}
std::size_t MaxChallenges() const;
/*
* Generates a challenge for the given address and returns the challenge string
*/
std::string GenerateChallenge( const netadr_t& source )
{
auto challenge = Challenge( source );
Push( challenge );
return challenge.String();
}
std::string GenerateChallenge( const netadr_t& source );
/*
* Add a challenge to the pool
*/
void Push( const Challenge& challenge )
{
auto lock = Lock();
Cleanup();
if ( challenges.size() >= MaxChallenges() )
{
challenges.pop_front();
}
challenges.push_back( challenge );
}
void Push( const Challenge& challenge );
/*
* Check if a challenge matches any of the registered ones
* If it does and it's valid, it'll return false
*/
bool Match( const Challenge& challenge )
{
auto lock = Lock();
Cleanup();
auto it = std::find_if( challenges.begin(), challenges.end(),
[&challenge]( const Challenge& ch ) {
return ch.Matches( challenge );
} );
if ( it != challenges.end() )
{
challenges.erase( it );
return true;
}
return false;
}
bool Match( const Challenge& challenge );
private:
ChallengeManager() = default;
@@ -213,18 +153,7 @@ class ChallengeManager
* Removes outdated challenges
* PRE: The caller has acquired a lock on mutex
*/
void Cleanup()
{
auto now = Challenge::Clock::now();
challenges.erase(
std::remove_if( challenges.begin(), challenges.end(),
[&now]( const Challenge& challenge ) {
return !challenge.ValidAt( now );
}
),
challenges.end()
);
}
void Cleanup();
std::mutex mutex;
std::deque<Challenge> challenges;
@@ -346,7 +346,6 @@ extern GameVM gvm; // game virtual machine
extern cvar_t *sv_fps;
extern cvar_t *sv_timeout;
extern cvar_t *sv_zombietime;
extern cvar_t *sv_rconPassword;
extern cvar_t *sv_privatePassword;
extern cvar_t *sv_allowDownload;
extern cvar_t *sv_maxclients;
@@ -35,7 +35,7 @@ Maryland 20850 USA.
// sv_client.c -- server code for dealing with clients
#include "server.h"
#include "CryptoChallege.h"
#include "CryptoChallenge.h"
static void SV_CloseDownload( client_t *cl );
@@ -667,7 +667,6 @@ void SV_Init()
Cvar_Get( "sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM );
// server vars
sv_rconPassword = Cvar_Get( "rconPassword", "", CVAR_TEMP );
sv_privatePassword = Cvar_Get( "sv_privatePassword", "", CVAR_TEMP );
sv_fps = Cvar_Get( "sv_fps", "40", CVAR_TEMP );
sv_timeout = Cvar_Get( "sv_timeout", "240", CVAR_TEMP );
Oops, something went wrong.

0 comments on commit 1c11a0a

Please sign in to comment.