version 1.220, 2004/08/02 11:02:02
|
version 1.226, 2004/08/10 11:30:24
|
Line 50 use File::Copy;
|
Line 50 use File::Copy;
|
use LONCAPA::ConfigFileEdit; |
use LONCAPA::ConfigFileEdit; |
use LONCAPA::lonlocal; |
use LONCAPA::lonlocal; |
use LONCAPA::lonssl; |
use LONCAPA::lonssl; |
|
use Fcntl qw(:flock); |
|
|
my $DEBUG = 0; # Non zero to enable debug log entries. |
my $DEBUG = 0; # Non zero to enable debug log entries. |
|
|
Line 121 my @passwderrors = ("ok",
|
Line 122 my @passwderrors = ("ok",
|
"lcpasswd Cannot set new passwd.", |
"lcpasswd Cannot set new passwd.", |
"lcpasswd Username has invalid characters", |
"lcpasswd Username has invalid characters", |
"lcpasswd Invalid characters in password", |
"lcpasswd Invalid characters in password", |
"11", "12", |
"lcpasswd User already exists", |
"lcpasswd Password mismatch"); |
"lcpasswd Something went wrong with user addition.", |
|
"lcpasswd Password mismatch", |
|
"lcpasswd Error filename is invalid"); |
|
|
|
|
# The array below are lcuseradd error strings.: |
# The array below are lcuseradd error strings.: |
Line 159 sub ResetStatistics {
|
Line 162 sub ResetStatistics {
|
$Failures = 0; |
$Failures = 0; |
} |
} |
|
|
|
|
|
|
#------------------------------------------------------------------------ |
#------------------------------------------------------------------------ |
# |
# |
# LocalConnection |
# LocalConnection |
Line 191 sub LocalConnection {
|
Line 192 sub LocalConnection {
|
."$clientdns ne $thisserver </font>"); |
."$clientdns ne $thisserver </font>"); |
close $Socket; |
close $Socket; |
return undef; |
return undef; |
} |
} else { |
else { |
|
chomp($initcmd); # Get rid of \n in filename. |
chomp($initcmd); # Get rid of \n in filename. |
my ($init, $type, $name) = split(/:/, $initcmd); |
my ($init, $type, $name) = split(/:/, $initcmd); |
Debug(" Init command: $init $type $name "); |
Debug(" Init command: $init $type $name "); |
Line 323 sub InsecureConnection {
|
Line 323 sub InsecureConnection {
|
$answer =~s/\W//g; |
$answer =~s/\W//g; |
if($challenge eq $answer) { |
if($challenge eq $answer) { |
return 1; |
return 1; |
} |
} else { |
else { |
|
logthis("<font color='blue'>WARNING client did not respond to challenge</font>"); |
logthis("<font color='blue'>WARNING client did not respond to challenge</font>"); |
&status("No challenge reqply"); |
&status("No challenge reqply"); |
return 0; |
return 0; |
Line 371 sub isClient {
|
Line 370 sub isClient {
|
# - This allows dynamic changes to the manager table |
# - This allows dynamic changes to the manager table |
# without the need to signal to the lond. |
# without the need to signal to the lond. |
# |
# |
|
|
sub ReadManagerTable { |
sub ReadManagerTable { |
|
|
# Clean out the old table first.. |
# Clean out the old table first.. |
Line 653 sub PushFile {
|
Line 651 sub PushFile {
|
&logthis('<font color="red"> Pushfile: unable to install ' |
&logthis('<font color="red"> Pushfile: unable to install ' |
.$tablefile." $! </font>"); |
.$tablefile." $! </font>"); |
return "error:$!"; |
return "error:$!"; |
} |
} else { |
else { |
|
&logthis('<font color="green"> Installed new '.$tablefile |
&logthis('<font color="green"> Installed new '.$tablefile |
."</font>"); |
."</font>"); |
|
|
Line 1223 sub user_authorization_type {
|
Line 1220 sub user_authorization_type {
|
my $userinput = "$cmd:$tail"; |
my $userinput = "$cmd:$tail"; |
|
|
# Pull the domain and username out of the command tail. |
# Pull the domain and username out of the command tail. |
# and call GetAuthType to determine the authentication type. |
# and call get_auth_type to determine the authentication type. |
|
|
my ($udom,$uname)=split(/:/,$tail); |
my ($udom,$uname)=split(/:/,$tail); |
my $result = &GetAuthType($udom, $uname); |
my $result = &get_auth_type($udom, $uname); |
if($result eq "nouser") { |
if($result eq "nouser") { |
&Failure( $replyfd, "unknown_user\n", $userinput); |
&Failure( $replyfd, "unknown_user\n", $userinput); |
} else { |
} else { |
# |
# |
# We only want to pass the second field from GetAuthType |
# We only want to pass the second field from get_auth_type |
# for ^krb.. otherwise we'll be handing out the encrypted |
# for ^krb.. otherwise we'll be handing out the encrypted |
# password for internals e.g. |
# password for internals e.g. |
# |
# |
Line 1239 sub user_authorization_type {
|
Line 1236 sub user_authorization_type {
|
if($type =~ /^krb/) { |
if($type =~ /^krb/) { |
$type = $result; |
$type = $result; |
} |
} |
&Reply( $replyfd, "$type\n", $userinput); |
&Reply( $replyfd, "$type:\n", $userinput); |
} |
} |
|
|
return 1; |
return 1; |
Line 1417 sub authenticate_handler {
|
Line 1414 sub authenticate_handler {
|
|
|
register_handler("auth", \&authenticate_handler, 1, 1, 0); |
register_handler("auth", \&authenticate_handler, 1, 1, 0); |
|
|
|
# |
|
# Change a user's password. Note that this function is complicated by |
|
# the fact that a user may be authenticated in more than one way: |
|
# At present, we are not able to change the password for all types of |
|
# authentication methods. Only for: |
|
# unix - unix password or shadow passoword style authentication. |
|
# local - Locally written authentication mechanism. |
|
# For now, kerb4 and kerb5 password changes are not supported and result |
|
# in an error. |
|
# FUTURE WORK: |
|
# Support kerberos passwd changes? |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# Implicit inputs: |
|
# The authentication systems describe above have their own forms of implicit |
|
# input into the authentication process that are described above. |
|
sub change_password_handler { |
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my $userinput = $cmd.":".$tail; # Reconstruct client's string. |
|
|
|
# |
|
# udom - user's domain. |
|
# uname - Username. |
|
# upass - Current password. |
|
# npass - New password. |
|
|
|
my ($udom,$uname,$upass,$npass)=split(/:/,$tail); |
|
|
|
$upass=&unescape($upass); |
|
$npass=&unescape($npass); |
|
&Debug("Trying to change password for $uname"); |
|
|
|
# First require that the user can be authenticated with their |
|
# old password: |
|
|
|
my $validated = &validate_user($udom, $uname, $upass); |
|
if($validated) { |
|
my $realpasswd = &get_auth_type($udom, $uname); # Defined since authd. |
|
|
|
my ($howpwd,$contentpwd)=split(/:/,$realpasswd); |
|
if ($howpwd eq 'internal') { |
|
&Debug("internal auth"); |
|
my $salt=time; |
|
$salt=substr($salt,6,2); |
|
my $ncpass=crypt($npass,$salt); |
|
if(&rewrite_password_file($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); |
|
} |
|
} elsif ($howpwd eq 'unix') { |
|
# Unix means we have to access /etc/password |
|
&Debug("auth is unix"); |
|
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 |
|
# locally written auth handler). |
|
# |
|
&Failure( $client, "auth_mode_error\n", $userinput); |
|
} |
|
|
|
} else { |
|
&Failure( $client, "non_authorized\n", $userinput); |
|
} |
|
|
|
return 1; |
|
} |
|
register_handler("passwd", \&change_password_handler, 1, 1, 0); |
|
|
|
|
|
# |
|
# Create a new user. User in this case means a lon-capa user. |
|
# The user must either already exist in some authentication realm |
|
# like kerberos or the /etc/passwd. If not, a user completely local to |
|
# this loncapa system is created. |
|
# |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# Implicit inputs: |
|
# The authentication systems describe above have their own forms of implicit |
|
# input into the authentication process that are described above. |
|
sub add_user_handler { |
|
|
|
my ($cmd, $tail, $client) = @_; |
|
|
|
|
|
my ($udom,$uname,$umode,$npass)=split(/:/,$tail); |
|
my $userinput = $cmd.":".$tail; # Reconstruct the full request line. |
|
|
|
&Debug("cmd =".$cmd." $udom =".$udom." uname=".$uname); |
|
|
|
|
|
if($udom eq $currentdomainid) { # Reject new users for other domains... |
|
|
|
my $oldumask=umask(0077); |
|
chomp($npass); |
|
$npass=&unescape($npass); |
|
my $passfilename = &password_path($udom, $uname); |
|
&Debug("Password file created will be:".$passfilename); |
|
if (-e $passfilename) { |
|
&Failure( $client, "already_exists\n", $userinput); |
|
} else { |
|
my @fpparts=split(/\//,$passfilename); |
|
my $fpnow=$fpparts[0].'/'.$fpparts[1].'/'.$fpparts[2]; |
|
my $fperror=''; |
|
for (my $i=3;$i<= ($#fpparts-1);$i++) { |
|
$fpnow.='/'.$fpparts[$i]; |
|
unless (-e $fpnow) { |
|
&logthis("mkdir $fpnow"); |
|
unless (mkdir($fpnow,0777)) { |
|
$fperror="error: ".($!+0)." mkdir failed while attempting " |
|
."makeuser"; |
|
} |
|
} |
|
} |
|
unless ($fperror) { |
|
my $result=&make_passwd_file($uname, $umode,$npass, $passfilename); |
|
&Reply($client, $result, $userinput); #BUGBUG - could be fail |
|
} else { |
|
&Failure($client, "$fperror\n", $userinput); |
|
} |
|
} |
|
umask($oldumask); |
|
} else { |
|
&Failure($client, "not_right_domain\n", |
|
$userinput); # Even if we are multihomed. |
|
|
|
} |
|
return 1; |
|
|
|
} |
|
®ister_handler("makeuser", \&add_user_handler, 1, 1, 0); |
|
|
|
# |
|
# Change the authentication method of a user. Note that this may |
|
# also implicitly change the user's password if, for example, the user is |
|
# joining an existing authentication realm. Known authentication realms at |
|
# this time are: |
|
# internal - Purely internal password file (only loncapa knows this user) |
|
# local - Institutionally written authentication module. |
|
# unix - Unix user (/etc/passwd with or without /etc/shadow). |
|
# kerb4 - kerberos version 4 |
|
# kerb5 - kerberos version 5 |
|
# |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# Implicit inputs: |
|
# The authentication systems describe above have their own forms of implicit |
|
# input into the authentication process that are described above. |
|
# |
|
sub change_authentication_handler { |
|
|
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my $userinput = "$cmd:$tail"; # Reconstruct user input. |
|
|
|
my ($udom,$uname,$umode,$npass)=split(/:/,$tail); |
|
&Debug("cmd = ".$cmd." domain= ".$udom."uname =".$uname." umode= ".$umode); |
|
if ($udom ne $currentdomainid) { |
|
&Failure( $client, "not_right_domain\n", $client); |
|
} else { |
|
|
|
chomp($npass); |
|
|
|
$npass=&unescape($npass); |
|
my $passfilename = &password_path($udom, $uname); |
|
if ($passfilename) { # Not allowed to create a new user!! |
|
my $result=&make_passwd_file($uname, $umode,$npass,$passfilename); |
|
&Reply($client, $result, $userinput); |
|
} else { |
|
&Failure($client, "non_authorized", $userinput); # Fail the user now. |
|
} |
|
} |
|
return 1; |
|
} |
|
®ister_handler("changeuserauth", \&change_authentication_handler, 1,1, 0); |
|
|
|
# |
|
# Determines if this is the home server for a user. The home server |
|
# for a user will have his/her lon-capa passwd file. Therefore all we need |
|
# to do is determine if this file exists. |
|
# |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# Implicit inputs: |
|
# The authentication systems describe above have their own forms of implicit |
|
# input into the authentication process that are described above. |
|
# |
|
sub is_home_handler { |
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my $userinput = "$cmd:$tail"; |
|
|
|
my ($udom,$uname)=split(/:/,$tail); |
|
chomp($uname); |
|
my $passfile = &password_filename($udom, $uname); |
|
if($passfile) { |
|
&Reply( $client, "found\n", $userinput); |
|
} else { |
|
&Failure($client, "not_found\n", $userinput); |
|
} |
|
return 1; |
|
} |
|
®ister_handler("home", \&is_home_handler, 0,1,0); |
|
|
|
# |
|
# Process an update request for a resource?? I think what's going on here is |
|
# that a resource has been modified that we hold a subscription to. |
|
# If the resource is not local, then we must update, or at least invalidate our |
|
# cached copy of the resource. |
|
# FUTURE WORK: |
|
# I need to look at this logic carefully. My druthers would be to follow |
|
# typical caching logic, and simple invalidate the cache, drop any subscription |
|
# an let the next fetch start the ball rolling again... however that may |
|
# actually be more difficult than it looks given the complex web of |
|
# proxy servers. |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# Implicit inputs: |
|
# The authentication systems describe above have their own forms of implicit |
|
# input into the authentication process that are described above. |
|
# |
|
sub update_resource_handler { |
|
|
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my $userinput = "$cmd:$tail"; |
|
|
|
my $fname= $tail; # This allows interactive testing |
|
|
|
|
|
my $ownership=ishome($fname); |
|
if ($ownership eq 'not_owner') { |
|
if (-e $fname) { |
|
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, |
|
$atime,$mtime,$ctime,$blksize,$blocks)=stat($fname); |
|
my $now=time; |
|
my $since=$now-$atime; |
|
if ($since>$perlvar{'lonExpire'}) { |
|
my $reply=&reply("unsub:$fname","$clientname"); |
|
unlink("$fname"); |
|
} else { |
|
my $transname="$fname.in.transfer"; |
|
my $remoteurl=&reply("sub:$fname","$clientname"); |
|
my $response; |
|
alarm(120); |
|
{ |
|
my $ua=new LWP::UserAgent; |
|
my $request=new HTTP::Request('GET',"$remoteurl"); |
|
$response=$ua->request($request,$transname); |
|
} |
|
alarm(0); |
|
if ($response->is_error()) { |
|
unlink($transname); |
|
my $message=$response->status_line; |
|
&logthis("LWP GET: $message for $fname ($remoteurl)"); |
|
} else { |
|
if ($remoteurl!~/\.meta$/) { |
|
alarm(120); |
|
{ |
|
my $ua=new LWP::UserAgent; |
|
my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta'); |
|
my $mresponse=$ua->request($mrequest,$fname.'.meta'); |
|
if ($mresponse->is_error()) { |
|
unlink($fname.'.meta'); |
|
} |
|
} |
|
alarm(0); |
|
} |
|
rename($transname,$fname); |
|
} |
|
} |
|
&Reply( $client, "ok\n", $userinput); |
|
} else { |
|
&Failure($client, "not_found\n", $userinput); |
|
} |
|
} else { |
|
&Failure($client, "rejected\n", $userinput); |
|
} |
|
return 1; |
|
} |
|
®ister_handler("update", \&update_resource_handler, 0 ,1, 0); |
|
|
|
# |
|
# Fetch a user file from a remote server to the user's home directory |
|
# userfiles subdir. |
|
# Parameters: |
|
# $cmd - The command that got us here. |
|
# $tail - Tail of the command (remaining parameters). |
|
# $client - File descriptor connected to client. |
|
# Returns |
|
# 0 - Requested to exit, caller should shut down. |
|
# 1 - Continue processing. |
|
# |
|
sub fetch_user_file_handler { |
|
|
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my $userinput = "$cmd:$tail"; |
|
my $fname = $tail; |
|
my ($udom,$uname,$ufile)=split(/\//,$fname); |
|
my $udir=&propath($udom,$uname).'/userfiles'; |
|
unless (-e $udir) { |
|
mkdir($udir,0770); |
|
} |
|
if (-e $udir) { |
|
$ufile=~s/^[\.\~]+//; |
|
$ufile=~s/\///g; |
|
my $destname=$udir.'/'.$ufile; |
|
my $transname=$udir.'/'.$ufile.'.in.transit'; |
|
my $remoteurl='http://'.$clientip.'/userfiles/'.$fname; |
|
my $response; |
|
alarm(120); |
|
{ |
|
my $ua=new LWP::UserAgent; |
|
my $request=new HTTP::Request('GET',"$remoteurl"); |
|
$response=$ua->request($request,$transname); |
|
} |
|
alarm(0); |
|
if ($response->is_error()) { |
|
unlink($transname); |
|
my $message=$response->status_line; |
|
&logthis("LWP GET: $message for $fname ($remoteurl)"); |
|
&Failure($client, "failed\n", $userinput); |
|
} else { |
|
if (!rename($transname,$destname)) { |
|
&logthis("Unable to move $transname to $destname"); |
|
unlink($transname); |
|
&Failure($client, "failed\n", $userinput); |
|
} else { |
|
&Reply($client, "ok\n", $userinput); |
|
} |
|
} |
|
} else { |
|
&Failure($client, "not_home\n", $userinput); |
|
} |
|
return 1; |
|
} |
|
®ister_handler("fetchuserfile", \&fetch_user_file_handler, 0, 1, 0); |
|
|
|
# |
|
# Remove a file from a user's home directory userfiles subdirectory. |
|
# Parameters: |
|
# cmd - the Lond request keyword that got us here. |
|
# tail - the part of the command past the keyword. |
|
# client- File descriptor connected with the client. |
|
# |
|
# Returns: |
|
# 1 - Continue processing. |
|
|
|
sub remove_user_file_handler { |
|
my ($cmd, $tail, $client) = @_; |
|
|
|
my ($fname) = split(/:/, $tail); # Get rid of any tailing :'s lonc may have sent. |
|
|
|
my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|); |
|
&logthis("$udom - $uname - $ufile"); |
|
if ($ufile =~m|/\.\./|) { |
|
# any files paths with /../ in them refuse |
|
# to deal with |
|
&Failure($client, "refused\n", "$cmd:$tail"); |
|
} else { |
|
my $udir = &propath($udom,$uname); |
|
if (-e $udir) { |
|
my $file=$udir.'/userfiles/'.$ufile; |
|
if (-e $file) { |
|
unlink($file); |
|
if (-e $file) { |
|
&Failure($client, "failed\n", "$cmd:$tail"); |
|
} else { |
|
&Reply($client, "ok\n", "$cmd:$tail"); |
|
} |
|
} else { |
|
&Failure($client, "not_found\n", "$cmd:$tail"); |
|
} |
|
} else { |
|
&Failure($client, "not_home\n", "$cmd:$tail"); |
|
} |
|
} |
|
return 1; |
|
} |
|
®ister_handler("removeuserfile", \&remove_user_file_handler, 0,1,0); |
|
|
#--------------------------------------------------------------- |
#--------------------------------------------------------------- |
# |
# |
# Getting, decoding and dispatching requests: |
# Getting, decoding and dispatching requests: |
Line 1427 register_handler("auth", \&authenticate_
|
Line 1849 register_handler("auth", \&authenticate_
|
# Gets a Request message from the client. The transaction |
# Gets a Request message from the client. The transaction |
# is defined as a 'line' of text. We remove the new line |
# is defined as a 'line' of text. We remove the new line |
# from the text line. |
# from the text line. |
# |
# |
sub get_request { |
sub get_request { |
my $input = <$client>; |
my $input = <$client>; |
chomp($input); |
chomp($input); |
Line 1531 sub process_request {
|
Line 1953 sub process_request {
|
#------------------- Commands not yet in spearate handlers. -------------- |
#------------------- Commands not yet in spearate handlers. -------------- |
|
|
|
|
# ---------------------------------------------------------------------- passwd |
|
if ($userinput =~ /^passwd/) { # encoded and client |
|
if (($wasenc==1) && isClient) { |
|
my |
|
($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput); |
|
chomp($npass); |
|
$upass=&unescape($upass); |
|
$npass=&unescape($npass); |
|
&Debug("Trying to change password for $uname"); |
|
my $proname=propath($udom,$uname); |
|
my $passfilename="$proname/passwd"; |
|
if (-e $passfilename) { |
|
my $realpasswd; |
|
{ my $pf = IO::File->new($passfilename); |
|
$realpasswd=<$pf>; } |
|
chomp($realpasswd); |
|
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); |
|
{ |
|
my $pf; |
|
if ($pf = IO::File->new(">$passfilename")) { |
|
print $pf "internal:$ncpass\n"; |
|
&logthis("Result of password change for $uname: pwchange_success"); |
|
print $client "ok\n"; |
|
} else { |
|
&logthis("Unable to open $uname passwd to change password"); |
|
print $client "non_authorized\n"; |
|
} |
|
} |
|
|
|
} else { |
|
print $client "non_authorized\n"; |
|
} |
|
} 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($?)); |
|
print $client "$result\n"; |
|
} else { |
|
print $client "non_authorized\n"; |
|
} |
|
} else { |
|
print $client "auth_mode_error\n"; |
|
} |
|
} else { |
|
print $client "unknown_user\n"; |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
|
|
} |
|
# -------------------------------------------------------------------- makeuser |
|
} elsif ($userinput =~ /^makeuser/) { # encoded and client. |
|
&Debug("Make user received"); |
|
my $oldumask=umask(0077); |
|
if (($wasenc==1) && isClient) { |
|
my |
|
($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput); |
|
&Debug("cmd =".$cmd." $udom =".$udom. |
|
" uname=".$uname); |
|
chomp($npass); |
|
$npass=&unescape($npass); |
|
my $proname=propath($udom,$uname); |
|
my $passfilename="$proname/passwd"; |
|
&Debug("Password file created will be:". |
|
$passfilename); |
|
if (-e $passfilename) { |
|
print $client "already_exists\n"; |
|
} elsif ($udom ne $currentdomainid) { |
|
print $client "not_right_domain\n"; |
|
} else { |
|
my @fpparts=split(/\//,$proname); |
|
my $fpnow=$fpparts[0].'/'.$fpparts[1].'/'.$fpparts[2]; |
|
my $fperror=''; |
|
for (my $i=3;$i<=$#fpparts;$i++) { |
|
$fpnow.='/'.$fpparts[$i]; |
|
unless (-e $fpnow) { |
|
unless (mkdir($fpnow,0777)) { |
|
$fperror="error: ".($!+0) |
|
." mkdir failed while attempting " |
|
."makeuser"; |
|
} |
|
} |
|
} |
|
unless ($fperror) { |
|
my $result=&make_passwd_file($uname, $umode,$npass, |
|
$passfilename); |
|
print $client $result; |
|
} else { |
|
print $client "$fperror\n"; |
|
} |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
|
|
} |
|
umask($oldumask); |
|
# -------------------------------------------------------------- changeuserauth |
|
} elsif ($userinput =~ /^changeuserauth/) { # encoded & client |
|
&Debug("Changing authorization"); |
|
if (($wasenc==1) && isClient) { |
|
my |
|
($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput); |
|
chomp($npass); |
|
&Debug("cmd = ".$cmd." domain= ".$udom. |
|
"uname =".$uname." umode= ".$umode); |
|
$npass=&unescape($npass); |
|
my $proname=&propath($udom,$uname); |
|
my $passfilename="$proname/passwd"; |
|
if ($udom ne $currentdomainid) { |
|
print $client "not_right_domain\n"; |
|
} else { |
|
my $result=&make_passwd_file($uname, $umode,$npass, |
|
$passfilename); |
|
print $client $result; |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
|
|
} |
|
# ------------------------------------------------------------------------ home |
|
} elsif ($userinput =~ /^home/) { # client clear or encoded |
|
if(isClient) { |
|
my ($cmd,$udom,$uname)=split(/:/,$userinput); |
|
chomp($uname); |
|
my $proname=propath($udom,$uname); |
|
if (-e $proname) { |
|
print $client "found\n"; |
|
} else { |
|
print $client "not_found\n"; |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
|
|
} |
|
# ---------------------------------------------------------------------- update |
|
} elsif ($userinput =~ /^update/) { # client clear or encoded. |
|
if(isClient) { |
|
my ($cmd,$fname)=split(/:/,$userinput); |
|
my $ownership=ishome($fname); |
|
if ($ownership eq 'not_owner') { |
|
if (-e $fname) { |
|
my ($dev,$ino,$mode,$nlink, |
|
$uid,$gid,$rdev,$size, |
|
$atime,$mtime,$ctime, |
|
$blksize,$blocks)=stat($fname); |
|
my $now=time; |
|
my $since=$now-$atime; |
|
if ($since>$perlvar{'lonExpire'}) { |
|
my $reply= |
|
&reply("unsub:$fname","$clientname"); |
|
unlink("$fname"); |
|
} else { |
|
my $transname="$fname.in.transfer"; |
|
my $remoteurl= |
|
&reply("sub:$fname","$clientname"); |
|
my $response; |
|
{ |
|
my $ua=new LWP::UserAgent; |
|
my $request=new HTTP::Request('GET',"$remoteurl"); |
|
$response=$ua->request($request,$transname); |
|
} |
|
if ($response->is_error()) { |
|
unlink($transname); |
|
my $message=$response->status_line; |
|
&logthis( |
|
"LWP GET: $message for $fname ($remoteurl)"); |
|
} else { |
|
if ($remoteurl!~/\.meta$/) { |
|
my $ua=new LWP::UserAgent; |
|
my $mrequest= |
|
new HTTP::Request('GET',$remoteurl.'.meta'); |
|
my $mresponse= |
|
$ua->request($mrequest,$fname.'.meta'); |
|
if ($mresponse->is_error()) { |
|
unlink($fname.'.meta'); |
|
} |
|
} |
|
rename($transname,$fname); |
|
} |
|
} |
|
print $client "ok\n"; |
|
} else { |
|
print $client "not_found\n"; |
|
} |
|
} else { |
|
print $client "rejected\n"; |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
|
|
} |
|
# -------------------------------------- fetch a user file from a remote server |
|
} elsif ($userinput =~ /^fetchuserfile/) { # Client clear or enc. |
|
if(isClient) { |
|
my ($cmd,$fname)=split(/:/,$userinput); |
|
my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|); |
|
my $udir=propath($udom,$uname).'/userfiles'; |
|
unless (-e $udir) { mkdir($udir,0770); } |
|
if (-e $udir) { |
|
$ufile=~s/^[\.\~]+//; |
|
my $path = $udir; |
|
if ($ufile =~m|(.+)/([^/]+)$|) { |
|
my @parts=split('/',$1); |
|
foreach my $part (@parts) { |
|
$path .= '/'.$part; |
|
if ((-e $path)!=1) { |
|
mkdir($path,0770); |
|
} |
|
} |
|
} |
|
my $destname=$udir.'/'.$ufile; |
|
my $transname=$udir.'/'.$ufile.'.in.transit'; |
|
my $remoteurl='http://'.$clientip.'/userfiles/'.$fname; |
|
my $response; |
|
{ |
|
my $ua=new LWP::UserAgent; |
|
my $request=new HTTP::Request('GET',"$remoteurl"); |
|
$response=$ua->request($request,$transname); |
|
} |
|
if ($response->is_error()) { |
|
unlink($transname); |
|
my $message=$response->status_line; |
|
&logthis("LWP GET: $message for $fname ($remoteurl)"); |
|
print $client "failed\n"; |
|
} else { |
|
if (!rename($transname,$destname)) { |
|
&logthis("Unable to move $transname to $destname"); |
|
unlink($transname); |
|
print $client "failed\n"; |
|
} else { |
|
print $client "ok\n"; |
|
} |
|
} |
|
} else { |
|
print $client "not_home\n"; |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
} |
|
# --------------------------------------------------------- remove a user file |
|
} elsif ($userinput =~ /^removeuserfile/) { # Client clear or enc. |
|
if(isClient) { |
|
my ($cmd,$fname)=split(/:/,$userinput); |
|
my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|); |
|
&logthis("$udom - $uname - $ufile"); |
|
if ($ufile =~m|/\.\./|) { |
|
# any files paths with /../ in them refuse |
|
# to deal with |
|
print $client "refused\n"; |
|
} else { |
|
my $udir=propath($udom,$uname); |
|
if (-e $udir) { |
|
my $file=$udir.'/userfiles/'.$ufile; |
|
if (-e $file) { |
|
unlink($file); |
|
if (-e $file) { |
|
print $client "failed\n"; |
|
} else { |
|
print $client "ok\n"; |
|
} |
|
} else { |
|
print $client "not_found\n"; |
|
} |
|
} else { |
|
print $client "not_home\n"; |
|
} |
|
} |
|
} else { |
|
Reply($client, "refused\n", $userinput); |
|
} |
|
# ------------------------------------------ authenticate access to a user file |
# ------------------------------------------ authenticate access to a user file |
} elsif ($userinput =~ /^tokenauthuserfile/) { # Client only |
|
|
if ($userinput =~ /^tokenauthuserfile/) { # Client only |
if(isClient) { |
if(isClient) { |
my ($cmd,$fname,$session)=split(/:/,$userinput); |
my ($cmd,$fname,$session)=split(/:/,$userinput); |
chomp($session); |
chomp($session); |
Line 2024 sub process_request {
|
Line 2145 sub process_request {
|
foreach my $pair (@pairs) { |
foreach my $pair (@pairs) { |
my ($key,$value)=split(/=/,$pair); |
my ($key,$value)=split(/=/,$pair); |
&ManagePermissions($key, $udom, $uname, |
&ManagePermissions($key, $udom, $uname, |
&GetAuthType( $udom, |
&get_auth_type( $udom, |
$uname)); |
$uname)); |
$hash{$key}=$value; |
$hash{$key}=$value; |
} |
} |
Line 2481 sub process_request {
|
Line 2602 sub process_request {
|
print $store2 "done\n"; |
print $store2 "done\n"; |
close $store2; |
close $store2; |
print $client "ok\n"; |
print $client "ok\n"; |
} |
} else { |
else { |
|
print $client "error: ".($!+0) |
print $client "error: ".($!+0) |
." IO::File->new Failed ". |
." IO::File->new Failed ". |
"while attempting queryreply\n"; |
"while attempting queryreply\n"; |
Line 2996 sub register_handler {
|
Line 3116 sub register_handler {
|
|
|
$Dispatcher{$request_name} = \@entry; |
$Dispatcher{$request_name} = \@entry; |
|
|
|
|
} |
} |
|
|
|
|
Line 3043 sub catchexception {
|
Line 3162 sub catchexception {
|
$server->close(); |
$server->close(); |
die($error); |
die($error); |
} |
} |
|
|
sub timeout { |
sub timeout { |
&status("Handling Timeout"); |
&status("Handling Timeout"); |
&logthis("<font color='red'>CRITICAL: TIME OUT ".$$."</font>"); |
&logthis("<font color='red'>CRITICAL: TIME OUT ".$$."</font>"); |
Line 3051 sub timeout {
|
Line 3169 sub timeout {
|
} |
} |
# -------------------------------- Set signal handlers to record abnormal exits |
# -------------------------------- Set signal handlers to record abnormal exits |
|
|
|
|
$SIG{'QUIT'}=\&catchexception; |
$SIG{'QUIT'}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
|
|
Line 3251 sub checkchildren {
|
Line 3370 sub checkchildren {
|
&logthis('Going to check on the children'); |
&logthis('Going to check on the children'); |
my $docdir=$perlvar{'lonDocRoot'}; |
my $docdir=$perlvar{'lonDocRoot'}; |
foreach (sort keys %children) { |
foreach (sort keys %children) { |
sleep 1; |
#sleep 1; |
unless (kill 'USR1' => $_) { |
unless (kill 'USR1' => $_) { |
&logthis ('Child '.$_.' is dead'); |
&logthis ('Child '.$_.' is dead'); |
&logstatus($$.' is dead'); |
&logstatus($$.' is dead'); |
|
delete($children{$_}); |
} |
} |
} |
} |
sleep 5; |
sleep 5; |
Line 3273 sub checkchildren {
|
Line 3393 sub checkchildren {
|
#my $result=`echo 'Killed lond process $_.' | mailto $emailto -s '$subj' > /dev/null`; |
#my $result=`echo 'Killed lond process $_.' | mailto $emailto -s '$subj' > /dev/null`; |
#$execdir=$perlvar{'lonDaemons'}; |
#$execdir=$perlvar{'lonDaemons'}; |
#$result=`/bin/cp $execdir/logs/lond.log $execdir/logs/lond.log.$_`; |
#$result=`/bin/cp $execdir/logs/lond.log $execdir/logs/lond.log.$_`; |
|
delete($children{$_}); |
alarm(0); |
alarm(0); |
} |
} |
} |
} |
Line 3280 sub checkchildren {
|
Line 3401 sub checkchildren {
|
$SIG{ALRM} = 'DEFAULT'; |
$SIG{ALRM} = 'DEFAULT'; |
$SIG{__DIE__} = \&catchexception; |
$SIG{__DIE__} = \&catchexception; |
&status("Finished checking children"); |
&status("Finished checking children"); |
|
&logthis('Finished Checking children'); |
} |
} |
|
|
# --------------------------------------------------------------------- Logging |
# --------------------------------------------------------------------- Logging |
Line 3350 sub logstatus {
|
Line 3472 sub logstatus {
|
&status("Doing logging"); |
&status("Doing logging"); |
my $docdir=$perlvar{'lonDocRoot'}; |
my $docdir=$perlvar{'lonDocRoot'}; |
{ |
{ |
my $fh=IO::File->new(">>$docdir/lon-status/londstatus.txt"); |
|
print $fh $$."\t".$clientname."\t".$currenthostid."\t" |
|
.$status."\t".$lastlog."\t $keymode\n"; |
|
$fh->close(); |
|
} |
|
&status("Finished londstatus.txt"); |
|
{ |
|
my $fh=IO::File->new(">$docdir/lon-status/londchld/$$.txt"); |
my $fh=IO::File->new(">$docdir/lon-status/londchld/$$.txt"); |
print $fh $status."\n".$lastlog."\n".time."\n$keymode"; |
print $fh $status."\n".$lastlog."\n".time."\n$keymode"; |
$fh->close(); |
$fh->close(); |
} |
} |
|
&status("Finished $$.txt"); |
|
{ |
|
open(LOG,">>$docdir/lon-status/londstatus.txt"); |
|
flock(LOG,LOCK_EX); |
|
print LOG $$."\t".$clientname."\t".$currenthostid."\t" |
|
.$status."\t".$lastlog."\t $keymode\n"; |
|
flock(DB,LOCK_UN); |
|
close(LOG); |
|
} |
&status("Finished logging"); |
&status("Finished logging"); |
} |
} |
|
|
Line 3675 sub make_new_child {
|
Line 3799 sub make_new_child {
|
$inittype = ""; # This forces insecure attempt. |
$inittype = ""; # This forces insecure attempt. |
&logthis("<font color=\"blue\"> Certificates not " |
&logthis("<font color=\"blue\"> Certificates not " |
."installed -- trying insecure auth</font>"); |
."installed -- trying insecure auth</font>"); |
} |
} else { # SSL certificates are in place so |
else { # SSL certificates are in place so |
|
} # Leave the inittype alone. |
} # Leave the inittype alone. |
} |
} |
|
|
Line 3812 sub ManagePermissions
|
Line 3935 sub ManagePermissions
|
system("$execdir/lchtmldir $userhome $user $authtype"); |
system("$execdir/lchtmldir $userhome $user $authtype"); |
} |
} |
} |
} |
|
|
|
|
|
# |
|
# Return the full path of a user password file, whether it exists or not. |
|
# Parameters: |
|
# domain - Domain in which the password file lives. |
|
# user - name of the user. |
|
# Returns: |
|
# Full passwd path: |
|
# |
|
sub password_path { |
|
my ($domain, $user) = @_; |
|
|
|
|
|
my $path = &propath($domain, $user); |
|
$path .= "/passwd"; |
|
|
|
return $path; |
|
} |
|
|
|
# Password Filename |
|
# Returns the path to a passwd file given domain and user... only if |
|
# it exists. |
|
# Parameters: |
|
# domain - Domain in which to search. |
|
# user - username. |
|
# Returns: |
|
# - If the password file exists returns its path. |
|
# - If the password file does not exist, returns undefined. |
|
# |
|
sub password_filename { |
|
my ($domain, $user) = @_; |
|
|
|
Debug ("PasswordFilename called: dom = $domain user = $user"); |
|
|
|
my $path = &password_path($domain, $user); |
|
Debug("PasswordFilename got path: $path"); |
|
if(-e $path) { |
|
return $path; |
|
} else { |
|
return undef; |
|
} |
|
} |
|
|
|
# |
|
# Rewrite the contents of the user's passwd file. |
|
# Parameters: |
|
# domain - domain of the user. |
|
# name - User's name. |
|
# contents - New contents of the file. |
|
# Returns: |
|
# 0 - Failed. |
|
# 1 - Success. |
|
# |
|
sub rewrite_password_file { |
|
my ($domain, $user, $contents) = @_; |
|
|
|
my $file = &password_filename($domain, $user); |
|
if (defined $file) { |
|
my $pf = IO::File->new(">$file"); |
|
if($pf) { |
|
print $pf "$contents\n"; |
|
return 1; |
|
} else { |
|
return 0; |
|
} |
|
} else { |
|
return 0; |
|
} |
|
|
|
} |
|
|
# |
# |
# GetAuthType - Determines the authorization type of a user in a domain. |
# get_auth_type - Determines the authorization type of a user in a domain. |
|
|
# Returns the authorization type or nouser if there is no such user. |
# Returns the authorization type or nouser if there is no such user. |
# |
# |
sub GetAuthType |
sub get_auth_type |
{ |
{ |
|
|
my ($domain, $user) = @_; |
my ($domain, $user) = @_; |
|
|
Debug("GetAuthType( $domain, $user ) \n"); |
Debug("get_auth_type( $domain, $user ) \n"); |
my $proname = &propath($domain, $user); |
my $proname = &propath($domain, $user); |
my $passwdfile = "$proname/passwd"; |
my $passwdfile = "$proname/passwd"; |
if( -e $passwdfile ) { |
if( -e $passwdfile ) { |
Line 3838 sub GetAuthType
|
Line 4033 sub GetAuthType
|
} |
} |
|
|
return "$authtype:$availinfo"; |
return "$authtype:$availinfo"; |
} |
} else { |
else { |
|
Debug("Returning nouser"); |
Debug("Returning nouser"); |
return "nouser"; |
return "nouser"; |
} |
} |
Line 3879 sub validate_user {
|
Line 4073 sub validate_user {
|
# the user has been assigned. If the authentication type is |
# the user has been assigned. If the authentication type is |
# "nouser", the user does not exist so we will return 0. |
# "nouser", the user does not exist so we will return 0. |
|
|
my $contents = &GetAuthType($domain, $user); |
my $contents = &get_auth_type($domain, $user); |
my ($howpwd, $contentpwd) = split(/:/, $contents); |
my ($howpwd, $contentpwd) = split(/:/, $contents); |
|
|
my $null = pack("C",0); # Used by kerberos auth types. |
my $null = pack("C",0); # Used by kerberos auth types. |
Line 3919 sub validate_user {
|
Line 4113 sub validate_user {
|
$password); |
$password); |
if(!$k4error) { |
if(!$k4error) { |
$validated = 1; |
$validated = 1; |
} |
} else { |
else { |
|
$validated = 0; |
$validated = 0; |
&logthis('krb4: '.$user.', '.$contentpwd.', '. |
&logthis('krb4: '.$user.', '.$contentpwd.', '. |
&Authen::Krb4::get_err_txt($Authen::Krb4::error)); |
&Authen::Krb4::get_err_txt($Authen::Krb4::error)); |
} |
} |
} |
} else { |
else { |
|
$validated = 0; # Password has a match with null. |
$validated = 0; # Password has a match with null. |
} |
} |
} |
} elsif ($howpwd eq "krb5") { # User is in kerberos 5 auth. domain. |
elsif ($howpwd eq "krb5") { # User is in kerberos 5 auth. domain. |
|
if(!($password =~ /$null/)) { # Null password not allowed. |
if(!($password =~ /$null/)) { # Null password not allowed. |
my $krbclient = &Authen::Krb5::parse_name($user.'@' |
my $krbclient = &Authen::Krb5::parse_name($user.'@' |
.$contentpwd); |
.$contentpwd); |
Line 3943 sub validate_user {
|
Line 4134 sub validate_user {
|
$password, |
$password, |
$credentials); |
$credentials); |
$validated = ($krbreturn == 1); |
$validated = ($krbreturn == 1); |
} |
} else { |
else { |
|
$validated = 0; |
$validated = 0; |
} |
} |
} |
} elsif ($howpwd eq "localauth") { |
elsif ($howpwd eq "localauth") { |
|
# Authenticate via installation specific authentcation method: |
# Authenticate via installation specific authentcation method: |
$validated = &localauth::localauth($user, |
$validated = &localauth::localauth($user, |
$password, |
$password, |
$contentpwd); |
$contentpwd); |
} |
} else { # Unrecognized auth is also bad. |
else { # Unrecognized auth is also bad. |
|
$validated = 0; |
$validated = 0; |
} |
} |
} else { |
} else { |
Line 4216 sub make_passwd_file {
|
Line 4404 sub make_passwd_file {
|
return "no_priv_account_error\n"; |
return "no_priv_account_error\n"; |
} |
} |
|
|
my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd"; |
my $execpath ="$perlvar{'lonDaemons'}/"."lcuseradd"; |
|
|
|
my $lc_error_file = $execdir."/tmp/lcuseradd".$$.".status"; |
{ |
{ |
&Debug("Executing external: ".$execpath); |
&Debug("Executing external: ".$execpath); |
&Debug("user = ".$uname.", Password =". $npass); |
&Debug("user = ".$uname.", Password =". $npass); |
Line 4224 sub make_passwd_file {
|
Line 4414 sub make_passwd_file {
|
print $se "$uname\n"; |
print $se "$uname\n"; |
print $se "$npass\n"; |
print $se "$npass\n"; |
print $se "$npass\n"; |
print $se "$npass\n"; |
|
print $se "$lc_error_file\n"; # Status -> unique file. |
} |
} |
my $useraddok = $?; |
my $error = IO::File->new("< $lc_error_file"); |
|
my $useraddok = <$error>; |
|
$error->close; |
|
unlink($lc_error_file); |
|
|
|
chomp $useraddok; |
|
|
if($useraddok > 0) { |
if($useraddok > 0) { |
&logthis("Failed lcuseradd: ".&lcuseraddstrerror($useraddok)); |
my $error_text = &lcuseraddstrerror($useraddok); |
|
&logthis("Failed lcuseradd: $error_text"); |
|
$result = "lcuseradd_failed:$error_text\n"; |
|
} else { |
|
my $pf = IO::File->new(">$passfilename"); |
|
print $pf "unix:\n"; |
} |
} |
my $pf = IO::File->new(">$passfilename"); |
|
print $pf "unix:\n"; |
|
} |
} |
} elsif ($umode eq 'none') { |
} elsif ($umode eq 'none') { |
{ |
{ |
my $pf = IO::File->new(">$passfilename"); |
my $pf = IO::File->new("> $passfilename"); |
print $pf "none:\n"; |
print $pf "none:\n"; |
} |
} |
} else { |
} else { |