=== modified file 'Makefile' --- Makefile 2011-07-13 02:24:39 +0000 +++ Makefile 2011-07-27 17:58:27 +0000 @@ -23,7 +23,7 @@ OPTIMIZE=-Os LANGUAGE=-std=gnu99 htmldir=man -version=1.3.0 +version=1.3.1 SED=sed ## Use these settings for a traditional /usr/local install === modified file 'NEWS' --- NEWS 2011-03-08 19:41:59 +0000 +++ NEWS 2011-07-27 17:58:27 +0000 @@ -1,6 +1,11 @@ This NEWS file records noteworthy changes, very tersely. See the manual for detailed information. +Version 1.3.1 (2011-07-27) +* Client: +** Client now retries all Mandos servers periodically. +** Work around Debian bug #633582 - fixes "Permission denied" problem. + Version 1.3.0 (2011-03-08) * Server: ** Updated for Python 2.6. === modified file 'README' --- README 2011-02-27 17:26:35 +0000 +++ README 2011-08-07 14:49:02 +0000 @@ -180,3 +180,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . + + +#+STARTUP: showall === modified file 'TODO' --- TODO 2011-07-25 18:47:45 +0000 +++ TODO 2011-07-31 13:05:34 +0000 @@ -11,7 +11,6 @@ ** TODO [#B] Use struct sockaddr_storage instead of a union ** TODO [#B] Use getaddrinfo(hints=AI_NUMERICHOST) instead of inet_pton() ** TODO [#B] Use getnameinfo(serv=NULL, NI_NUMERICHOST) instead of inet_ntop() -** TODO [#B] Accept [] around IPv6 address in --connect option; see [[http://tools.ietf.org/html/rfc5952][RFC 5952 - A Recommendation for IPv6 Address Text Representation]] * splashy ** TODO [#B] use scandir(3) instead of readdir(3) === modified file 'common.ent' --- common.ent 2011-03-08 19:41:59 +0000 +++ common.ent 2011-07-27 17:58:27 +0000 @@ -1,3 +1,3 @@ - + === modified file 'debian/changelog' --- debian/changelog 2011-03-08 19:41:59 +0000 +++ debian/changelog 2011-07-27 17:58:27 +0000 @@ -1,3 +1,11 @@ +mandos (1.3.1-1) unstable; urgency=low + + * New upstream release. + * Conflict with correct version of dropbear. + * New version uses argparse; depend on python (<=2.7) | python-argparse. + + -- Teddy Hogeborn Wed, 27 Jul 2011 19:47:17 +0200 + mandos (1.3.0-1) unstable; urgency=low * New upstream release. === modified file 'mandos' --- mandos 2011-06-23 22:27:15 +0000 +++ mandos 2011-07-27 17:58:27 +0000 @@ -82,7 +82,7 @@ SO_BINDTODEVICE = None -version = "1.3.0" +version = "1.3.1" #logger = logging.getLogger('mandos') logger = logging.Logger('mandos') === modified file 'mandos-ctl' --- mandos-ctl 2011-03-15 20:13:05 +0000 +++ mandos-ctl 2011-07-27 17:58:27 +0000 @@ -59,7 +59,7 @@ server_path = "/" server_interface = domain + ".Mandos" client_interface = domain + ".Mandos.Client" -version = "1.3.0" +version = "1.3.1" def timedelta_to_milliseconds(td): """Convert a datetime.timedelta object to milliseconds""" === modified file 'mandos-keygen' --- mandos-keygen 2011-03-08 19:41:59 +0000 +++ mandos-keygen 2011-07-27 17:58:27 +0000 @@ -21,7 +21,7 @@ # Contact the authors at . # -VERSION="1.3.0" +VERSION="1.3.1" KEYDIR="/etc/keys/mandos" KEYTYPE=DSA === modified file 'mandos-monitor' --- mandos-monitor 2011-04-02 06:37:18 +0000 +++ mandos-monitor 2011-07-27 17:58:27 +0000 @@ -22,7 +22,8 @@ # Contact the authors at . # -from __future__ import division, absolute_import, print_function, unicode_literals +from __future__ import (division, absolute_import, print_function, + unicode_literals) import sys import os @@ -51,7 +52,7 @@ domain = 'se.bsnet.fukt' server_interface = domain + '.Mandos' client_interface = domain + '.Mandos.Client' -version = "1.3.0" +version = "1.3.1" # Always run in monochrome mode urwid.curses_display.curses.has_colors = lambda : False @@ -86,16 +87,17 @@ self.proxy = proxy_object # Mandos Client proxy object self.properties = dict() - self.proxy.connect_to_signal("PropertyChanged", - self.property_changed, - client_interface, - byte_arrays=True) + self.property_changed_match = ( + self.proxy.connect_to_signal("PropertyChanged", + self.property_changed, + client_interface, + byte_arrays=True)) self.properties.update( self.proxy.GetAll(client_interface, dbus_interface = dbus.PROPERTIES_IFACE)) - #XXX This break good super behaviour! + #XXX This breaks good super behaviour # super(MandosClientPropertyCache, self).__init__( # *args, **kwargs) @@ -105,6 +107,11 @@ """ # Update properties dict with new value self.properties[property] = value + + def delete(self, *args, **kwargs): + self.property_changed_match.remove() + super(MandosClientPropertyCache, self).__init__( + *args, **kwargs) class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache): @@ -154,26 +161,28 @@ if self.need_approval: self.using_timer(True) - self.proxy.connect_to_signal("CheckerCompleted", - self.checker_completed, - client_interface, - byte_arrays=True) - self.proxy.connect_to_signal("CheckerStarted", - self.checker_started, - client_interface, - byte_arrays=True) - self.proxy.connect_to_signal("GotSecret", - self.got_secret, - client_interface, - byte_arrays=True) - self.proxy.connect_to_signal("NeedApproval", - self.need_approval, - client_interface, - byte_arrays=True) - self.proxy.connect_to_signal("Rejected", - self.rejected, - client_interface, - byte_arrays=True) + self.match_objects = ( + self.proxy.connect_to_signal("CheckerCompleted", + self.checker_completed, + client_interface, + byte_arrays=True), + self.proxy.connect_to_signal("CheckerStarted", + self.checker_started, + client_interface, + byte_arrays=True), + self.proxy.connect_to_signal("GotSecret", + self.got_secret, + client_interface, + byte_arrays=True), + self.proxy.connect_to_signal("NeedApproval", + self.need_approval, + client_interface, + byte_arrays=True), + self.proxy.connect_to_signal("Rejected", + self.rejected, + client_interface, + byte_arrays=True)) + #self.logger('Created client %s' % (self.properties["Name"])) def property_changed(self, property=None, value=None): super(self, MandosClientWidget).property_changed(property, @@ -341,12 +350,16 @@ self.update() return True # Keep calling this - def delete(self): + def delete(self, *args, **kwargs): if self._update_timer_callback_tag is not None: gobject.source_remove(self._update_timer_callback_tag) self._update_timer_callback_tag = None + for match in self.match_objects: + match.remove() + self.match_objects = () if self.delete_hook is not None: self.delete_hook(self) + return super(MandosClientWidget, self).delete(*args, **kwargs) def render(self, maxcolrow, focus=False): """Render differently if we have focus. @@ -580,7 +593,7 @@ #self.log_message("Wrap mode: " + self.log_wrap) def find_and_remove_client(self, path, name): - """Find an client from its object path and remove it. + """Find a client by its object path and remove it. This is connected to the ClientRemoved signal from the Mandos server object.""" @@ -588,8 +601,10 @@ client = self.clients_dict[path] except KeyError: # not found? + self.log_message("Unknown client %r (%r) removed", name, + path) return - self.remove_client(client, path) + client.delete() def add_new_client(self, path): client_proxy_object = self.bus.get_object(self.busname, path) === modified file 'mandos.lsm' --- mandos.lsm 2011-03-08 19:41:59 +0000 +++ mandos.lsm 2011-07-27 17:58:27 +0000 @@ -1,7 +1,7 @@ Begin4 Title: Mandos -Version: 1.3.0 -Entered-date: 2011-03-08 +Version: 1.3.1 +Entered-date: 2011-07-27 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,10 +12,10 @@ Maintained-by: teddy@fukt.bsnet.se (Teddy Hogeborn), belorn@fukt.bsnet.se (Björn Påhlsson) Primary-site: http://www.fukt.bsnet.se/mandos - 133K mandos_1.3.0.orig.tar.gz + 136K mandos_1.3.1.orig.tar.gz Alternate-site: ftp://ftp.fukt.bsnet.se/pub/mandos - 133K mandos_1.3.0.orig.tar.gz -Platforms: Requires GCC, GNU libC, Avahi, GnuPG, Python 2.5, and + 136K mandos_1.3.1.orig.tar.gz +Platforms: Requires GCC, GNU libC, Avahi, GnuPG, Python 2.6, and various other libraries. While made for Debian GNU/Linux, it is probably portable to other distributions, but not other Unixes. Copying-policy: GNU General Public License version 3.0 or later === modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2011-07-16 00:29:19 +0000 +++ plugins.d/mandos-client.c 2011-08-07 14:49:02 +0000 @@ -187,6 +187,7 @@ return buffer_capacity; } +/* Add server to set of servers to retry periodically */ int add_server(const char *ip, uint16_t port, AvahiIfIndex if_index, int af){ @@ -204,12 +205,12 @@ perror_plus("strdup"); return -1; } - /* unique case of first server */ + /* Special case of first server */ if (mc.current_server == NULL){ new_server->next = new_server; new_server->prev = new_server; mc.current_server = new_server; - /* Placing the new server last in the list */ + /* Place the new server last in the list */ } else { new_server->next = mc.current_server; new_server->prev = mc.current_server->prev; @@ -282,7 +283,7 @@ return false; } - /* Set GPGME home directory for the OpenPGP engine only */ + /* Set GPGME home directory for the OpenPGP engine only */ rc = gpgme_get_engine_info(&engine_info); if(rc != GPG_ERR_NO_ERROR){ fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n", @@ -1205,7 +1206,7 @@ struct timespec now; struct timespec waited_time; intmax_t block_time; - + while(true){ if(mc.current_server == NULL){ if (debug){ @@ -1236,11 +1237,11 @@ block_time = ((retry_interval - ((intmax_t)waited_time.tv_sec * 1000)) - ((intmax_t)waited_time.tv_nsec / 1000000)); - + if (debug){ - fprintf(stderr, "Blocking for %ld ms\n", block_time); + fprintf(stderr, "Blocking for %" PRIdMAX " ms\n", block_time); } - + if(block_time <= 0){ ret = start_mandos_communication(mc.current_server->ip, mc.current_server->port, @@ -1411,7 +1412,8 @@ errno = 0; retry_interval = strtod(arg, &tmp); if(errno != 0 or tmp == arg or *tmp != '\0' - or (retry_interval * 1000) > INT_MAX){ + or (retry_interval * 1000) > INT_MAX + or retry_interval < 0){ argp_error(state, "Bad retry interval"); } break; @@ -1468,40 +1470,44 @@ perror_plus("seteuid"); } - int seckey_fd = open(PATHDIR "/" SECKEY, O_RDONLY); - if(seckey_fd == -1){ - perror_plus("open"); - } else { - ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st)); - if(ret == -1){ - perror_plus("fstat"); + if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){ + int seckey_fd = open(seckey, O_RDONLY); + if(seckey_fd == -1){ + perror_plus("open"); } else { - if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ - ret = fchown(seckey_fd, uid, gid); - if(ret == -1){ - perror_plus("fchown"); + ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st)); + if(ret == -1){ + perror_plus("fstat"); + } else { + if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ + ret = fchown(seckey_fd, uid, gid); + if(ret == -1){ + perror_plus("fchown"); + } } } + TEMP_FAILURE_RETRY(close(seckey_fd)); } - TEMP_FAILURE_RETRY(close(seckey_fd)); } - int pubkey_fd = open(PATHDIR "/" PUBKEY, O_RDONLY); - if(pubkey_fd == -1){ - perror_plus("open"); - } else { - ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st)); - if(ret == -1){ - perror_plus("fstat"); + if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){ + int pubkey_fd = open(pubkey, O_RDONLY); + if(pubkey_fd == -1){ + perror_plus("open"); } else { - if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ - ret = fchown(pubkey_fd, uid, gid); - if(ret == -1){ - perror_plus("fchown"); + ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st)); + if(ret == -1){ + perror_plus("fstat"); + } else { + if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ + ret = fchown(pubkey_fd, uid, gid); + if(ret == -1){ + perror_plus("fchown"); + } } } + TEMP_FAILURE_RETRY(close(pubkey_fd)); } - TEMP_FAILURE_RETRY(close(pubkey_fd)); } /* Lower privileges */ @@ -1829,27 +1835,37 @@ port = (uint16_t)tmpmax; *address = '\0'; - address = connect_to; /* Colon in address indicates IPv6 */ int af; - if(strchr(address, ':') != NULL){ + if(strchr(connect_to, ':') != NULL){ af = AF_INET6; + /* Accept [] around IPv6 address - see RFC 5952 */ + if(connect_to[0] == '[' and address[-1] == ']') + { + connect_to++; + address[-1] = '\0'; + } } else { af = AF_INET; } + address = connect_to; if(quit_now){ goto end; } - + while(not quit_now){ ret = start_mandos_communication(address, port, if_index, af); if(quit_now or ret == 0){ break; } - sleep((int)retry_interval or 1); - }; - + if(debug){ + fprintf(stderr, "Retrying in %d seconds\n", + (int)retry_interval); + } + sleep((int)retry_interval); + } + if (not quit_now){ exitcode = EXIT_SUCCESS; } @@ -1992,9 +2008,10 @@ if(tempdir_created){ struct dirent **direntries = NULL; struct dirent *direntry = NULL; - ret = scandir(tempdir, &direntries, notdotentries, alphasort); - if (ret > 0){ - for(int i = 0; i < ret; i++){ + int numentries = scandir(tempdir, &direntries, notdotentries, + alphasort); + if (numentries > 0){ + for(int i = 0; i < numentries; i++){ direntry = direntries[i]; char *fullname = NULL; ret = asprintf(&fullname, "%s/%s", tempdir, @@ -2012,10 +2029,9 @@ } } - /* need to be cleaned even if ret == 0 because man page doesn't - specify */ + /* need to clean even if 0 because man page doesn't specify */ free(direntries); - if (ret == -1){ + if (numentries == -1){ perror_plus("scandir"); } ret = rmdir(tempdir); === modified file 'plugins.d/mandos-client.xml' --- plugins.d/mandos-client.xml 2011-06-23 22:27:15 +0000 +++ plugins.d/mandos-client.xml 2011-07-31 13:05:34 +0000 @@ -137,9 +137,9 @@ using TLS with an OpenPGP key to ensure authenticity and confidentiality. This client program keeps running, trying all servers on the network, until it receives a satisfactory reply - or a TERM signal is received. If no servers are found, or after - all servers have been tried, it waits indefinitely for new - servers to appear. + or a TERM signal. After all servers have been tried, all + servers are periodically retried. If no servers are found it + will wait indefinitely for new servers to appear. This program is not meant to be run directly; it is really meant @@ -303,10 +303,10 @@ >SECONDS - All Mandos servers servers are tried repeatedly until a - password is received. This value specifies, in seconds, - how long between each successive try for the - same server. The default is 10 seconds. + All Mandos servers are tried repeatedly until a password + is received. This value specifies, in seconds, how long + between each successive try for the same + server. The default is 10 seconds. @@ -388,9 +388,9 @@ server could be found and the password received from it could be successfully decrypted and output on standard output. The program will exit with a non-zero exit status only if a critical - error occurs. Otherwise, it will forever connect to new - Mandos servers as they appear, trying - to get a decryptable password and print it. + error occurs. Otherwise, it will forever connect to any + discovered Mandos servers, trying to + get a decryptable password and print it. === modified file 'plugins.d/password-prompt.c' --- plugins.d/password-prompt.c 2011-07-25 18:47:45 +0000 +++ plugins.d/password-prompt.c 2011-07-27 17:58:27 +0000 @@ -214,7 +214,7 @@ if (ret == -1){ error(1, errno, "scandir"); } - free(dirent); + free(direntries); return ret > 0; }