mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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.
This commit is contained in:
@@ -19,6 +19,7 @@ app_DATA = \
|
|||||||
krb.con.template \
|
krb.con.template \
|
||||||
krbrealm.con.template \
|
krbrealm.con.template \
|
||||||
ntp.conf.server.template \
|
ntp.conf.server.template \
|
||||||
|
preferences.html.template \
|
||||||
radius.radiusd.conf.template \
|
radius.radiusd.conf.template \
|
||||||
referint-conf.ldif \
|
referint-conf.ldif \
|
||||||
dna-posix.ldif \
|
dna-posix.ldif \
|
||||||
|
33
ipa-server/ipa-install/share/preferences.html.template
Normal file
33
ipa-server/ipa-install/share/preferences.html.template
Normal file
@@ -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>
|
@@ -77,6 +77,11 @@ class CertDB(object):
|
|||||||
new_args = new_args + args
|
new_args = new_args + args
|
||||||
ipautil.run(new_args, stdin)
|
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):
|
def create_noise_file(self):
|
||||||
ipautil.backup_file(self.noise_fname)
|
ipautil.backup_file(self.noise_fname)
|
||||||
f = open(self.noise_fname, "w")
|
f = open(self.noise_fname, "w")
|
||||||
@@ -108,7 +113,7 @@ class CertDB(object):
|
|||||||
self.run_certutil(["-S", "-n", self.cacert_name,
|
self.run_certutil(["-S", "-n", self.cacert_name,
|
||||||
"-s", "cn=CAcert",
|
"-s", "cn=CAcert",
|
||||||
"-x",
|
"-x",
|
||||||
"-t", "CT,,",
|
"-t", "CT,,C",
|
||||||
"-m", self.next_serial(),
|
"-m", self.next_serial(),
|
||||||
"-v", self.valid_months,
|
"-v", self.valid_months,
|
||||||
"-z", self.noise_fname,
|
"-z", self.noise_fname,
|
||||||
@@ -130,7 +135,7 @@ class CertDB(object):
|
|||||||
|
|
||||||
def load_cacert(self, cacert_fname):
|
def load_cacert(self, cacert_fname):
|
||||||
self.run_certutil(["-A", "-n", self.cacert_name,
|
self.run_certutil(["-A", "-n", self.cacert_name,
|
||||||
"-t", "CT,CT,",
|
"-t", "CT,,C",
|
||||||
"-a",
|
"-a",
|
||||||
"-i", cacert_fname])
|
"-i", cacert_fname])
|
||||||
|
|
||||||
@@ -139,7 +144,17 @@ class CertDB(object):
|
|||||||
if not cdb:
|
if not cdb:
|
||||||
cdb = self
|
cdb = self
|
||||||
self.request_cert(name)
|
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)
|
self.add_cert(self.certder_fname, nickname)
|
||||||
os.unlink(self.certreq_fname)
|
os.unlink(self.certreq_fname)
|
||||||
os.unlink(self.certder_fname)
|
os.unlink(self.certder_fname)
|
||||||
@@ -151,7 +166,7 @@ class CertDB(object):
|
|||||||
"-z", self.noise_fname,
|
"-z", self.noise_fname,
|
||||||
"-f", self.passwd_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",
|
p = subprocess.Popen(["/usr/bin/certutil",
|
||||||
"-d", self.secdir,
|
"-d", self.secdir,
|
||||||
"-C", "-c", self.cacert_name,
|
"-C", "-c", self.cacert_name,
|
||||||
@@ -179,8 +194,37 @@ class CertDB(object):
|
|||||||
# n - not critical
|
# n - not critical
|
||||||
p.stdin.write("2\n9\nn\n1\n9\nn\n")
|
p.stdin.write("2\n9\nn\n1\n9\nn\n")
|
||||||
p.wait()
|
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):
|
def add_cert(self, cert_fname, nickname):
|
||||||
self.run_certutil(["-A", "-n", nickname,
|
self.run_certutil(["-A", "-n", nickname,
|
||||||
"-t", "u,u,u",
|
"-t", "u,u,u",
|
||||||
|
@@ -25,6 +25,7 @@ import pwd
|
|||||||
import fileinput
|
import fileinput
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import shutil
|
||||||
|
|
||||||
import service
|
import service
|
||||||
import certs
|
import certs
|
||||||
@@ -49,9 +50,10 @@ class HTTPInstance(service.Service):
|
|||||||
service.Service.__init__(self, "httpd")
|
service.Service.__init__(self, "httpd")
|
||||||
|
|
||||||
def create_instance(self, realm, fqdn):
|
def create_instance(self, realm, fqdn):
|
||||||
self.sub_dict = { "REALM" : realm, "FQDN": fqdn }
|
|
||||||
self.fqdn = fqdn
|
self.fqdn = fqdn
|
||||||
self.realm = realm
|
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")
|
self.start_creation(7, "Configuring the web interface")
|
||||||
|
|
||||||
@@ -60,6 +62,7 @@ class HTTPInstance(service.Service):
|
|||||||
self.__configure_http()
|
self.__configure_http()
|
||||||
self.__create_http_keytab()
|
self.__create_http_keytab()
|
||||||
self.__setup_ssl()
|
self.__setup_ssl()
|
||||||
|
self.__setup_autoconfig()
|
||||||
|
|
||||||
self.step("restarting httpd")
|
self.step("restarting httpd")
|
||||||
self.restart()
|
self.restart()
|
||||||
@@ -141,4 +144,31 @@ class HTTPInstance(service.Service):
|
|||||||
ds_ca.cur_serial = 2000
|
ds_ca.cur_serial = 2000
|
||||||
ca.create_from_cacert(ds_ca.cacert_fname)
|
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_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")
|
||||||
|
@@ -12,9 +12,12 @@ RewriteRule ^/(.*) http://$FQDN/$$1 [L,R=301]
|
|||||||
# Redirect to the secure port if not displaying an error or retrieving
|
# Redirect to the secure port if not displaying an error or retrieving
|
||||||
# configuration.
|
# configuration.
|
||||||
RewriteCond %{SERVER_PORT} !^443$$
|
RewriteCond %{SERVER_PORT} !^443$$
|
||||||
RewriteCond %{REQUEST_URI} !^/(errors|config)/
|
RewriteCond %{REQUEST_URI} !^/(errors|config|favicon.ico)
|
||||||
RewriteRule ^/(.*) https://$FQDN/$$1 [L,R=301,NC]
|
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 *>
|
<Proxy *>
|
||||||
AuthType Kerberos
|
AuthType Kerberos
|
||||||
AuthName "Kerberos Login"
|
AuthName "Kerberos Login"
|
||||||
|
@@ -9,6 +9,20 @@ have <a href="/errors/ssbrowser.html">configured your
|
|||||||
browser correctly</a>. If you are still unable to access
|
browser correctly</a>. If you are still unable to access
|
||||||
the IPA Web interface, please contact the helpdesk on for additional assistance.
|
the IPA Web interface, please contact the helpdesk on for additional assistance.
|
||||||
</p>
|
</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>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Reference in New Issue
Block a user