summaryrefslogtreecommitdiffstats
path: root/ipa-server
diff options
context:
space:
mode:
authorKarl MacMillan <kmacmill@redhat.com>2007-12-12 11:19:42 -0500
committerKarl MacMillan <kmacmill@redhat.com>2007-12-12 11:19:42 -0500
commit1c3849eb576dc9d4cd3d4a39aff9da78be0ddcba (patch)
tree1d9ee1113e0e48e35d787af7ee42ea03145538ee /ipa-server
parent8792559f7440cac54072395a7677f31e9b029dc7 (diff)
downloadfreeipa-1c3849eb576dc9d4cd3d4a39aff9da78be0ddcba.tar.gz
freeipa-1c3849eb576dc9d4cd3d4a39aff9da78be0ddcba.tar.xz
freeipa-1c3849eb576dc9d4cd3d4a39aff9da78be0ddcba.zip
User provided certs.
Diffstat (limited to 'ipa-server')
-rw-r--r--ipa-server/ipa-install/Makefile.am1
-rw-r--r--ipa-server/ipa-install/ipa-server-certinstall156
-rw-r--r--ipa-server/ipaserver/certs.py49
-rw-r--r--ipa-server/ipaserver/dsinstance.py2
-rw-r--r--ipa-server/ipaserver/httpinstance.py18
-rw-r--r--ipa-server/ipaserver/installutils.py19
6 files changed, 224 insertions, 21 deletions
diff --git a/ipa-server/ipa-install/Makefile.am b/ipa-server/ipa-install/Makefile.am
index b9ce69156..37dd325e8 100644
--- a/ipa-server/ipa-install/Makefile.am
+++ b/ipa-server/ipa-install/Makefile.am
@@ -8,6 +8,7 @@ sbin_SCRIPTS = \
ipa-server-install \
ipa-replica-install \
ipa-replica-prepare \
+ ipa-server-certinstall \
ipa-radius-install \
$(NULL)
diff --git a/ipa-server/ipa-install/ipa-server-certinstall b/ipa-server/ipa-install/ipa-server-certinstall
new file mode 100644
index 000000000..932a6be18
--- /dev/null
+++ b/ipa-server/ipa-install/ipa-server-certinstall
@@ -0,0 +1,156 @@
+#! /usr/bin/python -E
+# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
+#
+# Copyright (C) 2007 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; version 2 or later
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+import sys
+sys.path.append("/usr/share/ipa")
+
+import traceback
+
+import krbV, ldap, getpass
+
+from ipaserver import certs, dsinstance, httpinstance, ipaldap, installutils
+
+def get_realm_name():
+ c = krbV.default_context()
+ return c.default_realm
+
+def parse_options():
+ from optparse import OptionParser
+ parser = OptionParser()
+
+ parser.add_option("-d", "--dirsrv", dest="dirsrv", action="store_true",
+ default=False, help="install certificate for the directory server")
+ parser.add_option("-w", "--http", dest="http", action="store_true",
+ default=False, help="install certificate for the http server")
+
+
+ options, args = parser.parse_args()
+
+ if not options.dirsrv and not options.http:
+ parser.error("you must specify dirsrv and/or http")
+
+ if len(args) != 1:
+ parser.error("you must provide a pkcs12 filename")
+
+ return options, args[0]
+
+def set_ds_cert_name(cert_name, dm_password):
+ conn = ipaldap.IPAdmin("127.0.0.1")
+ conn.simple_bind_s("cn=directory manager", dm_password)
+
+ mod = [(ldap.MOD_REPLACE, "nsSSLPersonalitySSL", cert_name)]
+
+ conn.modify_s("cn=RSA,cn=encryption,cn=config", mod)
+
+ conn.unbind()
+
+def set_http_cert_name(cert_name):
+ # find the existing cert name
+ fd = open(httpinstance.NSS_CONF)
+ nick_name = None
+ file = []
+ for line in fd:
+ if "NSSNickname" in line:
+ file.append('NSSNickname "%s"\n' % cert_name)
+ else:
+ file.append(line)
+ fd.close()
+
+ fd = open(httpinstance.NSS_CONF, "w")
+ fd.write("".join(file))
+ fd.close()
+
+
+def choose_server_cert(server_certs):
+ print "Please select the certificate to use:"
+ num = 1
+ for cert in server_certs:
+ print "%d. %s" % (num, cert[0])
+ num += 1
+
+ cert_num = 0
+ while 1:
+ cert_input = raw_input("Certificate number [1]: ")
+ print ""
+ if cert_input == "":
+ break
+ else:
+ try:
+ num = int(cert_input)
+ except ValueError:
+ print "invalid number"
+ continue
+ if num > len(server_certs):
+ print "number out of range"
+ continue
+ cert_num = num - 1
+ break
+ return server_certs[cert_num]
+
+
+def import_cert(dirname, pkcs12_fname):
+ cdb = certs.CertDB(dirname)
+ cdb.create_passwd_file(False)
+ cdb.create_certdbs()
+ try:
+ cdb.import_pkcs12(pkcs12_fname)
+ except RuntimeError, e:
+ print str(e)
+ sys.exit(1)
+
+ server_certs = cdb.find_server_certs()
+ if len(server_certs) == 0:
+ print "could not find a suitable server cert in import"
+ sys.exit(1)
+ elif len(server_certs) == 1:
+ server_cert = server_certs[0]
+ else:
+ server_cert = choose_server_cert(server_certs)
+
+ cdb.trust_root_cert(server_cert[0])
+
+ return server_cert
+
+def main():
+ options, pkcs12_fname = parse_options()
+
+ try:
+ if options.dirsrv:
+ dm_password = getpass.getpass("Directory Manager password: ")
+ realm = get_realm_name()
+ dirname = dsinstance.config_dirname(realm)
+ server_cert = import_cert(dirname, pkcs12_fname)
+ set_ds_cert_name(server_cert[0], dm_password)
+
+ if options.http:
+ dirname = httpinstance.NSS_DIR
+ server_cert = import_cert(dirname, pkcs12_fname)
+ print server_cert
+ set_http_cert_name(server_cert[0])
+
+ except Exception, e:
+ print "an unexpected error occurred: %s" % str(e)
+ traceback.print_exc()
+ return 1
+
+ return 0
+
+
+sys.exit(main())
diff --git a/ipa-server/ipaserver/certs.py b/ipa-server/ipaserver/certs.py
index fb6b01d0e..77052c13e 100644
--- a/ipa-server/ipaserver/certs.py
+++ b/ipa-server/ipaserver/certs.py
@@ -17,7 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-import os, stat, subprocess
+import os, stat, subprocess, re
import sha
from ipa import ipautil
@@ -196,6 +196,50 @@ class CertDB(object):
f.close()
self.set_perms(self.pin_fname)
+ def trust_root_cert(self, nickname):
+ p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
+ "-O", "-n", nickname], stdout=subprocess.PIPE)
+
+ chain = p.stdout.read()
+ chain = chain.split("\n")
+
+ root_nickname = re.match('\ *"(.*)".*', chain[0]).groups()[0]
+
+ self.run_certutil(["-M", "-n", root_nickname,
+ "-t", "CT,CT,"])
+
+ def find_server_certs(self):
+ p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
+ "-L"], stdout=subprocess.PIPE)
+
+ certs = p.stdout.read()
+
+ certs = certs.split("\n")
+
+ server_certs = []
+
+ for cert in certs:
+ fields = cert.split()
+ if not len(fields):
+ continue
+ flags = fields[-1]
+ if 'u' in flags:
+ name = " ".join(fields[0:-1])
+ server_certs.append((name, flags))
+
+ return server_certs
+
+
+ def import_pkcs12(self, pkcs12_fname):
+ try:
+ ipautil.run(["/usr/bin/pk12util", "-d", self.secdir,
+ "-i", pkcs12_fname])
+ except ipautil.CalledProcessError, e:
+ if e.returncode == 17:
+ raise RuntimeError("incorrect password")
+ else:
+ raise RuntimeError("unknown error import pkcs#12 file")
+
def create_self_signed(self, passwd=True):
self.create_noise_file()
self.create_passwd_file(passwd)
@@ -208,6 +252,3 @@ class CertDB(object):
self.create_passwd_file(passwd)
self.create_certdbs()
self.load_cacert(cacert_fname)
-
-
-
diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py
index 5edc3879e..818710fb6 100644
--- a/ipa-server/ipaserver/dsinstance.py
+++ b/ipa-server/ipaserver/dsinstance.py
@@ -322,7 +322,7 @@ class DsInstance(service.Service):
conn.addEntry(entry)
conn.unbind()
-
+
def __add_default_layout(self):
self.step("adding default layout")
txt = ipautil.template_file(ipautil.SHARE_DIR + "bootstrap-template.ldif", self.sub_dict)
diff --git a/ipa-server/ipaserver/httpinstance.py b/ipa-server/ipaserver/httpinstance.py
index 1799cca07..de0b3af82 100644
--- a/ipa-server/ipaserver/httpinstance.py
+++ b/ipa-server/ipaserver/httpinstance.py
@@ -29,6 +29,7 @@ import time
import service
import certs
import dsinstance
+import installutils
from ipa.ipautil import *
HTTPD_DIR = "/etc/httpd"
@@ -43,21 +44,6 @@ successfully change with the command:
Try updating the policycoreutils and selinux-policy packages.
"""
-def update_file(filename, orig, subst):
- if os.path.exists(filename):
- pattern = "%s" % re.escape(orig)
- p = re.compile(pattern)
- for line in fileinput.input(filename, inplace=1):
- if not p.search(line):
- sys.stdout.write(line)
- else:
- sys.stdout.write(p.sub(subst, line))
- fileinput.close()
- return 0
- else:
- print "File %s doesn't exist." % filename
- return 1
-
class HTTPInstance(service.Service):
def __init__(self):
service.Service.__init__(self, "httpd")
@@ -145,7 +131,7 @@ class HTTPInstance(service.Service):
def __set_mod_nss_port(self):
self.step("Setting mod_nss port to 443")
- if update_file(NSS_CONF, '8443', '443') != 0:
+ if installutils.update_file(NSS_CONF, '8443', '443') != 0:
print "Updating %s failed." % NSS_CONF
def __setup_ssl(self):
diff --git a/ipa-server/ipaserver/installutils.py b/ipa-server/ipaserver/installutils.py
index a403e8154..25cd1555c 100644
--- a/ipa-server/ipaserver/installutils.py
+++ b/ipa-server/ipaserver/installutils.py
@@ -21,6 +21,10 @@ import logging
import socket
import errno
import getpass
+import os
+import re
+import fileinput
+import sys
def get_fqdn():
fqdn = ""
@@ -105,4 +109,19 @@ def read_password(user):
print ""
return pwd
+def update_file(filename, orig, subst):
+ if os.path.exists(filename):
+ pattern = "%s" % re.escape(orig)
+ p = re.compile(pattern)
+ for line in fileinput.input(filename, inplace=1):
+ if not p.search(line):
+ sys.stdout.write(line)
+ else:
+ sys.stdout.write(p.sub(subst, line))
+ fileinput.close()
+ return 0
+ else:
+ print "File %s doesn't exist." % filename
+ return 1
+