Diff for /loncom/lond between versions 1.178.2.11 and 1.178.2.14

version 1.178.2.11, 2004/03/22 09:41:53 version 1.178.2.14, 2004/04/07 09:39:18
Line 237  sub TieUserHash { Line 237  sub TieUserHash {
     $namespace=~s/\//\_/g; # / -> _      $namespace=~s/\//\_/g; # / -> _
     $namespace=~s/\W//g; # whitespace eliminated.      $namespace=~s/\W//g; # whitespace eliminated.
     my $proname     = propath($domain, $user);      my $proname     = propath($domain, $user);
          
     # If this is a namespace for which a history is kept,      # If this is a namespace for which a history is kept,
     # make the history log entry:      # make the history log entry:
           
Line 254  sub TieUserHash { Line 254  sub TieUserHash {
     #  Tie the database.      #  Tie the database.
           
     my %hash;      my %hash;
     if(tie(%hash, 'GDBM_FILE', "$proname/$namespace.db",      if(tie(%hash, 'GDBM_File', "$proname/$namespace.db",
    $how, 0640)) {     $how, 0640)) {
  return \%hash;   return \%hash;
     }      }
Line 739  sub AuthenticateHandler { Line 739  sub AuthenticateHandler {
     chomp($upass);      chomp($upass);
     $upass=unescape($upass);      $upass=unescape($upass);
   
     # Fetch the user authentication information:      my $pwdcorrect = ValidateUser($udom, $uname, $upass);
          if($pwdcorrect) {
     my $realpasswd = GetAuthType($udom, $uname);   Reply( $client, "authorized\n", $userinput);
     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);  
  }  
  #   #
  #   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 {      } else {
  Failure( $client, "non_authorized\n", $userinput);   Failure( $client, "non_authorized\n", $userinput);
     }      }
   
     return 1;      return 1;
 }  }
 RegisterHandler("auth", \&AuthenticateHandler, 1, 1, 0);  RegisterHandler("auth", \&AuthenticateHandler, 1, 1, 0);
Line 882  sub ChangePasswordHandler { Line 792  sub ChangePasswordHandler {
     $upass=&unescape($upass);      $upass=&unescape($upass);
     $npass=&unescape($npass);      $npass=&unescape($npass);
     &Debug("Trying to change password for $uname");      &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);   my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
  if ($howpwd eq 'internal') {   if ($howpwd eq 'internal') {
     &Debug("internal auth");      &Debug("internal auth");
     if (crypt($upass,$contentpwd) eq $contentpwd) {      my $salt=time;
  my $salt=time;      $salt=substr($salt,6,2);
  $salt=substr($salt,6,2);      my $ncpass=crypt($npass,$salt);
  my $ncpass=crypt($npass,$salt);      if(RewritePwFile($udom, $uname, "internal:$ncpass")) {
  if(RewritePwFile($udom, $uname, "internal:$ncpass")) {   &logthis("Result of password change for "
     &logthis("Result of password change for "   ."$uname: pwchange_success");
      ."$uname: pwchange_success");   Reply($client, "ok\n", $userinput);
     Reply($client, "ok\n", $userinput);  
  } else {  
     &logthis("Unable to open $uname passwd "                 
      ."to change password");  
     Failure( $client, "non_authorized\n",$userinput);  
  }  
     } else {      } 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') {   } elsif ($howpwd eq 'unix') {
     # Unix means we have to access /etc/password      # Unix means we have to access /etc/password
     # one way or another.  
     # First: Make sure the current password is  
     #        correct  
     &Debug("auth is unix");      &Debug("auth is unix");
     $contentpwd=(getpwnam($uname))[1];      my $execdir=$perlvar{'lonDaemons'};
     my $pwdcorrect = "0";      &Debug("Opening lcpasswd pipeline");
     my $pwauth_path="/usr/local/sbin/pwauth";      my $pf = IO::File->new("|$execdir/lcpasswd > "
     unless ($contentpwd eq 'x') {     ."$perlvar{'lonDaemons'}"
  $pwdcorrect= (crypt($upass,$contentpwd) eq $contentpwd);     ."/logs/lcpasswd.log");
     } elsif (-e $pwauth_path) {      print $pf "$uname\n$npass\n$npass\n";
  open PWAUTH, "|$pwauth_path" or      close $pf;
     die "Cannot invoke authentication";      my $err = $?;
  print PWAUTH "$uname\n$upass\n";      my $result = ($err>0 ? 'pwchange_failure' : 'ok');
  close PWAUTH;      &logthis("Result of password change for $uname: ".
  &Debug("exited pwauth with $? ($uname,$upass) ");       &lcpasswdstrerror($?));
  $pwdcorrect=($? == 0);      Reply($client, "$result\n", $userinput);
     }  
     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);  
     }  
  } else {   } else {
     # this just means that the current password mode is not      # this just means that the current password mode is not
     # one we know how to change (e.g the kerberos auth modes or      # one we know how to change (e.g the kerberos auth modes or
Line 945  sub ChangePasswordHandler { Line 837  sub ChangePasswordHandler {
     #      #
     Reply( $client, "auth_mode_error\n", $userinput);      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);   Reply( $client, "non_authorized\n", $userinput);
     }      }
   
     return 1;      return 1;
 }  }
 RegisterHandler("passwd", \&ChangePasswordHandler, 1, 1, 0);  RegisterHandler("passwd", \&ChangePasswordHandler, 1, 1, 0);
Line 998  sub AddUserHandler { Line 890  sub AddUserHandler {
     for (my $i=3;$i<= ($#fpparts-1);$i++) {      for (my $i=3;$i<= ($#fpparts-1);$i++) {
  $fpnow.='/'.$fpparts[$i];    $fpnow.='/'.$fpparts[$i]; 
  unless (-e $fpnow) {   unless (-e $fpnow) {
       &logthis("mkdir $fpnow");
     unless (mkdir($fpnow,0777)) {      unless (mkdir($fpnow,0777)) {
  $fperror="error: ".($!+0)." mkdir failed while attempting "   $fperror="error: ".($!+0)." mkdir failed while attempting "
     ."makeuser";      ."makeuser";
Line 1097  sub IsHomeHandler { Line 990  sub IsHomeHandler {
         
     my ($udom,$uname)=split(/:/,$tail);      my ($udom,$uname)=split(/:/,$tail);
     chomp($uname);      chomp($uname);
     my $passfile = PasswordPath($udom, $uname);      my $passfile = PasswordFilename($udom, $uname);
     if($passfile) {      if($passfile) {
  Reply( $client, "found\n", $userinput);   Reply( $client, "found\n", $userinput);
     } else {      } else {
Line 1308  sub UnsubscribeHandler { Line 1201  sub UnsubscribeHandler {
 }  }
 RegisterHandler("unusb", \&UnsubscribeHandler, 0, 1, 0);  RegisterHandler("unusb", \&UnsubscribeHandler, 0, 1, 0);
   
 #   Subscribe to a resource.  #   Subscribe to a resource
 #  #
 # Parameters:  # Parameters:
 #    $cmd      - The command that got us here.  #    $cmd      - The command that got us here.
Line 4247  sub GetAuthType { Line 4140  sub GetAuthType {
     }      }
 }  }
   
   #
   #  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 = (getpwnam($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 {  sub addline {
     my ($fname,$hostid,$ip,$newline)=@_;      my ($fname,$hostid,$ip,$newline)=@_;
     my $contents;      my $contents;
Line 4266  sub addline { Line 4288  sub addline {
     $sh->close();      $sh->close();
     return $found;      return $found;
 }  }
   #
   #    Get chat messages.
   #
 sub getchat {  sub getchat {
     my ($cdom,$cname,$udom,$uname)=@_;      my ($cdom,$cname,$udom,$uname)=@_;
     my %hash;      my %hash;
Line 4291  sub getchat { Line 4315  sub getchat {
     }      }
     return (@participants,@entries);      return (@participants,@entries);
 }  }
   #
   #   Add a chat message
   #
 sub chatadd {  sub chatadd {
     my ($cdom,$cname,$newchat)=@_;      my ($cdom,$cname,$newchat)=@_;
     my %hash;      my %hash;
Line 4462  sub make_passwd_file { Line 4488  sub make_passwd_file {
     print $pf "localauth:$npass\n";      print $pf "localauth:$npass\n";
  }   }
     } elsif ($umode eq 'unix') {      } elsif ($umode eq 'unix') {
  {   #
     my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd";   #  Don't allow the creation of privileged accounts!!! that would
     {   #  be real bad!!!
  &Debug("Executing external: ".$execpath);   #
  &Debug("user  = ".$uname.", Password =". $npass);   my $uid = getpwnam($uname);
  my $se = IO::File->new("|$execpath > $perlvar{'lonDaemons'}/logs/lcuseradd.log");   if((defined $uid) && ($uid == 0)) {
  print $se "$uname\n";      return "no_priv_account_error\n";
  print $se "$npass\n";  
  print $se "$npass\n";  
     }  
     my $useraddok = $?;  
     if($useraddok > 0) {  
  &logthis("Failed lcuseradd: ".&lcuseraddstrerror($useraddok));  
     }  
     my $pf = IO::File->new(">$passfilename");  
     print $pf "unix:\n";  
  }   }
   
    #
    my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd";
   
    &Debug("Executing external: ".$execpath);
    &Debug("user  = ".$uname.", Password =". $npass);
    my $se = IO::File->new("|$execpath > $perlvar{'lonDaemons'}/logs/lcuseradd.log");
    print $se "$uname\n";
    print $se "$npass\n";
    print $se "$npass\n";
   
    my $useraddok = $?;
    if($useraddok > 0) {
       &logthis("Failed lcuseradd: ".&lcuseraddstrerror($useraddok));
    }
    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");

Removed from v.1.178.2.11  
changed lines
  Added in v.1.178.2.14


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>