/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2012-05-12 15:45:57 UTC
  • Revision ID: teddy@recompile.se-20120512154557-r1yzcb8su8byp4us
* mandos (Client.enable, Client.disable, ClientDBus.approve): Call
                    self.send_changedstate() after change, not before.
  (Client.disable): Bug fix: Handle disable_initiator_tag and
                    checker_initiator_tag of 0.
  (Client.init_checker): Bug fix: Remove old checker_initiator_tag and
                         disable_initiator_tag, if any.
  (Client.bump_timeout): Bug fix: Remove old disable_initiator_tag, if
                         any.
  (ClientDBus.Timeout_dbus_property): Bug fix: Use self.expires.
  (ClientHandler.handle): Bug fix: timedelta_to_milliseconds is a
                          global function, not a class method.
* mandos-monitor (MandosClientWidget._update_timer_callback_lock):
  Removed.  All users changed.
  (MandosClientWidget.last_checked_ok): Removed (unused).
  (MandosClientWidget.__init__): Don't call self.using_timer().
  (MandosClientWidget.property_changed): Removed unused version.
  (MandosClientWidget.using_timer): Stop using the counter
                                    self._update_timer_callback_lock;
                                    be strictly boolean.
  (MandosClientWidget.need_approval): Don't call self.using_timer().
  (MandosClientWidget.update): Call self.using_timer() throughout.
                               Bug fix: Never show negative timers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
379
379
                                 self.server_state_changed)
380
380
        self.server_state_changed(self.server.GetState())
381
381
 
382
 
 
383
382
class AvahiServiceToSyslog(AvahiService):
384
383
    def rename(self):
385
384
        """Add the new name to the syslog messages"""
390
389
                                .format(self.name)))
391
390
        return ret
392
391
 
393
 
 
394
392
def timedelta_to_milliseconds(td):
395
393
    "Convert a datetime.timedelta() to milliseconds"
396
394
    return ((td.days * 24 * 60 * 60 * 1000)
397
395
            + (td.seconds * 1000)
398
396
            + (td.microseconds // 1000))
399
397
 
400
 
 
401
398
class Client(object):
402
399
    """A representation of a client host served by this server.
403
400
    
442
439
    """
443
440
    
444
441
    runtime_expansions = ("approval_delay", "approval_duration",
445
 
                          "created", "enabled", "expires",
446
 
                          "fingerprint", "host", "interval",
447
 
                          "last_approval_request", "last_checked_ok",
 
442
                          "created", "enabled", "fingerprint",
 
443
                          "host", "interval", "last_checked_ok",
448
444
                          "last_enabled", "name", "timeout")
449
445
    client_defaults = { "timeout": "5m",
450
446
                        "extended_timeout": "15m",
691
687
                                      self.current_checker_command)
692
688
        # Start a new checker if needed
693
689
        if self.checker is None:
694
 
            # Escape attributes for the shell
695
 
            escaped_attrs = dict(
696
 
                (attr, re.escape(unicode(getattr(self, attr))))
697
 
                for attr in
698
 
                self.runtime_expansions)
699
690
            try:
700
 
                command = self.checker_command % escaped_attrs
701
 
            except TypeError as error:
702
 
                logger.error('Could not format string "%s"',
703
 
                             self.checker_command, exc_info=error)
704
 
                return True # Try again later
 
691
                # In case checker_command has exactly one % operator
 
692
                command = self.checker_command % self.host
 
693
            except TypeError:
 
694
                # Escape attributes for the shell
 
695
                escaped_attrs = dict(
 
696
                    (attr,
 
697
                     re.escape(unicode(str(getattr(self, attr, "")),
 
698
                                       errors=
 
699
                                       'replace')))
 
700
                    for attr in
 
701
                    self.runtime_expansions)
 
702
                
 
703
                try:
 
704
                    command = self.checker_command % escaped_attrs
 
705
                except TypeError as error:
 
706
                    logger.error('Could not format string "%s"',
 
707
                                 self.checker_command, exc_info=error)
 
708
                    return True # Try again later
705
709
            self.current_checker_command = command
706
710
            try:
707
711
                logger.info("Starting checker %r for %s",
713
717
                self.checker = subprocess.Popen(command,
714
718
                                                close_fds=True,
715
719
                                                shell=True, cwd="/")
 
720
                self.checker_callback_tag = (gobject.child_watch_add
 
721
                                             (self.checker.pid,
 
722
                                              self.checker_callback,
 
723
                                              data=command))
 
724
                # The checker may have completed before the gobject
 
725
                # watch was added.  Check for this.
 
726
                pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
 
727
                if pid:
 
728
                    gobject.source_remove(self.checker_callback_tag)
 
729
                    self.checker_callback(pid, status, command)
716
730
            except OSError as error:
717
731
                logger.error("Failed to start subprocess",
718
732
                             exc_info=error)
719
 
            self.checker_callback_tag = (gobject.child_watch_add
720
 
                                         (self.checker.pid,
721
 
                                          self.checker_callback,
722
 
                                          data=command))
723
 
            # The checker may have completed before the gobject
724
 
            # watch was added.  Check for this.
725
 
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
726
 
            if pid:
727
 
                gobject.source_remove(self.checker_callback_tag)
728
 
                self.checker_callback(pid, status, command)
729
733
        # Re-run this periodically if run by gobject.timeout_add
730
734
        return True
731
735
    
1921
1925
                                           str(self.interface
1922
1926
                                               + '\0'))
1923
1927
                except socket.error as error:
1924
 
                    if error.errno == errno.EPERM:
 
1928
                    if error[0] == errno.EPERM:
1925
1929
                        logger.error("No permission to"
1926
1930
                                     " bind to interface %s",
1927
1931
                                     self.interface)
1928
 
                    elif error.errno == errno.ENOPROTOOPT:
 
1932
                    elif error[0] == errno.ENOPROTOOPT:
1929
1933
                        logger.error("SO_BINDTODEVICE not available;"
1930
1934
                                     " cannot bind to interface %s",
1931
1935
                                     self.interface)
1932
 
                    elif error.errno == errno.ENODEV:
1933
 
                        logger.error("Interface %s does not"
1934
 
                                     " exist, cannot bind",
1935
 
                                     self.interface)
1936
1936
                    else:
1937
1937
                        raise
1938
1938
        # Only bind(2) the socket if we really need to.
2288
2288
        os.setgid(gid)
2289
2289
        os.setuid(uid)
2290
2290
    except OSError as error:
2291
 
        if error.errno != errno.EPERM:
 
2291
        if error[0] != errno.EPERM:
2292
2292
            raise error
2293
2293
    
2294
2294
    if debug:
2462
2462
            # "pidfile" was never created
2463
2463
            pass
2464
2464
        del pidfilename
 
2465
        signal.signal(signal.SIGINT, signal.SIG_IGN)
2465
2466
    
2466
2467
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
2467
2468
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())