Finished login from stored trusted login.html file
[CGIscriptor.git] / JavaScript / CGIscriptorSession.js
blob0f2963807f5aaa486b1c528af7636f634cd7c245
1 /*
2 * LICENSE
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Copyright 2012-2013 Rob van Son
20 * email: R.J.J.H.vanSon@gmail.com
21 * NKI-AVL Amsterdam
23 // Global variables, set by the server as CGI parameter values
24 var CGIscriptorSessionType="<SCRIPT TYPE="text/ssperl" CGI='$SESSIONTYPE=""'>
25 $SESSIONTYPE;</SCRIPT>";
26 var CGIscriptorChallengeTicket="<SCRIPT TYPE="text/ssperl" CGI='$CHALLENGETICKET=""'>
27 $CHALLENGETICKET;</SCRIPT>";
29 var CGIscriptorLoginticket="<SCRIPT TYPE='text/ssperl' CGI='$LOGINTICKET=""'>
30 $LOGINTICKET</SCRIPT>";
31 var CGIscriptorServerSalt="<SCRIPT TYPE='text/ssperl' CGI='$SERVERSALT=""'>
32 $SERVERSALT</SCRIPT>";
33 var CGIscriptorRandomSalt="<SCRIPT TYPE='text/ssperl' CGI='$RANDOMSALT=""'>
34 $RANDOMSALT</SCRIPT>";
36 // OnSubmit functions
37 function LoginSubmit () {
38 var success=check_username_password();
39 // Set the LOGINTICKET value in FORM
40 var formID = document.getElementById("LOGINTICKET");
41 if(formID) {
42 formID.value = CGIscriptorLoginticket;
45 SetSessionCookie();
46 HashPassword(CGIscriptorRandomSalt);
47 hidePasswords();
48 return success;
51 function ChangePasswordSubmit () {
52 if(! check_password_fields())return false;
53 // Set the LOGINTICKET value in FORM
54 var formID = document.getElementById("LOGINTICKET");
55 if(formID) {
56 formID.value = CGIscriptorLoginticket;
59 EncryptNewPassword("CGIUSERNAME");
60 HashPassword(CGIscriptorRandomSalt);
61 hidePasswords();
62 return true;
65 function CreateUserSubmit () {
66 if(! check_password_fields())return false;
67 // Set the LOGINTICKET value in FORM
68 var formID = document.getElementById("LOGINTICKET");
69 if(formID) {
70 formID.value = CGIscriptorLoginticket;
73 EncryptNewPassword("NEWUSERNAME");
74 HashPassword(CGIscriptorRandomSalt);
75 hidePasswords();
76 return true;
79 // Function definitions
80 function hex_sha1 (plaintext) {
81 var shaObj = new jsSHA(plaintext, "ASCII");
82 return shaObj.getHash("SHA-1", "HEX");
84 function hex_sha256 (plaintext) {
85 var shaObj = new jsSHA(plaintext, "ASCII");
86 return shaObj.getHash("SHA-256", "HEX");
88 function hex_sha512 (plaintext) {
89 var shaObj = new jsSHA(plaintext, "ASCII");
90 return shaObj.getHash("SHA-256", "HEX");
92 function chained_sha (plaintext) {
93 return hex_sha256( hex_sha256( hex_sha512(plaintext) ) );
96 function loadSessionData (SessionType, ChallengeTicket) {
97 if(SessionType == 'CHALLENGE')
98 setChallengeParameters(ChallengeTicket);
99 else if(SessionType == 'SESSION')
100 setSessionParameters();
101 return SessionType;
104 function createCookie(name,value,days,path) {
105 if (days) {
106 var date = new Date();
107 date.setTime(date.getTime()+(days*24*60*60*1000));
108 var expires = "; expires="+date.toGMTString();
110 else var expires = "";
111 var match = document.cookie.match('/('+name+'\=[^\;]*\);/');
112 if(match){
113 while(match) {
114 document.cookie = document.cookie.replace(match[1], name+"="+value);
115 match = document.cookie.match('/('+name+'\=[^\;]*\);/');
117 } else {
118 document.cookie = name+"=-";
119 document.cookie = name+"="+value+expires+"; path=/"+path;
124 function readCookie(name) {
125 var nameEQ = name + "=";
126 var ca = document.cookie.split(';');
127 for(var i=0;i < ca.length;i++) {
128 var c = ca[i];
129 while (c.charAt(0)==' ') c = c.substring(1,c.length);
130 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
132 return null;
135 function eraseCookie(name) {
136 createCookie(name,"",-1);
139 // Combine the PASSWORD with the site SERVERSALT and hash it
140 // Combine this Hash iwth the extra SERVERSALT, and hash them
141 function HashPassword(extsalt) {
142 var hash = HashSessionSeed(extsalt);
143 var password = document.getElementById('PASSWORD');
144 if(password){
145 password.value = hash;
146 } else {
147 alert("NO PASSWORD IN FORM");
148 return 0;
150 return hash;
153 // REMEMBER: Set the session cookie BEFORE you hash the password!!!
154 function SetSessionCookie() {
155 var loginticket = CGIscriptorLoginticket;
156 var randomsalt = CGIscriptorRandomSalt;
157 var hash = HashSessionSeed(loginticket);
158 // Dom.storage.enabled must be set!
159 if (!sessionStorage || typeof(sessionStorage) == 'undefined' ) {
160 alert('Your browser does not support HTML5 sessionStorage. Set Dom.storage.enabled or try upgrading.');
161 return 0;
163 else sessionStorage.setItem("CGIscriptorPRIVATE", hash);
165 // Store a secret key, if one is given
166 SetSecretKey();
168 return hash;
171 function SetSecretKey() {
172 var loginticket = CGIscriptorLoginticket;
173 var randomsalt = CGIscriptorRandomSalt;
174 var secretkey = "";
175 if (!sessionStorage || typeof(sessionStorage) == 'undefined' ) {
176 alert('Your browser does not support HTML5 sessionStorage. Set Dom.storage.enabled or try upgrading.');
177 return "";
179 else if (loginticket && randomsalt) {
180 secretkey = HashSessionSeed(loginticket+randomsalt);
181 sessionStorage.setItem("CGIscriptorSECRET", secretkey);
184 return secretkey;
187 // Hash(sessionseed+hash(password+username+salt.toLowerCase()))
188 function HashSessionSeed(sessionseed) {
189 var hash1 = "";
190 var hash2 = "";
191 var passwordvalue = document.getElementById('PASSWORD');
192 var saltvalue = CGIscriptorServerSalt;
193 var username = document.getElementById('CGIUSERNAME');
194 hash1 = hex_sha256(passwordvalue.value+username.value.toLowerCase()+saltvalue);
195 if(sessionseed != "")
196 hash2 = hex_sha256(hash1+sessionseed);
197 else
198 hash2 = hash1;
199 return hash2;
202 // Remember to hash the repeat too! Or else it will be send in the clear
203 function HashNewPassword(userid) {
204 var hash1 = "";
205 var newpassword = document.getElementById('NEWPASSWORD');
206 var newpasswordrep = document.getElementById('NEWPASSWORDREP');
207 var username = document.getElementById(userid);
208 if(newpassword.value == "" ) {
209 newpassword.value = "";
210 return 0;
212 if(newpasswordrep && (newpasswordrep.value == ""|| newpassword.value != newpasswordrep.value)) {
213 newpassword.value = "";
214 newpasswordrep.value = "";
215 return 0;
217 var saltvalue = CGIscriptorServerSalt;
218 hash1 = hex_sha256(newpassword.value+username.value.toLowerCase()+saltvalue);
219 newpassword.value = hash1;
220 newpasswordrep.value = hash1;
221 return hash1;
224 function XOR_hex_strings(hex1, hex2) {
225 var resultHex = "";
226 var maxlength = Math.max(hex1.length, hex2.length);
228 for(var i=0; i < maxlength; ++i) {
229 var h1 = hex1.charAt(i);
230 if(! h1) h1='0';
231 var h2 = hex2.charAt(i);
232 if(! h2) h2 ='0';
233 var d1 = parseInt(h1,16);
234 var d2 = parseInt(h2,16);
235 var resultD = d1^d2;
236 resultHex = resultHex+resultD.toString(16);
238 return resultHex;
241 function EncryptNewPassword(userid) {
242 var newpassword = document.getElementById('NEWPASSWORD');
243 var newpasswordrep = document.getElementById('NEWPASSWORDREP');
244 var secretkey = SetSecretKey();
246 // This hashes the newpassword field!
247 HashNewPassword(userid);
248 var encrypted = XOR_hex_strings(secretkey, newpassword.value);
249 newpassword.value = encrypted;
250 newpasswordrep.value = encrypted;
251 return encrypted;
254 function DecryptNewPassword(key, encrypted) {
255 decrypted = XOR_hex_strings(key, encrypted);
257 return decrypted;
260 function add_cgiparam(elem, attr, param) {
261 var elems = document.getElementsByTagName(elem);
262 for (var i = 0; i < elems.length; i++)
264 var n=elems[i][attr].indexOf("?");
265 if(n<0)
266 elems[i][attr] = elems[i][attr] + "?" + param;
267 else
268 elems[i][attr] = elems[i][attr] + "&" + param;
272 function setSessionParameters() {
273 var cgiScriptorPRIVATE = sessionStorage.getItem("CGIscriptorPRIVATE");
274 // Use existing cookie
275 if(! cgiScriptorPRIVATE) return true;
277 var sessionset = readCookie("CGIscriptorSESSION");
278 if(!(sessionset && sessionset.match(/[\S]/)))return false;
280 var sessionticket = "";
281 sessionticket = hex_sha256(cgiScriptorPRIVATE);
282 if(!sessionticket) return false;
283 createCookie("CGIscriptorSESSION",sessionticket, 0, "");
285 // Without cookies, use this
286 // var sessionparm = document.getElementById('SESSIONTICKET');
287 // if(sessionparm) sessionparm.value = sessionticket;
288 // add_cgiparam('a', 'href', "SESSIONTICKET="+sessionticket);
289 // add_cgiparam('form', 'action', "SESSIONTICKET="+sessionticket);
291 // UNCOMMENT for use in a local version of the Private/Login.html web page.
292 // add_cgiparam('form', 'action', "SETCGISESSIONCOOKIE="+sessionticket);
294 return true;
296 function setChallengeParameters(sessionset) {
297 if(!(sessionset && sessionset.match(/[\S]/)))return false;
299 var sessionticket = "";
300 var sessionkey = sessionStorage.getItem("CGIscriptorPRIVATE");
301 if(!sessionkey) return false;
302 sessionticket = hex_sha256(sessionkey+sessionset);
303 createCookie("CGIscriptorCHALLENGE",sessionticket, 0, "");
305 // Without cookies, use this
306 // var sessionparm = document.getElementById('CHALLENGETICKET');
307 // if(sessionparm) sessionparm.value = sessionticket;
309 // add_cgiparam('a', 'href', "CHALLENGETICKET="+sessionticket);
310 // add_cgiparam('form', 'action', "CHALLENGETICKET="+sessionticket);
311 return true;
314 function clear_persistent_data () {
315 createCookie("CGIscriptorSESSION","", 0, "");
316 createCookie("CGIscriptorCHALLENGE","", 0, "");
317 sessionStorage.setItem("CGIscriptorPRIVATE", "");
318 return true;
321 function check_password_fields ( ) {
322 var newpassword = document.getElementById('NEWPASSWORD');
323 var newpasswordrep = document.getElementById('NEWPASSWORDREP');
324 if(newpassword.value == "" || newpasswordrep.value == "") {
325 alert("No passwords");
326 return false;
328 if(newpassword.value == newpasswordrep.value) {
329 var submitbutton = document.getElementById('SUBMIT');
330 submitbutton.style.color = "Black";
331 return true;
333 alert("Passwords differ");
334 return false;
337 function check_username_password ( ) {
338 var username = document.getElementById('CGIUSERNAME');
339 var password = document.getElementById('PASSWORD');
340 if(username.value.match(/[a-zA-Z0-9]/) && password.value.match(/[a-zA-Z0-9]/))
341 return true;
342 alert("Please enter a user name and password");
343 return false;
346 function revealPasswords () {
347 var inputs = document.getElementsByTagName("input");
348 for (i=(inputs.length-1); i>=0; i--) {
349 var curr = inputs[i];
350 if (curr.type.toLowerCase()=="password") {
351 curr.type = "TEXT";
357 function hidePasswords () {
358 var inputs = document.getElementsByTagName("input");
359 for (i=(inputs.length-1); i>=0; i--) {
360 var curr = inputs[i];
361 if (curr.type.toLowerCase()=="text") {
362 curr.type = "PASSWORD";
368 function togglePasswords (hide, show, value) {
369 if(value.match(hide)) {
370 hidePasswords ();
371 return value.replace(hide, show);
372 } else {
373 revealPasswords ();
374 return value.replace(show, hide);
378 // Get a loginticket, salt, and random salt from a hidden loginFrame
379 // For use in a local version of the Private/Login.html web page.
380 // UNFINISHED WORK only useful with IPADDRESS sessions
381 // Put the following line in your local version of the HTML page to activate
382 // Replace http://localhost:8080/Private/index.html with the correct URL of the login page
383 // <iFrame id="loginFrame" src="http://localhost:8080/Private/index.html" hidden>Login frame</iFrame>
385 function getLoginData(){
386 var frameID = document.getElementById("loginFrame");
387 var iFrameHeader;
388 if ( frameID.contentDocument )
389 { // FF
390 iFrameHeader = frameID.contentDocument.getElementsByTagName('head')[0];
391 iFrameHTML = frameID.contentDocument.getElementsByTagName('html')[0];
393 else if ( frameID.contentWindow )
394 { // IE
395 iFrameHeader = frameID.contentWindow.document.getElementsByTagName('head')[0];
396 iFrameHTML = frameID.contentWindow.document.getElementsByTagName('html')[0];
399 // Login ticket
400 var myLoginexp = /CGIscriptorLoginticket="([a-f0-9]{64})"/;
401 var myLogin = iFrameHeader.innerHTML.match(myLoginexp);
402 if(myLogin) {
403 CGIscriptorLoginticket = myLogin[1];
404 } else {
405 alert("Login not possible: Are you already logged in?\nLogin ticket missing");
408 // Server Salt
409 var mySaltexp = /CGIscriptorServerSalt="([a-f0-9]{64})"/;
410 var mySalt = iFrameHeader.innerHTML.match(mySaltexp);
411 if(mySalt){
412 CGIscriptorServerSalt = mySalt[1];
413 } else if(myLogin) {
414 alert("Login not possible: Are you already logged in?\nServer salt missing");
417 // Random Salt
418 var myRandomexp = /CGIscriptorRandomSalt="([a-f0-9]{64})"/;
419 var myRandom = iFrameHeader.innerHTML.match(myRandomexp);
420 if(myRandom){
421 CGIscriptorRandomSalt = myRandom[1];
422 } else if(myLogin && mySalt) {
423 alert("Login not possible: Are you already logged in?\nRandom salt missing");
426 // Clean out frame
427 iFrameHTML.innerHTML = "<html><head><title>EMPTY</title></head><body><h1>EMPTY</h1></body></html>";