Annotation of loncom/interface/lonpreferences.pm, revision 1.3
1.1 www 1: # The LearningOnline Network
2: # Preferences
3: #
1.3 ! matthew 4: # $Id: lonpreferences.pm,v 1.2 2001/12/19 17:17:46 albertel Exp $
1.2 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.1 www 28: # (Internal Server Error Handler
29: #
30: # (Login Screen
31: # 5/21/99,5/22,5/25,5/26,5/31,6/2,6/10,7/12,7/14,
32: # 1/14/00,5/29,5/30,6/1,6/29,7/1,11/9 Gerd Kortemeyer)
33: #
34: # 3/1/1 Gerd Kortemeyer)
35: #
36: # 3/1 Gerd Kortemeyer
37: #
1.3 ! matthew 38: # 2/13/02 2/14 2/15 Matthew Hall
! 39: #
! 40: # This package uses the "londes.js" javascript code.
! 41: #
! 42: # TODOs that have to be completed:
! 43: # interface with lonnet to change the password
! 44:
1.1 www 45: package Apache::lonpreferences;
46:
47: use strict;
48: use Apache::Constants qw(:common);
1.3 ! matthew 49: use Apache::File;
! 50: use Crypt::DES;
! 51: use DynaLoader; # for Crypt::DES version
! 52:
! 53: #------------------- forms to be output
! 54: my $passwordform =<<ENDPASSWORDFORM;
! 55: <form name="client" action="/adm/preferences" method="post">
! 56: <input type="hidden" name="action" value="changepass">
! 57: <input type="submit" value="Change password">
! 58: </form>
! 59: ENDPASSWORDFORM
! 60:
! 61: my $environmentform = <<ENDENVIRONMENTFORM;
! 62: <p>
! 63: There are currently no environment variables you can change.
! 64: </p>
! 65: <!----
! 66: You may set the following environment variables:
! 67: <table>
! 68: <tr><th>Environment Setting</th><th>Current Value</th></tr>
! 69: <tr>
! 70: <td colspan="2">
! 71: <font color="#ff0000">No variables currently set up</font>
! 72: </td>
! 73: </tr>
! 74: </table>
! 75: -->
! 76: ENDENVIRONMENTFORM
! 77: #------------------ end of forms to be output
! 78:
! 79: ################################################################
! 80: # Handler subroutines #
! 81: ################################################################
! 82: #
! 83: # Write lonnet::passwd to do the call below.
! 84: # Use:
! 85: # my $answer=reply("encrypt:passwd:$udom:$uname:$upass",$tryserver);
! 86: #
! 87: # I really should write some javascript to check on the client side for
! 88: # mismatched passwords, but other problems are more pressing
! 89: #
! 90: ##################################################
! 91: # password associated functions #
! 92: ##################################################
! 93: sub des_keys {
! 94: # Make a new key for DES encryption
! 95: # Each key has two parts which are returned seperately
! 96: my @hexstr=('0','1','2','3','4','5','6','7',
! 97: '8','9','a','b','c','d','e','f');
! 98: my $lkey='';
! 99: for (0..7) {
! 100: $lkey.=$hexstr[rand(15)];
! 101: }
! 102: my $ukey='';
! 103: for (0..7) {
! 104: $ukey.=$hexstr[rand(15)];
! 105: }
! 106: return ($lkey,$ukey);
! 107: }
! 108:
! 109: sub des_decrypt {
! 110: my ($key,$cyphertext) = @_;
! 111: my $keybin=pack("H16",$key);
! 112: my $cypher;
! 113: if ($Crypt::DES::VERSION>=2.03) {
! 114: $cypher=new Crypt::DES $keybin;
! 115: } else {
! 116: $cypher=new DES $keybin;
! 117: }
! 118: my $plaintext=
! 119: $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));
! 120: $plaintext.=
! 121: $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));
! 122: $plaintext=unpack("a8",$plaintext);
! 123: $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)));
! 124: unpack("a8",$plaintext);
! 125: return $plaintext;
! 126: }
! 127:
! 128: sub passwordchanger {
! 129: # Passwords are encrypted using londes.js (DES encryption)
! 130: #
! 131: my $r = shift;
! 132: my $user = $ENV{'user.name'};
! 133: my $domain = $ENV{'user.domain'};
! 134: my $homeserver = $ENV{'user.home'};
! 135: my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
! 136: # Check for authentication types that allow changing of the password.
! 137: return if ($currentauth !~ /^(unix|internal):/);
! 138: #
! 139: # Generate keys
! 140: my ($lkey_cpass ,$ukey_cpass ) = &des_keys();
! 141: my ($lkey_npass1,$ukey_npass1) = &des_keys();
! 142: my ($lkey_npass2,$ukey_npass2) = &des_keys();
! 143: # Store the keys
! 144: my $lonhost = $r->dir_config('lonHostID');
! 145: my $logtoken=Apache::lonnet::reply('tmpput:'
! 146: .$ukey_cpass . $lkey_cpass .'&'
! 147: .$ukey_npass1 . $lkey_npass1.'&'
! 148: .$ukey_npass2 . $lkey_npass2,
! 149: $lonhost);
! 150: # Hexify these keys
! 151: $ukey_cpass = hex($ukey_cpass);
! 152: $lkey_cpass = hex($lkey_cpass);
! 153: $ukey_npass1= hex($ukey_npass1);
! 154: $lkey_npass1= hex($lkey_npass1);
! 155: $ukey_npass2= hex($ukey_npass2);
! 156: $lkey_npass2= hex($lkey_npass2);
! 157: # Output javascript to deal with passwords
! 158: $r->print(<<ENDHEADER);
! 159: <html>
! 160: <head>
! 161: <title>The LearningOnline Network with CAPA</title>
! 162: </head>
! 163: ENDHEADER
! 164: # Output DES javascript
! 165: {
! 166: my $include = $r->dir_config('lonIncludes');
! 167: my $jsh=Apache::File->new($include."/londes.js");
! 168: $r->print(<$jsh>);
! 169: }
! 170: $r->print(<<ENDFORM);
! 171:
! 172: <body bgcolor="#FFFFFF" onLoad="init();">
1.1 www 173:
1.3 ! matthew 174: <script language="JavaScript">
! 175:
! 176: function send() {
! 177: uextkey=this.document.client.elements.ukey_cpass.value;
! 178: lextkey=this.document.client.elements.lkey_cpass.value;
! 179: initkeys();
! 180:
! 181: this.document.server.elements.currentpass.value
! 182: =crypted(this.document.client.elements.currentpass.value);
! 183:
! 184: uextkey=this.document.client.elements.ukey_npass1.value;
! 185: lextkey=this.document.client.elements.lkey_npass1.value;
! 186: initkeys();
! 187: this.document.server.elements.newpass_1.value
! 188: =crypted(this.document.client.elements.newpass_1.value);
! 189:
! 190: uextkey=this.document.client.elements.ukey_npass2.value;
! 191: lextkey=this.document.client.elements.lkey_npass2.value;
! 192: initkeys();
! 193: this.document.server.elements.newpass_2.value
! 194: =crypted(this.document.client.elements.newpass_2.value);
! 195:
! 196: this.document.server.submit();
! 197: }
! 198:
! 199: </script>
! 200: <h1>Preferences for $user</h1>
! 201: <h3>$user is a member of domain $domain</h3>
! 202: <p>
! 203: Change password for $user
! 204: </p>
! 205: <p>
! 206: <!-- We seperate the forms into 'server' and 'client' in order to
! 207: ensure that unencrypted passwords will not be sent out by a
! 208: crappy browser -->
! 209:
! 210: <form name="server" action="/adm/preferences" method="post">
! 211: <input type="hidden" name="logtoken" value="$logtoken" />
! 212: <input type="hidden" name="action" value="verify_and_change_pass" />
! 213: <input type="hidden" name="currentpass" value="" />
! 214: <input type="hidden" name="newpass_1" value="" />
! 215: <input type="hidden" name="newpass_2" value="" />
! 216: </form>
! 217:
! 218: <form name="client" >
! 219: <table>
! 220: <tr><td align="right"> Current password: </td>
! 221: <td><input type="password" name="currentpass" /> </td></tr>
! 222: <tr><td align="right"> New password: </td>
! 223: <td><input type="password" name="newpass_1" /> </td></tr>
! 224: <tr><td align="right"> Confirm password: </td>
! 225: <td><input type="password" name="newpass_2" /> </td></tr>
! 226: <tr><td colspan="2" align="center">
! 227: <input type="button" value="Change Password" onClick="send();">
! 228: </table>
! 229: <input type="hidden" name="ukey_cpass" value="$ukey_cpass" />
! 230: <input type="hidden" name="lkey_cpass" value="$lkey_cpass" />
! 231: <input type="hidden" name="ukey_npass1" value="$ukey_npass1" />
! 232: <input type="hidden" name="lkey_npass1" value="$lkey_npass1" />
! 233: <input type="hidden" name="ukey_npass2" value="$ukey_npass2" />
! 234: <input type="hidden" name="lkey_npass2" value="$lkey_npass2" />
! 235: </form>
! 236: </p>
! 237: ENDFORM
! 238: #
! 239: return;
! 240: }
! 241:
! 242: sub verify_and_change_password {
! 243: my $r = shift;
! 244: my $user = $ENV{'user.name'};
! 245: my $domain = $ENV{'user.domain'};
! 246: my $homeserver = $ENV{'user.home'};
! 247: my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
! 248: #
! 249: $r->print("<h1>verify and change password</h1>\n");
! 250: #
! 251: my $currentpass = $ENV{'form.currentpass'};
! 252: my $newpass1 = $ENV{'form.newpass_1'};
! 253: my $newpass2 = $ENV{'form.newpass_2'};
! 254: my $logtoken = $ENV{'form.logtoken'};
! 255: # Check for empty data
! 256: if (!(defined($currentpass) &&
! 257: defined($newpass1) &&
! 258: defined($newpass2))){
! 259: $r->print("<font color='#ff0000'>ERROR</font> Password data was ".
! 260: "blank.\n");
! 261: return;
! 262: }
! 263: # Get the keys
! 264: my $lonhost = $r->dir_config('lonHostID');
! 265: my $tmpinfo = Apache::lonnet::reply('tmpget:'.$logtoken,$lonhost);
! 266: if (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost')) {
! 267: $r->print(<<ENDERROR);
! 268: <p>
! 269: <font color="#ff0000">ERROR:</font> Unable to retrieve stored token for
! 270: password decryption.
! 271: </p>
! 272: ENDERROR
! 273: return;
! 274: }
! 275: my ($ckey,$n1key,$n2key)=split(/&/,$tmpinfo);
! 276: # decrypt
! 277: my $currentpass = &des_decrypt($ckey ,$currentpass);
! 278: my $newpass1 = &des_decrypt($n1key,$newpass1);
! 279: my $newpass2 = &des_decrypt($n2key,$newpass2);
! 280: # Sanity check
! 281: if ($newpass1 ne $newpass2) {
! 282: $r->print('<font color="#ff0000">ERROR:</font>The new passwords you '.
! 283: 'entered do not match. Please try again.');
! 284: &passwordchanger($r);
! 285: return;
! 286: }
! 287: }
! 288:
! 289: ################################################################
! 290: # Main handler #
! 291: ################################################################
1.1 www 292: sub handler {
293: my $r = shift;
1.3 ! matthew 294: my $user = $ENV{'user.name'};
! 295: my $domain = $ENV{'user.domain'};
1.1 www 296: $r->content_type('text/html');
297: $r->send_http_header;
298: return OK if $r->header_only;
1.3 ! matthew 299: # Spit out the header
! 300: if ($ENV{'form.action'} eq 'changepass') {
! 301: &passwordchanger($r);
! 302: } elsif ($ENV{'form.action'} eq 'verify_and_change_pass') {
! 303: &verify_and_change_password($r);
! 304: } else {
! 305: $r->print(<<ENDHEADER);
1.1 www 306: <html>
307: <head>
308: <title>The LearningOnline Network with CAPA</title>
309: </head>
1.3 ! matthew 310: <body bgcolor="#FFFFFF" >
! 311: <h1>Preferences for $user</h1>
! 312: <h3>$user is a member of domain $domain</h3>
! 313: ENDHEADER
! 314: # Determine current authentication method
! 315: my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain);
! 316: if ($currentauth =~ /^(unix|internal):/) {
! 317: $r->print($passwordform);
! 318: }
! 319: $r->print($environmentform);
! 320: }
! 321: # Spit out the footer
! 322: $r->print(<<ENDFOOTER);
1.1 www 323: </body>
324: </html>
1.3 ! matthew 325: ENDFOOTER
1.1 www 326: return OK;
327: }
328:
329: 1;
330: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>