=== modified file '.bzrignore' --- .bzrignore 2008-09-26 05:04:15 +0000 +++ .bzrignore 2008-09-30 07:23:39 +0000 @@ -5,6 +5,7 @@ debian/po/messages.mo debian/po/templates.pot keydir +man plugin-runner plugins.d/mandos-client plugins.d/password-prompt === modified file 'Makefile' --- Makefile 2008-09-26 19:47:21 +0000 +++ Makefile 2008-09-30 18:59:44 +0000 @@ -13,6 +13,9 @@ #COVERAGE=--coverage OPTIMIZE=-Os LANGUAGE=-std=gnu99 +htmldir=man +version=1.0 +SED=sed ## Use these settings for a traditional /usr/local install # PREFIX=$(DESTDIR)/usr/local @@ -39,7 +42,8 @@ # Do not change these two CFLAGS=$(WARN) $(DEBUG) $(FORTIFY) $(COVERAGE) $(OPTIMIZE) \ - $(LANGUAGE) $(GNUTLS_CFLAGS) $(AVAHI_CFLAGS) $(GPGME_CFLAGS) + $(LANGUAGE) $(GNUTLS_CFLAGS) $(AVAHI_CFLAGS) $(GPGME_CFLAGS) \ + -DVERSION='"$(version)"' LDFLAGS=$(COVERAGE) # Commands to format a DocBook document into a manual page @@ -53,65 +57,120 @@ $(notdir $<); \ $(MANPOST) $(notdir $@) # DocBook-to-man post-processing to fix a '\n' escape bug -MANPOST=sed --in-place --expression='s,\\\\en,\\en,g;s,\\n,\\en,g' +MANPOST=$(SED) --in-place --expression='s,\\\\en,\\en,g;s,\\n,\\en,g' + +DOCBOOKTOHTML=xsltproc --nonet --xinclude \ + --param make.year.ranges 1 \ + --param make.single.year.ranges 1 \ + --param man.output.quietly 1 \ + --param man.authors.section.enabled 0 \ + --param citerefentry.link 1 \ + --output $@ \ + /usr/share/xml/docbook/stylesheet/nwalsh/xhtml/docbook.xsl \ + $<; $(HTMLPOST) $@ +# Fix citerefentry links +HTMLPOST=$(SED) --in-place --expression='s/\(\)\([^<]*\)\(<\/span>(\)\([^)]*\)\()<\/span><\/a>\)/\1\3.\5\2\3\4\5\6/g' PLUGINS=plugins.d/password-prompt plugins.d/mandos-client \ plugins.d/usplash plugins.d/splashy plugins.d/askpass-fifo -PROGS=plugin-runner $(PLUGINS) +CPROGS=plugin-runner $(PLUGINS) +PROGS=mandos mandos-keygen $(CPROGS) DOCS=mandos.8 plugin-runner.8mandos mandos-keygen.8 \ plugins.d/mandos-client.8mandos \ plugins.d/password-prompt.8mandos mandos.conf.5 \ mandos-clients.conf.5 -objects=$(addsuffix .o,$(PROGS)) +htmldocs=$(addsuffix .xhtml,$(DOCS)) + +objects=$(addsuffix .o,$(CPROGS)) all: $(PROGS) doc: $(DOCS) -%.5: %.xml legalnotice.xml - $(DOCBOOKTOMAN) - -%.8: %.xml legalnotice.xml - $(DOCBOOKTOMAN) - -%.8mandos: %.xml legalnotice.xml - $(DOCBOOKTOMAN) - -mandos.8: mandos.xml mandos-options.xml overview.xml legalnotice.xml - $(DOCBOOKTOMAN) - -mandos-keygen.8: mandos-keygen.xml overview.xml legalnotice.xml - $(DOCBOOKTOMAN) - -mandos.conf.5: mandos.conf.xml mandos-options.xml legalnotice.xml - $(DOCBOOKTOMAN) - -plugin-runner.8mandos: plugin-runner.xml overview.xml legalnotice.xml - $(DOCBOOKTOMAN) +html: $(htmldocs) + +%.5: %.xml common.ent legalnotice.xml + $(DOCBOOKTOMAN) +%.5.xhtml: %.xml common.ent legalnotice.xml + $(DOCBOOKTOHTML) + +%.8: %.xml common.ent legalnotice.xml + $(DOCBOOKTOMAN) +%.8.xhtml: %.xml common.ent legalnotice.xml + $(DOCBOOKTOHTML) + +%.8mandos: %.xml common.ent legalnotice.xml + $(DOCBOOKTOMAN) +%.8mandos.xhtml: %.xml common.ent legalnotice.xml + $(DOCBOOKTOHTML) + +mandos.8: mandos.xml common.ent mandos-options.xml overview.xml \ + legalnotice.xml + $(DOCBOOKTOMAN) +mandos.8.xhtml: mandos.xml common.ent mandos-options.xml \ + overview.xml legalnotice.xml + $(DOCBOOKTOHTML) + +mandos-keygen.8: mandos-keygen.xml common.ent overview.xml \ + legalnotice.xml + $(DOCBOOKTOMAN) +mandos-keygen.8.xhtml: mandos-keygen.xml common.ent overview.xml \ + legalnotice.xml + $(DOCBOOKTOHTML) + +mandos.conf.5: mandos.conf.xml common.ent mandos-options.xml \ + legalnotice.xml + $(DOCBOOKTOMAN) +mandos.conf.5.xhtml: mandos.conf.xml common.ent mandos-options.xml \ + legalnotice.xml + $(DOCBOOKTOHTML) + +plugin-runner.8mandos: plugin-runner.xml common.ent overview.xml \ + legalnotice.xml + $(DOCBOOKTOMAN) +plugin-runner.8mandos.xhtml: plugin-runner.xml common.ent \ + overview.xml legalnotice.xml + $(DOCBOOKTOHTML) plugins.d/mandos-client.8mandos: plugins.d/mandos-client.xml \ + common.ent \ mandos-options.xml \ overview.xml legalnotice.xml $(DOCBOOKTOMAN) +plugins.d/mandos-client.8mandos.xhtml: plugins.d/mandos-client.xml \ + common.ent \ + mandos-options.xml \ + overview.xml legalnotice.xml + $(DOCBOOKTOHTML) + +# Update all these files with version number $(version) +common.ent: Makefile + $(SED) --in-place --expression='s/^\($$/\1$(version)"/' $@ + +mandos: Makefile + $(SED) --in-place --expression='s/^\(version = "\)[^"]*"/\1$(version)"/' $@ + +mandos-keygen: Makefile + $(SED) --in-place --expression='s/^\(VERSION="\)[^"]*"/\1$(version)"/' $@ plugins.d/mandos-client: plugins.d/mandos-client.o $(LINK.o) $(GNUTLS_LIBS) $(AVAHI_LIBS) $(GPGME_LIBS) \ $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@ -.PHONY : all doc clean distclean run-client run-server install \ +.PHONY : all doc html clean distclean run-client run-server install \ install-server install-client uninstall uninstall-server \ uninstall-client purge purge-server purge-client clean: - -rm --force $(PROGS) $(objects) $(DOCS) core + -rm --force $(CPROGS) $(objects) $(htmldocs) $(DOCS) core distclean: clean mostlyclean: clean maintainer-clean: clean -rm --force --recursive keydir confdir -check: +check: all ./mandos --check # Run the client with a local config and key @@ -141,6 +200,11 @@ install: install-server install-client-nokey +install-html: $(htmldocs) + install --directory $(htmldir) + install --mode=u=rw,go=r --target-directory=$(htmldir) \ + $(htmldocs) + install-server: doc install --directory $(CONFDIR) install --mode=u=rwx,go=rx mandos $(PREFIX)/sbin/mandos @@ -239,9 +303,6 @@ $(MANDIR)/man8/mandos-keygen.8.gz \ $(MANDIR)/man8/password-prompt.8mandos.gz \ $(MANDIR)/man8/mandos-client.8mandos.gz - if [ "$(CONFDIR)" != "$(PREFIX)/lib/mandos" ]; then \ - rm --force $(CONFDIR)/plugins.d/README; \ - fi -rmdir $(PREFIX)/lib/mandos/plugins.d $(CONFDIR)/plugins.d \ $(PREFIX)/lib/mandos $(CONFDIR) $(KEYDIR) update-initramfs -k all -u === modified file 'README' --- README 2008-09-17 00:34:09 +0000 +++ README 2008-09-30 03:19:39 +0000 @@ -130,6 +130,34 @@ on your door and the sudden absence of all the servers in your server room. Which it does nicely. +* The Plugin System + In the early designs, the mandos-client(8mandos) program (which + retrieves a password from the Mandos server) also prompted for a + password on the terminal, in case a Mandos server could not be + found. This duality of purpose was seen to be too complex to be a + viable way to continue. Instead, the programs are now separated + into mandos-client(8mandos) and password-prompt(8mandos), and a + plugin-runner(8mandos) exist to run them both in parallel, allowing + the first plugin to succeed to provide the password. This opened up + for any number of additional plugins to run, all competing to be the + first to find a password and provide it to the plugin runner. + + Three additional plugins are provided: + * usplash + This prompts for a password when using usplash(8). + * splashy + This prompts for a password when using splashy(8). + * askpass-fifo + To provide compatibility with the "askpass" program from + cryptsetup, this plugin listens to the same FIFO as askpass would + do. + + (None of these take any options or reads any files.) + + More plugins could easily be written and added by the system + administrator; see the section called "WRITING PLUGINS" in + plugin-runner(8mandos) to learn the plugin requirements. + * Copyright Copyright © 2008 Teddy Hogeborn === modified file 'TODO' --- TODO 2008-09-23 15:21:27 +0000 +++ TODO 2008-09-30 19:37:06 +0000 @@ -58,7 +58,8 @@ * TODO Web site ** DONE http://www.fukt.bsnet.se/mandos Redirects to the wiki page -** DONE http://wiki.fukt.bsnet.se/wiki/Mandos +** TODO http://wiki.fukt.bsnet.se/wiki/Mandos + http://liw.fi/free-software-website/ * Mailing list ** DONE mandos-dev === added file 'common.ent' --- common.ent 1970-01-01 00:00:00 +0000 +++ common.ent 2008-09-30 07:23:39 +0000 @@ -0,0 +1,3 @@ + + + === modified file 'debian/control' --- debian/control 2008-09-21 13:42:34 +0000 +++ debian/control 2008-09-30 03:19:39 +0000 @@ -2,11 +2,14 @@ Section: admin Priority: extra Maintainer: Mandos Maintainers +Uploaders: Teddy Hogeborn , + Björn Påhlsson Build-Depends: debhelper (>= 7), docbook-xsl, libavahi-core-dev, libgpgme11-dev, libgnutls-dev, xsltproc, po-debconf, pkg-config Standards-Version: 3.8.0 -Vcs-Bzr: ftp://anonymous@ftp.fukt.bsnet.se/pub/mandos/latest +Vcs-Bzr: http://ftp.fukt.bsnet.se/pub/mandos/trunk +Vcs-Browser: http://bzr.fukt.bsnet.se/loggerhead/mandos/trunk/files Homepage: http://www.fukt.bsnet.se/mandos Package: mandos === modified file 'debian/mandos-client.lintian-overrides' --- debian/mandos-client.lintian-overrides 2008-09-26 19:47:21 +0000 +++ debian/mandos-client.lintian-overrides 2008-09-30 19:05:13 +0000 @@ -1,5 +1,6 @@ mandos-client binary: manpage-has-errors-from-man usr/share/man/man8/plugin-runner.8mandos.gz 297: warning [p 4, 5.8i]: can't break line mandos-client binary: non-standard-dir-perm etc/keys/mandos/ 0700 != 0755 +mandos-client binary: non-standard-dir-perm etc/mandos/plugins.d/ 0700 != 0755 mandos-client binary: setuid-binary usr/lib/mandos/plugins.d/mandos-client 4755 root/root mandos-client binary: setuid-binary usr/lib/mandos/plugins.d/askpass-fifo 4755 root/root mandos-client binary: setuid-binary usr/lib/mandos/plugins.d/splashy 4755 root/root === modified file 'debian/rules' --- debian/rules 2008-09-21 12:04:02 +0000 +++ debian/rules 2008-09-30 18:59:44 +0000 @@ -72,6 +72,7 @@ dh_compress dh_fixperms --exclude etc/keys/mandos \ --exclude etc/mandos/clients.conf \ + --exclude etc/mandos/plugins.d \ --exclude usr/lib/mandos/plugins.d dh_installdeb dh_shlibdeps === modified file 'mandos' --- mandos 2008-09-19 20:42:17 +0000 +++ mandos 2008-09-26 21:54:54 +0000 @@ -34,7 +34,6 @@ import SocketServer import socket -import select from optparse import OptionParser import datetime import errno @@ -62,6 +61,7 @@ import avahi from dbus.mainloop.glib import DBusGMainLoop import ctypes +import ctypes.util version = "1.0" @@ -81,6 +81,7 @@ class AvahiError(Exception): def __init__(self, value): self.value = value + super(AvahiError, self).__init__() def __str__(self): return repr(self.value) @@ -108,11 +109,11 @@ a sensible number of times """ def __init__(self, interface = avahi.IF_UNSPEC, name = None, - type = None, port = None, TXT = None, domain = "", + servicetype = None, port = None, TXT = None, domain = "", host = "", max_renames = 32768): self.interface = interface self.name = name - self.type = type + self.type = servicetype self.port = port if TXT is None: self.TXT = [] @@ -127,7 +128,7 @@ if self.rename_count >= self.max_renames: logger.critical(u"No suitable Zeroconf service name found" u" after %i retries, exiting.", - rename_count) + self.rename_count) raise AvahiServiceError("Too many renames") self.name = server.GetAlternativeServiceName(self.name) logger.info(u"Changing Zeroconf service name to %r ...", @@ -222,10 +223,12 @@ interval = property(lambda self: self._interval, _set_interval) del _set_interval - def __init__(self, name = None, stop_hook=None, config={}): + def __init__(self, name = None, stop_hook=None, config=None): """Note: the 'checker' key in 'config' sets the 'checker_command' attribute and *not* the 'checker' attribute.""" + if config is None: + config = {} self.name = name logger.debug(u"Creating client %r", self.name) # Uppercase and remove spaces from fingerprint for later @@ -237,9 +240,9 @@ if "secret" in config: self.secret = config["secret"].decode(u"base64") elif "secfile" in config: - sf = open(config["secfile"]) - self.secret = sf.read() - sf.close() + secfile = open(config["secfile"]) + self.secret = secfile.read() + secfile.close() else: raise TypeError(u"No secret or secfile for client %s" % self.name) @@ -415,28 +418,28 @@ (crt, ctypes.byref(datum), gnutls.library.constants.GNUTLS_OPENPGP_FMT_RAW) # Verify the self signature in the key - crtverify = ctypes.c_uint(); + crtverify = ctypes.c_uint() gnutls.library.functions.gnutls_openpgp_crt_verify_self\ (crt, 0, ctypes.byref(crtverify)) if crtverify.value != 0: gnutls.library.functions.gnutls_openpgp_crt_deinit(crt) raise gnutls.errors.CertificateSecurityError("Verify failed") # New buffer for the fingerprint - buffer = ctypes.create_string_buffer(20) - buffer_length = ctypes.c_size_t() + buf = ctypes.create_string_buffer(20) + buf_len = ctypes.c_size_t() # Get the fingerprint from the certificate into the buffer gnutls.library.functions.gnutls_openpgp_crt_get_fingerprint\ - (crt, ctypes.byref(buffer), ctypes.byref(buffer_length)) + (crt, ctypes.byref(buf), ctypes.byref(buf_len)) # Deinit the certificate gnutls.library.functions.gnutls_openpgp_crt_deinit(crt) # Convert the buffer to a Python bytestring - fpr = ctypes.string_at(buffer, buffer_length.value) + fpr = ctypes.string_at(buf, buf_len.value) # Convert the bytestring to hexadecimal notation hex_fpr = u''.join(u"%02X" % ord(char) for char in fpr) return hex_fpr -class tcp_handler(SocketServer.BaseRequestHandler, object): +class TCP_handler(SocketServer.BaseRequestHandler, object): """A TCP request handler class. Instantiated by IPv6_TCPServer for each request to handle it. Note: This will run in its own forked process.""" @@ -469,7 +472,7 @@ if self.server.settings["priority"]: priority = self.server.settings["priority"] gnutls.library.functions.gnutls_priority_set_direct\ - (session._c_object, priority, None); + (session._c_object, priority, None) try: session.handshake() @@ -529,7 +532,7 @@ self.clients = kwargs["clients"] del kwargs["clients"] self.enabled = False - return super(type(self), self).__init__(*args, **kwargs) + super(IPv6_TCPServer, self).__init__(*args, **kwargs) def server_bind(self): """This overrides the normal server_bind() function to bind to an interface if one was specified, and also NOT to @@ -564,10 +567,10 @@ # if_nametoindex # (self.settings # ["interface"])) - return super(type(self), self).server_bind() + return super(IPv6_TCPServer, self).server_bind() def server_activate(self): if self.enabled: - return super(type(self), self).server_activate() + return super(IPv6_TCPServer, self).server_activate() def enable(self): self.enabled = True @@ -591,8 +594,8 @@ timevalue = datetime.timedelta(0) for s in interval.split(): try: - suffix=unicode(s[-1]) - value=int(s[:-1]) + suffix = unicode(s[-1]) + value = int(s[:-1]) if suffix == u"d": delta = datetime.timedelta(value) elif suffix == u"s": @@ -638,8 +641,6 @@ """Call the C function if_nametoindex(), or equivalent""" global if_nametoindex try: - if "ctypes.util" not in sys.modules: - import ctypes.util if_nametoindex = ctypes.cdll.LoadLibrary\ (ctypes.util.find_library("c")).if_nametoindex except (OSError, AttributeError): @@ -683,9 +684,6 @@ def main(): - global main_loop_started - main_loop_started = False - parser = OptionParser(version = "%%prog %s" % version) parser.add_option("-i", "--interface", type="string", metavar="IF", help="Bind to interface IF") @@ -706,7 +704,7 @@ default="/etc/mandos", metavar="DIR", help="Directory to search for configuration" " files") - (options, args) = parser.parse_args() + options = parser.parse_args()[0] if options.check: import doctest @@ -769,7 +767,7 @@ clients = Set() tcp_server = IPv6_TCPServer((server_settings["address"], server_settings["port"]), - tcp_handler, + TCP_handler, settings=server_settings, clients=clients) pidfilename = "/var/run/mandos.pid" @@ -803,7 +801,7 @@ global service service = AvahiService(name = server_settings["servicename"], - type = "_mandos._tcp", ); + servicetype = "_mandos._tcp", ) if server_settings["interface"]: service.interface = if_nametoindex\ (server_settings["interface"]) @@ -852,7 +850,7 @@ pidfile.write(str(pid) + "\n") pidfile.close() del pidfile - except IOError, err: + except IOError: logger.error(u"Could not write to file %r with PID %d", pidfilename, pid) except NameError: @@ -910,7 +908,6 @@ (*args[2:], **kwargs) or True) logger.debug(u"Starting main loop") - main_loop_started = True main_loop.run() except AvahiError, error: logger.critical(u"AvahiError: %s" + unicode(error)) === modified file 'mandos-clients.conf.xml' --- mandos-clients.conf.xml 2008-09-12 19:12:40 +0000 +++ mandos-clients.conf.xml 2008-09-30 07:23:39 +0000 @@ -1,10 +1,11 @@ /etc/mandos/clients.conf"> - + + +%common; ]> @@ -12,7 +13,7 @@ Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP; === modified file 'mandos-keygen.xml' --- mandos-keygen.xml 2008-09-19 23:31:34 +0000 +++ mandos-keygen.xml 2008-09-30 07:23:39 +0000 @@ -1,9 +1,10 @@ - + + +%common; ]> @@ -11,7 +12,7 @@ Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP; === modified file 'mandos-options.xml' --- mandos-options.xml 2008-09-06 16:31:49 +0000 +++ mandos-options.xml 2008-09-30 03:19:39 +0000 @@ -58,8 +58,8 @@ Zeroconf service name. The default is Mandos. This only needs to be - changed this if it, for some reason, is necessary to run more than - one server on the same host, which would not + changed if for some reason is would be necessary to run more than + one server on the same host. This would not normally be useful. If there are name collisions on the same network, the newer server will automatically rename itself to Mandos #2, and === modified file 'mandos.conf.xml' --- mandos.conf.xml 2008-09-12 19:12:40 +0000 +++ mandos.conf.xml 2008-09-30 07:23:39 +0000 @@ -1,10 +1,11 @@ /etc/mandos/mandos.conf"> - + + +%common; ]> @@ -12,7 +13,7 @@ Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP; === modified file 'mandos.xml' --- mandos.xml 2008-09-21 12:20:55 +0000 +++ mandos.xml 2008-09-30 07:23:39 +0000 @@ -1,17 +1,18 @@ - + + +%common; ]> - + Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP; === modified file 'plugin-runner.c' --- plugin-runner.c 2008-09-26 04:54:35 +0000 +++ plugin-runner.c 2008-09-30 07:23:39 +0000 @@ -69,7 +69,7 @@ #define PDIR "/lib/mandos/plugins.d" #define AFILE "/conf/conf.d/mandos/plugin-runner.conf" -const char *argp_program_version = "plugin-runner 1.0"; +const char *argp_program_version = "plugin-runner " VERSION; const char *argp_program_bug_address = ""; typedef struct plugin{ === modified file 'plugin-runner.xml' --- plugin-runner.xml 2008-09-19 00:00:51 +0000 +++ plugin-runner.xml 2008-09-30 07:23:39 +0000 @@ -1,9 +1,10 @@ - + + +%common; ]> @@ -11,7 +12,7 @@ Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP; === modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2008-09-19 20:42:17 +0000 +++ plugins.d/mandos-client.c 2008-09-30 07:23:39 +0000 @@ -101,17 +101,13 @@ #define BUFFER_SIZE 256 -/* - #define PATHDIR "/conf/conf.d/mandos" -*/ - #define PATHDIR "/conf/conf.d/mandos" #define SECKEY "seckey.txt" #define PUBKEY "pubkey.txt" bool debug = false; static const char mandos_protocol_version[] = "1"; -const char *argp_program_version = "mandos-client 1.0"; +const char *argp_program_version = "mandos-client " VERSION; const char *argp_program_bug_address = ""; /* Used for passing in values through the Avahi callback functions */ === modified file 'plugins.d/mandos-client.xml' --- plugins.d/mandos-client.xml 2008-09-12 19:12:40 +0000 +++ plugins.d/mandos-client.xml 2008-09-30 07:23:39 +0000 @@ -1,17 +1,18 @@ - + + +%common; ]> Mandos Manual - + Mandos - &VERSION; + &version; &TIMESTAMP; @@ -449,11 +450,11 @@ The only remaining weak point is that someone with physical access to the client hard drive might turn off the client computer, read the OpenPGP keys directly from the hard drive, - and communicate with the server. The defense against this is - that the server is supposed to notice the client disappearing - and will stop giving out the encrypted data. Therefore, it is - important to set the timeout and checker interval values tightly - on the server. See mandos8. === modified file 'plugins.d/password-prompt.c' --- plugins.d/password-prompt.c 2008-09-19 20:42:17 +0000 +++ plugins.d/password-prompt.c 2008-09-30 07:23:39 +0000 @@ -52,7 +52,7 @@ volatile bool quit_now = false; bool debug = false; -const char *argp_program_version = "password-prompt 1.0"; +const char *argp_program_version = "password-prompt " VERSION; const char *argp_program_bug_address = ""; static void termination_handler(__attribute__((unused))int signum){ === modified file 'plugins.d/password-prompt.xml' --- plugins.d/password-prompt.xml 2008-09-06 16:31:49 +0000 +++ plugins.d/password-prompt.xml 2008-09-30 07:23:39 +0000 @@ -1,9 +1,10 @@ - + + +%common; ]> @@ -11,7 +12,7 @@ Mandos Manual Mandos - &VERSION; + &version; &TIMESTAMP;