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>