mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-25 08:21:05 -06:00
Kerberos authentication extension
The extension should replace signed code (configure.jar) used for Firefox configuration. Using privileged code is not possible since Firefox 15 [1] [2]. Extension is bootstrapped which means it can be used without browser restart on Firefox 4 and later. How it works: Extension listens on each page's document element for event 'kerberos-auth-config' which should be raised on custom data element. Communication data is transferred through data element's attributes [3]. The only required attribute is 'method'. Currently there are two possible values: 'configure' and 'can_configure'. 'can_configure' method serves for detecting if the extension is installed. 'configure' method does the actual configuration. Possible optional options for 'configure' can be found in kerberosauth.js:kerberosauth.config_options. Currently they are: 'referer', 'native_gss_lib', 'trusted_uris', 'allow_proxies'. Result of a method is stored in data element's 'answer' attribute. When 'configure' method is used, the extension asks the user if he wants to configure the browser, it should prevent silent configuration by malicious pages. Possible enhancement: * add UI for manual edit * more configurations ie. for gss_lib, sspi (good with UI or with enhanced config page) * introspection of client (read ipa client install config and such) Ticket: https://fedorahosted.org/freeipa/ticket/3094 [1] https://bugzilla.mozilla.org/show_bug.cgi?id=546848 [2] https://bugzilla.mozilla.org/show_bug.cgi?id=757046 [3] https://developer.mozilla.org/en-US/docs/Code_snippets/Interaction_between_privileged_and_non-privileged_pages
This commit is contained in:
parent
459c83fb75
commit
b4e19509c0
88
install/ffextension/bootstrap.js
vendored
Normal file
88
install/ffextension/bootstrap.js
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Heavily inspired by Dave Townsend's post:
|
||||
// Playing with windows in restartless (bootstrapped) extensions
|
||||
// http://www.oxymoronical.com/blog/2011/01/Playing-with-windows-in-restartless-bootstrapped-extensions
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
var WindowListener = {
|
||||
|
||||
setupBrowserUI: function(domWindow) {
|
||||
var doc = domWindow.document;
|
||||
domWindow.kerberosauth_listener = kerberosauth_listener(domWindow);
|
||||
doc.addEventListener('kerberos-auth-config', domWindow.kerberosauth_listener, false, true);
|
||||
},
|
||||
|
||||
tearDownBrowserUI: function(domWindow) {
|
||||
|
||||
var doc = domWindow.document;
|
||||
doc.removeEventListener('kerberos-auth-config', domWindow.kerberosauth_listener);
|
||||
delete domWindow.kerberosauth_listener;
|
||||
},
|
||||
|
||||
// nsIWindowMediatorListener functions
|
||||
onOpenWindow: function(xulWindow) {
|
||||
// A new window has opened
|
||||
var domWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowInternal);
|
||||
|
||||
// Wait for it to finish loading
|
||||
domWindow.addEventListener("load", function listener() {
|
||||
domWindow.removeEventListener("load", listener, false);
|
||||
|
||||
// If this is a browser window then setup its UI
|
||||
if (domWindow.document.documentElement.getAttribute("windowtype") === "navigator:browser") {
|
||||
WindowListener.setupBrowserUI(domWindow);
|
||||
}
|
||||
}, false);
|
||||
},
|
||||
|
||||
onCloseWindow: function(xulWindow) {
|
||||
},
|
||||
|
||||
onWindowTitleChange: function(xulWindow, newTitle) {
|
||||
}
|
||||
};
|
||||
|
||||
function startup(data, reason) {
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||
|
||||
Cu['import']("chrome://kerberosauth/content/kerberosauth.js");
|
||||
|
||||
// Get the list of browser windows already open
|
||||
var windows = wm.getEnumerator("navigator:browser");
|
||||
while (windows.hasMoreElements()) {
|
||||
var domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
|
||||
|
||||
WindowListener.setupBrowserUI(domWindow);
|
||||
}
|
||||
|
||||
// Wait for any new browser windows to open
|
||||
wm.addListener(WindowListener);
|
||||
}
|
||||
|
||||
function shutdown(data, reason) {
|
||||
// When the application is shutting down we normally don't have to clean
|
||||
// up any UI changes made
|
||||
if (reason == APP_SHUTDOWN)
|
||||
return;
|
||||
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
|
||||
// Get the list of browser windows already open
|
||||
var windows = wm.getEnumerator("navigator:browser");
|
||||
while (windows.hasMoreElements()) {
|
||||
var domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
|
||||
WindowListener.tearDownBrowserUI(domWindow);
|
||||
}
|
||||
|
||||
// Stop listening for any new browser windows to open
|
||||
wm.removeListener(WindowListener);
|
||||
|
||||
Cu.unload("chrome://kerberosauth/content/kerberosauth.js");
|
||||
}
|
||||
|
||||
function install() {}
|
||||
function uninstall() {}
|
4
install/ffextension/chrome.manifest
Normal file
4
install/ffextension/chrome.manifest
Normal file
@ -0,0 +1,4 @@
|
||||
content kerberosauth chrome/content/
|
||||
resource kerberosauth chrome/content/
|
||||
overlay chrome://browser/content/browser.xul resource://kerberosauth/kerberosauth_overlay.xul
|
||||
locale kerberosauth en-US locale/en-US/
|
175
install/ffextension/chrome/content/kerberosauth.js
Normal file
175
install/ffextension/chrome/content/kerberosauth.js
Normal file
@ -0,0 +1,175 @@
|
||||
/* Authors:
|
||||
* Petr Vobornik <pvoborni@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat
|
||||
* see file 'COPYING' for use and warranty information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = ["kerberosauth", "kerberosauth_listener"];
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
var kerberosauth = {
|
||||
|
||||
// Dictionary of configuration options this extension can configure.
|
||||
// An alias (key) is set for each options. Using a set of aliases limits
|
||||
// configuration pages from supplying potential malicious options.
|
||||
config_options: {
|
||||
referer: ['network.http.sendRefererHeader', 'int'],
|
||||
native_gss_lib: ['network.negotiate-auth.using-native-gsslib', 'bool'],
|
||||
trusted_uris: ['network.negotiate-auth.trusted-uris', 'str'],
|
||||
allow_proxies: ['network.negotiate-auth.allow-proxies', 'bool']
|
||||
},
|
||||
|
||||
// Some preconfigurations to make things easier. Can be good if UI is added
|
||||
// (mostly for future usage).
|
||||
predefined_configurations: {
|
||||
ipa: {
|
||||
referer: '2',
|
||||
native_gss_lib: 'true',
|
||||
trusted_uris: '',
|
||||
allow_proxies: 'true'
|
||||
}
|
||||
},
|
||||
|
||||
page_listener: function(event, dom_window) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var conf = {
|
||||
event: event,
|
||||
window: dom_window || window,
|
||||
element: event.target
|
||||
};
|
||||
|
||||
if (!conf.element.hasAttribute('method')) return;
|
||||
|
||||
var method = conf.element.getAttribute('method');
|
||||
|
||||
if (method === 'configure') self.configure(conf);
|
||||
if (method === 'can_configure') self.send_response(conf.element, { answer: 'true' });
|
||||
},
|
||||
|
||||
send_response: function(element, options) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
var doc = element.ownerDocument;
|
||||
|
||||
for (var opt in options) {
|
||||
element.setAttribute(opt, options[opt]);
|
||||
}
|
||||
|
||||
var answer_event = doc.createEvent("HTMLEvents");
|
||||
answer_event.initEvent("kerberos-auth-answer", true, false);
|
||||
element.dispatchEvent(answer_event);
|
||||
},
|
||||
|
||||
notify_installed: function(window) {
|
||||
var doc = window.document;
|
||||
var event = doc.createEvent("HTMLEvents");
|
||||
event.initEvent("kerberos-auth-installed", true, false);
|
||||
doc.dispatchEvent(event);
|
||||
},
|
||||
|
||||
configure: function(conf) {
|
||||
var self = this;
|
||||
|
||||
var options = {}; // options to be configured
|
||||
var opt;
|
||||
|
||||
// use predefined configuration if supplied
|
||||
if (conf.element.hasAttribute('predefined')) {
|
||||
var predefined = conf.element.getAttribute('predefined');
|
||||
|
||||
var pconfig = self.predefined_configurations[predefined];
|
||||
if (pconfig) {
|
||||
for (opt in pconfig) {
|
||||
options[opt] = pconfig[opt];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite predefined with supplied and only supported options
|
||||
for (var i=0; i < conf.element.attributes.length; i++) {
|
||||
var attr = conf.element.attributes[i].name;
|
||||
if (attr in self.config_options) {
|
||||
options[attr] = conf.element.getAttribute(attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.prompt(conf, options)) {
|
||||
self.configure_core(conf, options);
|
||||
self.send_response(conf.element, { answer: 'configured' });
|
||||
} else {
|
||||
self.send_response(conf.element, { answer: 'aborted' });
|
||||
}
|
||||
},
|
||||
|
||||
configure_core: function(conf, options) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
for (var opt in options) {
|
||||
|
||||
var name = self.config_options[opt][0];
|
||||
var type = self.config_options[opt][1];
|
||||
var value = options[opt];
|
||||
|
||||
if (type === 'str') {
|
||||
prefs.setCharPref(name, value);
|
||||
} else if (type ==='int') {
|
||||
prefs.setIntPref(name, Number(value));
|
||||
} else if (type === 'bool') {
|
||||
prefs.setBoolPref(name, value === 'true');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
prompt: function(conf, options) {
|
||||
var strs = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://kerberosauth/locale/kerberosauth.properties");
|
||||
|
||||
var prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].
|
||||
getService(Ci.nsIPromptService);
|
||||
|
||||
var title = strs.GetStringFromName('prompt_title');
|
||||
var text = strs.GetStringFromName('prompt_topic');
|
||||
|
||||
if (options.trusted_uris) {
|
||||
text += strs.GetStringFromName('prompt_domain').replace('${domain}', options.trusted_uris);
|
||||
}
|
||||
text += strs.GetStringFromName('prompt_question');
|
||||
|
||||
var flags = prompts.STD_YES_NO_BUTTONS;
|
||||
|
||||
var confirmed = prompts.confirmEx(conf.window, title, text, flags, "","","",
|
||||
null,{value: false}) === 0;
|
||||
return confirmed;
|
||||
}
|
||||
};
|
||||
|
||||
var kerberosauth_listener = function(window) {
|
||||
|
||||
return function(event) {
|
||||
|
||||
kerberosauth.page_listener(event, window);
|
||||
};
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<overlay id="kerberosauthOverlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/x-javascript">
|
||||
Components.utils['import']("resource://kerberosauth/kerberosauth.js");
|
||||
window.addEventListener('kerberos-auth-config', kerberosauth_listener(window), false, true);
|
||||
</script>
|
||||
</overlay>
|
26
install/ffextension/install.rdf
Normal file
26
install/ffextension/install.rdf
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
|
||||
<em:id>kerberosauth@redhat.com</em:id>
|
||||
<em:name>Kerberos Configuration</em:name>
|
||||
<em:version>0.1</em:version>
|
||||
<em:description>Configures browser to use negotiate authentication</em:description>
|
||||
<em:type>2</em:type>
|
||||
<em:creator>Red Hat, Inc.</em:creator>
|
||||
<em:developer>Petr Vobornik</em:developer>
|
||||
<em:homepageURL>http://www.redhat.com/</em:homepageURL>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
||||
<!-- Firefox -->
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>10.0</em:minVersion>
|
||||
<em:maxVersion>15.0.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
4
install/ffextension/locale/en-US/kerberosauth.properties
Normal file
4
install/ffextension/locale/en-US/kerberosauth.properties
Normal file
@ -0,0 +1,4 @@
|
||||
prompt_title=Kerberos configuration confirmation
|
||||
prompt_topic=The page you are visiting is trying to configure Firefox for Kerberos authentication.
|
||||
prompt_domain=\n\nDomain: ${domain}
|
||||
prompt_question=\n\nDo you want to configure the browser?
|
Loading…
Reference in New Issue
Block a user