[LON-CAPA-cvs] cvs: loncom /interface lonpreferences.pm
matthew
lon-capa-cvs@mail.lon-capa.org
Fri, 15 Feb 2002 22:04:39 -0000
This is a MIME encoded message
--matthew1013810679
Content-Type: text/plain
matthew Fri Feb 15 17:04:39 2002 EDT
Modified files:
/loncom/interface lonpreferences.pm
Log:
Commit of working but not complete code, in case my machine crashes over the
weekend. I've put too much effort into this javascript that I don't want to
take any chances. Can now attempt to change password. More changes will be
forthcoming.
--matthew1013810679
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20020215170439.txt"
Index: loncom/interface/lonpreferences.pm
diff -u loncom/interface/lonpreferences.pm:1.2 loncom/interface/lonpreferences.pm:1.3
--- loncom/interface/lonpreferences.pm:1.2 Wed Dec 19 12:17:46 2001
+++ loncom/interface/lonpreferences.pm Fri Feb 15 17:04:39 2002
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Preferences
#
-# $Id: lonpreferences.pm,v 1.2 2001/12/19 17:17:46 albertel Exp $
+# $Id: lonpreferences.pm,v 1.3 2002/02/15 22:04:39 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -35,29 +35,294 @@
#
# 3/1 Gerd Kortemeyer
#
+# 2/13/02 2/14 2/15 Matthew Hall
+#
+# This package uses the "londes.js" javascript code.
+#
+# TODOs that have to be completed:
+# interface with lonnet to change the password
+
package Apache::lonpreferences;
use strict;
use Apache::Constants qw(:common);
+use Apache::File;
+use Crypt::DES;
+use DynaLoader; # for Crypt::DES version
+
+#------------------- forms to be output
+my $passwordform =<<ENDPASSWORDFORM;
+<form name="client" action="/adm/preferences" method="post">
+<input type="hidden" name="action" value="changepass">
+<input type="submit" value="Change password">
+</form>
+ENDPASSWORDFORM
+
+my $environmentform = <<ENDENVIRONMENTFORM;
+<p>
+There are currently no environment variables you can change.
+</p>
+<!----
+ You may set the following environment variables:
+ <table>
+ <tr><th>Environment Setting</th><th>Current Value</th></tr>
+ <tr>
+ <td colspan="2">
+ <font color="#ff0000">No variables currently set up</font>
+ </td>
+ </tr>
+ </table>
+ -->
+ENDENVIRONMENTFORM
+#------------------ end of forms to be output
+
+################################################################
+# Handler subroutines #
+################################################################
+#
+# Write lonnet::passwd to do the call below.
+# Use:
+# my $answer=reply("encrypt:passwd:$udom:$uname:$upass",$tryserver);
+#
+# I really should write some javascript to check on the client side for
+# mismatched passwords, but other problems are more pressing
+#
+##################################################
+# password associated functions #
+##################################################
+sub des_keys {
+ # Make a new key for DES encryption
+ # Each key has two parts which are returned seperately
+ my @hexstr=('0','1','2','3','4','5','6','7',
+ '8','9','a','b','c','d','e','f');
+ my $lkey='';
+ for (0..7) {
+ $lkey.=$hexstr[rand(15)];
+ }
+ my $ukey='';
+ for (0..7) {
+ $ukey.=$hexstr[rand(15)];
+ }
+ return ($lkey,$ukey);
+}
+
+sub des_decrypt {
+ my ($key,$cyphertext) = @_;
+ my $keybin=pack("H16",$key);
+ my $cypher;
+ if ($Crypt::DES::VERSION>=2.03) {
+ $cypher=new Crypt::DES $keybin;
+ } else {
+ $cypher=new DES $keybin;
+ }
+ my $plaintext=
+ $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));
+ $plaintext.=
+ $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));
+ $plaintext=unpack("a8",$plaintext);
+ $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)));
+ unpack("a8",$plaintext);
+ return $plaintext;
+}
+
+sub passwordchanger {
+ # Passwords are encrypted using londes.js (DES encryption)
+ #
+ my $r = shift;
+ my $user = $ENV{'user.name'};
+ my $domain = $ENV{'user.domain'};
+ my $homeserver = $ENV{'user.home'};
+ my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
+ # Check for authentication types that allow changing of the password.
+ return if ($currentauth !~ /^(unix|internal):/);
+ #
+ # Generate keys
+ my ($lkey_cpass ,$ukey_cpass ) = &des_keys();
+ my ($lkey_npass1,$ukey_npass1) = &des_keys();
+ my ($lkey_npass2,$ukey_npass2) = &des_keys();
+ # Store the keys
+ my $lonhost = $r->dir_config('lonHostID');
+ my $logtoken=Apache::lonnet::reply('tmpput:'
+ .$ukey_cpass . $lkey_cpass .'&'
+ .$ukey_npass1 . $lkey_npass1.'&'
+ .$ukey_npass2 . $lkey_npass2,
+ $lonhost);
+ # Hexify these keys
+ $ukey_cpass = hex($ukey_cpass);
+ $lkey_cpass = hex($lkey_cpass);
+ $ukey_npass1= hex($ukey_npass1);
+ $lkey_npass1= hex($lkey_npass1);
+ $ukey_npass2= hex($ukey_npass2);
+ $lkey_npass2= hex($lkey_npass2);
+ # Output javascript to deal with passwords
+ $r->print(<<ENDHEADER);
+<html>
+<head>
+<title>The LearningOnline Network with CAPA</title>
+</head>
+ENDHEADER
+ # Output DES javascript
+ {
+ my $include = $r->dir_config('lonIncludes');
+ my $jsh=Apache::File->new($include."/londes.js");
+ $r->print(<$jsh>);
+ }
+ $r->print(<<ENDFORM);
+
+<body bgcolor="#FFFFFF" onLoad="init();">
+<script language="JavaScript">
+
+ function send() {
+ uextkey=this.document.client.elements.ukey_cpass.value;
+ lextkey=this.document.client.elements.lkey_cpass.value;
+ initkeys();
+
+ this.document.server.elements.currentpass.value
+ =crypted(this.document.client.elements.currentpass.value);
+
+ uextkey=this.document.client.elements.ukey_npass1.value;
+ lextkey=this.document.client.elements.lkey_npass1.value;
+ initkeys();
+ this.document.server.elements.newpass_1.value
+ =crypted(this.document.client.elements.newpass_1.value);
+
+ uextkey=this.document.client.elements.ukey_npass2.value;
+ lextkey=this.document.client.elements.lkey_npass2.value;
+ initkeys();
+ this.document.server.elements.newpass_2.value
+ =crypted(this.document.client.elements.newpass_2.value);
+
+ this.document.server.submit();
+ }
+
+</script>
+<h1>Preferences for $user</h1>
+<h3>$user is a member of domain $domain</h3>
+<p>
+Change password for $user
+</p>
+<p>
+<!-- We seperate the forms into 'server' and 'client' in order to
+ ensure that unencrypted passwords will not be sent out by a
+ crappy browser -->
+
+<form name="server" action="/adm/preferences" method="post">
+<input type="hidden" name="logtoken" value="$logtoken" />
+<input type="hidden" name="action" value="verify_and_change_pass" />
+<input type="hidden" name="currentpass" value="" />
+<input type="hidden" name="newpass_1" value="" />
+<input type="hidden" name="newpass_2" value="" />
+</form>
+
+<form name="client" >
+<table>
+<tr><td align="right"> Current password: </td>
+ <td><input type="password" name="currentpass" /> </td></tr>
+<tr><td align="right"> New password: </td>
+ <td><input type="password" name="newpass_1" /> </td></tr>
+<tr><td align="right"> Confirm password: </td>
+ <td><input type="password" name="newpass_2" /> </td></tr>
+<tr><td colspan="2" align="center">
+ <input type="button" value="Change Password" onClick="send();">
+</table>
+<input type="hidden" name="ukey_cpass" value="$ukey_cpass" />
+<input type="hidden" name="lkey_cpass" value="$lkey_cpass" />
+<input type="hidden" name="ukey_npass1" value="$ukey_npass1" />
+<input type="hidden" name="lkey_npass1" value="$lkey_npass1" />
+<input type="hidden" name="ukey_npass2" value="$ukey_npass2" />
+<input type="hidden" name="lkey_npass2" value="$lkey_npass2" />
+</form>
+</p>
+ENDFORM
+ #
+ return;
+}
+
+sub verify_and_change_password {
+ my $r = shift;
+ my $user = $ENV{'user.name'};
+ my $domain = $ENV{'user.domain'};
+ my $homeserver = $ENV{'user.home'};
+ my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
+ #
+ $r->print("<h1>verify and change password</h1>\n");
+ #
+ my $currentpass = $ENV{'form.currentpass'};
+ my $newpass1 = $ENV{'form.newpass_1'};
+ my $newpass2 = $ENV{'form.newpass_2'};
+ my $logtoken = $ENV{'form.logtoken'};
+ # Check for empty data
+ if (!(defined($currentpass) &&
+ defined($newpass1) &&
+ defined($newpass2))){
+ $r->print("<font color='#ff0000'>ERROR</font> Password data was ".
+ "blank.\n");
+ return;
+ }
+ # Get the keys
+ my $lonhost = $r->dir_config('lonHostID');
+ my $tmpinfo = Apache::lonnet::reply('tmpget:'.$logtoken,$lonhost);
+ if (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost')) {
+ $r->print(<<ENDERROR);
+<p>
+<font color="#ff0000">ERROR:</font> Unable to retrieve stored token for
+password decryption.
+</p>
+ENDERROR
+ return;
+ }
+ my ($ckey,$n1key,$n2key)=split(/&/,$tmpinfo);
+ # decrypt
+ my $currentpass = &des_decrypt($ckey ,$currentpass);
+ my $newpass1 = &des_decrypt($n1key,$newpass1);
+ my $newpass2 = &des_decrypt($n2key,$newpass2);
+ # Sanity check
+ if ($newpass1 ne $newpass2) {
+ $r->print('<font color="#ff0000">ERROR:</font>The new passwords you '.
+ 'entered do not match. Please try again.');
+ &passwordchanger($r);
+ return;
+ }
+}
+
+################################################################
+# Main handler #
+################################################################
sub handler {
my $r = shift;
+ my $user = $ENV{'user.name'};
+ my $domain = $ENV{'user.domain'};
$r->content_type('text/html');
$r->send_http_header;
return OK if $r->header_only;
-
-# --------------------------------------------------- Print login screen header
- $r->print(<<ENDDOCUMENT);
+ # Spit out the header
+ if ($ENV{'form.action'} eq 'changepass') {
+ &passwordchanger($r);
+ } elsif ($ENV{'form.action'} eq 'verify_and_change_pass') {
+ &verify_and_change_password($r);
+ } else {
+ $r->print(<<ENDHEADER);
<html>
<head>
<title>The LearningOnline Network with CAPA</title>
</head>
-<body bgcolor="#FFFFFF">
-<h1>Preferences</h1>
-<img src="/adm/lonKaputt/lonconstruct.gif">
+<body bgcolor="#FFFFFF" >
+<h1>Preferences for $user</h1>
+<h3>$user is a member of domain $domain</h3>
+ENDHEADER
+ # Determine current authentication method
+ my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
+ if ($currentauth =~ /^(unix|internal):/) {
+ $r->print($passwordform);
+ }
+ $r->print($environmentform);
+ }
+ # Spit out the footer
+ $r->print(<<ENDFOOTER);
</body>
</html>
-ENDDOCUMENT
+ENDFOOTER
return OK;
}
--matthew1013810679--