4a2e09ca81fabe83792a6f5540584bc86842e1ea
[gssweb.git] / chrome / app / navigator.gss.js
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 /* This file gets injected into the web page verbatim */
38
39 var GSSEap = (function () 
40   {
41     function GSSEap(config)
42     {
43         // Public attributes
44         this.version = "0.0.1";
45         this.implemented_methods = ["gss_import_name", "gss_display_name", "gss_init_sec_context", "gss_acquire_cred"];
46         // MRW -- combine success/error callback hashes?
47         this.callbacks = {};
48         this.errors = {};
49         this.appTag = config.appTag || "";
50         this.default_error = config.error || 
51             function (major, minor, error, appTag) {
52                 console.warn(error);
53             };
54         window.addEventListener(
55             "message",
56             this.dispatch_responses.bind(this)
57         );
58     }
59     GSSEap.prototype.dispatch_responses = function (event) 
60     {
61         var method;
62         var nonce;
63         var callback;
64         var app_tag;
65         var error;
66
67         /* This message is destined for us only if all the following apply:
68         * - The data.method_name is one of the methods implemented by this
69         *   object
70         * - data.return_values exists
71         * - data.cookies exists
72         * - One of my callbacks matches the nonce in
73         *   data.cookies.navigator_gss_tag
74         * - One of my methods matches the nonce in 
75         *   data.cookies.navigator_gss_tag and that method matches
76         *   data.method
77         */
78         method = event.data.method;
79         if (
80              ( -1 == this.implemented_methods.indexOf(method) ) ||
81              ("undefined" == typeof (event.data.return_values)) ||
82              ("undefined" == typeof (event.data.cookies)))
83         {
84             return;
85         }
86
87         nonce = event.data.cookies.navigator_gss_tag;
88         event.data.cookies.navigator_gss_tag = undefined;
89         callback = this.callbacks[nonce];
90         if ("undefined" == typeof (callback)) {
91             return;
92         }
93
94         // We now know that this message is for us!
95         this.callbacks[nonce] = undefined;
96         app_tag = event.data.cookies.app_tag;
97         error = this.errors[nonce] || this.default_error;
98
99         if (this.gss_error(event.data.return_values.major_status))
100         {
101             var errMsg = "Error during " + method + ": " + 
102               "Major status message: " + 
103               event.data.return_values.errors.major_status_message + 
104               "; Minor status message: " + 
105               event.data.return_values.errors.minor_status_message;
106             error(
107               event.data.return_values.major_status,
108               event.data.return_values.minor_status, 
109               errMsg,
110               app_tag);
111         } else {
112             callback(event.data.return_values, app_tag);
113         }
114     };
115
116
117     GSSEap.prototype.init_sec_context = function (params) 
118     {
119         /* variables */
120         // internal variables
121         var nonce;
122         
123         // Required parameters
124         var target_name = params.target_name;
125         var callback = params.success || this.success;
126
127         // Optional & defaulted parameters (some are defaulted at lower layer)
128         var context_handle = params.context_handle;
129         var cred_handle = params.cred_handle; 
130         var mech_type = params.mech_type; 
131         var req_flags = params.req_flags;
132         var time_req = params.time_req;
133         var input_token = params.input_token;
134
135         var error = params.error || this.default_error; 
136         var app_tag = params.app_tag || this.appTag;
137
138         /* Error checking */
139         // Call an error if we don't have the required parameters.
140         // - name
141         // - success()
142         if ( "undefined" == typeof(target_name) ||
143              "undefined" == typeof(callback) )
144         {
145           error(-1, -1, 
146             "init_sec_context called missing either target_name or success callback"
147           );
148           return;
149         }
150         
151         /* Setup */
152         nonce = navigator.generateNonce();
153
154         /* Main processing */
155         // Save our callback, method name, and error function
156         this.callbacks[nonce] = callback;
157         this.errors[nonce] = error;
158         
159         // Now pass the request on to the C code
160         window.postMessage({
161             "method":"gss_init_sec_context",
162             "arguments":
163             {
164                 "target_name": target_name,
165                 "context_handle": context_handle,
166                 "cred_handle": cred_handle,
167                 "mech_type": mech_type,
168                 "req_flags": req_flags,
169                 "time_req": time_req,
170                 "input_token": input_token
171                 
172             },
173             "cookies":
174             {
175                 "navigator_gss_tag": nonce,
176                 "app_tag": app_tag
177             }
178         }, "*");
179         
180     };
181
182     GSSEap.prototype.display_name = function(params)
183     {
184         /* Variables */
185         // required parameters
186         var input_name = params.input_name;
187         var callback = params.success;
188
189         if ( "undefined" == typeof(name) ||
190              "undefined" == typeof(callback) )
191         {
192           error(-1, -1, 
193             "import_name called missing either name or success callback"
194           );
195           return;
196         }
197
198         var error = params.error || this.default_error; 
199         var app_tag = params.app_tag || this.appTag;
200         
201         /* Setup */
202         nonce = navigator.generateNonce();
203
204
205         /* Main processing */
206         // Save our callback, method name, and error function
207         this.callbacks[nonce] = callback;
208         this.errors[nonce] = error;
209         
210         // Now pass the request on to the C code
211         window.postMessage({
212             "method":"gss_display_name",
213             "arguments":
214             {
215                 "input_name": input_name,
216             },
217             "cookies":
218             {
219                 "navigator_gss_tag": nonce,
220                 "app_tag": app_tag
221             }
222         }, "*");
223         
224     }
225
226     GSSEap.prototype.import_name = function (params) 
227     {
228         /* variables */
229         // internal variables
230         var nonce;
231         
232         // Required parameters
233         var name = params.name;
234         var callback = params.success;
235         
236         // Optional & defaulted parameters
237         var name_type = params.name_type || "{1 2 840 113554 1 2 1 4 }";
238         var error = params.error || this.default_error; 
239         var app_tag = params.app_tag || this.appTag;
240
241
242         /* Error checking */
243         // Call an error if we don't have the required parameters.
244         // - name
245         // - success()
246         if ( "undefined" == typeof(name) ||
247              "undefined" == typeof(callback) )
248         {
249           error(-1, -1, 
250             "import_name called missing either name or success callback"
251           );
252           return;
253         }
254
255         
256         /* Setup */
257         nonce = navigator.generateNonce();
258
259
260         /* Main processing */
261         // Save our callback, method name, and error function
262         this.callbacks[nonce] = callback;
263         this.errors[nonce] = error;
264         
265         // Now pass the request on to the C code
266         window.postMessage({
267             "method":"gss_import_name",
268             "arguments":
269             {
270                 "input_name": name,
271                 "input_name_type": name_type
272             },
273             "cookies":
274             {
275                 "navigator_gss_tag": nonce,
276                 "app_tag": app_tag
277             }
278         }, "*");
279         
280     };
281
282     GSSEap.prototype.gss_error = function (major) 
283     {
284         var callingMask;
285         var routineMask;
286         var mask;
287
288         callingMask = 255 << 24;
289         routineMask = 255 << 16;
290         mask = callingMask | routineMask;
291
292         return (0 != (major & mask));
293     };
294     return GSSEap;
295 })();
296
297 navigator.gss_eap = GSSEap;