=== modified file 'Makefile' --- Makefile 2009-01-10 21:49:25 +0000 +++ Makefile 2009-01-15 04:55:10 +0000 @@ -16,7 +16,7 @@ OPTIMIZE=-Os LANGUAGE=-std=gnu99 htmldir=man -version=1.0.3 +version=1.0.4 SED=sed ## Use these settings for a traditional /usr/local install === modified file 'NEWS' --- NEWS 2009-01-06 02:42:53 +0000 +++ NEWS 2009-01-15 04:55:10 +0000 @@ -1,6 +1,18 @@ This NEWS file records noteworthy changes, very tersely. See the manual for detailed information. +Version 1.0.4 (2009-01-15) +* Server +** Only find matched user/group pairs when searching for suitable + nonprivileged user/group to switch to. + +* Client +** New kernel parameter "mandos=off" makes client not run at boot. +** Fix linking errors and compilation warnings on AMD64. +** Parse numbers in command line options better. +** The splashy and usplash plugins are more robust while traversing + /proc, and will not abort if a process suddenly disappears. + Version 1.0.3 (2009-01-06) * Server ** Now tries to change to user and group "_mandos" before falling back === 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/changelog' --- debian/changelog 2009-01-06 22:43:19 +0000 +++ debian/changelog 2009-01-15 04:55:10 +0000 @@ -1,3 +1,12 @@ +mandos (1.0.4-1) unstable; urgency=low + + * New upstream release. + * debian/watch: New file. + * debian/mandos-client.README.Debian: Document new "mandos=off" kernel + parameter. + + -- Teddy Hogeborn Thu, 15 Jan 2009 05:49:22 +0100 + mandos (1.0.3-2) unstable; urgency=low * Removed some now-unused debconf files. === 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 21:49:25 +0000 +++ mandos 2009-01-15 05:27:55 +0000 @@ -35,7 +35,7 @@ import SocketServer import socket -from optparse import OptionParser +import optparse import datetime import errno import gnutls.crypto @@ -66,7 +66,7 @@ import ctypes import ctypes.util -version = "1.0.3" +version = "1.0.4" logger = logging.Logger('mandos') syslogger = (logging.handlers.SysLogHandler @@ -889,7 +889,7 @@ def main(): - parser = OptionParser(version = "%%prog %s" % version) + parser = optparse.OptionParser(version = "%%prog %s" % version) parser.add_option("-i", "--interface", type="string", metavar="IF", help="Bind to interface IF") parser.add_option("-a", "--address", type="string", === modified file 'mandos-ctl' (properties changed: +x to -x) --- mandos-ctl 2009-01-10 21:45:37 +0000 +++ mandos-ctl 2009-01-15 04:55:10 +0000 @@ -30,7 +30,7 @@ server_path = '/Mandos' server_interface = 'org.mandos_system.Mandos' client_interface = 'org.mandos_system.Mandos.Client' -version = "1.0.2" +version = "1.0.4" bus = dbus.SystemBus() mandos_dbus_objc = bus.get_object(busname, server_path) === modified file 'mandos-keygen' --- mandos-keygen 2009-01-06 02:42:53 +0000 +++ mandos-keygen 2009-01-15 04:55:10 +0000 @@ -21,7 +21,7 @@ # Contact the authors at . # -VERSION="1.0.3" +VERSION="1.0.4" KEYDIR="/etc/keys/mandos" KEYTYPE=DSA === modified file 'mandos.lsm' --- mandos.lsm 2009-01-10 21:49:25 +0000 +++ mandos.lsm 2009-01-15 04:55:10 +0000 @@ -1,7 +1,7 @@ Begin4 Title: Mandos -Version: 1.0.3 -Entered-date: 2009-01-06 +Version: 1.0.4 +Entered-date: 2009-01-15 Description: The Mandos system allows computers to have encrypted root file systems and at the same time be capable of remote and/or unattended reboots. @@ -12,9 +12,9 @@ Maintained-by: teddy@fukt.bsnet.se (Teddy Hogeborn), belorn@fukt.bsnet.se (Björn Påhlsson) Primary-site: http://www.fukt.bsnet.se/mandos - 92K mandos_1.0.3.orig.tar.gz + 94K mandos_1.0.4.orig.tar.gz Alternate-site: ftp://ftp.fukt.bsnet.se/pub/mandos - 92K mandos_1.0.3.orig.tar.gz + 94K mandos_1.0.4.orig.tar.gz Platforms: Requires GCC, GNU libC, Avahi, GnuPG, Python 2.4, and various other libraries. While made for Debian GNU/Linux, it is probably portable to other distributions, but not other Unixes. === 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/mandos-client.c' --- plugins.d/mandos-client.c 2009-01-10 06:00:50 +0000 +++ plugins.d/mandos-client.c 2009-01-14 14:20:17 +0000 @@ -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-10 06:00:50 +0000 +++ plugins.d/password-prompt.c 2009-01-13 04:35:19 +0000 @@ -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-10 06:23:04 +0000 +++ plugins.d/splashy.c 2009-01-14 14:20:17 +0000 @@ -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 */ @@ -267,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 06:23:04 +0000 +++ plugins.d/usplash.c 2009-01-14 14:20:17 +0000 @@ -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 */ @@ -486,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");