[NoCat] Patch: CypherSecret-02.patch
Karl Gaissmaier
karl.gaissmaier at kiz.uni-ulm.de
Mon, 28 Jul 2003 23:57:57 +0200
--------------Boundary-00=_L09RU2RHXYRQ6K8AFHJU
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 8bit
Name:
CypherSecret-02.patch
Affected Files:
authserv.conf
cgi-bin/login
lib/NoCat.pm
Version: Patch against 0.82 or later
Severity:
important, but depends on the user group (we are at a University!)
Prohibits the standard cleartext passwords in the html source
Description:
the cgi param password is replaced with cryptpwd. The algorithm
building the symmetric encryption is the same as in the
radius protocol. The encryption code is nearly literally copied from
Authen::Radius. The already exchanged and periodically altered
token is used as a salt.
Future:
Perhaps with the usage of CGI::Session the whole authentication
and renewal algorithm should be cleaned up and improved.
--
Karl Gaissmaier KIZ/Infrastructure, University of Ulm, Germany
Email:karl.gaissmaier@kiz.uni-ulm.de Service Group Network
--------------Boundary-00=_L09RU2RHXYRQ6K8AFHJU
Content-Type: text/x-diff;
charset="us-ascii";
name="CypherSecret-02.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="CypherSecret-02.patch"
diff -Naur NoCatAuth-nightly/authserv.conf NoCatAuth-mod/authserv.conf
--- NoCatAuth-nightly/authserv.conf Mon Mar 17 23:46:11 2003
+++ NoCatAuth-mod/authserv.conf Mon Jul 14 09:56:42 2003
@@ -12,6 +12,13 @@
#
Verbosity 10
+#
+# CypherSecret -- used for symmetric encryption of the
+# user password. Without a CypherSecret the cleartext password is
+# viewable in the html sources, the browser cache, the history, the ...
+#
+CypherSecret mysecret
+
##
# PGPKeyPath -- The directory in which PGP keys are stored.
# NoCat tries to find this in the pgp/ directory above
diff -Naur NoCatAuth-nightly/cgi-bin/login NoCatAuth-mod/cgi-bin/login
--- NoCatAuth-nightly/cgi-bin/login Thu Aug 15 04:05:18 2002
+++ NoCatAuth-mod/cgi-bin/login Mon Jul 14 10:30:11 2003
@@ -52,6 +52,13 @@
$authserv->display( FatalForm => "Your gateway token is undefined. Problem with the gateway?" )
unless $params->{token};
+# did we get a crypted password, generate the cleartext for authentication
+if ($authserv->{CypherSecret} and not $params->{pass}) {
+ my $salt = $params->{token};
+ $params->{pass} = $authserv->encrypt_pwd($params->{cryptpwd}, $salt)
+ if $params->{cryptpwd};
+};
+
# If the user skipped authentication...
if ( $params->{user} eq ANONYMOUS or $params->{mode} =~ /^skip/io ) {
$params->{user} = ANONYMOUS;
@@ -80,10 +87,27 @@
# Either we're requesting the renewal popup box...
if ( $params->{mode} =~ /^popup/io ) {
$form = ( $params->{gateway} ? "PassiveRenewForm" : "RenewForm" );
+ # create cryptpwd with new token as salt
+ if ($authserv->{CypherSecret}) {
+ my $salt = $params->{token};
+ $params->{cryptpwd} = $authserv->encrypt_pwd($params->{pass}, $salt);
+ # be sure no cleartext password can be in the html forms or url's
+ delete $params->{pass};
+ };
+
$params->{redirect} = $authserv->renew_url;
# Or we're either logging in, or renewing, in which case, notify the gateway.
} elsif ($gw = $authserv->notify( Permit => $params )) {
+
+ # create cryptpwd with new token as salt
+ if ($authserv->{CypherSecret} and not $gw->{Error}) {
+ my $salt = $gw->{Token} || $gw->{token};
+ $params->{cryptpwd} = $authserv->encrypt_pwd($params->{pass}, $salt);
+ # be sure no cleartext password can be in the html forms or url's
+ delete $params->{pass};
+ };
+
if ( $gw->{Error} ) {
# Oddly enough, this isn't really success.
$form = "ExpiredForm";
diff -Naur NoCatAuth-nightly/lib/NoCat.pm NoCatAuth-mod/lib/NoCat.pm
--- NoCatAuth-nightly/lib/NoCat.pm Sun Jul 13 12:00:04 2003
+++ NoCatAuth-mod/lib/NoCat.pm Mon Jul 14 09:56:42 2003
@@ -14,6 +14,7 @@
use FindBin;
use Exporter;
use Carp;
+use Digest::MD5 qw();
use vars qw( @ISA @EXPORT_OK *FILE );
use strict;
@@ -378,6 +379,26 @@
return NoCat::Peer->new( Parent => $self, @_ );
}
+sub encrypt_pwd {
+ # based on the algorithm used in the radius protocol
+ croak "parameter(s) missing" unless scalar @_ == 3;
+ my ($self, $pwd, $token) = @_;
+ my ($i, $ct, @pwdp, @xor);
+
+ # algorithm copied nearly literally from Authen::Radius by kg
+ # this only works for passwords <= 16 chars
+ $pwd .= "\0" x (16 - length($pwd) % 16);
+ @pwdp = unpack('C16', pack('a16', $pwd));
+ $ct = Digest::MD5->new;
+ $ct->add ($self->{CypherSecret}, $token);
+ @xor = unpack('C16', $ct->digest());
+ for $i (0..15) {
+ $pwdp[$i] ^= $xor[$i];
+ }
+
+ pack('C' . length($pwd), @pwdp);
+}
+
1;
__END__
@@ -477,6 +498,8 @@
=item template() Pass a template, and optional hashref, and it returns the filled template.
+=item encrypt_pwd() Symmetrically encrypts a string. Algorithm copied from Authen::Radius()
+
=item gateway() Returns a NoCat::Gateway object
=item firewall() Returns a NoCat::Firewall object
--------------Boundary-00=_L09RU2RHXYRQ6K8AFHJU--