/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: 2009-11-19 18:31:28 UTC
  • Revision ID: teddy@fukt.bsnet.se-20091119183128-ttstewh61xmtnil1
* Makefile (LINK_FORTIFY_LD): Bug fix: removed "-fPIE".
* mandos-keygen: Bug fix: Fix quoting for the "--password" option.

Show diffs side-by-side

added added

removed removed

Lines of Context:
79
79
        SO_BINDTODEVICE = None
80
80
 
81
81
 
82
 
version = "1.0.12"
 
82
version = "1.0.14"
83
83
 
84
84
logger = logging.Logger(u'mandos')
85
85
syslogger = (logging.handlers.SysLogHandler
292
292
        elif u"secfile" in config:
293
293
            with closing(open(os.path.expanduser
294
294
                              (os.path.expandvars
295
 
                               (config[u"secfile"])))) as secfile:
 
295
                               (config[u"secfile"])),
 
296
                              "rb")) as secfile:
296
297
                self.secret = secfile.read()
297
298
        else:
298
299
            raise TypeError(u"No secret or secfile for client %s"
324
325
        self.checker_initiator_tag = (gobject.timeout_add
325
326
                                      (self.interval_milliseconds(),
326
327
                                       self.start_checker))
327
 
        # Also start a new checker *right now*.
328
 
        self.start_checker()
329
328
        # Schedule a disable() when 'timeout' has passed
330
329
        self.disable_initiator_tag = (gobject.timeout_add
331
330
                                   (self.timeout_milliseconds(),
332
331
                                    self.disable))
333
332
        self.enabled = True
 
333
        # Also start a new checker *right now*.
 
334
        self.start_checker()
334
335
    
335
 
    def disable(self):
 
336
    def disable(self, quiet=True):
336
337
        """Disable this client."""
337
338
        if not getattr(self, "enabled", False):
338
339
            return False
339
 
        logger.info(u"Disabling client %s", self.name)
 
340
        if not quiet:
 
341
            logger.info(u"Disabling client %s", self.name)
340
342
        if getattr(self, u"disable_initiator_tag", False):
341
343
            gobject.source_remove(self.disable_initiator_tag)
342
344
            self.disable_initiator_tag = None
398
400
        # is as it should be.
399
401
        
400
402
        # If a checker exists, make sure it is not a zombie
401
 
        if self.checker is not None:
 
403
        try:
402
404
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
 
405
        except (AttributeError, OSError), error:
 
406
            if (isinstance(error, OSError)
 
407
                and error.errno != errno.ECHILD):
 
408
                raise error
 
409
        else:
403
410
            if pid:
404
411
                logger.warning(u"Checker was a zombie")
405
412
                gobject.source_remove(self.checker_callback_tag)
461
468
        logger.debug(u"Stopping checker for %(name)s", vars(self))
462
469
        try:
463
470
            os.kill(self.checker.pid, signal.SIGTERM)
464
 
            #os.sleep(0.5)
 
471
            #time.sleep(0.5)
465
472
            #if self.checker.poll() is None:
466
473
            #    os.kill(self.checker.pid, signal.SIGKILL)
467
474
        except OSError, error:
620
627
        """Standard D-Bus method, overloaded to insert property tags.
621
628
        """
622
629
        xmlstring = dbus.service.Object.Introspect(self, object_path,
623
 
                                           connection)
624
 
        document = xml.dom.minidom.parseString(xmlstring)
625
 
        del xmlstring
626
 
        def make_tag(document, name, prop):
627
 
            e = document.createElement(u"property")
628
 
            e.setAttribute(u"name", name)
629
 
            e.setAttribute(u"type", prop._dbus_signature)
630
 
            e.setAttribute(u"access", prop._dbus_access)
631
 
            return e
632
 
        for if_tag in document.getElementsByTagName(u"interface"):
633
 
            for tag in (make_tag(document, name, prop)
634
 
                        for name, prop
635
 
                        in self._get_all_dbus_properties()
636
 
                        if prop._dbus_interface
637
 
                        == if_tag.getAttribute(u"name")):
638
 
                if_tag.appendChild(tag)
639
 
        xmlstring = document.toxml(u"utf-8")
640
 
        document.unlink()
 
630
                                                   connection)
 
631
        try:
 
632
            document = xml.dom.minidom.parseString(xmlstring)
 
633
            def make_tag(document, name, prop):
 
634
                e = document.createElement(u"property")
 
635
                e.setAttribute(u"name", name)
 
636
                e.setAttribute(u"type", prop._dbus_signature)
 
637
                e.setAttribute(u"access", prop._dbus_access)
 
638
                return e
 
639
            for if_tag in document.getElementsByTagName(u"interface"):
 
640
                for tag in (make_tag(document, name, prop)
 
641
                            for name, prop
 
642
                            in self._get_all_dbus_properties()
 
643
                            if prop._dbus_interface
 
644
                            == if_tag.getAttribute(u"name")):
 
645
                    if_tag.appendChild(tag)
 
646
                # Add the names to the return values for the
 
647
                # "org.freedesktop.DBus.Properties" methods
 
648
                if (if_tag.getAttribute(u"name")
 
649
                    == u"org.freedesktop.DBus.Properties"):
 
650
                    for cn in if_tag.getElementsByTagName(u"method"):
 
651
                        if cn.getAttribute(u"name") == u"Get":
 
652
                            for arg in cn.getElementsByTagName(u"arg"):
 
653
                                if (arg.getAttribute(u"direction")
 
654
                                    == u"out"):
 
655
                                    arg.setAttribute(u"name", u"value")
 
656
                        elif cn.getAttribute(u"name") == u"GetAll":
 
657
                            for arg in cn.getElementsByTagName(u"arg"):
 
658
                                if (arg.getAttribute(u"direction")
 
659
                                    == u"out"):
 
660
                                    arg.setAttribute(u"name", u"props")
 
661
            xmlstring = document.toxml(u"utf-8")
 
662
            document.unlink()
 
663
        except (AttributeError, xml.dom.DOMException,
 
664
                xml.parsers.expat.ExpatError), error:
 
665
            logger.error(u"Failed to override Introspection method",
 
666
                         error)
641
667
        return xmlstring
642
668
 
643
669
 
680
706
                                       variant_level=1))
681
707
        return r
682
708
    
683
 
    def disable(self, signal = True):
 
709
    def disable(self, quiet = False):
684
710
        oldstate = getattr(self, u"enabled", False)
685
 
        r = Client.disable(self)
686
 
        if signal and oldstate != self.enabled:
 
711
        r = Client.disable(self, quiet=quiet)
 
712
        if not quiet and oldstate != self.enabled:
687
713
            # Emit D-Bus signal
688
714
            self.PropertyChanged(dbus.String(u"enabled"),
689
715
                                 dbus.Boolean(False, variant_level=1))
758
784
    ## D-Bus methods & signals
759
785
    _interface = u"se.bsnet.fukt.Mandos.Client"
760
786
    
 
787
    # CheckedOK - method
 
788
    @dbus.service.method(_interface)
 
789
    def CheckedOK(self):
 
790
        return self.checked_ok()
 
791
    
761
792
    # CheckerCompleted - signal
762
793
    @dbus.service.signal(_interface, signature=u"nxs")
763
794
    def CheckerCompleted(self, exitcode, waitstatus, command):
776
807
        "D-Bus signal"
777
808
        pass
778
809
    
779
 
    # ReceivedSecret - signal
 
810
    # GotSecret - signal
780
811
    @dbus.service.signal(_interface)
781
 
    def ReceivedSecret(self):
 
812
    def GotSecret(self):
782
813
        "D-Bus signal"
783
814
        pass
784
815
    
788
819
        "D-Bus signal"
789
820
        pass
790
821
    
 
822
    # Enable - method
 
823
    @dbus.service.method(_interface)
 
824
    def Enable(self):
 
825
        "D-Bus method"
 
826
        self.enable()
 
827
    
 
828
    # StartChecker - method
 
829
    @dbus.service.method(_interface)
 
830
    def StartChecker(self):
 
831
        "D-Bus method"
 
832
        self.start_checker()
 
833
    
 
834
    # Disable - method
 
835
    @dbus.service.method(_interface)
 
836
    def Disable(self):
 
837
        "D-Bus method"
 
838
        self.disable()
 
839
    
 
840
    # StopChecker - method
 
841
    @dbus.service.method(_interface)
 
842
    def StopChecker(self):
 
843
        self.stop_checker()
 
844
    
791
845
    # name - property
792
846
    @dbus_service_property(_interface, signature=u"s", access=u"read")
793
847
    def name_dbus_property(self):
833
887
            self.disable()
834
888
    
835
889
    # last_checked_ok - property
836
 
    @dbus_service_property(_interface, signature=u"s", access=u"read")
837
 
    def last_checked_ok_dbus_property(self):
 
890
    @dbus_service_property(_interface, signature=u"s",
 
891
                           access=u"readwrite")
 
892
    def last_checked_ok_dbus_property(self, value=None):
 
893
        if value is not None:
 
894
            self.checked_ok()
 
895
            return
838
896
        if self.last_checked_ok is None:
839
897
            return dbus.String(u"")
840
898
        return dbus.String(self._datetime_to_dbus(self
914
972
    def object_path_dbus_property(self):
915
973
        return self.dbus_object_path # is already a dbus.ObjectPath
916
974
    
917
 
    # secret = property xxx
 
975
    # secret = property
918
976
    @dbus_service_property(_interface, signature=u"ay",
919
977
                           access=u"write", byte_arrays=True)
920
978
    def secret_dbus_property(self, value):
1222
1280
        cmd, args = cmdline.rstrip(u"\r\n").split(None, 1)
1223
1281
        
1224
1282
        if cmd == u"NOTFOUND":
1225
 
            logger.warning(u"Client not found for fingerprint: %s",
1226
 
                           args)
 
1283
            fpr, address = args.split(None, 1)
 
1284
            logger.warning(u"Client not found for fingerprint: %s, ad"
 
1285
                           u"dress: %s", fpr, address)
1227
1286
            if self.use_dbus:
1228
1287
                # Emit D-Bus signal
1229
 
                mandos_dbus_service.ClientNotFound(args)
 
1288
                mandos_dbus_service.ClientNotFound(fpr, address)
1230
1289
        elif cmd == u"INVALID":
1231
1290
            for client in self.clients:
1232
1291
                if client.name == args:
1244
1303
                    client.checked_ok()
1245
1304
                    if self.use_dbus:
1246
1305
                        # Emit D-Bus signal
1247
 
                        client.ReceivedSecret()
 
1306
                        client.GotSecret()
1248
1307
                    break
1249
1308
            else:
1250
1309
                logger.error(u"Sending secret to unknown client %s",
1288
1347
            elif suffix == u"w":
1289
1348
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1290
1349
            else:
1291
 
                raise ValueError
1292
 
        except (ValueError, IndexError):
1293
 
            raise ValueError
 
1350
                raise ValueError(u"Unknown suffix %r" % suffix)
 
1351
        except (ValueError, IndexError), e:
 
1352
            raise ValueError(e.message)
1294
1353
        timevalue += delta
1295
1354
    return timevalue
1296
1355
 
1335
1394
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
1336
1395
        if not stat.S_ISCHR(os.fstat(null).st_mode):
1337
1396
            raise OSError(errno.ENODEV,
1338
 
                          u"/dev/null not a character device")
 
1397
                          u"%s not a character device"
 
1398
                          % os.path.devnull)
1339
1399
        os.dup2(null, sys.stdin.fileno())
1340
1400
        os.dup2(null, sys.stdout.fileno())
1341
1401
        os.dup2(null, sys.stderr.fileno())
1508
1568
    bus = dbus.SystemBus()
1509
1569
    # End of Avahi example code
1510
1570
    if use_dbus:
1511
 
        bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos", bus)
 
1571
        try:
 
1572
            bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos",
 
1573
                                            bus, do_not_queue=True)
 
1574
        except dbus.exceptions.NameExistsException, e:
 
1575
            logger.error(unicode(e) + u", disabling D-Bus")
 
1576
            use_dbus = False
 
1577
            server_settings[u"use_dbus"] = False
 
1578
            tcp_server.use_dbus = False
1512
1579
    protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET
1513
1580
    service = AvahiService(name = server_settings[u"servicename"],
1514
1581
                           servicetype = u"_mandos._tcp",
1552
1619
        pass
1553
1620
    del pidfilename
1554
1621
    
1555
 
    def cleanup():
1556
 
        "Cleanup function; run on exit"
1557
 
        service.cleanup()
1558
 
        
1559
 
        while tcp_server.clients:
1560
 
            client = tcp_server.clients.pop()
1561
 
            client.disable_hook = None
1562
 
            client.disable()
1563
 
    
1564
 
    atexit.register(cleanup)
1565
 
    
1566
1622
    if not debug:
1567
1623
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1568
1624
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1580
1636
                "D-Bus signal"
1581
1637
                pass
1582
1638
            
1583
 
            @dbus.service.signal(_interface, signature=u"s")
1584
 
            def ClientNotFound(self, fingerprint):
 
1639
            @dbus.service.signal(_interface, signature=u"ss")
 
1640
            def ClientNotFound(self, fingerprint, address):
1585
1641
                "D-Bus signal"
1586
1642
                pass
1587
1643
            
1613
1669
                        tcp_server.clients.remove(c)
1614
1670
                        c.remove_from_connection()
1615
1671
                        # Don't signal anything except ClientRemoved
1616
 
                        c.disable(signal=False)
 
1672
                        c.disable(quiet=True)
1617
1673
                        # Emit D-Bus signal
1618
1674
                        self.ClientRemoved(object_path, c.name)
1619
1675
                        return
1620
 
                raise KeyError
 
1676
                raise KeyError(object_path)
1621
1677
            
1622
1678
            del _interface
1623
1679
        
1624
1680
        mandos_dbus_service = MandosDBusService()
1625
1681
    
 
1682
    def cleanup():
 
1683
        "Cleanup function; run on exit"
 
1684
        service.cleanup()
 
1685
        
 
1686
        while tcp_server.clients:
 
1687
            client = tcp_server.clients.pop()
 
1688
            if use_dbus:
 
1689
                client.remove_from_connection()
 
1690
            client.disable_hook = None
 
1691
            # Don't signal anything except ClientRemoved
 
1692
            client.disable(quiet=True)
 
1693
            if use_dbus:
 
1694
                # Emit D-Bus signal
 
1695
                mandos_dbus_service.ClientRemoved(client.dbus_object_path,
 
1696
                                                  client.name)
 
1697
    
 
1698
    atexit.register(cleanup)
 
1699
    
1626
1700
    for client in tcp_server.clients:
1627
1701
        if use_dbus:
1628
1702
            # Emit D-Bus signal
1651
1725
            service.activate()
1652
1726
        except dbus.exceptions.DBusException, error:
1653
1727
            logger.critical(u"DBusException: %s", error)
 
1728
            cleanup()
1654
1729
            sys.exit(1)
1655
1730
        # End of Avahi example code
1656
1731
        
1663
1738
        main_loop.run()
1664
1739
    except AvahiError, error:
1665
1740
        logger.critical(u"AvahiError: %s", error)
 
1741
        cleanup()
1666
1742
        sys.exit(1)
1667
1743
    except KeyboardInterrupt:
1668
1744
        if debug:
1669
1745
            print >> sys.stderr
1670
1746
        logger.debug(u"Server received KeyboardInterrupt")
1671
1747
    logger.debug(u"Server exiting")
 
1748
    # Must run before the D-Bus bus name gets deregistered
 
1749
    cleanup()
1672
1750
 
1673
1751
if __name__ == '__main__':
1674
1752
    main()