Start work on firefox support
authorMark Donnelly <mark@painless-security.com>
Wed, 26 Nov 2014 17:18:52 +0000 (12:18 -0500)
committerMark Donnelly <mark@painless-security.com>
Wed, 26 Nov 2014 17:18:52 +0000 (12:18 -0500)
xpi/lib/main.js
xpi/lib/navigator.gss.js [new file with mode: 0644]
xpi/package.json

index 6bd10ae..9d7ad47 100644 (file)
-var widgets = require("sdk/widget");
 var tabs = require("sdk/tabs");
-
 const {Cu} = require("chrome");
 
-function myDump(message) {
-  dump("\n");
-  dump("**********************************************************************\n");
-  dump("**********************************************************************\n");
-  dump("** " + message + " **\n");
-  dump("**********************************************************************\n");
-  dump("**********************************************************************\n");
+for (i = 0; i < 10; i++) {
+  console.log("");
 }
 
-myDump("About to load ctypes");
+console.log("About to load ctypes");
 Cu.import("resource://gre/modules/ctypes.jsm");
+console.log("  ... loaded.");
 
-/************************
- ** Declaring types    **
- ************************/
-const gss_buffer_t_struct = ctypes.StructType(
-    "gss_buffer_t",
-    [
-        {"length": ctypes.size_t},
-        {"value":  ctypes.void_t.ptr}
-    ]
-);
-const gss_buffer_t = ctypes.PointerType(gss_buffer_t_struct);
-const gss_OID_struct = ctypes.StructType(
-    "gss_OID", 
-    [
-        {"length" :   ctypes.uint32_t},
-        {"elements" : ctypes.voidptr_t}
-    ]
-);
-const gss_OID = ctypes.PointerType(gss_OID_struct);
-const gss_name_t = ctypes.StructType("gss_name_t");
-
-const gss_cred_id_struct = ctypes.StructType("gss_cred_id_struct");
-const gss_cred_id_t = ctypes.PointerType(gss_cred_id_struct);
-
-const gss_ctx_id_struct = ctypes.StructType("gss_ctx_id_struct");
-const gss_ctx_id_t = ctypes.PointerType(gss_ctx_id_struct);
-
-const gss_channel_bindings_struct = ctypes.StructType(
-    "gss_channel_bindings_struct",
-    [
-       {"initiator_addrtype": ctypes.uint32_t},
-       {"initiator_address":  gss_buffer_t_struct},
-       {"acceptor_addrtype":  ctypes.uint32_t},
-       {"acceptor_address":   gss_buffer_t_struct},
-       {"application_data":   gss_buffer_t_struct}
-    ]
-);
-const gss_channel_bindings_t = ctypes.PointerType(gss_channel_bindings_struct);
-
-const gss_status_struct = ctypes.StructType(
-    "gss_status_struct",
-    [
-       {"major": ctypes.uint32_t},
-       {"minor": ctypes.uint32_t}
-    ]
-);
-const gss_status_t = ctypes.PointerType(gss_status_struct);
-
-
-/**********************
- * Utility functions  *
- **********************/
-function generate_gss_buffer(buff) {
-  myDump("Generate a gss_buffer_t for (" + buff + ")");
+var json_gssapi;
 
-  var buffString = ctypes.char.array()(buff);
-
-  var gss_buffer = new gss_buffer_t_struct();
-  gss_buffer.length = new ctypes.size_t(buff.length);
-  gss_buffer.value = buffString.address();
-
-  myDump("Returning the buffer_t");
-  return gss_buffer; 
-}
-
-//"1.3.6.1.5.5.2" - spnego
-//"1.2.840.113554.1.2.1.4" - nt hostservice
-
-function str_to_oid(oid_str)
-{
-    var buffer = generate_gss_buffer(oid_str);
-    var oid = new gss_OID_struct();
-    var oid_ptr = oid.address();
-    minStatus = new ctypes.uint32_t(0);
-    var majStatus;
-    
-    myDump("Abotut to str_to_oid: " + oid_str);
-    majStatus = gss_str_to_oid(
-       minStatus.address(), 
-       buffer.address(), 
-       oid_ptr.address() );
-    myDump("Finished the str_to_oid: " + majStatus + "/" + minStatus);
-    
-    myDump("   returned oid: [ length: " + oid_ptr.contents.length + " ]");
-    
-    return(oid_ptr.contents);
-}
 
-function import_name(name)
-{
-    myDump("Entering import_name(" + name + ")");
-    var name_buffer     = generate_gss_buffer(name);
-    var input_name_type = new gss_OID();
-    var oid             = str_to_oid("1.2.840.113554.1.2.1.4");
-                          /* GSS_C_NT_HOSTBASED_SERVICE */
-    var output_name_ptr = gss_name_t.ptr(ctypes.UInt64("0x0"));
-    var minor           = new ctypes.uint32_t(0);
-    var major;
-    
-    var printable = new gss_buffer_t_struct();
-    var printtype = new gss_OID();
-    
-    major = gss_import_name(
-       minor.address(),
-       name_buffer.address(),
-       oid.address(),
-       output_name_ptr.address()
-    );
-    myDump("Finished the gss_import_name: " + major + "/" + minor);
-    
-    major = gss_display_name(
-       minor.address(),
-       output_name_ptr,
-       printable.address(),
-       printtype.address()
-    );
-    myDump("Display name: [ length: " + printable.length + 
-          " value: " + printable.value + " ]");
-    myDump("Display name type: [ length: " + printtype.length + " ]");
-    
-    return(output_name_ptr);
+// TODO: detect which OS we're running, and proactively search for the
+//       correct library name.
+console.log("About to load libjsongssapi");
+try {
+    json_gssapi = ctypes.open("libjsongssapi.so");
 }
-
-
-try{
-    var libkrb5;
-    var libgss_utils;
-    try{
-       libkrb5 = ctypes.open("libgssapi_krb5.so");
-       libgss_utils = ctypes.open("libgssapi_utils.so");
+catch (e) {
+    try {
+        json_gssapi = ctypes.open("libjsongssapi.dll");
     }
     catch (e) {
-       myDump("Could not open utils: " + e);
-       libkrb5 = ctypes.open("libgss.dll");
-       libgss_utils = ctypes.open("libgssapi_utils.dll");
+        console.log("  ... " + e);
     }
+}
+console.log("  ... loaded.");
 
-    myDump("libkrb5 return value: " + libkrb5);
-    myDump("libgss_utils return value: " + libgss_utils);
-    
-    myDump("ctypes.open");
-
-    /**************************************************************
-     ** Function definitions
-     **************************************************************/
-    const gss_str_to_oid = libkrb5.declare("gss_str_to_oid",
-        ctypes.default_abi, 
-        ctypes.uint32_t,     /* Return value           */
-        ctypes.uint32_t.ptr, /* arg: minor_status */
-        gss_buffer_t,        /* arg: oid_str */
-        gss_OID.ptr);        /* arg: oid */
-    myDump("gss_str_to_oid function is " + gss_str_to_oid);
-
-    const gss_display_name = libkrb5.declare("gss_display_name",
-        ctypes.default_abi, 
-        ctypes.uint32_t,     /* Return value           */
-        ctypes.uint32_t.ptr, /* arg: minor_status */
-        gss_name_t.ptr,      /* arg: input_name */
-        gss_buffer_t,        /* arg: output_name_buffer */
-        gss_OID.ptr);        /* arg: ouptut_name_type */
-    myDump("gss_str_to_oid function is " + gss_str_to_oid);
-
-    const gss_import_name = libkrb5.declare("gss_import_name", 
-        ctypes.default_abi, 
-        ctypes.uint32_t,     /* Return value           */
-        ctypes.uint32_t.ptr, /* arg: minor status      */
-        gss_buffer_t,        /* arg: input_name_buffer */
-        gss_OID,             /* arg: input_name_type   */
-        ctypes.PointerType(gss_name_t).ptr );     /* arg: output_name       */
-    myDump("gss_import_name is function is " + gss_import_name);
-
-    const gss_init_sec_context = libkrb5.declare("gss_init_sec_context", 
-        ctypes.default_abi, 
-        ctypes.uint32_t,     /* Return value              */
-        ctypes.uint32_t.ptr, /* arg: minor status         */
-        gss_cred_id_t,       /* arg: claimant_cred_handle */
-        gss_ctx_id_t.ptr,    /* arg: context_handle       */
-        gss_name_t.ptr,      /* arg: target_name          */
-        gss_OID,             /* arg: mech_type            */
-        ctypes.uint32_t,     /* arg: req_flags            */
-        ctypes.uint32_t,     /* arg: time_req             */
-        gss_channel_bindings_t, /* arg: channel_bindings, reserved for future use */
-        gss_buffer_t,        /* arg: input_token          */
-        gss_OID.ptr,         /* arg: actual_mech_type     */
-        gss_buffer_t,        /* arg: output_token         */
-        ctypes.uint32_t.ptr, /* arg: ret_flags            */
-        ctypes.uint32_t.ptr  /* arg: time_rec             */
-    );
-    myDump("gss_init_sec_context function is " + gss_init_sec_context);
-    
-    const gss_construct_sec_context = libgss_utils.declare(
-       "gss_construct_sec_context", 
-       ctypes.default_abi,
-       ctypes.uint32_t,         /* Return value - boolean                             */
-       gss_status_t,            /* arg: Status struct pointer                         */
-       gss_cred_id_t,           /* arg: claimant_cred_handle - reserved for future    */
-       gss_ctx_id_t.ptr,        /* arg: context_handle, the output of the function    */
-       gss_name_t.ptr,          /* arg: target_name - the other endpoint              */
-       gss_OID,                 /* arg: mech_type - the desired mechanism type        */
-       ctypes.uint32_t,         /* arg: req_flags                                     */
-       ctypes.uint32_t,         /* arg: time_req                                      */
-       gss_channel_bindings_t   /* arg: input_chan_bindings - reserved for future use */
-    );
-
-
-
-    var majStatus, minStatus, output_name_ptr;
-    minStatus = new ctypes.uint32_t(0);
-    
-    output_name_ptr = import_name('http@www.project-moonshot.org/PROJECT-MOONSHOT.ORG');
-    
-    var cred_handle = gss_cred_id_struct.ptr(ctypes.UInt64("0x0"));
-    var context_handle = gss_ctx_id_struct.ptr(ctypes.UInt64("0x0"));
-    var GSS_C_NO_OID = gss_OID_struct().address();
-    var null_mechanism = gss_OID_struct.ptr(ctypes.UInt64("0x0"));
-    var channel_bindings = new gss_channel_bindings_struct();
-    var input_token = new gss_buffer_t_struct();
-    var actual_mech_type = gss_OID();
-    var output_token = new gss_buffer_t_struct();
-    var ret_flags = new ctypes.uint32_t(0);
-    var time_rec = new ctypes.uint32_t(0);
-    var status = new gss_status_struct();
-    
-    var success = gss_construct_sec_context(
-       status.address(),
-       cred_handle,
-       context_handle.address(),
-       output_name_ptr,
-       null_mechanism,
-       ctypes.uint32_t(0),          /* req_flags   */
-       ctypes.uint32_t(0),          /* time_req    */
-       channel_bindings.address()
-    );
-    
-    myDump("gss_construct_sec_context call: " + success + 
-           " [0x" + status.major.toString(16) + "/" + status.minor + "]");
-/*
-    do
-    {
-
-       majStatus = gss_init_sec_context(
-           minStatus.address(),
-           cred_handle,
-           context_handle.address(),
-           output_name_ptr,
-           GSS_C_NO_OID,                /* Default OID * /
-           ctypes.uint32_t(0),          /* req_flags   * /
-           ctypes.uint32_t(0),          /* time_req    * /
-           channel_bindings.address(),
-           input_token.address(),
-           actual_mech_type.address(),
-           output_token.address(),
-           ret_flags.address(),
-           time_rec.address()
-       );
-        myDump("Finished the init_sec_context: " + majStatus + "/" + minStatus);
-        myDump(": " + output_name_ptr);
+console.log("Declaring the call_gss function:");
+const call_gss = json_gssapi.declare("gss_request",
+    ctypes.default_abi,
+    ctypes.char.ptr,
+    ctypes.char.ptr);
+console.log("  ... declared.");
 
+console.log("Calling import_name");
+var reply;
+reply = call_gss("{\"method\":\"gss_import_name\",\"arguments\":{\"input_name\":\"HTTP@localhost\",\"input_name_type\":\"{1 2 840 113554 1 2 1 4 }\"}}");
+console.log("  ... Reply: " + reply.readString());
 
-    } while ((majStatus & 1) == 1)
-*/
 
-    myDump("All calls succeeded");
-    
-    libkrb5.close();
-    myDump("close");
-    
-}
-catch (e)
-{
-    myDump("Caught exception: " + e);
-}
 
+var data = require("sdk/self").data;
+var pageMod = require("sdk/page-mod");
 
+pageMod.PageMod({
+  include: "*",
+  contentScriptFile: data.url("navigator.gss.js")
+});
diff --git a/xpi/lib/navigator.gss.js b/xpi/lib/navigator.gss.js
new file mode 100644 (file)
index 0000000..a2ed28c
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2014, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+console.log('Loading navigator.gss.js - #9');
+
+/* This file gets injected into the web page verbatim */
+
+var GSSEap = (function () 
+  {
+    function GSSEap(config)
+    {
+        // Public attributes
+        this.version = "0.0.1";
+        this.implemented_methods = ["gss_import_name", "gss_display_name", "gss_init_sec_context", "gss_acquire_cred"];
+       // MRW -- combine success/error callback hashes?
+        this.callbacks = {};
+        this.errors = {};
+        this.appTag = config.appTag || "";
+        this.default_error = config.error || 
+            function (major, minor, error, appTag) {
+                console.warn(error);
+            };
+        window.addEventListener(
+            "message",
+            this.dispatch_responses.bind(this)
+        );
+    }
+    GSSEap.prototype.dispatch_responses = function (event) 
+    {
+        var method;
+        var nonce;
+        var callback;
+        var app_tag;
+        var error;
+
+        /* This message is destined for us only if all the following apply:
+        * - The data.method_name is one of the methods implemented by this
+        *   object
+        * - data.return_values exists or data.error_mssage exists
+        * - data.cookies exists
+        * - One of my callbacks matches the nonce in
+        *   data.cookies.navigator_gss_tag
+        * - One of my methods matches the nonce in 
+        *   data.cookies.navigator_gss_tag and that method matches
+        *   data.method
+        */
+        method = event.data.method;
+        if (
+             ( -1 == this.implemented_methods.indexOf(method) ) ||
+             (  ("undefined" == typeof (event.data.return_values) ) &&
+                ("undefined" == typeof (event.data.error_message) ) ) ||
+             ("undefined" == typeof (event.data.cookies)))
+        {
+            return;
+        }
+
+        nonce = event.data.cookies.navigator_gss_tag;
+        event.data.cookies.navigator_gss_tag = undefined;
+        callback = this.callbacks[nonce];
+        if ("undefined" == typeof (callback)) {
+            return;
+        }
+
+        // We now know that this message is for us!
+        this.callbacks[nonce] = undefined;
+        app_tag = event.data.cookies.app_tag;
+        error = this.errors[nonce] || this.default_error;
+
+        if ("undefined" != typeof(event.data.error_message) )
+        {
+            error(-1, -1, "Error parsing message: " + event.data.error_message, app_tag);
+        }
+        else if (this.gss_error(event.data.return_values.major_status))
+        {
+            var errMsg = "Error during " + method + ": " + 
+              "Major status message: " + 
+              event.data.return_values.errors.major_status_message + 
+              "; Minor status message: " + 
+              event.data.return_values.errors.minor_status_message;
+            error(
+              event.data.return_values.major_status,
+              event.data.return_values.minor_status, 
+              errMsg,
+              app_tag);
+        } else {
+            callback(event.data.return_values, app_tag);
+        }
+    };
+
+
+    GSSEap.prototype.init_sec_context = function (params) 
+    {
+        /* variables */
+        // internal variables
+        var nonce;
+        
+        // Required parameters
+        var target_name = params.target_name;
+        var callback = params.success || this.success;
+
+        // Optional & defaulted parameters (some are defaulted at lower layer)
+        var context_handle = params.context_handle;
+        var cred_handle = params.cred_handle; 
+       var mech_type = params.mech_type; 
+       var req_flags = params.req_flags;
+       var time_req = params.time_req;
+       var input_token = params.input_token;
+
+        var error = params.error || this.default_error; 
+        var app_tag = params.app_tag || this.appTag;
+
+        /* Error checking */
+        // Call an error if we don't have the required parameters.
+        // - name
+        // - success()
+        if ( "undefined" == typeof(target_name) ||
+             "undefined" == typeof(callback) )
+        {
+          error(-1, -1, 
+            "init_sec_context called missing either target_name or success callback"
+          );
+          return;
+        }
+        
+        /* Setup */
+        nonce = navigator.generateNonce();
+
+        /* Main processing */
+        // Save our callback, method name, and error function
+        this.callbacks[nonce] = callback;
+        this.errors[nonce] = error;
+        
+        // Now pass the request on to the C code
+        window.postMessage({
+            "method":"gss_init_sec_context",
+            "arguments":
+            {
+                "target_name": target_name,
+               "context_handle": context_handle,
+               "cred_handle": cred_handle,
+               "mech_type": mech_type,
+               "req_flags": req_flags,
+               "time_req": time_req,
+               "input_token": input_token
+               
+            },
+            "cookies":
+            {
+                "navigator_gss_tag": nonce,
+                "app_tag": app_tag
+            }
+        }, "*");
+        
+    };
+
+    GSSEap.prototype.display_name = function(params)
+    {
+        /* Variables */
+        // required parameters
+        var input_name = params.input_name;
+        var callback = params.success;
+
+        if ( "undefined" == typeof(name) ||
+             "undefined" == typeof(callback) )
+        {
+          error(-1, -1, 
+            "import_name called missing either name or success callback"
+          );
+          return;
+        }
+
+        var error = params.error || this.default_error; 
+        var app_tag = params.app_tag || this.appTag;
+        
+        /* Setup */
+        nonce = navigator.generateNonce();
+
+
+        /* Main processing */
+        // Save our callback, method name, and error function
+        this.callbacks[nonce] = callback;
+        this.errors[nonce] = error;
+        
+        // Now pass the request on to the C code
+        window.postMessage({
+            "method":"gss_display_name",
+            "arguments":
+            {
+                "input_name": input_name,
+            },
+            "cookies":
+            {
+                "navigator_gss_tag": nonce,
+                "app_tag": app_tag
+            }
+        }, "*");
+        
+    }
+
+    GSSEap.prototype.import_name = function (params) 
+    {
+        /* variables */
+        // internal variables
+        var nonce;
+        
+        // Required parameters
+        var name = params.name;
+        var callback = params.success;
+        
+        // Optional & defaulted parameters
+        var name_type = params.name_type || "{1 2 840 113554 1 2 1 4 }";
+        var error = params.error || this.default_error; 
+        var app_tag = params.app_tag || this.appTag;
+
+
+        /* Error checking */
+        // Call an error if we don't have the required parameters.
+        // - name
+        // - success()
+        if ( "undefined" == typeof(name) ||
+             "undefined" == typeof(callback) )
+        {
+          error(-1, -1, 
+            "import_name called missing either name or success callback"
+          );
+          return;
+        }
+
+        
+        /* Setup */
+        nonce = navigator.generateNonce();
+
+
+        /* Main processing */
+        // Save our callback, method name, and error function
+        this.callbacks[nonce] = callback;
+        this.errors[nonce] = error;
+        
+        // Now pass the request on to the C code
+        window.postMessage({
+            "method":"gss_import_name",
+            "arguments":
+            {
+                "input_name": name,
+                "input_name_type": name_type
+            },
+            "cookies":
+            {
+                "navigator_gss_tag": nonce,
+                "app_tag": app_tag
+            }
+        }, "*");
+        
+    };
+
+    GSSEap.prototype.gss_error = function (major) 
+    {
+        var callingMask;
+        var routineMask;
+        var mask;
+
+        callingMask = 255 << 24;
+        routineMask = 255 << 16;
+        mask = callingMask | routineMask;
+
+        return (0 != (major & mask));
+    };
+    return GSSEap;
+})();
+
+navigator.gss_eap = GSSEap;
index 8272b6d..9df78bf 100644 (file)
@@ -1,9 +1,9 @@
 {
-  "name": "xtnd",
-  "title": "xtnd",
+  "name": "gssweb",
+  "title": "GSSWeb",
   "id": "jid1-NfTB1x7j36TqCw",
-  "description": "a basic add-on",
-  "author": "",
-  "license": "MPL 2.0",
+  "description": "GSS-EAP and GSSWeb package provider",
+  "author": "mark@painless-security.com",
+  "license": "Copyright (c) 2014, JANET(UK)\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n\n3. Neither the name of JANET(UK) nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\nFOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\nOF THE POSSIBILITY OF SUCH DAMAGE.",
   "version": "0.1"
 }