guesmi 0 Posted May 25, 2017 Share Posted May 25, 2017 I am trying to make an extension that will communicate with a native messaging host chrome-token-signing (https://github.com/open-eid/chrome-token-signing).I use gemalto smart card reader . I installed extension , it return an cmd window when I exit or put any string . I have message log TEST: ERROR {"message":"Error when communicating with the native messaging host."} Do I need to do Something I have installed the host in the registry like HKEY_LOCAL_MACHINE\software\Google\Chrome\NativeMessagingHosts\ee.ria.esteid and value C:\Users\dev\Desktop\chrome-token-signing\host-windows\ee.ria.esteid.jsonThe native application manifest.json: { "name": "ee.ria.esteid", "description": "Give signatures with your eID on the web", "path": "chrome-token-signing.exe", "type": "stdio", "allowed_origins": [ "chrome-extension://ckjefchnfjhjfedoccjbhjpbncimppeg/" ] } manifest.json of extension { "name": "Token signing", "version": "0.0.24", "minimum_chrome_version": "40.0", "manifest_version": 2, "description": "Use your eID smart card on the web", "icons": { "48": "icon48.png", "128": "icon128.png" }, "content_scripts": [{ "matches": ["*://*/*", "file:///*"], "exclude_matches": ["*://www.overdrive.com/*"], "js": ["content.js"], "run_at": "document_end", "all_frames": true }], "background": { "scripts": ["background.js"] }, "permissions": ["nativeMessaging"], "applications": { "gecko": { "id": "{443830f0-1fff-4f9a-aa1e-444bafbc7319}" } } } background.js var NO_NATIVE_URL = "https://open-eid.github.io/chrome-token- signing/missing.html"; var HELLO_URL = "https://open-eid.github.io/chrome-token-signing/hello.html"; var DEVELOPER_URL = "https://github.com/open-eid/chrome-token- signing/wiki/DeveloperTips"; var NATIVE_HOST = "ee.ria.esteid"; var K_SRC = "src"; var K_ORIGIN = "origin"; var K_NONCE = "nonce"; var K_RESULT = "result"; var K_TAB = "tab"; var K_EXTENSION = "extension"; // Stores the longrunning ports per tab // Used to route all request from a tab to the same host instance var ports = {}; // Probed to false if host component is OK. var missing = true; console.log("Background page activated"); // XXX: probe test, because connectNative() does not allow to check the presence // of native component for some reason typeof chrome.runtime.onStartup !== 'undefined' && chrome.runtime.onStartup.addListener(function() { // Also probed for in onInstalled() _testNativeComponent().then(function(result) { if (result === "ok") { missing = false; } }); }); // Force kill of native process // Becasue Port.disconnect() does not work function _killPort(tab) { if (tab in ports) { console.log("KILL " + tab); // Force killing with an empty message ports[tab].postMessage({}); } } // Check if native implementation is OK resolves with "ok", "missing" or "forbidden" function _testNativeComponent() { return new Promise(function(resolve, reject) { chrome.runtime.sendNativeMessage(NATIVE_HOST, {}, function(response) { if (!response) { console.log("TEST: ERROR " + JSON.stringify(chrome.runtime.lastError)); // Try to be smart and do some string matching var permissions = "Access to the specified native messaging host is forbidden."; var missing = "Specified native messaging host not found."; if (chrome.runtime.lastError.message === permissions) { resolve("forbidden") } else if (chrome.runtime.lastError.message === missing) { resolve("missing"); } else { resolve("missing"); } } else { console.log("TEST: " + JSON.stringify(response)); if (response["result"] === "invalid_argument") { resolve("ok"); } else { resolve("missing"); // TODO: something better here } } }); }); } // When extension is installed, check for native component or direct to helping page typeof chrome.runtime.onInstalled !== 'undefined' && chrome.runtime.onInstalled.addListener(function(details) { if (details.reason === "install" || details.reason === "update") { _testNativeComponent().then(function(result) { var url = null; if (result === "ok" && details.reason === "install") { // Also set the flag, onStartup() shall be called only // on next startup missing = false; // TODO: Add back HELLO page on install // once there is a nice tutorial url = HELLO_URL; } else if (result === "forbidden") { url = DEVELOPER_URL; } else if (result === "missing"){ url = NO_NATIVE_URL; } if (url) { chrome.tabs.create({'url': url + "?" + details.reason}); } }); } }); // When message is received from page send it to native chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { if(sender.id !== chrome.runtime.id && sender.extensionId !== chrome.runtime.id) { console.log('WARNING: Ignoring message not from our extension'); // Not our extension, do nothing return; } if (sender.tab) { // Check if page is DONE and close the native component without doing anything else if (request["type"] === "DONE") { console.log("DONE " + sender.tab.id); if (sender.tab.id in ports) { // FIXME: would want to use Port.disconnect() here _killPort(sender.tab.id); } } else { request[K_TAB] = sender.tab.id; if (missing) { _testNativeComponent().then(function(result) { if (result === "ok") { missing = false; _forward(request); } else { return _fail_with (request, "no_implementation"); } }); } else { // TODO: Check if the URL is in allowed list or not // Either way forward to native currently _forward(request); } } } }); // Send the message back to the originating tab function _reply(tab, msg) { msg[K_SRC] = "background.js"; msg[K_EXTENSION] = chrome.runtime.getManifest().version; chrome.tabs.sendMessage(tab, msg); } // Fail an incoming message if the underlying implementation is not // present function _fail_with(msg, result) { var resp = {}; resp[K_NONCE] = msg[K_NONCE]; resp[K_RESULT] = result; _reply(msg[K_TAB], resp); } // Forward a message to the native component function _forward(message) { var tabid = message[K_TAB]; console.log("SEND " + tabid + ": " + JSON.stringify(message)); // Open a port if necessary if(!ports[tabid]) { // For some reason there does not seem to be a way to detect missing components from longrunning ports // So we probe before opening a new port. console.log("OPEN " + tabid + ": " + NATIVE_HOST); // create a new port var port = chrome.runtime.connectNative(NATIVE_HOST); // XXX: does not indicate anything for some reason. if (!port) { console.log("OPEN ERROR: " + JSON.stringify(chrome.runtime.lastError)); } port.onMessage.addListener(function(response) { if (response) { console.log("RECV "+tabid+": " + JSON.stringify(response)); _reply(tabid, response); } else { console.log("ERROR "+tabid+": " + JSON.stringify(chrome.runtime.lastError)); _fail_with(message, "technical_error"); } }); port.onDisconnect.addListener(function() { console.log("QUIT " + tabid); delete ports[tabid]; // TODO: reject all pending promises for tab, if any }); ports[tabid] = port; ports[tabid].postMessage(message); } else { // Port already open ports[tabid].postMessage(message); } } content.js /* * Chrome token signing extension * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ var inuse = false; // Forward the message from page.js to background.js window.addEventListener("message", function(event) { // We only accept messages from ourselves if (event.source !== window) return; // and forward to extension if (event.data.src && (event.data.src === "page.js")) { event.data["origin"] = location.origin; chrome.runtime.sendMessage(event.data, function(response) {}); // Only add unload handler if extension has been used if (!inuse) { // close the native component if page unloads window.addEventListener("beforeunload", function(event) { chrome.runtime.sendMessage({src: 'page.js', type: 'DONE'}); }, false); inuse = true; } page.js /* * Chrome token signing extension * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // Promises var _eid_promises = {}; // Turn the incoming message from extension // into pending Promise resolving window.addEventListener("message", function(event) { if(event.source !== window) return; if(event.data.src && (event.data.src === "background.js")) { console.log("Page received: "); console.log(event.data); // Get the promise if(event.data.nonce) { var p = _eid_promises[event.data.nonce]; // resolve if(event.data.result === "ok") { if(event.data.signature !== undefined) { p.resolve({hex: event.data.signature}); } else if(event.data.version !== undefined) { p.resolve(event.data.extension + "/" + event.data.version); } else if(event.data.cert !== undefined) { p.resolve({hex: event.data.cert}); } else { console.log("No idea how to handle message"); console.log(event.data); } } else { // reject p.reject(new Error(event.data.result)); } delete _eid_promises[event.data.nonce]; } else { console.log("No nonce in event msg"); } } }, false); function TokenSigning() { function nonce() { var val = ""; var hex = "abcdefghijklmnopqrstuvwxyz0123456789"; for(var i = 0; i < 16; i++) val += hex.charAt(Math.floor(Math.random() * hex.length)); return val; } function messagePromise(msg) { return new Promise(function(resolve, reject) { // amend with necessary metadata msg["nonce"] = nonce(); msg["src"] = "page.js"; // send message window.postMessage(msg, "*"); // and store promise callbacks _eid_promises[msg.nonce] = { resolve: resolve, reject: reject }; }); } this.getCertificate = function(options) { var msg = {type: "CERT", lang: options.lang}; console.log("getCertificate()"); return messagePromise(msg); }; this.sign = function(cert, hash, options) { var msg = {type: "SIGN", cert: cert.hex, hash: hash.hex, hashtype: hash.type, lang: options.lang}; console.log("sign()"); return messagePromise(msg); }; this.getVersion = function() { console.log("getVersion()"); return messagePromise({ type: "VERSION" }); }; } Link to comment Share on other sites More sharing options...
Administrators Marcos 4,718 Posted May 25, 2017 Administrators Share Posted May 25, 2017 Since this is an ESET forum intended for discussing ESET's products and malware and security issues and your query seems to be unrelated to ESET products, I would strongly recommend asking users in another more appropriate forum. Link to comment Share on other sites More sharing options...
Recommended Posts