[LON-CAPA-cvs] cvs: loncom(Refactoring) / lond
foxr
lon-capa-cvs@mail.lon-capa.org
Tue, 23 Mar 2004 11:50:12 -0000
This is a MIME encoded message
--foxr1080042612
Content-Type: text/plain
foxr Tue Mar 23 06:50:12 2004 EDT
Modified files: (Branch: Refactoring)
/loncom lond
Log:
Clean compile after refactoring the hell out of the authentication based
functions.
--foxr1080042612
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20040323065012.txt"
Index: loncom/lond
diff -u loncom/lond:1.178.2.12 loncom/lond:1.178.2.13
--- loncom/lond:1.178.2.12 Mon Mar 22 05:02:24 2004
+++ loncom/lond Tue Mar 23 06:50:12 2004
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.178.2.12 2004/03/22 10:02:24 foxr Exp $
+# $Id: lond,v 1.178.2.13 2004/03/23 11:50:12 foxr Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -53,7 +53,7 @@
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.178.2.12 $'; #' stupid emacs
+my $VERSION='$Revision: 1.178.2.13 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid;
my $currentdomainid;
@@ -237,7 +237,7 @@
$namespace=~s/\//\_/g; # / -> _
$namespace=~s/\W//g; # whitespace eliminated.
my $proname = propath($domain, $user);
-
+
# If this is a namespace for which a history is kept,
# make the history log entry:
@@ -739,106 +739,16 @@
chomp($upass);
$upass=unescape($upass);
- # Fetch the user authentication information:
-
- my $realpasswd = GetAuthType($udom, $uname);
- if($realpasswd ne "nouser") { # nouser means no passwd file.
- my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
- my $pwdcorrect=0;
- #
- # Authenticate against password stored in the internal file.
- #
- Debug("Authenticating via $howpwd");
- if ($howpwd eq 'internal') {
- &Debug("Internal auth");
- $pwdcorrect= (crypt($upass,$contentpwd) eq $contentpwd);
- #
- # Authenticate against the unix password file.
- #
- } elsif ($howpwd eq 'unix') {
- &Debug("Unix auth");
- if((getpwnam($uname))[1] eq "") { #no such user!
- $pwdcorrect = 0;
- } else {
- $contentpwd=(getpwnam($uname))[1];
- my $pwauth_path="/usr/local/sbin/pwauth";
- unless ($contentpwd eq 'x') { # Not in shadow file.
- $pwdcorrect= (crypt($upass,$contentpwd) eq $contentpwd);
- } elsif (-e $pwauth_path) { # In shadow file so
- open PWAUTH, "|$pwauth_path" or # use external program
- die "Cannot invoke authentication";
- print PWAUTH "$uname\n$upass\n";
- close PWAUTH;
- $pwdcorrect=!$?;
- }
- }
- #
- # Authenticate against a Kerberos 4 server:
- #
- } elsif ($howpwd eq 'krb4') {
- my $null=pack("C",0);
- unless ($upass=~/$null/) {
- my $krb4_error = &Authen::Krb4::get_pw_in_tkt($uname,
- "",
- $contentpwd,
- 'krbtgt',
- $contentpwd,
- 1,
- $upass);
- if (!$krb4_error) {
- $pwdcorrect = 1;
- } else {
- $pwdcorrect=0;
- # log error if it is not a bad password
- if ($krb4_error != 62) {
- &logthis('krb4:'.$uname.','.$contentpwd.','.
- &Authen::Krb4::get_err_txt($Authen::Krb4::error));
- }
- }
- }
- #
- # Authenticate against a Kerberos 5 server:
- #
- } elsif ($howpwd eq 'krb5') {
- my $null=pack("C",0);
- unless ($upass=~/$null/) {
- my $krbclient=&Authen::Krb5::parse_name($uname.'@'.$contentpwd);
- my $krbservice="krbtgt/".$contentpwd."\@".$contentpwd;
- my $krbserver=&Authen::Krb5::parse_name($krbservice);
- my $credentials=&Authen::Krb5::cc_default();
- $credentials->initialize($krbclient);
- my $krbreturn = &Authen::Krb5::get_in_tkt_with_password($krbclient,
- $krbserver,
- $upass,
- $credentials);
- $pwdcorrect = ($krbreturn == 1);
- } else {
- $pwdcorrect=0;
- }
- #
- # Finally, the user may have written in an authentication module.
- # in that case, if requested, authenticate against it.
- #
- } elsif ($howpwd eq 'localauth') {
- $pwdcorrect=&localauth::localauth($uname,$upass,$contentpwd);
- }
+ my $pwdcorrect = ValidateUser($udom, $uname, $upass);
+ if($pwdcorrect) {
+ Reply( $client, "authorized\n", $userinput);
#
- # Successfully authorized.
+ # Bad credentials: Failed to authorize
#
- if ($pwdcorrect) {
- Reply( $client, "authorized\n", $userinput);
- #
- # Bad credentials: Failed to authorize
- #
- } else {
- Failure( $client, "non_authorized\n", $userinput);
- }
- # Used to be unknown_user but that allows crackers to
- # distinguish between bad username and bad password so...
- #
} else {
Failure( $client, "non_authorized\n", $userinput);
}
+
return 1;
}
RegisterHandler("auth", \&AuthenticateHandler, 1, 1, 0);
@@ -882,62 +792,44 @@
$upass=&unescape($upass);
$npass=&unescape($npass);
&Debug("Trying to change password for $uname");
- my $realpasswd = GetAuthType($udom, $uname);
- if ($realpasswd ne "nouser") {
+
+ # First require that the user can be authenticated with their
+ # old password:
+
+ my $validated = ValidUser($udom, $uname, $upass);
+ if($validated) {
+ my $realpasswd = GetAuthType($udom, $uname); # Defined since authd.
+
my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
if ($howpwd eq 'internal') {
&Debug("internal auth");
- if (crypt($upass,$contentpwd) eq $contentpwd) {
- my $salt=time;
- $salt=substr($salt,6,2);
- my $ncpass=crypt($npass,$salt);
- if(RewritePwFile($udom, $uname, "internal:$ncpass")) {
- &logthis("Result of password change for "
- ."$uname: pwchange_success");
- Reply($client, "ok\n", $userinput);
- } else {
- &logthis("Unable to open $uname passwd "
- ."to change password");
- Failure( $client, "non_authorized\n",$userinput);
- }
+ my $salt=time;
+ $salt=substr($salt,6,2);
+ my $ncpass=crypt($npass,$salt);
+ if(RewritePwFile($udom, $uname, "internal:$ncpass")) {
+ &logthis("Result of password change for "
+ ."$uname: pwchange_success");
+ Reply($client, "ok\n", $userinput);
} else {
- Failure($client, "non_authorized\n", $userinput);
+ &logthis("Unable to open $uname passwd "
+ ."to change password");
+ Failure( $client, "non_authorized\n",$userinput);
}
} elsif ($howpwd eq 'unix') {
# Unix means we have to access /etc/password
- # one way or another.
- # First: Make sure the current password is
- # correct
&Debug("auth is unix");
- $contentpwd=(getpwnam($uname))[1];
- my $pwdcorrect = "0";
- my $pwauth_path="/usr/local/sbin/pwauth";
- unless ($contentpwd eq 'x') {
- $pwdcorrect= (crypt($upass,$contentpwd) eq $contentpwd);
- } elsif (-e $pwauth_path) {
- open PWAUTH, "|$pwauth_path" or
- die "Cannot invoke authentication";
- print PWAUTH "$uname\n$upass\n";
- close PWAUTH;
- &Debug("exited pwauth with $? ($uname,$upass) ");
- $pwdcorrect=($? == 0);
- }
- if ($pwdcorrect) {
- my $execdir=$perlvar{'lonDaemons'};
- &Debug("Opening lcpasswd pipeline");
- my $pf = IO::File->new("|$execdir/lcpasswd > "
- ."$perlvar{'lonDaemons'}"
- ."/logs/lcpasswd.log");
- print $pf "$uname\n$npass\n$npass\n";
- close $pf;
- my $err = $?;
- my $result = ($err>0 ? 'pwchange_failure' : 'ok');
- &logthis("Result of password change for $uname: ".
- &lcpasswdstrerror($?));
- Reply($client, "$result\n", $userinput);
- } else {
- Reply($client, "non_authorized\n", $userinput);
- }
+ my $execdir=$perlvar{'lonDaemons'};
+ &Debug("Opening lcpasswd pipeline");
+ my $pf = IO::File->new("|$execdir/lcpasswd > "
+ ."$perlvar{'lonDaemons'}"
+ ."/logs/lcpasswd.log");
+ print $pf "$uname\n$npass\n$npass\n";
+ close $pf;
+ my $err = $?;
+ my $result = ($err>0 ? 'pwchange_failure' : 'ok');
+ &logthis("Result of password change for $uname: ".
+ &lcpasswdstrerror($?));
+ Reply($client, "$result\n", $userinput);
} else {
# this just means that the current password mode is not
# one we know how to change (e.g the kerberos auth modes or
@@ -945,12 +837,12 @@
#
Reply( $client, "auth_mode_error\n", $userinput);
}
- } else {
- # used to be unknonw user but that gives out too much info..
- # so make it the same as if the initial passwd was bad.
- #
+
+ }
+ else {
Reply( $client, "non_authorized\n", $userinput);
}
+
return 1;
}
RegisterHandler("passwd", \&ChangePasswordHandler, 1, 1, 0);
@@ -1308,7 +1200,7 @@
}
RegisterHandler("unusb", \&UnsubscribeHandler, 0, 1, 0);
-# Subscribe to a resource.
+# Subscribe to a resource
#
# Parameters:
# $cmd - The command that got us here.
@@ -4247,6 +4139,135 @@
}
}
+#
+# Validate a user given their domain, name and password. This utility
+# function is used by both AuthenticateHandler and ChangePasswordHandler
+# to validate the login credentials of a user.
+# Parameters:
+# $domain - The domain being logged into (this is required due to
+# the capability for multihomed systems.
+# $user - The name of the user being validated.
+# $password - The user's propoposed password.
+#
+# Returns:
+# 1 - The domain,user,pasword triplet corresponds to a valid
+# user.
+# 0 - The domain,user,password triplet is not a valid user.
+#
+sub ValidateUser {
+ my $domain = shift;
+ my $user = shift;
+ my $password= shift;
+
+ # Why negative ~pi you may well ask? Well this function is about
+ # authentication, and therefore very important to get right.
+ # I've initialized the flag that determines whether or not I've
+ # validated correctly to a value it's not supposed to get.
+ # At the end of this function. I'll ensure that it's not still that
+ # value so we don't just wind up returning some accidental value
+ # as a result of executing an unforseen code path that
+ # did not set $validated.
+
+ my $validated = -3.14159;
+
+ # How we authenticate is determined by the type of authentication
+ # the user has been assigned. If the authentication type is
+ # "nouser", the user does not exist so we will return 0.
+
+ my $contents = GetAuthType($domain, $user);
+ my ($howpwd, $contentpwd) = split(/:/, $contents);
+
+ my $null = pack("C",0); # Used by kerberos auth types.
+
+ if ($howpwd ne 'nouser') {
+
+ if($howpwd eq "internal") { # Encrypted is in local password file.
+ $validated = (crypt($password, $contentpwd) eq $contentpwd);
+ }
+ elsif ($howpwd eq "unix") { # User is a normal unix user.
+ $contentpwd = (getpwname($user))[1];
+ if($contentpwd) {
+ if($contentpwd eq 'x') { # Shadow password file...
+ my $pwauth_path = "/usr/local/sbin/pwauth";
+ open PWAUTH, "|$pwauth_path" or
+ die "Cannot invoke authentication";
+ print PWAUTH "$user\n$password\n";
+ close PWAUTH;
+ $validated = ! $?;
+
+ } else { # Passwords in /etc/passwd.
+ $validated = (crypt($password,
+ $contentpwd) eq $contentpwd);
+ }
+ } else {
+ $validated = 0;
+ }
+ }
+ elsif ($howpwd eq "krb4") { # user is in kerberos 4 auth. domain.
+ if(! ($password =~ /$null/) ) {
+ my $k4error = &Authen::Krb4::get_pw_in_tkt($user,
+ "",
+ $contentpwd,,
+ 'krbtgt',
+ $contentpwd,
+ 1,
+ $password);
+ if(!$k4error) {
+ $validated = 1;
+ }
+ else {
+ $validated = 0;
+ &logthis('krb4: '.$user.', '.$contentpwd.', '.
+ &Authen::Krb4::get_err_txt($Authen::Krb4::error));
+ }
+ }
+ else {
+ $validated = 0; # Password has a match with null.
+ }
+ }
+ elsif ($howpwd eq "krb5") { # User is in kerberos 5 auth. domain.
+ if(!($password =~ /$null/)) { # Null password not allowed.
+ my $krbclient = &Authen::Krb5::parse_name($user.'@'
+ .$contentpwd);
+ my $krbservice = "krbtgt/".$contentpwd."\@".$contentpwd;
+ my $krbserver = &Authen::Krb5::parse_name($krbservice);
+ my $credentials= &Authen::Krb5::cc_default();
+ $credentials->initialize($krbclient);
+ my $krbreturn = &Authen::KRb5::get_in_tkt_with_password($krbclient,
+ $krbserver,
+ $password,
+ $credentials);
+ $validated = ($krbreturn == 1);
+ }
+ else {
+ $validated = 0;
+ }
+ }
+ elsif ($howpwd eq "localauth") {
+ # Authenticate via installation specific authentcation method:
+ $validated = &localauth::localauth($user,
+ $password,
+ $contentpwd);
+ }
+ else { # Unrecognized auth is also bad.
+ $validated = 0;
+ }
+ } else {
+ $validated = 0;
+ }
+ #
+ # $validated has the correct stat of the authentication:
+ #
+
+ unless ($validated != -3.14159) {
+ die "ValidateUser - failed to set the value of validated";
+ }
+ return $validated;
+}
+
+#
+# Add a line to the subscription list?
+#
sub addline {
my ($fname,$hostid,$ip,$newline)=@_;
my $contents;
@@ -4266,7 +4287,9 @@
$sh->close();
return $found;
}
-
+#
+# Get chat messages.
+#
sub getchat {
my ($cdom,$cname,$udom,$uname)=@_;
my %hash;
@@ -4291,7 +4314,9 @@
}
return (@participants,@entries);
}
-
+#
+# Add a chat message
+#
sub chatadd {
my ($cdom,$cname,$newchat)=@_;
my %hash;
--foxr1080042612--