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