dec4f1d64d7286cb53c3c79662917753e8baa40f
[gssweb.git] / xpi / chrome / content / nav.gss.js
1 console.log('Loading nav.gss.js - #1');
2 /*
3  * Copyright (c) 2014, JANET(UK)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of JANET(UK) nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32  * OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35
36 console.log('Loading navigator.gss.js - #1');
37
38 navigator.generateNonce = function() {
39   // TODO: Make sure that we don't have a collision!
40   // Random integer in the range [0..(2^32-1)]
41   return Math.floor(Math.random() * ( 4294967295 )) ;
42 }
43
44
45
46 /* This file gets injected into the web page verbatim */
47
48 var GSSEap = (function () 
49   {
50     function GSSEap(config)
51     {
52         // Public attributes
53         this.version = "0.0.1";
54         this.implemented_methods = ["gss_import_name", "gss_display_name", "gss_init_sec_context", "gss_acquire_cred"];
55         // MRW -- combine success/error callback hashes?
56         this.callbacks = {};
57         this.errors = {};
58         this.appTag = config.appTag || "";
59         this.default_error = config.error || 
60             function (major, minor, error, appTag) {
61                 console.warn(error);
62             };
63         window.addEventListener(
64             "message",
65             this.dispatch_responses.bind(this)
66         );
67     }
68     GSSEap.prototype.dispatch_responses = function (event) 
69     {
70         var method;
71         var nonce;
72         var callback;
73         var app_tag;
74         var error;
75
76         /* This message is destined for us only if all the following apply:
77         * - The data.method_name is one of the methods implemented by this
78         *   object
79         * - data.return_values exists or data.error_mssage exists
80         * - data.cookies exists
81         * - One of my callbacks matches the nonce in
82         *   data.cookies.navigator_gss_tag
83         * - One of my methods matches the nonce in 
84         *   data.cookies.navigator_gss_tag and that method matches
85         *   data.method
86         */
87         method = event.data.method;
88         if (
89              ( -1 == this.implemented_methods.indexOf(method) ) ||
90              (  ("undefined" == typeof (event.data.return_values) ) &&
91                 ("undefined" == typeof (event.data.error_message) ) ) ||
92              ("undefined" == typeof (event.data.cookies)))
93         {
94             return;
95         }
96
97         nonce = event.data.cookies.navigator_gss_tag;
98         event.data.cookies.navigator_gss_tag = undefined;
99         callback = this.callbacks[nonce];
100         if ("undefined" == typeof (callback)) {
101             return;
102         }
103
104         // We now know that this message is for us!
105         this.callbacks[nonce] = undefined;
106         app_tag = event.data.cookies.app_tag;
107         error = this.errors[nonce] || this.default_error;
108
109         if ("undefined" != typeof(event.data.error_message) )
110         {
111             error(-1, -1, "Error parsing message: " + event.data.error_message, app_tag);
112         }
113         else if (this.gss_error(event.data.return_values.major_status))
114         {
115             var errMsg = "Error during " + method + ": " + 
116               "Major status message: " + 
117               event.data.return_values.errors.major_status_message + 
118               "; Minor status message: " + 
119               event.data.return_values.errors.minor_status_message;
120             error(
121               event.data.return_values.major_status,
122               event.data.return_values.minor_status, 
123               errMsg,
124               app_tag);
125         } else {
126             callback(event.data.return_values, app_tag);
127         }
128     };
129
130
131     GSSEap.prototype.init_sec_context = function (params) 
132     {
133         /* variables */
134         // internal variables
135         var nonce;
136         
137         // Required parameters
138         var target_name = params.target_name;
139         var callback = params.success || this.success;
140
141         // Optional & defaulted parameters (some are defaulted at lower layer)
142         var context_handle = params.context_handle;
143         var cred_handle = params.cred_handle; 
144         var mech_type = params.mech_type; 
145         var req_flags = params.req_flags;
146         var time_req = params.time_req;
147         var input_token = params.input_token;
148
149         var error = params.error || this.default_error; 
150         var app_tag = params.app_tag || this.appTag;
151
152         /* Error checking */
153         // Call an error if we don't have the required parameters.
154         // - name
155         // - success()
156         if ( "undefined" == typeof(target_name) ||
157              "undefined" == typeof(callback) )
158         {
159           error(-1, -1, 
160             "init_sec_context called missing either target_name or success callback"
161           );
162           return;
163         }
164         
165         /* Setup */
166         nonce = navigator.generateNonce();
167
168         /* Main processing */
169         // Save our callback, method name, and error function
170         this.callbacks[nonce] = callback;
171         this.errors[nonce] = error;
172         
173         // Now pass the request on to the C code
174         window.postMessage({
175             "method":"gss_init_sec_context",
176             "arguments":
177             {
178                 "target_name": target_name,
179                 "context_handle": context_handle,
180                 "cred_handle": cred_handle,
181                 "mech_type": mech_type,
182                 "req_flags": req_flags,
183                 "time_req": time_req,
184                 "input_token": input_token
185                 
186             },
187             "cookies":
188             {
189                 "navigator_gss_tag": nonce,
190                 "app_tag": app_tag
191             }
192         }, "*");
193         
194     };
195
196     GSSEap.prototype.display_name = function(params)
197     {
198         /* Variables */
199         // required parameters
200         var input_name = params.input_name;
201         var callback = params.success;
202
203         if ( "undefined" == typeof(name) ||
204              "undefined" == typeof(callback) )
205         {
206           error(-1, -1, 
207             "import_name called missing either name or success callback"
208           );
209           return;
210         }
211
212         var error = params.error || this.default_error; 
213         var app_tag = params.app_tag || this.appTag;
214         
215         /* Setup */
216         nonce = navigator.generateNonce();
217
218
219         /* Main processing */
220         // Save our callback, method name, and error function
221         this.callbacks[nonce] = callback;
222         this.errors[nonce] = error;
223         
224         // Now pass the request on to the C code
225         window.postMessage({
226             "method":"gss_display_name",
227             "arguments":
228             {
229                 "input_name": input_name,
230             },
231             "cookies":
232             {
233                 "navigator_gss_tag": nonce,
234                 "app_tag": app_tag
235             }
236         }, "*");
237         
238     }
239
240     GSSEap.prototype.import_name = function (params) 
241     {
242         /* variables */
243         // internal variables
244         var nonce;
245         
246         // Required parameters
247         var name = params.name;
248         var callback = params.success;
249         
250         // Optional & defaulted parameters
251         var name_type = params.name_type || "{1 2 840 113554 1 2 1 4 }";
252         var error = params.error || this.default_error; 
253         var app_tag = params.app_tag || this.appTag;
254
255
256         /* Error checking */
257         // Call an error if we don't have the required parameters.
258         // - name
259         // - success()
260         if ( "undefined" == typeof(name) ||
261              "undefined" == typeof(callback) )
262         {
263           error(-1, -1, 
264             "import_name called missing either name or success callback"
265           );
266           return;
267         }
268
269         
270         /* Setup */
271         nonce = navigator.generateNonce();
272
273
274         /* Main processing */
275         // Save our callback, method name, and error function
276         this.callbacks[nonce] = callback;
277         this.errors[nonce] = error;
278         
279         // Now pass the request on to the C code
280         window.postMessage({
281             "method":"gss_import_name",
282             "arguments":
283             {
284                 "input_name": name,
285                 "input_name_type": name_type
286             },
287             "cookies":
288             {
289                 "navigator_gss_tag": nonce,
290                 "app_tag": app_tag
291             }
292         }, "*");
293         
294     };
295
296     GSSEap.prototype.gss_error = function (major) 
297     {
298         var callingMask;
299         var routineMask;
300         var mask;
301
302         callingMask = 255 << 24;
303         routineMask = 255 << 16;
304         mask = callingMask | routineMask;
305
306         return (0 != (major & mask));
307     };
308     return GSSEap;
309 })();
310
311
312 navigator.gss_eap = GSSEap;