diff options
-rwxr-xr-x | ca/rpkic | 19 | ||||
-rw-r--r-- | rpki/cli.py | 22 | ||||
-rw-r--r-- | rpki/irdb/zookeeper.py | 13 | ||||
-rw-r--r-- | rpki/rpkic.py | 98 |
4 files changed, 122 insertions, 30 deletions
@@ -15,19 +15,32 @@ if __name__ == "__main__": import sys import rpki.autoconf + argv = [sys.executable, os.path.abspath(sys.argv[0])] + argv.extend(sys.argv[1:]) + + already_ran_sudo = os.getenv("SUDO_COMMAND") == " ".join(argv) + try: uid = pwd.getpwnam(rpki.autoconf.RPKI_USER).pw_uid except: uid = None - if uid is None or uid == os.geteuid(): + euid = os.geteuid() + + if already_ran_sudo or uid is None or uid == euid or euid == 0: + + if not already_ran_sudo: + for name in ("SUDO_COMMAND", "SUDO_GID", "SUDO_UID", "SUDO_USER"): + if name in os.environ: + del os.environ[name] + import rpki.rpkic rpki.rpkic.main() else: + try: - argv = [rpki.autoconf.SUDO, "-u", rpki.autoconf.RPKI_USER, sys.executable] - argv.extend(os.path.abspath(a) if i == 0 else a for i, a in enumerate(sys.argv)) + argv.insert(0, rpki.autoconf.SUDO) os.execv(argv[0], argv) sys.exit("rpkic startup failure, no exception so don't know why, sorry") diff --git a/rpki/cli.py b/rpki/cli.py index 2f007101..cbd2b1e1 100644 --- a/rpki/cli.py +++ b/rpki/cli.py @@ -165,7 +165,7 @@ class Cmd(cmd.Cmd): old_completer_delims = readline.get_completer_delims() if self.histfile is not None: try: - readline.read_history_file(self.histfile) + self.read_history() except IOError: pass try: @@ -174,11 +174,29 @@ class Cmd(cmd.Cmd): finally: if self.histfile is not None and readline.get_current_history_length(): try: - readline.write_history_file(self.histfile) + self.save_history() except IOError: pass readline.set_completer_delims(old_completer_delims) + def read_history(self): + """ + Read readline history from file. + + This is a separate method so that subclasses can wrap it when necessary. + """ + + readline.read_history_file(self.histfile) + + def save_history(self): + """ + Save readline history to file. + + This is a separate method so that subclasses can wrap it when necessary. + """ + + readline.write_history_file(self.histfile) + else: cmdloop_with_history = cmd.Cmd.cmdloop diff --git a/rpki/irdb/zookeeper.py b/rpki/irdb/zookeeper.py index e7d9965c..9d40263c 100644 --- a/rpki/irdb/zookeeper.py +++ b/rpki/irdb/zookeeper.py @@ -382,15 +382,10 @@ class Zookeeper(object): configure_rootd() because that's easier for the GUI. """ - try: - self.resource_ca.repositories.get(handle = self.handle) - return None - - except rpki.irdb.models.Repository.DoesNotExist: - e = Element(tag_oob_publisher_request, nsmap = oob_nsmap, version = oob_version, - publisher_handle = self.handle) - B64Element(e, tag_oob_publisher_bpki_ta, self.resource_ca.certificate) - return etree_wrapper(e, msg = 'This is the "repository offer" file for you to use if you want to publish in your own repository') + e = Element(tag_oob_publisher_request, nsmap = oob_nsmap, version = oob_version, + publisher_handle = self.handle) + B64Element(e, tag_oob_publisher_bpki_ta, self.resource_ca.certificate) + return etree_wrapper(e, msg = 'This is the "repository offer" file for you to use if you want to publish in your own repository') def write_bpki_files(self): diff --git a/rpki/rpkic.py b/rpki/rpkic.py index 7d63bbe7..68cac4b2 100644 --- a/rpki/rpkic.py +++ b/rpki/rpkic.py @@ -24,17 +24,11 @@ an overview of the available commands; type "help foo" for (more) detailed help on the "foo" command. """ -# NB: As of this writing, I'm trying really hard to avoid having this -# program depend on a Django settings.py file. This may prove to be a -# waste of time in the long run, but for for now, this means that one -# has to be careful about exactly how and when one imports Django -# modules, or anything that imports Django modules. Bottom line is -# that we don't import such modules until we need them. - import os -import argparse import sys +import pwd import time +import argparse import rpki.config import rpki.sundial import rpki.log @@ -51,6 +45,25 @@ from rpki.cli import Cmd, parsecmd, cmdarg module_doc = __doc__ + +class swap_uids(object): + """ + Context manager to wrap os.setreuid() calls safely. + """ + + def __init__(self): + self.uid = os.getuid() + self.euid = os.geteuid() + + def __enter__(self): + os.setreuid(self.euid, self.uid) + return self + + def __exit__(self, _type, value, traceback): + os.setreuid(self.uid, self.euid) + return False + + class main(Cmd): prompt = "rpkic> " @@ -77,6 +90,8 @@ class main(Cmd): def __init__(self): + self.drop_privs() + Cmd.__init__(self) os.environ["TZ"] = "UTC" time.tzset() @@ -114,6 +129,50 @@ class main(Cmd): else: args.func(self, args) + + def drop_privs(self): + """ + Initialize UID swapping and drop unneeded privs. + + Any error here we don't understand is dangerous and therefore fatal. + """ + + try: + + try: + os.setgid(int(os.environ["SUDO_GID"])) + except KeyError: + pass + + try: + uid = int(os.environ["SUDO_UID"]) + except KeyError: + uid = os.getuid() + + try: + os.setreuid(uid, pwd.getpwnam(rpki.autoconf.RPKI_USER).pw_uid) + except (KeyError, OSError) as e: + sys.exit("Couldn't drop privs to user {}: {!s}".format(rpki.autoconf.RPKI_USER, e)) + + except Exception as e: + sys.exit("Fatal error trying to drop privs: {!s}".format(e)) + + def read_history(self): + """ + UID-swapping wrapper for parent .read_history() method. + """ + + with swap_uids(): + Cmd.read_history(self) + + def save_history(self): + """ + UID-swapping wrapper for parent .save_history() method. + """ + + with swap_uids(): + Cmd.save_history(self) + def read_config(self): # pylint: disable=W0201,W0602,W0621 @@ -224,13 +283,15 @@ class main(Cmd): rootd_case = self.zoo.run_rootd and self.zoo.handle == self.zoo.cfg.get("handle") r = self.zoo.initialize() - r.save("%s.identity.xml" % self.zoo.handle, - None if rootd_case else sys.stdout) + with swap_uids(): + r.save("%s.identity.xml" % self.zoo.handle, + None if rootd_case else sys.stdout) if rootd_case: r = self.zoo.configure_rootd() if r is not None: - r.save("%s.%s.repository-request.xml" % (self.zoo.handle, self.zoo.handle), sys.stdout) + with swap_uids(): + r.save("%s.%s.repository-request.xml" % (self.zoo.handle, self.zoo.handle), sys.stdout) self.zoo.write_bpki_files() @@ -250,7 +311,8 @@ class main(Cmd): self.zoo.reset_identity(args.handle) r = self.zoo.initialize_resource_bpki() - r.save("%s.identity.xml" % self.zoo.handle, sys.stdout) + with swap_uids(): + r.save("%s.identity.xml" % self.zoo.handle, sys.stdout) @parsecmd(argsubparsers) @@ -304,7 +366,8 @@ class main(Cmd): """ r, child_handle = self.zoo.configure_child(args.child_xml, args.child_handle, args.valid_until) - r.save("%s.%s.parent-response.xml" % (self.zoo.handle, child_handle), sys.stdout) + with swap_uids(): + r.save("%s.%s.parent-response.xml" % (self.zoo.handle, child_handle), sys.stdout) self.zoo.synchronize_ca() @@ -350,7 +413,8 @@ class main(Cmd): """ r, parent_handle = self.zoo.configure_parent(args.parent_xml, args.parent_handle) - r.save("%s.%s.repository-request.xml" % (self.zoo.handle, parent_handle), sys.stdout) + with swap_uids(): + r.save("%s.%s.repository-request.xml" % (self.zoo.handle, parent_handle), sys.stdout) @parsecmd(argsubparsers, @@ -383,7 +447,8 @@ class main(Cmd): r = self.zoo.configure_rootd() if r is not None: - r.save("%s.%s.repository-request.xml" % (self.zoo.handle, self.zoo.handle), sys.stdout) + with swap_uids(): + r.save("%s.%s.repository-request.xml" % (self.zoo.handle, self.zoo.handle), sys.stdout) self.zoo.write_bpki_files() @@ -419,7 +484,8 @@ class main(Cmd): """ r, client_handle = self.zoo.configure_publication_client(args.client_xml, args.sia_base, args.flat) - r.save("%s.repository-response.xml" % client_handle.replace("/", "."), sys.stdout) + with swap_uids(): + r.save("%s.repository-response.xml" % client_handle.replace("/", "."), sys.stdout) try: self.zoo.synchronize_pubd() except rpki.irdb.models.Repository.DoesNotExist: |