diff options
Diffstat (limited to 'lib/MasterServer/Core/Secure.pm')
| -rwxr-xr-x | lib/MasterServer/Core/Secure.pm | 128 |
1 files changed, 56 insertions, 72 deletions
diff --git a/lib/MasterServer/Core/Secure.pm b/lib/MasterServer/Core/Secure.pm index 07e48b8..51d1832 100755 --- a/lib/MasterServer/Core/Secure.pm +++ b/lib/MasterServer/Core/Secure.pm @@ -8,11 +8,8 @@ use Exporter 'import'; our @EXPORT = qw| load_ciphers secure_string - validated_beacon - validated_request - validate_string - charshift - get_validate_string |; + validate_string + compare_challenge |; ################################################################################ ## Supported Games list ciphers @@ -21,7 +18,6 @@ our @EXPORT = qw| load_ciphers ## data/supportedgames.pl file. ## ## Only config files after 5 October 2015 work with this script. -## IMPORTANT! Afterwards, the $self->{game} hash will be cleared! ################################################################################ sub load_ciphers { my $self = shift; @@ -47,14 +43,13 @@ sub load_ciphers { $self->{dbh}->rollback; $self->halt(); } - } # commit $self->{dbh}->commit; $self->log("info", "Cipher database successfully updated!"); - # unload the game variables from memory + # unload the game variables from masterserver memory $self->{game} = undef; } @@ -78,82 +73,54 @@ sub secure_string { # authenticate the \validate\ response for the \secure\ challenge. # returns 1 on valid response, 0 on invalid ################################################################################ -sub validated_beacon { - my ($self, $gamename, $secure, $enctype, $validate) = @_; +sub compare_challenge { + my ($self, %o) = @_; # debugging enabled? Then don't care about validation return 1 if ($self->{debug_validate}); - # enctype given? - $enctype = 0 unless $enctype; + # secure string too long? (because vulnerable in UE) + return 0 if (length $o{secure} > 16); - if ($self->{ignore_beacon_key} =~ m/$gamename/i){ - $self->log("secure", "ignored beacon validation for $gamename"); - return 1; - } + # additional conditions to skip checking provided? + $o{ignore} = "" unless $o{ignore}; - # compare received response with expected response - return ($self->validate_string($gamename, $secure, $enctype) eq $validate) || 0; -} + # ignore this game if asked to do so + if ($o{ignore} =~ m/$o{gamename}/i){ + $self->log("secure", "ignored beacon validation for $o{gamename}"); + return 1; + } -################################################################################ -# authenticate the \validate\ response for the \secure\ challenge. -# returns 1 on valid response, 0 on invalid -################################################################################ -sub validated_request { - my ($self, $gamename, $secure, $enctype, $validate) = @_; - - # debugging enabled? Then don't care about validation - return 1 if ($self->{debug_validate}); + # enctype given? + $o{enctype} = 0 unless $o{enctype}; - # enctype given? - $enctype = 0 unless $enctype; + # get cipher corresponding with the gamename + my $cip = $self->get_game_props($o{gamename})->{cipher}; - # ignore games and beacons that are listed - if ($self->{ignore_browser_key} =~ m/$gamename/i){ - $self->log("secure", "ignored browser validation for $gamename"); - return 1; - } - - # compare received response with expected response - return ($self->validate_string($gamename, $secure, $enctype) eq $validate) || 0; + # calculate validate string + my $val = get_validate_string($cip, $o{secure}, $o{enctype}); + + # return whether or not they match + return ($val eq $o{validate}); } ################################################################################ -# process the validate string as a response to the secure challenge -# returns: validate string (usually 8 characters long) +# obtain the secure/validate challenge string ################################################################################ sub validate_string { - my ($self, $game, $sec, $enc) = @_; + my ($self, %o) = @_; - # get cipher from gamename - my $cip = $self->get_cipher($game); + # secure string too long? (because vulnerable in UE) + return 0 if (length $o{secure} > 16); - # don't accept challenge longer than 16 characters (because vulnerable in UE) - if (length $sec > 16) { - return "invalid!"} + # get cipher from gamename + my $cip = $self->get_game_props(lc $o{gamename})->{cipher}; - # check for valid encryption choices - my $enc_val = (defined $enc && 0 <= $enc && $enc <= 2) ? $enc : 0; + # enctype given? + $o{enctype} = 0 unless $o{enctype}; # calculate and return validate string - return $self->get_validate_string($cip, $sec, $enc_val); -} - -################################################################################ -# rotate characters as part of the secure/validate algorithm. -# arg and return: int (representing a character) -################################################################################ -sub charshift { - my ($self, $reg) = @_; - return($reg + 65) if ($reg < 26); - return($reg + 71) if ($reg < 52); - return($reg - 4) if ($reg < 62); - return(43) if ($reg == 62); - return(47) if ($reg == 63); - - # if all else fails - return(0); + return get_validate_string($cip, $o{secure}, $o{enctype}); } ################################################################################ @@ -166,14 +133,15 @@ sub charshift { # was released under the GNU General Public License, for more information, see # the original software at http://aluigi.altervista.org/papers.htm#gsmsalg # -# conversion and modification of the algorithm by Darkelarious, June 2014. +# conversion and modification of the algorithm by Darkelarious, June 2014 with +# explicit, written permission of Luigi Auriemma. # # args: game cipher, 6-char challenge string, encryption type # returns: validate string (usually 8 characters long) # !! requires cipher hash to be configured in config! (imported or otherwise) ################################################################################ sub get_validate_string { - my ($self, $cipher_string, $secure_string, $enctype) = @_; + my ($cipher_string, $secure_string, $enctype) = @_; # use pre-built rotations for enctype # -- see GSMSALG 0.3.3 reference for copyright and more information @@ -245,7 +213,7 @@ sub get_validate_string { $tmp[$i] = $sec[$i] ^ $enc[($l + $m) & 0xff]; } -# part of the enctype 1-2 process + # part of the enctype 1-2 process for($sec_len = $i; $sec_len % 3; $sec_len++) { $tmp[$sec_len] = 0; } @@ -270,10 +238,10 @@ sub get_validate_string { $m = $m % 256; $n = $tmp[$i + 2]; $n = $n % 256; - $val[$p++] = $self->charshift($l >> 2); - $val[$p++] = $self->charshift((($l & 3 ) << 4) | ($m >> 4)); - $val[$p++] = $self->charshift((($m & 15) << 2) | ($n >> 6)); - $val[$p++] = $self->charshift($n & 63); + $val[$p++] = charshift($l >> 2); + $val[$p++] = charshift((($l & 3 ) << 4) | ($m >> 4)); + $val[$p++] = charshift((($m & 15) << 2) | ($n >> 6)); + $val[$p++] = charshift($n & 63); } # return to ascii characters @@ -283,4 +251,20 @@ sub get_validate_string { return $str; } +################################################################################ +# rotate characters as part of the secure/validate algorithm. +# arg and return: int (representing a character) +################################################################################ +sub charshift { + my $reg = shift; + return($reg + 65) if ($reg < 26); + return($reg + 71) if ($reg < 52); + return($reg - 4) if ($reg < 62); + return(43) if ($reg == 62); + return(47) if ($reg == 63); + + # if all else fails + return(0); +} + 1; |
