Updated documentation
[CGIscriptor.git] / Private / manual.html
blobee3e4f390df50ae1a8db7d8af12913a69517febb
1 <html>
2 <head>
3 <title>
4 Private data
5 </title>
6 <script type="text/javascript">
7 function createCookie(name,value,days,path) {
8 if (days) {
9 var date = new Date();
10 date.setTime(date.getTime()+(days*24*60*60*1000));
11 var expires = "; expires="+date.toGMTString();
13 else var expires = "";
14 var match = document.cookie.match('/('+name+'\=[^\;]*\);/');
15 if(match)
16 document.cookie = document.cookie.replace(match[1], name+"="+value);
17 else
18 document.cookie = name+"="+value+expires+"; path=/"+path;
21 function readCookie(name) {
22 var nameEQ = name + "=";
23 var ca = document.cookie.split(';');
24 for(var i=0;i < ca.length;i++) {
25 var c = ca[i];
26 while (c.charAt(0)==' ') c = c.substring(1,c.length);
27 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
29 return null;
32 function eraseCookie(name) {
33 createCookie(name,"",-1);
36 function add_cgiparam(elem, attr, param) {
37 var elems = document.getElementsByTagName(elem);
38 for (var i = 0; i < elems.length; i++)
40 var n=elems[i][attr].indexOf("?");
41 if(n<0)
42 elems[i][attr] = elems[i][attr] + "?" + param;
43 else
44 elems[i][attr] = elems[i][attr] + "&" + param;
48 function setSessionParameters() {
49 var sessionset = readCookie("CGIscriptorSESSION");
50 if(!(sessionset && sessionset.match(/[\S]/)))return false;
52 var sessionticket = "";
53 sessionticket = sessionStorage.getItem("CGIscriptorPRIVATE");
54 createCookie("CGIscriptorSESSION",sessionticket, 1, "Private");
56 // Without cookies, use this
57 // var sessionparm = document.getElementById('SESSIONTICKET');
58 // if(sessionparm) sessionparm.value = sessionticket;
59 // add_cgiparam('a', 'href', "SESSIONTICKET="+sessionticket);
60 // add_cgiparam('form', 'action', "SESSIONTICKET="+sessionticket);
61 return true;
63 function setChallengeParameters() {
64 var sessionset = readCookie("CGIscriptorCHALLENGE");
65 if(!(sessionset && sessionset.match(/[\S]/)))return false;
67 var sessionticket = "";
68 sessionticket = sessionStorage.getItem("CGIscriptorPRIVATE");
70 createCookie("CGIscriptorCHALLENGE",sessionticket, 1, "Private");
72 // Without cookies, use this
73 // var sessionparm = document.getElementById('CHALLENGETICKET');
74 // if(sessionparm) sessionparm.value = sessionticket;
75 // add_cgiparam('a', 'href', "CHALLENGETICKET="+sessionticket);
76 // add_cgiparam('form', 'action', "CHALLENGETICKET="+sessionticket);
77 return true;
80 window.onload = function() {
81 var challengeSet = setChallengeParameters();
82 if(! challengeSet)
83 setSessionParameters();
84 return true;
88 </script>
89 </head>
90 <body>
91 <p ALIGN=RIGHT><a href="?LOGOUT">Logout</a></p>
92 <p ALIGN=RIGHT><a href="ChangePassword.html">Change Password</a></p>
93 <h1 align=CENTER>Manual</h1>
94 <p align=CENTER>Logged in from <script type="text/ssperl" CGI='$LOGINIPADDRESS="" $LOGINPATH=""'>"$LOGINIPADDRESS $LOGINPATH"</script></p>
95 <p align=CENTER><form method=GET action="index.html">
96 <p align=CENTER><input type="submit" value="Go back to home page" /></p>
97 <input type="hidden" name="SESSIONTICKET" id="SESSIONTICKET" value="" />
98 <input type="hidden" name="CHALLENGETICKET" id="CHALLENGETICKET" value="" /><br />
99 </form>
100 </p>
103 <A NAME="SESSIONTICKETS"><H2 ALIGN="CENTER">SERVER SIDE SESSIONS AND ACCESS CONTROL (LOGIN)</H2></A>
105 An infrastructure for user acount authorization and file access control
106 is available. Each request is matched against a list of URL path patterns.
107 If the request matches, a Session Ticket is required to access the URL.
108 This Session Ticket should be present as a CGI parameter or Cookie:
109 </p>
111 CGI: SESSIONTICKET=&lt;value&gt;<br />
112 Cookie: CGIscriptorSESSION=&lt;value&gt;</p>
114 The example implementation stores Session Tickets as files in a local
115 directory. To create Session Tickets, a Login request must be given
116 with a LOGIN=&lt;value&gt; CGI parameter, a user name and a (doubly hashed)
117 password. The user name and (singly hashed) password are stored in a
118 PASSWORD ticket with the same name as the user account (name cleaned up
119 for security).
120 </p>
122 The example session model implements 3 functions:
123 <ol>
124 <li>Login<br />
125 The password is hashed with the user name and server side salt, and then
126 hashed with a Random salt. Client and Server both perform these actions and the
127 Server only grants access if restults are the same. The server side only
128 stores the password hashed with the user name and
129 server side salt. Neither the plain password, nor the hashed password is
130 ever exchanged. Only values hashed with the one-time salt are exchanged.
131 </li>
132 <li>Session<br />
133 For every access to a restricted URL, the Session Ticket is checked before
134 access is granted. There are three session modes. The first uses a fixed
135 Session Ticket that is stored as a cookie value in the browser (actually,
136 as a sessionStorage value). The second uses only the IP address at login
137 to authenticate requests. The third
138 is a Challenge mode, where the client has to calculate the value of the
139 one-time Session Ticket from a value derived from the password and
140 a random string.
141 </li>
142 <li>Password Change<br />
143 A new password is hashed with the user name and server side salt, and
144 then encrypted (XORed)
145 with the old password hashed with the user name and salt. That value is
146 exchanged and XORed with the stored old hashed(salt+password+username).
147 Again, the stored password value is never exchanged unencrypted.
148 </li>
149 </ol>
150 </p>
151 <H3 ALIGN="CENTER">Implementation</H3>
153 The session authentication mechanism is based on the exchange of ticket
154 identifiers. A ticket identifier is just a string of characters, a name
155 or a random 40 character hexadecimal string. Ticket identifiers should be
156 "safe" filenames (except user names). There are four types of tickets:
157 <ul>
158 <li>PASSWORD: User account descriptors, including a user name and password</li>
159 <li>LOGIN: Temporary anonymous tickets used during login</li>
160 <li>SESSION: Reusable authetication tokens that allow access to specific URLs</li>
161 <li>IPADDRESS: authetication tokens that allow access based on the IP address of the request</li>
162 <li>CHALLENGE: One-time authetication tokens that allow access to specific URLs</li>
163 </ul>
164 All tickets can have an expiration date in the form of a time duration
165 from creation, in seconds, minutes, hours, or days (<em>+duration</em>[smhd]).
166 An absolute time can be given in seconds since the epoch of the server host.
167 </p>
169 A Login page should create a LOGIN ticket file locally and send a
170 server specific SALT, a Random salt, and a LOGIN ticket
171 identifier. The server side compares the username and hashed password,
172 actually hashed(Random salt+hashed(SALT+password)) from the client with
173 the values it calculates from the stored Random salt from the LOGIN
174 ticket and the hashed(SALT+password) from the PASSWORD ticket. If
175 successful, a new SESSION ticket is generated as a hash sum of the LOGIN
176 ticket and the stored password. This SESSION ticket should also be
177 generated by the client and stored as sessionStorage and cookie values
178 as needed. The Username, IP address and Path are available as
179 $LoginUsername, $LoginIPaddress, and $LoginPath, respectively.
180 </p>
182 In the current example implementation, all random values are created as
183 a full, 160 bit SHA1 hash (Hex strings) of 32 bytes read from
184 /dev/urandom.
185 </p>
187 <H3 ALIGN="CENTER">Security considerations with Session tickets</H3>
189 For strong security, please use end-to-end encryption. This can be
190 achieved using a VPN (Virtual Private Network), SSH tunnel, or a HTTPS
191 capable server with OpenSSL. The session ticket system of CGIscriptor.pl
192 is intended to be used as a simple authentication mechanism WITHOUT
193 END-TO-END ENCRYPTION. The authenticating mechanism tries to use some
194 simple means to protect the authentication process from eavesdropping.
195 For this it uses a secure hash function, SHA1. For all practial purposes,
196 it is impossible to "decrypt" a SHA1 sum. But this login scheme is
197 only as secure as your browser. Which, in general, is not secure.
198 </p>
200 Humans tend to reuse passwords. A compromise of a site running
201 CGIscriptor.pl could therefore lead to a compromise of user accounts at
202 other sites. Therefore, plain text passwords are never stored, used, or
203 even exchanged. Instead, a server site SALT value is "encrypted" with
204 the plain password and user name, actually, all are concatenated and hashed
205 with a one-way secure hash function (SHA1) into a single string.
206 Whenever the word "password" is used, this hash sum is meant.
207 </p>
209 For the authentication and a change of password, the (old) password
210 is used to "encrypt" a random one-time token or the new password,
211 respectively. For authentication, decryption is not needed, so a secure
212 hash function (SHA1) is used to create a one-way hash sum "encryption".
213 A new password must be decrypted. New passwords are encryped by XORing
214 them with the old password.
215 </p>
219 </body>
220 </html>