/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-02-05 03:15:43 UTC
  • Revision ID: teddy@fukt.bsnet.se-20090205031543-cyd3j09i6iut38w1
* plugin-runner.c (struct plugin.status): Changed type to "int".
  (main): Check "proc->completed" before "proc->eof", since
          "completed" is of type "sig_atomic_t".

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
             (facility = logging.handlers.SysLogHandler.LOG_DAEMON,
74
74
              address = "/dev/log"))
75
75
syslogger.setFormatter(logging.Formatter
76
 
                       ('Mandos: %(levelname)s: %(message)s'))
 
76
                       ('Mandos [%(process)d]: %(levelname)s:'
 
77
                        ' %(message)s'))
77
78
logger.addHandler(syslogger)
78
79
 
79
80
console = logging.StreamHandler()
80
 
console.setFormatter(logging.Formatter('%(name)s: %(levelname)s:'
81
 
                                       ' %(message)s'))
 
81
console.setFormatter(logging.Formatter('%(name)s [%(process)d]:'
 
82
                                       ' %(levelname)s: %(message)s'))
82
83
logger.addHandler(console)
83
84
 
84
85
class AvahiError(Exception):
226
227
        if config is None:
227
228
            config = {}
228
229
        logger.debug(u"Creating client %r", self.name)
229
 
        self.use_dbus = use_dbus
230
 
        if self.use_dbus:
231
 
            self.dbus_object_path = (dbus.ObjectPath
232
 
                                     ("/Mandos/clients/"
233
 
                                      + self.name.replace(".", "_")))
234
 
            dbus.service.Object.__init__(self, bus,
235
 
                                         self.dbus_object_path)
 
230
        self.use_dbus = False   # During __init__
236
231
        # Uppercase and remove spaces from fingerprint for later
237
232
        # comparison purposes with return value from the fingerprint()
238
233
        # function
262
257
        self.disable_initiator_tag = None
263
258
        self.checker_callback_tag = None
264
259
        self.checker_command = config["checker"]
 
260
        self.last_connect = None
 
261
        # Only now, when this client is initialized, can it show up on
 
262
        # the D-Bus
 
263
        self.use_dbus = use_dbus
 
264
        if self.use_dbus:
 
265
            self.dbus_object_path = (dbus.ObjectPath
 
266
                                     ("/clients/"
 
267
                                      + self.name.replace(".", "_")))
 
268
            dbus.service.Object.__init__(self, bus,
 
269
                                         self.dbus_object_path)
265
270
    
266
271
    def enable(self):
267
272
        """Start this client's checker and timeout hooks"""
320
325
            # Emit D-Bus signal
321
326
            self.PropertyChanged(dbus.String(u"checker_running"),
322
327
                                 dbus.Boolean(False, variant_level=1))
323
 
        if (os.WIFEXITED(condition)
324
 
            and (os.WEXITSTATUS(condition) == 0)):
325
 
            logger.info(u"Checker for %(name)s succeeded",
326
 
                        vars(self))
 
328
        if os.WIFEXITED(condition):
 
329
            exitstatus = os.WEXITSTATUS(condition)
 
330
            if exitstatus == 0:
 
331
                logger.info(u"Checker for %(name)s succeeded",
 
332
                            vars(self))
 
333
                self.checked_ok()
 
334
            else:
 
335
                logger.info(u"Checker for %(name)s failed",
 
336
                            vars(self))
327
337
            if self.use_dbus:
328
338
                # Emit D-Bus signal
329
 
                self.CheckerCompleted(dbus.Boolean(True),
330
 
                                      dbus.UInt16(condition),
 
339
                self.CheckerCompleted(dbus.Int16(exitstatus),
 
340
                                      dbus.Int64(condition),
331
341
                                      dbus.String(command))
332
 
            self.bump_timeout()
333
 
        elif not os.WIFEXITED(condition):
 
342
        else:
334
343
            logger.warning(u"Checker for %(name)s crashed?",
335
344
                           vars(self))
336
345
            if self.use_dbus:
337
346
                # Emit D-Bus signal
338
 
                self.CheckerCompleted(dbus.Boolean(False),
339
 
                                      dbus.UInt16(condition),
340
 
                                      dbus.String(command))
341
 
        else:
342
 
            logger.info(u"Checker for %(name)s failed",
343
 
                        vars(self))
344
 
            if self.use_dbus:
345
 
                # Emit D-Bus signal
346
 
                self.CheckerCompleted(dbus.Boolean(False),
347
 
                                      dbus.UInt16(condition),
 
347
                self.CheckerCompleted(dbus.Int16(-1),
 
348
                                      dbus.Int64(condition),
348
349
                                      dbus.String(command))
349
350
    
350
 
    def bump_timeout(self):
 
351
    def checked_ok(self):
351
352
        """Bump up the timeout for this client.
352
353
        This should only be called when the client has been seen,
353
354
        alive and well.
449
450
            return now < (self.last_checked_ok + self.timeout)
450
451
    
451
452
    ## D-Bus methods & signals
452
 
    _interface = u"org.mandos_system.Mandos.Client"
 
453
    _interface = u"se.bsnet.fukt.Mandos.Client"
453
454
    
454
 
    # BumpTimeout - method
455
 
    BumpTimeout = dbus.service.method(_interface)(bump_timeout)
456
 
    BumpTimeout.__name__ = "BumpTimeout"
 
455
    # CheckedOK - method
 
456
    CheckedOK = dbus.service.method(_interface)(checked_ok)
 
457
    CheckedOK.__name__ = "CheckedOK"
457
458
    
458
459
    # CheckerCompleted - signal
459
 
    @dbus.service.signal(_interface, signature="bqs")
460
 
    def CheckerCompleted(self, success, condition, command):
 
460
    @dbus.service.signal(_interface, signature="nxs")
 
461
    def CheckerCompleted(self, exitcode, waitstatus, command):
461
462
        "D-Bus signal"
462
463
        pass
463
464
    
595
596
        != gnutls.library.constants.GNUTLS_CRT_OPENPGP):
596
597
        # ...do the normal thing
597
598
        return session.peer_certificate
598
 
    list_size = ctypes.c_uint()
 
599
    list_size = ctypes.c_uint(1)
599
600
    cert_list = (gnutls.library.functions
600
601
                 .gnutls_certificate_get_peers
601
602
                 (session._c_object, ctypes.byref(list_size)))
 
603
    if not bool(cert_list) and list_size.value != 0:
 
604
        raise gnutls.errors.GNUTLSError("error getting peer"
 
605
                                        " certificate")
602
606
    if list_size.value == 0:
603
607
        return None
604
608
    cert = cert_list[0]
673
677
        # using OpenPGP certificates.
674
678
        
675
679
        #priority = ':'.join(("NONE", "+VERS-TLS1.1", "+AES-256-CBC",
676
 
        #                "+SHA1", "+COMP-NULL", "+CTYPE-OPENPGP",
677
 
        #                "+DHE-DSS"))
 
680
        #                     "+SHA1", "+COMP-NULL", "+CTYPE-OPENPGP",
 
681
        #                     "+DHE-DSS"))
678
682
        # Use a fallback default, since this MUST be set.
679
683
        priority = self.server.settings.get("priority", "NORMAL")
680
684
        (gnutls.library.functions
688
692
            # Do not run session.bye() here: the session is not
689
693
            # established.  Just abandon the request.
690
694
            return
 
695
        logger.debug(u"Handshake succeeded")
691
696
        try:
692
697
            fpr = fingerprint(peer_certificate(session))
693
698
        except (TypeError, gnutls.errors.GNUTLSError), error:
695
700
            session.bye()
696
701
            return
697
702
        logger.debug(u"Fingerprint: %s", fpr)
 
703
        
698
704
        for c in self.server.clients:
699
705
            if c.fingerprint == fpr:
700
706
                client = c
713
719
            session.bye()
714
720
            return
715
721
        ## This won't work here, since we're in a fork.
716
 
        # client.bump_timeout()
 
722
        # client.checked_ok()
717
723
        sent_size = 0
718
724
        while sent_size < len(client.secret):
719
725
            sent = session.send(client.secret[sent_size:])
759
765
                                 u" bind to interface %s",
760
766
                                 self.settings["interface"])
761
767
                else:
762
 
                    raise error
 
768
                    raise
763
769
        # Only bind(2) the socket if we really need to.
764
770
        if self.server_address[0] or self.server_address[1]:
765
771
            if not self.server_address[0]:
786
792
 
787
793
def string_to_delta(interval):
788
794
    """Parse a string and return a datetime.timedelta
789
 
 
 
795
    
790
796
    >>> string_to_delta('7d')
791
797
    datetime.timedelta(7)
792
798
    >>> string_to_delta('60s')
941
947
    server_config.read(os.path.join(options.configdir, "mandos.conf"))
942
948
    # Convert the SafeConfigParser object to a dict
943
949
    server_settings = server_config.defaults()
944
 
    # Use getboolean on the boolean config options
945
 
    server_settings["debug"] = (server_config.getboolean
946
 
                                ("DEFAULT", "debug"))
947
 
    server_settings["use_dbus"] = (server_config.getboolean
948
 
                                   ("DEFAULT", "use_dbus"))
 
950
    # Use the appropriate methods on the non-string config options
 
951
    server_settings["debug"] = server_config.getboolean("DEFAULT",
 
952
                                                        "debug")
 
953
    server_settings["use_dbus"] = server_config.getboolean("DEFAULT",
 
954
                                                           "use_dbus")
 
955
    if server_settings["port"]:
 
956
        server_settings["port"] = server_config.getint("DEFAULT",
 
957
                                                       "port")
949
958
    del server_config
950
959
    
951
960
    # Override the settings from the config file with command line
992
1001
    pidfilename = "/var/run/mandos.pid"
993
1002
    try:
994
1003
        pidfile = open(pidfilename, "w")
995
 
    except IOError, error:
 
1004
    except IOError:
996
1005
        logger.error("Could not open file %r", pidfilename)
997
1006
    
998
1007
    try:
1010
1019
                uid = 65534
1011
1020
                gid = 65534
1012
1021
    try:
 
1022
        os.setgid(gid)
1013
1023
        os.setuid(uid)
1014
 
        os.setgid(gid)
1015
1024
    except OSError, error:
1016
1025
        if error[0] != errno.EPERM:
1017
1026
            raise error
1018
1027
    
 
1028
    # Enable all possible GnuTLS debugging
 
1029
    if debug:
 
1030
        # "Use a log level over 10 to enable all debugging options."
 
1031
        # - GnuTLS manual
 
1032
        gnutls.library.functions.gnutls_global_set_log_level(11)
 
1033
        
 
1034
        @gnutls.library.types.gnutls_log_func
 
1035
        def debug_gnutls(level, string):
 
1036
            logger.debug("GnuTLS: %s", string[:-1])
 
1037
        
 
1038
        (gnutls.library.functions
 
1039
         .gnutls_global_set_log_function(debug_gnutls))
 
1040
    
1019
1041
    global service
1020
1042
    service = AvahiService(name = server_settings["servicename"],
1021
1043
                           servicetype = "_mandos._tcp", )
1035
1057
                            avahi.DBUS_INTERFACE_SERVER)
1036
1058
    # End of Avahi example code
1037
1059
    if use_dbus:
1038
 
        bus_name = dbus.service.BusName(u"org.mandos-system.Mandos",
1039
 
                                        bus)
 
1060
        bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos", bus)
1040
1061
    
1041
1062
    clients.update(Set(Client(name = section,
1042
1063
                              config
1096
1117
        class MandosServer(dbus.service.Object):
1097
1118
            """A D-Bus proxy object"""
1098
1119
            def __init__(self):
1099
 
                dbus.service.Object.__init__(self, bus,
1100
 
                                             "/Mandos")
1101
 
            _interface = u"org.mandos_system.Mandos"
 
1120
                dbus.service.Object.__init__(self, bus, "/")
 
1121
            _interface = u"se.bsnet.fukt.Mandos"
1102
1122
            
1103
1123
            @dbus.service.signal(_interface, signature="oa{sv}")
1104
1124
            def ClientAdded(self, objpath, properties):
1112
1132
            
1113
1133
            @dbus.service.method(_interface, out_signature="ao")
1114
1134
            def GetAllClients(self):
 
1135
                "D-Bus method"
1115
1136
                return dbus.Array(c.dbus_object_path for c in clients)
1116
1137
            
1117
1138
            @dbus.service.method(_interface, out_signature="a{oa{sv}}")
1118
1139
            def GetAllClientsWithProperties(self):
 
1140
                "D-Bus method"
1119
1141
                return dbus.Dictionary(
1120
1142
                    ((c.dbus_object_path, c.GetAllProperties())
1121
1143
                     for c in clients),
1123
1145
            
1124
1146
            @dbus.service.method(_interface, in_signature="o")
1125
1147
            def RemoveClient(self, object_path):
 
1148
                "D-Bus method"
1126
1149
                for c in clients:
1127
1150
                    if c.dbus_object_path == object_path:
1128
1151
                        clients.remove(c)
1134
1157
                        return
1135
1158
                raise KeyError
1136
1159
            
1137
 
            @dbus.service.method(_interface, in_signature="s")
1138
 
            def RemoveClientByName(self, name):
1139
 
                for c in clients:
1140
 
                    if c.name == name:
1141
 
                        clients.remove(c)
1142
 
                        # Don't signal anything except ClientRemoved
1143
 
                        c.use_dbus = False
1144
 
                        c.disable()
1145
 
                        # Emit D-Bus signal
1146
 
                        self.ClientRemoved(c.dbus_object_path, name)
1147
 
                        return
1148
 
                raise KeyError
1149
 
            
1150
 
            @dbus.service.method(_interface)
1151
 
            def Quit(self):
1152
 
                main_loop.quit()
1153
 
            
1154
1160
            del _interface
1155
1161
        
1156
1162
        mandos_server = MandosServer()
1194
1200
        sys.exit(1)
1195
1201
    except KeyboardInterrupt:
1196
1202
        if debug:
1197
 
            print
 
1203
            print >> sys.stderr
 
1204
        logger.debug("Server received KeyboardInterrupt")
 
1205
    logger.debug("Server exiting")
1198
1206
 
1199
1207
if __name__ == '__main__':
1200
1208
    main()