diff options
author | Rob Crittenden <rcritten@redhat.com> | 2007-12-12 09:36:32 -0500 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2007-12-12 09:36:32 -0500 |
commit | 6390db3502eaee385cb990eef723bc4f27a633c0 (patch) | |
tree | 6c619192efd2e40f0c389a2eb01aa84ed99c912c | |
parent | 1c3849eb576dc9d4cd3d4a39aff9da78be0ddcba (diff) | |
download | freeipa-6390db3502eaee385cb990eef723bc4f27a633c0.tar.gz freeipa-6390db3502eaee385cb990eef723bc4f27a633c0.tar.xz freeipa-6390db3502eaee385cb990eef723bc4f27a633c0.zip |
Add automatic browser configuration for kerberos SSO using javascript.
This uses the UniversalPreferencesWrite function to set the browser
preferences to allow negotiation and ticket forwarding in the IPA domain.
A self-signed certificate is generated to sign the javascript.
-rw-r--r-- | ipa-server/ipa-install/share/Makefile.am | 1 | ||||
-rw-r--r-- | ipa-server/ipa-install/share/preferences.html.template | 33 | ||||
-rw-r--r-- | ipa-server/ipaserver/certs.py | 56 | ||||
-rw-r--r-- | ipa-server/ipaserver/httpinstance.py | 34 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/ipa.conf | 5 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/unauthorized.html | 14 |
6 files changed, 134 insertions, 9 deletions
diff --git a/ipa-server/ipa-install/share/Makefile.am b/ipa-server/ipa-install/share/Makefile.am index 36bb54e83..36837356d 100644 --- a/ipa-server/ipa-install/share/Makefile.am +++ b/ipa-server/ipa-install/share/Makefile.am @@ -19,6 +19,7 @@ app_DATA = \ krb.con.template \ krbrealm.con.template \ ntp.conf.server.template \ + preferences.html.template \ radius.radiusd.conf.template \ referint-conf.ldif \ dna-posix.ldif \ diff --git a/ipa-server/ipa-install/share/preferences.html.template b/ipa-server/ipa-install/share/preferences.html.template new file mode 100644 index 000000000..2d3684dcd --- /dev/null +++ b/ipa-server/ipa-install/share/preferences.html.template @@ -0,0 +1,33 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> + <title>Automatically set browser preferences</title> +</head> +<body> +<form action="undefined" method="get"> +<input type=button onclick="setPreferences()" name="prefs" value="Configure Firefox"> +</form> + +<script type="text/javascript"> +function setPreferences() { + try { + netscape.security.PrivilegeManager.enablePrivilege("UniversalPreferencesWrite"); + try { + navigator.preference("network.negotiate-auth.using-native-gsslib", true) + navigator.preference("network.negotiate-auth.delegation-uris", ".$DOMAIN") + navigator.preference("network.negotiate-auth.trusted-uris", ".$DOMAIN") + navigator.preference("network.negotiate-auth.allow-proxies", true) + } catch (e) { + alert("Unable to store preferences: " + e) + } + netscape.security.PrivilegeManager.disablePrivilege("UniversalPreferencesWrite"); + alert("Successfully configured Firefox for single sign on.") + } catch (e) { + alert("Unable to apply recommended settings.\n\nClick on the Certificate Authority link and select trust for all, then reload this page and try again.\n\nThe error returned was: " + e); + return; + } +} +</script> + +</body> +</html> diff --git a/ipa-server/ipaserver/certs.py b/ipa-server/ipaserver/certs.py index 77052c13e..eecfdf21c 100644 --- a/ipa-server/ipaserver/certs.py +++ b/ipa-server/ipaserver/certs.py @@ -77,6 +77,11 @@ class CertDB(object): new_args = new_args + args ipautil.run(new_args, stdin) + def run_signtool(self, args, stdin=None): + new_args = ["/usr/bin/signtool", "-d", self.secdir] + new_args = new_args + args + ipautil.run(new_args, stdin) + def create_noise_file(self): ipautil.backup_file(self.noise_fname) f = open(self.noise_fname, "w") @@ -108,7 +113,7 @@ class CertDB(object): self.run_certutil(["-S", "-n", self.cacert_name, "-s", "cn=CAcert", "-x", - "-t", "CT,,", + "-t", "CT,,C", "-m", self.next_serial(), "-v", self.valid_months, "-z", self.noise_fname, @@ -130,7 +135,7 @@ class CertDB(object): def load_cacert(self, cacert_fname): self.run_certutil(["-A", "-n", self.cacert_name, - "-t", "CT,CT,", + "-t", "CT,,C", "-a", "-i", cacert_fname]) @@ -139,7 +144,17 @@ class CertDB(object): if not cdb: cdb = self self.request_cert(name) - cdb.issue_cert(self.certreq_fname, self.certder_fname) + cdb.issue_server_cert(self.certreq_fname, self.certder_fname) + self.add_cert(self.certder_fname, nickname) + os.unlink(self.certreq_fname) + os.unlink(self.certder_fname) + + def create_signing_cert(self, nickname, name, other_certdb=None): + cdb = other_certdb + if not cdb: + cdb = self + self.request_cert(name) + cdb.issue_signing_cert(self.certreq_fname, self.certder_fname) self.add_cert(self.certder_fname, nickname) os.unlink(self.certreq_fname) os.unlink(self.certder_fname) @@ -151,7 +166,7 @@ class CertDB(object): "-z", self.noise_fname, "-f", self.passwd_fname]) - def issue_cert(self, certreq_fname, cert_fname): + def issue_server_cert(self, certreq_fname, cert_fname): p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir, "-C", "-c", self.cacert_name, @@ -179,8 +194,37 @@ class CertDB(object): # n - not critical p.stdin.write("2\n9\nn\n1\n9\nn\n") p.wait() - - + + def issue_signing_cert(self, certreq_fname, cert_fname): + p = subprocess.Popen(["/usr/bin/certutil", + "-d", self.secdir, + "-C", "-c", self.cacert_name, + "-i", certreq_fname, + "-o", cert_fname, + "-m", self.next_serial(), + "-v", self.valid_months, + "-f", self.passwd_fname, + "-1", "-5"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + + # Bah - this sucks, but I guess it isn't possible to fully + # control this with command line arguments. + # + # What this is requesting is: + # -1 (Create key usage extension) + # 0 - Digital Signature + # 5 - Cert signing key + # 9 - done + # n - not critical + # + # -5 (Create netscape cert type extension) + # 3 - Object Signing + # 9 - done + # n - not critical + p.stdin.write("0\n5\n9\nn\n3\n9\nn\n") + p.wait() + def add_cert(self, cert_fname, nickname): self.run_certutil(["-A", "-n", nickname, "-t", "u,u,u", diff --git a/ipa-server/ipaserver/httpinstance.py b/ipa-server/ipaserver/httpinstance.py index de0b3af82..a131faedc 100644 --- a/ipa-server/ipaserver/httpinstance.py +++ b/ipa-server/ipaserver/httpinstance.py @@ -25,6 +25,7 @@ import pwd import fileinput import sys import time +import shutil import service import certs @@ -49,9 +50,10 @@ class HTTPInstance(service.Service): service.Service.__init__(self, "httpd") def create_instance(self, realm, fqdn): - self.sub_dict = { "REALM" : realm, "FQDN": fqdn } self.fqdn = fqdn self.realm = realm + self.domain = fqdn[fqdn.find(".")+1:] + self.sub_dict = { "REALM" : realm, "FQDN": fqdn, "DOMAIN" : self.domain } self.start_creation(7, "Configuring the web interface") @@ -60,6 +62,7 @@ class HTTPInstance(service.Service): self.__configure_http() self.__create_http_keytab() self.__setup_ssl() + self.__setup_autoconfig() self.step("restarting httpd") self.restart() @@ -141,4 +144,31 @@ class HTTPInstance(service.Service): ds_ca.cur_serial = 2000 ca.create_from_cacert(ds_ca.cacert_fname) ca.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca) - + ca.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ds_ca) + + def __setup_autoconfig(self): + prefs_txt = template_file(SHARE_DIR + "preferences.html.template", self.sub_dict) + prefs_fd = open("/usr/share/ipa/html/preferences.html", "w") + prefs_fd.write(prefs_txt) + prefs_fd.close() + + # The signing cert is generated in __setup_ssl + ds_ca = certs.CertDB(dsinstance.config_dirname(self.realm)) + ca = certs.CertDB(NSS_DIR) + + # Publish the CA certificate + shutil.copy(ds_ca.cacert_fname, "/usr/share/ipa/html/ca.crt") + os.chmod("/usr/share/ipa/html/ca.crt", 0444) + + try: + shutil.rmtree("/tmp/ipa") + except: + pass + os.mkdir("/tmp/ipa") + shutil.copy("/usr/share/ipa/html/preferences.html", "/tmp/ipa") + + ca.run_signtool(["-k", "Signing-Cert", + "-Z", "/usr/share/ipa/html/configure.jar", + "-e", ".html", + "/tmp/ipa"]) + shutil.rmtree("/tmp/ipa") diff --git a/ipa-server/xmlrpc-server/ipa.conf b/ipa-server/xmlrpc-server/ipa.conf index fbf26b67c..4e8bf528f 100644 --- a/ipa-server/xmlrpc-server/ipa.conf +++ b/ipa-server/xmlrpc-server/ipa.conf @@ -12,9 +12,12 @@ RewriteRule ^/(.*) http://$FQDN/$$1 [L,R=301] # Redirect to the secure port if not displaying an error or retrieving # configuration. RewriteCond %{SERVER_PORT} !^443$$ -RewriteCond %{REQUEST_URI} !^/(errors|config)/ +RewriteCond %{REQUEST_URI} !^/(errors|config|favicon.ico) RewriteRule ^/(.*) https://$FQDN/$$1 [L,R=301,NC] +# This is required so the auto-configuration works with Firefox 2+ +AddType application/java-archive jar + <Proxy *> AuthType Kerberos AuthName "Kerberos Login" diff --git a/ipa-server/xmlrpc-server/unauthorized.html b/ipa-server/xmlrpc-server/unauthorized.html index 23a8d5c7d..e46ca538f 100644 --- a/ipa-server/xmlrpc-server/unauthorized.html +++ b/ipa-server/xmlrpc-server/unauthorized.html @@ -9,6 +9,20 @@ have <a href="/errors/ssbrowser.html">configured your browser correctly</a>. If you are still unable to access the IPA Web interface, please contact the helpdesk on for additional assistance. </p> +<p> +Import the <a href="/errors/ca.crt">IPA Certificate Authority</a>. +</p> +<p> +<script type="text/javascript"> + if (navigator.userAgent.indexOf("Firefox") != -1 || + navigator.userAgent.indexOf("SeaMonkey") != -1) + { + document.write("<p>You can automatically configure your browser to work with Kerberos by importing the Certificate Authority below and clicking on the Configure Browser button.</p>"); + document.write("<p>You <strong>must</strong> reload this page after importing the Certificate Authority for the automatic settings to work</p>"); + document.write("<object data=\"jar:/errots/configure.jar!/preferences.html\" type=\"text/html\"><\/object"); + } +</script> +</p> </ul> </body> </html> |