=== modified file 'Makefile' --- Makefile 2009-01-10 05:41:16 +0000 +++ Makefile 2009-01-15 04:21:32 +0000 @@ -77,7 +77,7 @@ PLUGINS=plugins.d/password-prompt plugins.d/mandos-client \ plugins.d/usplash plugins.d/splashy plugins.d/askpass-fifo CPROGS=plugin-runner $(PLUGINS) -PROGS=mandos mandos-keygen $(CPROGS) +PROGS=mandos mandos-keygen mandos-ctl $(CPROGS) DOCS=mandos.8 plugin-runner.8mandos mandos-keygen.8 \ plugins.d/mandos-client.8mandos \ plugins.d/password-prompt.8mandos mandos.conf.5 \ @@ -164,6 +164,11 @@ --expression='s/^\(VERSION="\)[^"]*"$$/\1$(version)"/' \ $@ +mandos-ctl: Makefile + $(SED) --in-place \ + --expression='s/^\(version = "\)[^"]*"$$/\1$(version)"/' \ + $@ + mandos.lsm: Makefile $(SED) --in-place \ --expression='s/^\(Version:\).*/\1\t$(version)/' \ === modified file 'README' --- README 2009-01-04 21:54:55 +0000 +++ README 2009-01-12 22:02:33 +0000 @@ -152,8 +152,6 @@ 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. === modified file 'TODO' --- TODO 2008-12-29 02:44:54 +0000 +++ TODO 2009-01-12 22:02:33 +0000 @@ -55,11 +55,14 @@ * [#A] Package ** /usr/share/initramfs-tools/hooks/mandos -*** TODO Do not install in initrd.img if configured not to. +*** TODO [#C] Do not install in initrd.img if configured not to. Use "/etc/initramfs-tools/conf.d/mandos"? Definitely a debconf question. -** TODO /etc/bash_completion.d/mandos +** TODO [#C] /etc/bash_completion.d/mandos From XML sources directly? +** TODO initramfs-tools-script :test: + Do not insert plugin-runner as keyscript if a kernel parameter + "mandos=off" is passed. #+STARTUP: showall === modified file 'debian/mandos-client.README.Debian' --- debian/mandos-client.README.Debian 2008-10-05 17:38:31 +0000 +++ debian/mandos-client.README.Debian 2009-01-15 02:52:02 +0000 @@ -42,4 +42,10 @@ Mandos client will be the new default way for getting a password for the root file system when booting. - -- Teddy Hogeborn , Sun, 5 Oct 2008 19:04:26 +0200 +* Emergency Escape + + If it ever should be necessary, the Mandos client can be temporarily + prevented from running at startup by passing the parameter + "mandos=off" to the kernel. + + -- Teddy Hogeborn , Mon, 12 Jan 2009 02:29:10 +0100 === added file 'debian/watch' --- debian/watch 1970-01-01 00:00:00 +0000 +++ debian/watch 2009-01-15 02:52:02 +0000 @@ -0,0 +1,2 @@ +version=3 +ftp://ftp.fukt.bsnet.se/pub/mandos/mandos[-_]([^\s]+?)(?:\.orig)?\.tar\.(?:gz|bz2|7z) === modified file 'initramfs-tools-script' --- initramfs-tools-script 2008-09-07 15:42:11 +0000 +++ initramfs-tools-script 2009-01-15 02:52:02 +0000 @@ -24,6 +24,12 @@ ;; esac +for param in `cat /proc/cmdline`; do + case "$param" in + mandos=off) exit 0;; + esac +done + chmod a=rwxt /tmp test -w /conf/conf.d/cryptroot === modified file 'mandos' --- mandos 2009-01-10 05:41:16 +0000 +++ mandos 2009-01-15 04:21:32 +0000 @@ -911,7 +911,7 @@ " files") parser.add_option("--no-dbus", action="store_false", dest="use_dbus", - help=optparse.SUPPRESS_HELP) + help=optparse.SUPPRESS_HELP) # XXX: Not done yet options = parser.parse_args()[0] if options.check: @@ -957,7 +957,7 @@ # For convenience debug = server_settings["debug"] use_dbus = server_settings["use_dbus"] - use_dbus = False + use_dbus = False # XXX: Not done yet if not debug: syslogger.setLevel(logging.WARNING) === added file 'mandos-ctl' --- mandos-ctl 1970-01-01 00:00:00 +0000 +++ mandos-ctl 2009-01-15 04:21:32 +0000 @@ -0,0 +1,187 @@ +#!/usr/bin/python +# -*- mode: python; coding: utf-8 -*- + +from __future__ import division +import sys +import dbus +from optparse import OptionParser +import locale +import datetime +import re + +locale.setlocale(locale.LC_ALL, u'') + +tablewords = { + 'name': u'Name', + 'enabled': u'Enabled', + 'timeout': u'Timeout', + 'last_checked_ok': u'Last Successful Check', + 'created': u'Created', + 'interval': u'Interval', + 'host': u'Host', + 'fingerprint': u'Fingerprint', + 'checker_running': u'Check Is Running', + 'last_enabled': u'Last Enabled', + 'checker': u'Checker', + } +defaultkeywords = ('name', 'enabled', 'timeout', 'last_checked_ok', + 'checker') +busname = 'org.mandos-system.Mandos' +server_path = '/Mandos' +server_interface = 'org.mandos_system.Mandos' +client_interface = 'org.mandos_system.Mandos.Client' +version = "1.0.2" + +bus = dbus.SystemBus() +mandos_dbus_objc = bus.get_object(busname, server_path) +mandos_serv = dbus.Interface(mandos_dbus_objc, + dbus_interface = server_interface) +mandos_clients = mandos_serv.GetAllClientsWithProperties() + +def datetime_to_milliseconds(dt): + "Return the 'timeout' attribute in milliseconds" + return ((dt.days * 24 * 60 * 60 * 1000) + + (dt.seconds * 1000) + + (dt.microseconds // 1000)) + +def milliseconds_to_string(ms): + td = datetime.timedelta(0, 0, 0, ms) + return "%s%02d:%02d:%02d" % (("%dT" % td.days) if td.days else "", # days + td.seconds // 3600, # hours + (td.seconds % 3600) // 60, # minutes + (td.seconds % 60)) # seconds + + +def string_to_delta(interval): + """Parse a string and return a datetime.timedelta + + >>> string_to_delta('7d') + datetime.timedelta(7) + >>> string_to_delta('60s') + datetime.timedelta(0, 60) + >>> string_to_delta('60m') + datetime.timedelta(0, 3600) + >>> string_to_delta('24h') + datetime.timedelta(1) + >>> string_to_delta(u'1w') + datetime.timedelta(7) + >>> string_to_delta('5m 30s') + datetime.timedelta(0, 330) + """ + timevalue = datetime.timedelta(0) + regexp = re.compile("\d+[dsmhw]") + + for s in regexp.findall(interval): + try: + suffix = unicode(s[-1]) + value = int(s[:-1]) + if suffix == u"d": + delta = datetime.timedelta(value) + elif suffix == u"s": + delta = datetime.timedelta(0, value) + elif suffix == u"m": + delta = datetime.timedelta(0, 0, 0, 0, value) + elif suffix == u"h": + delta = datetime.timedelta(0, 0, 0, 0, 0, value) + elif suffix == u"w": + delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value) + else: + raise ValueError + except (ValueError, IndexError): + raise ValueError + timevalue += delta + return timevalue + +def print_clients(clients): + def valuetostring(value, keyword): + if type(value) is dbus.Boolean: + return u"Yes" if value else u"No" + if keyword in ("timeout", "interval"): + return milliseconds_to_string(value) + return unicode(value) + + format_string = u' '.join(u'%%-%ds' % + max(len(tablewords[key]), + max(len(valuetostring(client[key], key)) + for client in + clients)) + for key in keywords) + print format_string % tuple(tablewords[key] for key in keywords) + for client in clients: + print format_string % tuple(valuetostring(client[key], key) + for key in keywords) + +parser = OptionParser(version = "%%prog %s" % version) +parser.add_option("-a", "--all", action="store_true", + help="Print all fields") +parser.add_option("-e", "--enable", action="store_true", + help="Enable specified client") +parser.add_option("-d", "--disable", action="store_true", + help="disable specified client") +parser.add_option("-b", "--bump-timeout", action="store_true", + help="Bump timeout of specified client") +parser.add_option("--start-checker", action="store_true", + help="Start checker for specified client") +parser.add_option("--stop-checker", action="store_true", + help="Stop checker for specified client") +parser.add_option("-v", "--is-valid", action="store_true", + help="Stop checker for specified client") +parser.add_option("-c", "--checker", type="string", + help="Set checker command for specified client") +parser.add_option("-t", "--timeout", type="string", + help="Set timeout for specified client") +parser.add_option("-i", "--interval", type="string", + help="Set checker interval for specified client") +parser.add_option("-H", "--host", type="string", + help="Set host for specified client") +parser.add_option("-s", "--secret", type="string", + help="Set password blob (file) for specified client") +options, client_names = parser.parse_args() + +clients=[] +for name in client_names: + for path, client in mandos_clients.iteritems(): + if client['name'] == name: + client_objc = bus.get_object(busname, path) + clients.append(dbus.Interface(client_objc, + dbus_interface + = client_interface)) + break + else: + print >> sys.stderr, "Client not found on server: %r" % name + sys.exit(1) + +if not clients: + keywords = defaultkeywords + if options.all: + keywords = ('name', 'enabled', 'timeout', 'last_checked_ok', + 'created', 'interval', 'host', 'fingerprint', + 'checker_running', 'last_enabled', 'checker') + print_clients(mandos_clients.values()) + +for client in clients: + if options.enable: + client.Enable() + if options.disable: + client.Disable() + if options.bump_timeout: + client.BumpTimeout() + if options.start_checker: + client.StartChecker() + if options.stop_checker: + client.StopChecker() + if options.is_valid: + sys.exit(0 if client.IsStillValid() else 1) + if options.checker: + client.SetChecker(options.checker) + if options.host: + client.SetHost(options.host) + if options.interval: + client.SetInterval(datetime_to_milliseconds + (string_to_delta(options.interval))) + if options.timeout: + client.SetTimeout(datetime_to_milliseconds + (string_to_delta(options.timeout))) + if options.secret: + client.SetSecret(dbus.ByteArray(open(options.secret, 'rb').read())) + === modified file 'plugin-runner.c' --- plugin-runner.c 2009-01-06 22:49:50 +0000 +++ plugin-runner.c 2009-01-14 14:20:17 +0000 @@ -64,6 +64,7 @@ sigprocmask(), SIG_BLOCK, SIGCHLD, SIG_UNBLOCK, kill() */ #include /* errno, EBADF */ +#include /* intmax_t, SCNdMAX, PRIdMAX, */ #define BUFFER_SIZE 256 @@ -99,15 +100,15 @@ or if none is found, creates a new one */ static plugin *getplugin(char *name){ /* Check for exiting plugin with that name */ - for (plugin *p = plugin_list; p != NULL; p = p->next){ - if ((p->name == name) - or (p->name and name and (strcmp(p->name, name) == 0))){ + for(plugin *p = plugin_list; p != NULL; p = p->next){ + if((p->name == name) + or (p->name and name and (strcmp(p->name, name) == 0))){ return p; } } /* Create a new plugin */ plugin *new_plugin = malloc(sizeof(plugin)); - if (new_plugin == NULL){ + if(new_plugin == NULL){ return NULL; } char *copy_name = NULL; @@ -124,7 +125,7 @@ .next = plugin_list }; new_plugin->argv = malloc(sizeof(char *) * 2); - if (new_plugin->argv == NULL){ + if(new_plugin->argv == NULL){ free(copy_name); free(new_plugin); return NULL; @@ -230,7 +231,7 @@ break; } if(pid == -1){ - if (errno != ECHILD){ + if(errno != ECHILD){ perror("waitpid"); } /* No child processes */ @@ -308,8 +309,9 @@ struct dirent *dirst; struct stat st; fd_set rfds_all; - int ret, maxfd = 0; + int ret, numchars, maxfd = 0; ssize_t sret; + intmax_t tmpmax; uid_t uid = 65534; gid_t gid = 65534; bool debug = false; @@ -372,11 +374,11 @@ { .name = NULL } }; - error_t parse_opt (int key, char *arg, __attribute__((unused)) - struct argp_state *state) { - switch (key) { + error_t parse_opt(int key, char *arg, __attribute__((unused)) + struct argp_state *state) { + switch(key) { case 'g': /* --global-options */ - if (arg != NULL){ + if(arg != NULL){ char *p; while((p = strsep(&arg, ",")) != NULL){ if(p[0] == '\0'){ @@ -398,7 +400,7 @@ } break; case 'o': /* --options-for */ - if (arg != NULL){ + if(arg != NULL){ char *p_name = strsep(&arg, ":"); if(p_name[0] == '\0' or arg == NULL){ break; @@ -435,7 +437,7 @@ } break; case 'd': /* --disable */ - if (arg != NULL){ + if(arg != NULL){ plugin *p = getplugin(arg); if(p == NULL){ return ARGP_ERR_UNKNOWN; @@ -444,7 +446,7 @@ } break; case 'e': /* --enable */ - if (arg != NULL){ + if(arg != NULL){ plugin *p = getplugin(arg); if(p == NULL){ return ARGP_ERR_UNKNOWN; @@ -463,14 +465,32 @@ /* This is already done by parse_opt_config_file() */ break; case 130: /* --userid */ - uid = (uid_t)strtol(arg, NULL, 10); + ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars); + if(ret < 1 or tmpmax != (uid_t)tmpmax + or arg[numchars] != '\0'){ + fprintf(stderr, "Bad user ID number: \"%s\", using %" + PRIdMAX "\n", arg, (intmax_t)uid); + } else { + uid = (uid_t)tmpmax; + } break; case 131: /* --groupid */ - gid = (gid_t)strtol(arg, NULL, 10); + ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars); + if(ret < 1 or tmpmax != (gid_t)tmpmax + or arg[numchars] != '\0'){ + fprintf(stderr, "Bad group ID number: \"%s\", using %" + PRIdMAX "\n", arg, (intmax_t)gid); + } else { + gid = (gid_t)tmpmax; + } break; case 132: /* --debug */ debug = true; break; +/* + * When adding more options before this line, remember to also add a + * "case" to the "parse_opt_config_file" function below. + */ case ARGP_KEY_ARG: /* Cryptsetup always passes an argument, which is an empty string if "none" was specified in /etc/crypttab. So if @@ -489,10 +509,10 @@ /* This option parser is the same as parse_opt() above, except it ignores everything but the --config-file option. */ - error_t parse_opt_config_file (int key, char *arg, - __attribute__((unused)) - struct argp_state *state) { - switch (key) { + error_t parse_opt_config_file(int key, char *arg, + __attribute__((unused)) + struct argp_state *state) { + switch(key) { case 'g': /* --global-options */ case 'G': /* --global-env */ case 'o': /* --options-for */ @@ -525,10 +545,10 @@ .args_doc = "", .doc = "Mandos plugin runner -- Run plugins" }; - /* Parse using the parse_opt_config_file in order to get the custom + /* Parse using parse_opt_config_file() in order to get the custom config file location, if any. */ - ret = argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, NULL); - if (ret == ARGP_ERR_UNKNOWN){ + ret = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, 0, NULL); + if(ret == ARGP_ERR_UNKNOWN){ fprintf(stderr, "Unknown error while parsing arguments\n"); exitstatus = EXIT_FAILURE; goto fallback; @@ -538,7 +558,7 @@ argp.parser = parse_opt; /* Open the configfile if available */ - if (argfile == NULL){ + if(argfile == NULL){ conffp = fopen(AFILE, "r"); } else { conffp = fopen(argfile, "r"); @@ -599,7 +619,7 @@ } else { /* Check for harmful errors and go to fallback. Other errors might not affect opening plugins */ - if (errno == EMFILE or errno == ENFILE or errno == ENOMEM){ + if(errno == EMFILE or errno == ENFILE or errno == ENOMEM){ perror("fopen"); exitstatus = EXIT_FAILURE; goto fallback; @@ -608,9 +628,9 @@ /* If there was any arguments from configuration file, pass them to parser as command arguments */ if(custom_argv != NULL){ - ret = argp_parse (&argp, custom_argc, custom_argv, ARGP_IN_ORDER, - 0, NULL); - if (ret == ARGP_ERR_UNKNOWN){ + ret = argp_parse(&argp, custom_argc, custom_argv, ARGP_IN_ORDER, + 0, NULL); + if(ret == ARGP_ERR_UNKNOWN){ fprintf(stderr, "Unknown error while parsing arguments\n"); exitstatus = EXIT_FAILURE; goto fallback; @@ -619,8 +639,8 @@ /* Parse actual command line arguments, to let them override the config file */ - ret = argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, NULL); - if (ret == ARGP_ERR_UNKNOWN){ + ret = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, 0, NULL); + if(ret == ARGP_ERR_UNKNOWN){ fprintf(stderr, "Unknown error while parsing arguments\n"); exitstatus = EXIT_FAILURE; goto fallback; @@ -633,7 +653,7 @@ for(char **a = p->argv; *a != NULL; a++){ fprintf(stderr, "\tArg: %s\n", *a); } - fprintf(stderr, "...and %u environment variables\n", p->envc); + fprintf(stderr, "...and %d environment variables\n", p->envc); for(char **a = p->environ; *a != NULL; a++){ fprintf(stderr, "\t%s\n", *a); } @@ -642,15 +662,15 @@ /* Strip permissions down to nobody */ ret = setuid(uid); - if (ret == -1){ + if(ret == -1){ perror("setuid"); } setgid(gid); - if (ret == -1){ + if(ret == -1){ perror("setgid"); } - if (plugindir == NULL){ + if(plugindir == NULL){ dir = opendir(PDIR); } else { dir = opendir(plugindir); @@ -683,7 +703,7 @@ /* All directory entries have been processed */ if(dirst == NULL){ - if (errno == EBADF){ + if(errno == EBADF){ perror("readdir"); exitstatus = EXIT_FAILURE; goto fallback; @@ -749,14 +769,14 @@ } ret = stat(filename, &st); - if (ret == -1){ + if(ret == -1){ perror("stat"); free(filename); continue; } /* Ignore non-executable files */ - if (not S_ISREG(st.st_mode) or (access(filename, X_OK) != 0)){ + if(not S_ISREG(st.st_mode) or (access(filename, X_OK) != 0)){ if(debug){ fprintf(stderr, "Ignoring plugin dir entry \"%s\"" " with bad type or mode\n", filename); @@ -809,7 +829,7 @@ int pipefd[2]; ret = pipe(pipefd); - if (ret == -1){ + if(ret == -1){ perror("pipe"); exitstatus = EXIT_FAILURE; goto fallback; @@ -828,7 +848,7 @@ goto fallback; } /* Block SIGCHLD until process is safely in process list */ - ret = sigprocmask (SIG_BLOCK, &sigchld_action.sa_mask, NULL); + ret = sigprocmask(SIG_BLOCK, &sigchld_action.sa_mask, NULL); if(ret < 0){ perror("sigprocmask"); exitstatus = EXIT_FAILURE; @@ -882,9 +902,9 @@ close(pipefd[1]); /* Close unused write end of pipe */ free(filename); plugin *new_plugin = getplugin(dirst->d_name); - if (new_plugin == NULL){ + if(new_plugin == NULL){ perror("getplugin"); - ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); + ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); if(ret < 0){ perror("sigprocmask"); } @@ -897,7 +917,7 @@ /* Unblock SIGCHLD so signal handler can be run if this process has already completed */ - ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); + ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); if(ret < 0){ perror("sigprocmask"); exitstatus = EXIT_FAILURE; @@ -906,7 +926,7 @@ FD_SET(new_plugin->fd, &rfds_all); - if (maxfd < new_plugin->fd){ + if(maxfd < new_plugin->fd){ maxfd = new_plugin->fd; } } @@ -929,7 +949,7 @@ while(plugin_list){ fd_set rfds = rfds_all; int select_ret = select(maxfd+1, &rfds, NULL, NULL, NULL); - if (select_ret == -1){ + if(select_ret == -1){ perror("select"); exitstatus = EXIT_FAILURE; goto fallback; @@ -946,16 +966,16 @@ if(debug){ if(WIFEXITED(proc->status)){ - fprintf(stderr, "Plugin %u exited with status %d\n", - (unsigned int) (proc->pid), + fprintf(stderr, "Plugin %" PRIdMAX " exited with status" + " %d\n", (intmax_t) (proc->pid), WEXITSTATUS(proc->status)); } else if(WIFSIGNALED(proc->status)) { - fprintf(stderr, "Plugin %u killed by signal %d\n", - (unsigned int) (proc->pid), + fprintf(stderr, "Plugin %" PRIdMAX " killed by signal" + " %d\n", (intmax_t) (proc->pid), WTERMSIG(proc->status)); } else if(WCOREDUMP(proc->status)){ - fprintf(stderr, "Plugin %d dumped core\n", - (unsigned int) (proc->pid)); + fprintf(stderr, "Plugin %" PRIdMAX " dumped core\n", + (intmax_t) (proc->pid)); } } @@ -975,8 +995,8 @@ proc = next_plugin; /* We are done modifying process list, so unblock signal */ - ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, - NULL); + ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, + NULL); if(ret < 0){ perror("sigprocmask"); exitstatus = EXIT_FAILURE; @@ -1011,7 +1031,7 @@ if(proc->buffer_length + BUFFER_SIZE > proc->buffer_size){ proc->buffer = realloc(proc->buffer, proc->buffer_size + (size_t) BUFFER_SIZE); - if (proc->buffer == NULL){ + if(proc->buffer == NULL){ perror("malloc"); exitstatus = EXIT_FAILURE; goto fallback; === modified file 'plugins.d/askpass-fifo.c' --- plugins.d/askpass-fifo.c 2009-01-10 02:21:13 +0000 +++ plugins.d/askpass-fifo.c 2009-01-10 06:00:50 +0000 @@ -1,6 +1,6 @@ /* -*- coding: utf-8 -*- */ /* - * Passprompt - Read a password from a FIFO and output it + * Askpass-FIFO - Read a password from a FIFO and output it * * Copyright © 2008,2009 Teddy Hogeborn * Copyright © 2008,2009 Björn Påhlsson === modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2009-01-10 02:21:13 +0000 +++ plugins.d/mandos-client.c 2009-01-14 14:20:17 +0000 @@ -1,6 +1,6 @@ /* -*- coding: utf-8 -*- */ /* - * Mandos client - get and decrypt data from a Mandos server + * Mandos-client - get and decrypt data from a Mandos server * * This program is partly derived from an example program for an Avahi * service browser, downloaded from @@ -36,7 +36,7 @@ #define _GNU_SOURCE /* TEMP_FAILURE_RETRY(), asprintf() */ #include /* fprintf(), stderr, fwrite(), - stdout, ferror() */ + stdout, ferror(), sscanf */ #include /* uint16_t, uint32_t */ #include /* NULL, size_t, ssize_t */ #include /* free(), EXIT_SUCCESS, EXIT_FAILURE, @@ -48,14 +48,16 @@ #include /* socket(), inet_pton(), sockaddr, sockaddr_in6, PF_INET6, SOCK_STREAM, INET6_ADDRSTRLEN, - uid_t, gid_t, open(), opendir(), DIR */ + uid_t, gid_t, open(), opendir(), + DIR */ #include /* open() */ #include /* socket(), struct sockaddr_in6, struct in6_addr, inet_pton(), connect() */ #include /* open() */ -#include /* opendir(), struct dirent, readdir() */ -#include /* PRIu16 */ +#include /* opendir(), struct dirent, readdir() + */ +#include /* PRIu16, intmax_t, SCNdMAX */ #include /* assert() */ #include /* perror(), errno */ #include /* time() */ @@ -67,7 +69,7 @@ getuid(), getgid(), setuid(), setgid() */ #include /* inet_pton(), htons */ -#include /* not, and */ +#include /* not, and, or */ #include /* struct argp_option, error_t, struct argp_state, struct argp, argp_parse(), ARGP_KEY_ARG, @@ -90,7 +92,8 @@ gnutls_* init_gnutls_session(), GNUTLS_* */ -#include /* gnutls_certificate_set_openpgp_key_file(), +#include + /* gnutls_certificate_set_openpgp_key_file(), GNUTLS_OPENPGP_FMT_BASE64 */ /* GPGME */ @@ -129,9 +132,9 @@ */ size_t adjustbuffer(char **buffer, size_t buffer_length, size_t buffer_capacity){ - if (buffer_length + BUFFER_SIZE > buffer_capacity){ + if(buffer_length + BUFFER_SIZE > buffer_capacity){ *buffer = realloc(*buffer, buffer_capacity + BUFFER_SIZE); - if (buffer == NULL){ + if(buffer == NULL){ return 0; } buffer_capacity += BUFFER_SIZE; @@ -163,14 +166,14 @@ } rc = gpgme_data_new_from_fd(&pgp_data, fd); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_data_new_from_fd: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } rc = gpgme_op_import(mc->ctx, pgp_data); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_op_import: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; @@ -184,22 +187,22 @@ return true; } - if (debug){ + if(debug){ fprintf(stderr, "Initialize gpgme\n"); } /* Init GPGME */ gpgme_check_version(NULL); rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } /* Set GPGME home directory for the OpenPGP engine only */ - rc = gpgme_get_engine_info (&engine_info); - if (rc != GPG_ERR_NO_ERROR){ + rc = gpgme_get_engine_info(&engine_info); + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; @@ -219,13 +222,13 @@ /* Create new GPGME "context" */ rc = gpgme_new(&(mc->ctx)); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_new: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } - if (not import_key(pubkey) or not import_key(seckey)){ + if(not import_key(pubkey) or not import_key(seckey)){ return false; } @@ -236,24 +239,24 @@ * Decrypt OpenPGP data. * Returns -1 on error */ -static ssize_t pgp_packet_decrypt (const mandos_context *mc, - const char *cryptotext, - size_t crypto_size, - char **plaintext){ +static ssize_t pgp_packet_decrypt(const mandos_context *mc, + const char *cryptotext, + size_t crypto_size, + char **plaintext){ gpgme_data_t dh_crypto, dh_plain; gpgme_error_t rc; ssize_t ret; size_t plaintext_capacity = 0; ssize_t plaintext_length = 0; - if (debug){ + if(debug){ fprintf(stderr, "Trying to decrypt OpenPGP data\n"); } /* Create new GPGME data buffer from memory cryptotext */ rc = gpgme_data_new_from_mem(&dh_crypto, cryptotext, crypto_size, 0); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return -1; @@ -261,7 +264,7 @@ /* Create new empty GPGME data buffer for the plaintext */ rc = gpgme_data_new(&dh_plain); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_data_new: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); gpgme_data_release(dh_crypto); @@ -271,14 +274,14 @@ /* Decrypt data from the cryptotext data buffer to the plaintext data buffer */ rc = gpgme_op_decrypt(mc->ctx, dh_crypto, dh_plain); - if (rc != GPG_ERR_NO_ERROR){ + if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); plaintext_length = -1; - if (debug){ + if(debug){ gpgme_decrypt_result_t result; result = gpgme_op_decrypt_result(mc->ctx); - if (result == NULL){ + if(result == NULL){ fprintf(stderr, "gpgme_op_decrypt_result failed\n"); } else { fprintf(stderr, "Unsupported algorithm: %s\n", @@ -311,7 +314,7 @@ } /* Seek back to the beginning of the GPGME plaintext data buffer */ - if (gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET) == -1){ + if(gpgme_data_seek(dh_plain, (off_t)0, SEEK_SET) == -1){ perror("gpgme_data_seek"); plaintext_length = -1; goto decrypt_end; @@ -322,7 +325,7 @@ plaintext_capacity = adjustbuffer(plaintext, (size_t)plaintext_length, plaintext_capacity); - if (plaintext_capacity == 0){ + if(plaintext_capacity == 0){ perror("adjustbuffer"); plaintext_length = -1; goto decrypt_end; @@ -331,7 +334,7 @@ ret = gpgme_data_read(dh_plain, *plaintext + plaintext_length, BUFFER_SIZE); /* Print the data, if any */ - if (ret == 0){ + if(ret == 0){ /* EOF */ break; } @@ -361,9 +364,10 @@ return plaintext_length; } -static const char * safer_gnutls_strerror (int value) { - const char *ret = gnutls_strerror (value); /* Spurious warning */ - if (ret == NULL) +static const char * safer_gnutls_strerror(int value) { + const char *ret = gnutls_strerror(value); /* Spurious warning from + -Wunreachable-code */ + if(ret == NULL) ret = "(unknown)"; return ret; } @@ -384,13 +388,13 @@ } ret = gnutls_global_init(); - if (ret != GNUTLS_E_SUCCESS) { - fprintf (stderr, "GnuTLS global_init: %s\n", - safer_gnutls_strerror(ret)); + if(ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "GnuTLS global_init: %s\n", + safer_gnutls_strerror(ret)); return -1; } - if (debug){ + if(debug){ /* "Use a log level over 10 to enable all debugging options." * - GnuTLS manual */ @@ -400,11 +404,13 @@ /* OpenPGP credentials */ gnutls_certificate_allocate_credentials(&mc->cred); - if (ret != GNUTLS_E_SUCCESS){ - fprintf (stderr, "GnuTLS memory error: %s\n", /* Spurious - warning */ - safer_gnutls_strerror(ret)); - gnutls_global_deinit (); + if(ret != GNUTLS_E_SUCCESS){ + fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious warning + * from + * -Wunreachable-code + */ + safer_gnutls_strerror(ret)); + gnutls_global_deinit(); return -1; } @@ -417,7 +423,7 @@ ret = gnutls_certificate_set_openpgp_key_file (mc->cred, pubkeyfilename, seckeyfilename, GNUTLS_OPENPGP_FMT_BASE64); - if (ret != GNUTLS_E_SUCCESS) { + if(ret != GNUTLS_E_SUCCESS) { fprintf(stderr, "Error[%d] while reading the OpenPGP key pair ('%s'," " '%s')\n", ret, pubkeyfilename, seckeyfilename); @@ -428,15 +434,15 @@ /* GnuTLS server initialization */ ret = gnutls_dh_params_init(&mc->dh_params); - if (ret != GNUTLS_E_SUCCESS) { - fprintf (stderr, "Error in GnuTLS DH parameter initialization:" - " %s\n", safer_gnutls_strerror(ret)); + if(ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "Error in GnuTLS DH parameter initialization:" + " %s\n", safer_gnutls_strerror(ret)); goto globalfail; } ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits); - if (ret != GNUTLS_E_SUCCESS) { - fprintf (stderr, "Error in GnuTLS prime generation: %s\n", - safer_gnutls_strerror(ret)); + if(ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "Error in GnuTLS prime generation: %s\n", + safer_gnutls_strerror(ret)); goto globalfail; } @@ -457,7 +463,7 @@ int ret; /* GnuTLS session creation */ ret = gnutls_init(session, GNUTLS_SERVER); - if (ret != GNUTLS_E_SUCCESS){ + if(ret != GNUTLS_E_SUCCESS){ fprintf(stderr, "Error in GnuTLS session initialization: %s\n", safer_gnutls_strerror(ret)); } @@ -465,29 +471,29 @@ { const char *err; ret = gnutls_priority_set_direct(*session, mc->priority, &err); - if (ret != GNUTLS_E_SUCCESS) { + if(ret != GNUTLS_E_SUCCESS) { fprintf(stderr, "Syntax error at: %s\n", err); fprintf(stderr, "GnuTLS error: %s\n", safer_gnutls_strerror(ret)); - gnutls_deinit (*session); + gnutls_deinit(*session); return -1; } } ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, mc->cred); - if (ret != GNUTLS_E_SUCCESS) { + if(ret != GNUTLS_E_SUCCESS) { fprintf(stderr, "Error setting GnuTLS credentials: %s\n", safer_gnutls_strerror(ret)); - gnutls_deinit (*session); + gnutls_deinit(*session); return -1; } /* ignore client certificate if any. */ - gnutls_certificate_server_set_request (*session, - GNUTLS_CERT_IGNORE); + gnutls_certificate_server_set_request(*session, + GNUTLS_CERT_IGNORE); - gnutls_dh_set_prime_bits (*session, mc->dh_bits); + gnutls_dh_set_prime_bits(*session, mc->dh_bits); return 0; } @@ -513,8 +519,8 @@ char interface[IF_NAMESIZE]; gnutls_session_t session; - ret = init_gnutls_session (mc, &session); - if (ret != 0){ + ret = init_gnutls_session(mc, &session); + if(ret != 0){ return -1; } @@ -542,7 +548,7 @@ /* It would be nice to have a way to detect if we were passed an IPv4 address here. Now we assume an IPv6 address. */ ret = inet_pton(AF_INET6, ip, &to.in6.sin6_addr); - if (ret < 0 ){ + if(ret < 0 ){ perror("inet_pton"); return -1; } @@ -550,7 +556,9 @@ fprintf(stderr, "Bad address: %s\n", ip); return -1; } - to.in6.sin6_port = htons(port); /* Spurious warning */ + to.in6.sin6_port = htons(port); /* Spurious warnings from + -Wconversion and + -Wunreachable-code */ to.in6.sin6_scope_id = (uint32_t)if_index; @@ -569,18 +577,18 @@ } ret = connect(tcp_sd, &to.in, sizeof(to)); - if (ret < 0){ + if(ret < 0){ perror("connect"); return -1; } const char *out = mandos_protocol_version; written = 0; - while (true){ + while(true){ size_t out_size = strlen(out); ret = (int)TEMP_FAILURE_RETRY(write(tcp_sd, out + written, out_size - written)); - if (ret == -1){ + if(ret == -1){ perror("write"); retval = -1; goto mandos_end; @@ -589,7 +597,7 @@ if(written < out_size){ continue; } else { - if (out == mandos_protocol_version){ + if(out == mandos_protocol_version){ written = 0; out = "\r\n"; } else { @@ -602,16 +610,16 @@ fprintf(stderr, "Establishing TLS session with %s\n", ip); } - gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd); + gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd); do{ - ret = gnutls_handshake (session); + ret = gnutls_handshake(session); } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); - if (ret != GNUTLS_E_SUCCESS){ + if(ret != GNUTLS_E_SUCCESS){ if(debug){ fprintf(stderr, "*** GnuTLS Handshake failed ***\n"); - gnutls_perror (ret); + gnutls_perror(ret); } retval = -1; goto mandos_end; @@ -627,7 +635,7 @@ while(true){ buffer_capacity = adjustbuffer(&buffer, buffer_length, buffer_capacity); - if (buffer_capacity == 0){ + if(buffer_capacity == 0){ perror("adjustbuffer"); retval = -1; goto mandos_end; @@ -635,21 +643,21 @@ sret = gnutls_record_recv(session, buffer+buffer_length, BUFFER_SIZE); - if (sret == 0){ + if(sret == 0){ break; } - if (sret < 0){ + if(sret < 0){ switch(sret){ case GNUTLS_E_INTERRUPTED: case GNUTLS_E_AGAIN: break; case GNUTLS_E_REHANDSHAKE: do{ - ret = gnutls_handshake (session); + ret = gnutls_handshake(session); } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); - if (ret < 0){ + if(ret < 0){ fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n"); - gnutls_perror (ret); + gnutls_perror(ret); retval = -1; goto mandos_end; } @@ -658,7 +666,7 @@ fprintf(stderr, "Unknown error while reading data from" " encrypted session with Mandos server\n"); retval = -1; - gnutls_bye (session, GNUTLS_SHUT_RDWR); + gnutls_bye(session, GNUTLS_SHUT_RDWR); goto mandos_end; } } else { @@ -670,18 +678,18 @@ fprintf(stderr, "Closing TLS session\n"); } - gnutls_bye (session, GNUTLS_SHUT_RDWR); + gnutls_bye(session, GNUTLS_SHUT_RDWR); - if (buffer_length > 0){ + if(buffer_length > 0){ decrypted_buffer_size = pgp_packet_decrypt(mc, buffer, buffer_length, &decrypted_buffer); - if (decrypted_buffer_size >= 0){ + if(decrypted_buffer_size >= 0){ written = 0; while(written < (size_t) decrypted_buffer_size){ - ret = (int)fwrite (decrypted_buffer + written, 1, - (size_t)decrypted_buffer_size - written, - stdout); + ret = (int)fwrite(decrypted_buffer + written, 1, + (size_t)decrypted_buffer_size - written, + stdout); if(ret == 0 and ferror(stdout)){ if(debug){ fprintf(stderr, "Error writing encrypted data: %s\n", @@ -708,7 +716,7 @@ if(ret == -1){ perror("close"); } - gnutls_deinit (session); + gnutls_deinit(session); return retval; } @@ -732,7 +740,7 @@ /* Called whenever a service has been resolved successfully or timed out */ - switch (event) { + switch(event) { default: case AVAHI_RESOLVER_FAILURE: fprintf(stderr, "(Avahi Resolver) Failed to resolve service '%s'" @@ -746,11 +754,11 @@ avahi_address_snprint(ip, sizeof(ip), address); if(debug){ fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %" - PRIu16 ") on port %d\n", name, host_name, ip, - interface, port); + PRIdMAX ") on port %" PRIu16 "\n", name, host_name, + ip, (intmax_t)interface, port); } int ret = start_mandos_communication(ip, port, interface, mc); - if (ret == 0){ + if(ret == 0){ avahi_simple_poll_quit(mc->simple_poll); } } @@ -774,7 +782,7 @@ /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ - switch (event) { + switch(event) { default: case AVAHI_BROWSER_FAILURE: @@ -789,7 +797,7 @@ the callback function is called the Avahi server will free the resolver for us. */ - if (!(avahi_s_service_resolver_new(mc->server, interface, + if(!(avahi_s_service_resolver_new(mc->server, interface, protocol, name, type, domain, AVAHI_PROTO_INET6, 0, resolve_callback, mc))) @@ -813,6 +821,8 @@ AvahiSServiceBrowser *sb = NULL; int error; int ret; + intmax_t tmpmax; + int numchars; int exitcode = EXIT_SUCCESS; const char *interface = "eth0"; struct ifreq network; @@ -864,11 +874,9 @@ { .name = NULL } }; - error_t parse_opt (int key, char *arg, - struct argp_state *state) { - /* Get the INPUT argument from `argp_parse', which we know is - a pointer to our plugin list pointer. */ - switch (key) { + error_t parse_opt(int key, char *arg, + struct argp_state *state) { + switch(key) { case 128: /* --debug */ debug = true; break; @@ -885,18 +893,19 @@ pubkey = arg; break; case 129: /* --dh-bits */ - errno = 0; - mc.dh_bits = (unsigned int) strtol(arg, NULL, 10); - if (errno){ - perror("strtol"); + ret = sscanf(arg, "%" SCNdMAX "%n", &tmpmax, &numchars); + if(ret < 1 or tmpmax != (typeof(mc.dh_bits))tmpmax + or arg[numchars] != '\0'){ + fprintf(stderr, "Bad number of DH bits\n"); exit(EXIT_FAILURE); } + mc.dh_bits = (typeof(mc.dh_bits))tmpmax; break; case 130: /* --priority */ mc.priority = arg; break; case ARGP_KEY_ARG: - argp_usage (state); + argp_usage(state); case ARGP_KEY_END: break; default: @@ -909,8 +918,8 @@ .args_doc = "", .doc = "Mandos client -- Get and decrypt" " passwords from a Mandos server" }; - ret = argp_parse (&argp, argc, argv, 0, 0, NULL); - if (ret == ARGP_ERR_UNKNOWN){ + ret = argp_parse(&argp, argc, argv, 0, 0, NULL); + if(ret == ARGP_ERR_UNKNOWN){ fprintf(stderr, "Unknown error while parsing arguments\n"); exitcode = EXIT_FAILURE; goto end; @@ -951,17 +960,17 @@ gid = getgid(); ret = setuid(uid); - if (ret == -1){ + if(ret == -1){ perror("setuid"); } setgid(gid); - if (ret == -1){ + if(ret == -1){ perror("setgid"); } ret = init_gnutls_global(&mc, pubkey, seckey); - if (ret == -1){ + if(ret == -1){ fprintf(stderr, "init_gnutls_global failed\n"); exitcode = EXIT_FAILURE; goto end; @@ -998,13 +1007,15 @@ exitcode = EXIT_FAILURE; goto end; } - errno = 0; - uint16_t port = (uint16_t) strtol(address+1, NULL, 10); - if(errno){ - perror("Bad port number"); + uint16_t port; + ret = sscanf(address+1, "%" SCNdMAX "%n", &tmpmax, &numchars); + if(ret < 1 or tmpmax != (uint16_t)tmpmax + or address[numchars+1] != '\0'){ + fprintf(stderr, "Bad port number\n"); exitcode = EXIT_FAILURE; goto end; } + port = (uint16_t)tmpmax; *address = '\0'; address = connect_to; ret = start_mandos_communication(address, port, if_index, &mc); @@ -1016,7 +1027,7 @@ goto end; } - if (not debug){ + if(not debug){ avahi_set_log_function(empty_log); } @@ -1025,7 +1036,7 @@ /* Allocate main Avahi loop object */ mc.simple_poll = avahi_simple_poll_new(); - if (mc.simple_poll == NULL) { + if(mc.simple_poll == NULL) { fprintf(stderr, "Avahi: Failed to create simple poll" " object.\n"); exitcode = EXIT_FAILURE; @@ -1051,7 +1062,7 @@ } /* Check if creating the Avahi server object succeeded */ - if (mc.server == NULL) { + if(mc.server == NULL) { fprintf(stderr, "Failed to create Avahi server: %s\n", avahi_strerror(error)); exitcode = EXIT_FAILURE; @@ -1063,7 +1074,7 @@ AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, &mc); - if (sb == NULL) { + if(sb == NULL) { fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(mc.server))); exitcode = EXIT_FAILURE; @@ -1072,7 +1083,7 @@ /* Run the main loop */ - if (debug){ + if(debug){ fprintf(stderr, "Starting Avahi loop search\n"); } @@ -1080,23 +1091,23 @@ end: - if (debug){ + if(debug){ fprintf(stderr, "%s exiting\n", argv[0]); } /* Cleanup things */ - if (sb != NULL) + if(sb != NULL) avahi_s_service_browser_free(sb); - if (mc.server != NULL) + if(mc.server != NULL) avahi_server_free(mc.server); - if (mc.simple_poll != NULL) + if(mc.simple_poll != NULL) avahi_simple_poll_free(mc.simple_poll); - if (gnutls_initalized){ + if(gnutls_initalized){ gnutls_certificate_free_credentials(mc.cred); - gnutls_global_deinit (); + gnutls_global_deinit(); gnutls_dh_params_deinit(mc.dh_params); } @@ -1110,14 +1121,16 @@ struct dirent *direntry; d = opendir(tempdir); if(d == NULL){ - perror("opendir"); + if(errno != ENOENT){ + perror("opendir"); + } } else { while(true){ direntry = readdir(d); if(direntry == NULL){ break; } - if (direntry->d_type == DT_REG){ + if(direntry->d_type == DT_REG){ char *fullname = NULL; ret = asprintf(&fullname, "%s/%s", tempdir, direntry->d_name); @@ -1136,7 +1149,7 @@ closedir(d); } ret = rmdir(tempdir); - if(ret == -1){ + if(ret == -1 and errno != ENOENT){ perror("rmdir"); } } === modified file 'plugins.d/password-prompt.c' --- plugins.d/password-prompt.c 2009-01-08 03:54:06 +0000 +++ plugins.d/password-prompt.c 2009-01-13 04:35:19 +0000 @@ -1,6 +1,6 @@ /* -*- coding: utf-8 -*- */ /* - * Passprompt - Read a password from the terminal and print it + * Password-prompt - Read a password from the terminal and print it * * Copyright © 2008,2009 Teddy Hogeborn * Copyright © 2008,2009 Björn Påhlsson @@ -81,8 +81,6 @@ }; error_t parse_opt (int key, char *arg, struct argp_state *state) { - /* Get the INPUT argument from `argp_parse', which we know is a - pointer to our plugin list pointer. */ switch (key) { case 'p': prefix = arg; @@ -91,7 +89,7 @@ debug = true; break; case ARGP_KEY_ARG: - argp_usage (state); + argp_usage(state); break; case ARGP_KEY_END: break; @@ -105,21 +103,21 @@ .args_doc = "", .doc = "Mandos password-prompt -- Read and" " output a password" }; - ret = argp_parse (&argp, argc, argv, 0, 0, NULL); - if (ret == ARGP_ERR_UNKNOWN){ + ret = argp_parse(&argp, argc, argv, 0, 0, NULL); + if(ret == ARGP_ERR_UNKNOWN){ fprintf(stderr, "Unknown error while parsing arguments\n"); return EXIT_FAILURE; } } - if (debug){ + if(debug){ fprintf(stderr, "Starting %s\n", argv[0]); } - if (debug){ + if(debug){ fprintf(stderr, "Storing current terminal attributes\n"); } - if (tcgetattr(STDIN_FILENO, &t_old) != 0){ + if(tcgetattr(STDIN_FILENO, &t_old) != 0){ perror("tcgetattr"); return EXIT_FAILURE; } @@ -133,7 +131,7 @@ perror("sigaction"); return EXIT_FAILURE; } - if (old_action.sa_handler != SIG_IGN){ + if(old_action.sa_handler != SIG_IGN){ ret = sigaction(SIGINT, &new_action, NULL); if(ret == -1){ perror("sigaction"); @@ -145,7 +143,7 @@ perror("sigaction"); return EXIT_FAILURE; } - if (old_action.sa_handler != SIG_IGN){ + if(old_action.sa_handler != SIG_IGN){ ret = sigaction(SIGHUP, &new_action, NULL); if(ret == -1){ perror("sigaction"); @@ -157,7 +155,7 @@ perror("sigaction"); return EXIT_FAILURE; } - if (old_action.sa_handler != SIG_IGN){ + if(old_action.sa_handler != SIG_IGN){ ret = sigaction(SIGTERM, &new_action, NULL); if(ret == -1){ perror("sigaction"); @@ -166,22 +164,22 @@ } - if (debug){ + if(debug){ fprintf(stderr, "Removing echo flag from terminal attributes\n"); } t_new = t_old; t_new.c_lflag &= ~ECHO; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){ + if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){ perror("tcsetattr-echo"); return EXIT_FAILURE; } - if (debug){ + if(debug){ fprintf(stderr, "Waiting for input from stdin \n"); } while(true){ - if (quit_now){ + if(quit_now){ if(debug){ fprintf(stderr, "Interrupted by signal, exiting.\n"); } @@ -213,7 +211,7 @@ } } ret = getline(&buffer, &n, stdin); - if (ret > 0){ + if(ret > 0){ status = EXIT_SUCCESS; /* Make n = data size instead of allocated buffer size */ n = (size_t)ret; @@ -234,8 +232,8 @@ } break; } - if (ret < 0){ - if (errno != EINTR and not feof(stdin)){ + if(ret < 0){ + if(errno != EINTR and not feof(stdin)){ perror("getline"); status = EXIT_FAILURE; break; @@ -253,14 +251,14 @@ free(buffer); - if (debug){ + if(debug){ fprintf(stderr, "Restoring terminal attributes\n"); } - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){ + if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){ perror("tcsetattr+echo"); } - if (debug){ + if(debug){ fprintf(stderr, "%s is exiting with status %d\n", argv[0], status); } === modified file 'plugins.d/splashy.c' --- plugins.d/splashy.c 2009-01-04 21:54:55 +0000 +++ plugins.d/splashy.c 2009-01-14 14:20:17 +0000 @@ -1,6 +1,6 @@ /* -*- coding: utf-8 -*- */ /* - * Passprompt - Read a password from splashy and output it + * Splashy - Read a password from splashy and output it * * Copyright © 2008,2009 Teddy Hogeborn * Copyright © 2008,2009 Björn Påhlsson @@ -30,12 +30,13 @@ SIG_IGN, kill(), SIGKILL */ #include /* NULL */ #include /* getenv() */ -#include /* asprintf(), perror() */ -#include /* EXIT_FAILURE, free(), strtoul(), +#include /* asprintf(), perror(), sscanf() */ +#include /* EXIT_FAILURE, free(), EXIT_SUCCESS */ #include /* pid_t, DIR, struct dirent, ssize_t */ #include /* opendir(), readdir(), closedir() */ +#include /* intmax_t, SCNdMAX */ #include /* struct stat, lstat(), S_ISLNK */ #include /* not, or, and */ #include /* readlink(), fork(), execl(), @@ -97,10 +98,18 @@ for(struct dirent *proc_ent = readdir(proc_dir); proc_ent != NULL; proc_ent = readdir(proc_dir)){ - pid_t pid = (pid_t) strtoul(proc_ent->d_name, NULL, 10); - if(pid == 0){ - /* Not a process */ - continue; + pid_t pid; + { + intmax_t tmpmax; + int numchars; + ret = sscanf(proc_ent->d_name, "%" SCNdMAX "%n", &tmpmax, + &numchars); + if(ret < 1 or tmpmax != (pid_t)tmpmax + or proc_ent->d_name[numchars] != '\0'){ + /* Not a process */ + continue; + } + pid = (pid_t)tmpmax; } /* Find the executable name by doing readlink() on the /proc//exe link */ @@ -120,6 +129,10 @@ struct stat exe_stat; ret = lstat(exe_link, &exe_stat); if(ret == -1){ + if(errno == ENOENT){ + free(exe_link); + continue; + } perror("lstat"); free(exe_link); free(prompt); @@ -263,7 +276,7 @@ /* Child; will become new splashy process */ /* Make the effective user ID (root) the only user ID instead of - the real user ID (mandos) */ + the real user ID (_mandos) */ ret = setuid(geteuid()); if(ret == -1){ perror("setuid"); === modified file 'plugins.d/usplash.c' --- plugins.d/usplash.c 2009-01-10 02:21:13 +0000 +++ plugins.d/usplash.c 2009-01-14 14:20:17 +0000 @@ -1,6 +1,6 @@ /* -*- coding: utf-8 -*- */ /* - * Passprompt - Read a password from usplash and output it + * Usplash - Read a password from usplash and output it * * Copyright © 2008,2009 Teddy Hogeborn * Copyright © 2008,2009 Björn Påhlsson @@ -36,17 +36,17 @@ dirent */ #include /* NULL */ #include /* strlen(), memcmp() */ -#include /* asprintf(), perror() */ +#include /* asprintf(), perror(), sscanf() */ #include /* close(), write(), readlink(), read(), STDOUT_FILENO, sleep(), fork(), setuid(), geteuid(), setsid(), chdir(), dup2(), STDERR_FILENO, execv() */ -#include /* free(), EXIT_FAILURE, strtoul(), - realloc(), EXIT_SUCCESS, malloc(), - _exit() */ +#include /* free(), EXIT_FAILURE, realloc(), + EXIT_SUCCESS, malloc(), _exit() */ #include /* getenv() */ #include /* opendir(), readdir(), closedir() */ +#include /* intmax_t, SCNdMAX */ #include /* struct stat, lstat(), S_ISLNK */ sig_atomic_t interrupted_by_signal = 0; @@ -170,10 +170,18 @@ for(struct dirent *proc_ent = readdir(proc_dir); proc_ent != NULL; proc_ent = readdir(proc_dir)){ - pid_t pid = (pid_t) strtoul(proc_ent->d_name, NULL, 10); - if(pid == 0){ - /* Not a process */ - continue; + pid_t pid; + { + intmax_t tmpmax; + int numchars; + ret = sscanf(proc_ent->d_name, "%" SCNdMAX "%n", &tmpmax, + &numchars); + if(ret < 1 or tmpmax != (pid_t)tmpmax + or proc_ent->d_name[numchars] != '\0'){ + /* Not a process */ + continue; + } + pid = (pid_t)tmpmax; } /* Find the executable name by doing readlink() on the /proc//exe link */ @@ -193,6 +201,10 @@ struct stat exe_stat; ret = lstat(exe_link, &exe_stat); if(ret == -1){ + if(errno == ENOENT){ + free(exe_link); + continue; + } perror("lstat"); free(exe_link); free(prompt); @@ -208,9 +220,6 @@ sret = readlink(exe_link, exe_target, sizeof(exe_target)); free(exe_link); - if(sret == -1){ - continue; - } } if((sret == ((ssize_t)sizeof(exe_target)-1)) and (memcmp(usplash_name, exe_target, @@ -485,7 +494,7 @@ /* Child; will become new usplash process */ /* Make the effective user ID (root) the only user ID instead of - the real user ID (mandos) */ + the real user ID (_mandos) */ ret = setuid(geteuid()); if(ret == -1){ perror("setuid");