/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: 2011-03-08 11:08:35 UTC
  • Revision ID: teddy@fukt.bsnet.se-20110308110835-3sh7b314tf7q3o1i
* plugins.d/password-prompt.c (conflict_detection): Check for both
                                                    "plymouth" and
                                                    "plymouthd".

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
import SocketServer as socketserver
38
38
import socket
39
 
import argparse
 
39
import optparse
40
40
import datetime
41
41
import errno
42
42
import gnutls.crypto
82
82
        SO_BINDTODEVICE = None
83
83
 
84
84
 
85
 
version = "1.3.1"
 
85
version = "1.2.3"
86
86
 
87
87
#logger = logging.getLogger('mandos')
88
88
logger = logging.Logger('mandos')
151
151
        self.group = None       # our entry group
152
152
        self.server = None
153
153
        self.bus = bus
154
 
        self.entry_group_state_changed_match = None
155
154
    def rename(self):
156
155
        """Derived from the Avahi example code"""
157
156
        if self.rename_count >= self.max_renames:
169
168
        self.remove()
170
169
        try:
171
170
            self.add()
172
 
        except dbus.exceptions.DBusException as error:
 
171
        except dbus.exceptions.DBusException, error:
173
172
            logger.critical("DBusException: %s", error)
174
173
            self.cleanup()
175
174
            os._exit(1)
176
175
        self.rename_count += 1
177
176
    def remove(self):
178
177
        """Derived from the Avahi example code"""
179
 
        if self.entry_group_state_changed_match is not None:
180
 
            self.entry_group_state_changed_match.remove()
181
 
            self.entry_group_state_changed_match = None
182
178
        if self.group is not None:
183
179
            self.group.Reset()
184
180
    def add(self):
185
181
        """Derived from the Avahi example code"""
186
 
        self.remove()
187
182
        if self.group is None:
188
183
            self.group = dbus.Interface(
189
184
                self.bus.get_object(avahi.DBUS_NAME,
190
185
                                    self.server.EntryGroupNew()),
191
186
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
192
 
        self.entry_group_state_changed_match = (
193
 
            self.group.connect_to_signal(
194
 
                'StateChanged', self .entry_group_state_changed))
 
187
            self.group.connect_to_signal('StateChanged',
 
188
                                         self
 
189
                                         .entry_group_state_changed)
195
190
        logger.debug("Adding Zeroconf service '%s' of type '%s' ...",
196
191
                     self.name, self.type)
197
192
        self.group.AddService(
220
215
    def cleanup(self):
221
216
        """Derived from the Avahi example code"""
222
217
        if self.group is not None:
223
 
            try:
224
 
                self.group.Free()
225
 
            except (dbus.exceptions.UnknownMethodException,
226
 
                    dbus.exceptions.DBusException) as e:
227
 
                pass
 
218
            self.group.Free()
228
219
            self.group = None
229
 
        self.remove()
230
 
    def server_state_changed(self, state, error=None):
 
220
    def server_state_changed(self, state):
231
221
        """Derived from the Avahi example code"""
232
222
        logger.debug("Avahi server state change: %i", state)
233
 
        bad_states = { avahi.SERVER_INVALID:
234
 
                           "Zeroconf server invalid",
235
 
                       avahi.SERVER_REGISTERING: None,
236
 
                       avahi.SERVER_COLLISION:
237
 
                           "Zeroconf server name collision",
238
 
                       avahi.SERVER_FAILURE:
239
 
                           "Zeroconf server failure" }
240
 
        if state in bad_states:
241
 
            if bad_states[state] is not None:
242
 
                if error is None:
243
 
                    logger.error(bad_states[state])
244
 
                else:
245
 
                    logger.error(bad_states[state] + ": %r", error)
246
 
            self.cleanup()
 
223
        if state == avahi.SERVER_COLLISION:
 
224
            logger.error("Zeroconf server name collision")
 
225
            self.remove()
247
226
        elif state == avahi.SERVER_RUNNING:
248
227
            self.add()
249
 
        else:
250
 
            if error is None:
251
 
                logger.debug("Unknown state: %r", state)
252
 
            else:
253
 
                logger.debug("Unknown state: %r: %r", state, error)
254
228
    def activate(self):
255
229
        """Derived from the Avahi example code"""
256
230
        if self.server is None:
257
231
            self.server = dbus.Interface(
258
232
                self.bus.get_object(avahi.DBUS_NAME,
259
 
                                    avahi.DBUS_PATH_SERVER,
260
 
                                    follow_name_owner_changes=True),
 
233
                                    avahi.DBUS_PATH_SERVER),
261
234
                avahi.DBUS_INTERFACE_SERVER)
262
235
        self.server.connect_to_signal("StateChanged",
263
236
                                 self.server_state_changed)
264
237
        self.server_state_changed(self.server.GetState())
265
238
 
266
239
 
267
 
def _timedelta_to_milliseconds(td):
268
 
    "Convert a datetime.timedelta() to milliseconds"
269
 
    return ((td.days * 24 * 60 * 60 * 1000)
270
 
            + (td.seconds * 1000)
271
 
            + (td.microseconds // 1000))
272
 
        
273
240
class Client(object):
274
241
    """A representation of a client host served by this server.
275
242
    
303
270
    secret:     bytestring; sent verbatim (over TLS) to client
304
271
    timeout:    datetime.timedelta(); How long from last_checked_ok
305
272
                                      until this client is disabled
306
 
    extended_timeout:   extra long timeout when password has been sent
307
273
    runtime_expansions: Allowed attributes for runtime expansion.
308
 
    expires:    datetime.datetime(); time (UTC) when a client will be
309
 
                disabled, or None
310
274
    """
311
275
    
312
276
    runtime_expansions = ("approval_delay", "approval_duration",
313
277
                          "created", "enabled", "fingerprint",
314
278
                          "host", "interval", "last_checked_ok",
315
279
                          "last_enabled", "name", "timeout")
316
 
        
 
280
    
 
281
    @staticmethod
 
282
    def _timedelta_to_milliseconds(td):
 
283
        "Convert a datetime.timedelta() to milliseconds"
 
284
        return ((td.days * 24 * 60 * 60 * 1000)
 
285
                + (td.seconds * 1000)
 
286
                + (td.microseconds // 1000))
 
287
    
317
288
    def timeout_milliseconds(self):
318
289
        "Return the 'timeout' attribute in milliseconds"
319
 
        return _timedelta_to_milliseconds(self.timeout)
320
 
 
321
 
    def extended_timeout_milliseconds(self):
322
 
        "Return the 'extended_timeout' attribute in milliseconds"
323
 
        return _timedelta_to_milliseconds(self.extended_timeout)    
 
290
        return self._timedelta_to_milliseconds(self.timeout)
324
291
    
325
292
    def interval_milliseconds(self):
326
293
        "Return the 'interval' attribute in milliseconds"
327
 
        return _timedelta_to_milliseconds(self.interval)
 
294
        return self._timedelta_to_milliseconds(self.interval)
328
295
 
329
296
    def approval_delay_milliseconds(self):
330
 
        return _timedelta_to_milliseconds(self.approval_delay)
 
297
        return self._timedelta_to_milliseconds(self.approval_delay)
331
298
    
332
299
    def __init__(self, name = None, disable_hook=None, config=None):
333
300
        """Note: the 'checker' key in 'config' sets the
360
327
        self.last_enabled = None
361
328
        self.last_checked_ok = None
362
329
        self.timeout = string_to_delta(config["timeout"])
363
 
        self.extended_timeout = string_to_delta(config["extended_timeout"])
364
330
        self.interval = string_to_delta(config["interval"])
365
331
        self.disable_hook = disable_hook
366
332
        self.checker = None
367
333
        self.checker_initiator_tag = None
368
334
        self.disable_initiator_tag = None
369
 
        self.expires = None
370
335
        self.checker_callback_tag = None
371
336
        self.checker_command = config["checker"]
372
337
        self.current_checker_command = None
392
357
            # Already enabled
393
358
            return
394
359
        self.send_changedstate()
 
360
        self.last_enabled = datetime.datetime.utcnow()
395
361
        # Schedule a new checker to be started an 'interval' from now,
396
362
        # and every interval from then on.
397
363
        self.checker_initiator_tag = (gobject.timeout_add
398
364
                                      (self.interval_milliseconds(),
399
365
                                       self.start_checker))
400
366
        # Schedule a disable() when 'timeout' has passed
401
 
        self.expires = datetime.datetime.utcnow() + self.timeout
402
367
        self.disable_initiator_tag = (gobject.timeout_add
403
368
                                   (self.timeout_milliseconds(),
404
369
                                    self.disable))
405
370
        self.enabled = True
406
 
        self.last_enabled = datetime.datetime.utcnow()
407
371
        # Also start a new checker *right now*.
408
372
        self.start_checker()
409
373
    
418
382
        if getattr(self, "disable_initiator_tag", False):
419
383
            gobject.source_remove(self.disable_initiator_tag)
420
384
            self.disable_initiator_tag = None
421
 
        self.expires = None
422
385
        if getattr(self, "checker_initiator_tag", False):
423
386
            gobject.source_remove(self.checker_initiator_tag)
424
387
            self.checker_initiator_tag = None
450
413
            logger.warning("Checker for %(name)s crashed?",
451
414
                           vars(self))
452
415
    
453
 
    def checked_ok(self, timeout=None):
 
416
    def checked_ok(self):
454
417
        """Bump up the timeout for this client.
455
418
        
456
419
        This should only be called when the client has been seen,
457
420
        alive and well.
458
421
        """
459
 
        if timeout is None:
460
 
            timeout = self.timeout
461
422
        self.last_checked_ok = datetime.datetime.utcnow()
462
423
        gobject.source_remove(self.disable_initiator_tag)
463
 
        self.expires = datetime.datetime.utcnow() + timeout
464
424
        self.disable_initiator_tag = (gobject.timeout_add
465
 
                                      (_timedelta_to_milliseconds(timeout),
 
425
                                      (self.timeout_milliseconds(),
466
426
                                       self.disable))
467
427
    
468
428
    def need_approval(self):
485
445
        # If a checker exists, make sure it is not a zombie
486
446
        try:
487
447
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
488
 
        except (AttributeError, OSError) as error:
 
448
        except (AttributeError, OSError), error:
489
449
            if (isinstance(error, OSError)
490
450
                and error.errno != errno.ECHILD):
491
451
                raise error
512
472
 
513
473
                try:
514
474
                    command = self.checker_command % escaped_attrs
515
 
                except TypeError as error:
 
475
                except TypeError, error:
516
476
                    logger.error('Could not format string "%s":'
517
477
                                 ' %s', self.checker_command, error)
518
478
                    return True # Try again later
537
497
                if pid:
538
498
                    gobject.source_remove(self.checker_callback_tag)
539
499
                    self.checker_callback(pid, status, command)
540
 
            except OSError as error:
 
500
            except OSError, error:
541
501
                logger.error("Failed to start subprocess: %s",
542
502
                             error)
543
503
        # Re-run this periodically if run by gobject.timeout_add
556
516
            #time.sleep(0.5)
557
517
            #if self.checker.poll() is None:
558
518
            #    os.kill(self.checker.pid, signal.SIGKILL)
559
 
        except OSError as error:
 
519
        except OSError, error:
560
520
            if error.errno != errno.ESRCH: # No such process
561
521
                raise
562
522
        self.checker = None
744
704
            xmlstring = document.toxml("utf-8")
745
705
            document.unlink()
746
706
        except (AttributeError, xml.dom.DOMException,
747
 
                xml.parsers.expat.ExpatError) as error:
 
707
                xml.parsers.expat.ExpatError), error:
748
708
            logger.error("Failed to override Introspection method",
749
709
                         error)
750
710
        return xmlstring
751
711
 
752
712
 
753
 
def datetime_to_dbus (dt, variant_level=0):
754
 
    """Convert a UTC datetime.datetime() to a D-Bus type."""
755
 
    if dt is None:
756
 
        return dbus.String("", variant_level = variant_level)
757
 
    return dbus.String(dt.isoformat(),
758
 
                       variant_level=variant_level)
759
 
 
760
713
class ClientDBus(Client, DBusObjectWithProperties):
761
714
    """A Client class using D-Bus
762
715
    
784
737
        DBusObjectWithProperties.__init__(self, self.bus,
785
738
                                          self.dbus_object_path)
786
739
        
787
 
    def notifychangeproperty(transform_func,
788
 
                             dbus_name, type_func=lambda x: x,
789
 
                             variant_level=1):
790
 
        """ Modify a variable so that its a property that announce its
791
 
        changes to DBus.
792
 
        transform_fun: Function that takes a value and transform it to
793
 
                       DBus type.
794
 
        dbus_name: DBus name of the variable
795
 
        type_func: Function that transform the value before sending it
796
 
                   to DBus
797
 
        variant_level: DBus variant level. default: 1
798
 
        """
799
 
        real_value = [None,]
800
 
        def setter(self, value):
801
 
            old_value = real_value[0]
802
 
            real_value[0] = value
803
 
            if hasattr(self, "dbus_object_path"):
804
 
                if type_func(old_value) != type_func(real_value[0]):
805
 
                    dbus_value = transform_func(type_func(real_value[0]),
806
 
                                                variant_level)
807
 
                    self.PropertyChanged(dbus.String(dbus_name),
808
 
                                         dbus_value)
809
 
 
810
 
        return property(lambda self: real_value[0], setter)
811
 
 
812
 
 
813
 
    expires = notifychangeproperty(datetime_to_dbus, "Expires")
814
 
    approvals_pending = notifychangeproperty(dbus.Boolean,
815
 
                                             "ApprovalPending",
816
 
                                             type_func = bool)
817
 
    enabled = notifychangeproperty(dbus.Boolean, "Enabled")
818
 
    last_enabled = notifychangeproperty(datetime_to_dbus,
819
 
                                        "LastEnabled")
820
 
    checker = notifychangeproperty(dbus.Boolean, "CheckerRunning",
821
 
                                   type_func = lambda checker: checker is not None)
822
 
    last_checked_ok = notifychangeproperty(datetime_to_dbus,
823
 
                                           "LastCheckedOK")
824
 
    last_approval_request = notifychangeproperty(datetime_to_dbus,
825
 
                                                 "LastApprovalRequest")
826
 
    approved_by_default = notifychangeproperty(dbus.Boolean,
827
 
                                               "ApprovedByDefault")
828
 
    approval_delay = notifychangeproperty(dbus.UInt16, "ApprovalDelay",
829
 
                                          type_func = _timedelta_to_milliseconds)
830
 
    approval_duration = notifychangeproperty(dbus.UInt16, "ApprovalDuration",
831
 
                                             type_func = _timedelta_to_milliseconds)
832
 
    host = notifychangeproperty(dbus.String, "Host")
833
 
    timeout = notifychangeproperty(dbus.UInt16, "Timeout",
834
 
                                   type_func = _timedelta_to_milliseconds)
835
 
    extended_timeout = notifychangeproperty(dbus.UInt16, "ExtendedTimeout",
836
 
                                            type_func = _timedelta_to_milliseconds)
837
 
    interval = notifychangeproperty(dbus.UInt16, "Interval",
838
 
                                    type_func = _timedelta_to_milliseconds)
839
 
    checker_command = notifychangeproperty(dbus.String, "Checker")
840
 
    
841
 
    del notifychangeproperty
 
740
    def _get_approvals_pending(self):
 
741
        return self._approvals_pending
 
742
    def _set_approvals_pending(self, value):
 
743
        old_value = self._approvals_pending
 
744
        self._approvals_pending = value
 
745
        bval = bool(value)
 
746
        if (hasattr(self, "dbus_object_path")
 
747
            and bval is not bool(old_value)):
 
748
            dbus_bool = dbus.Boolean(bval, variant_level=1)
 
749
            self.PropertyChanged(dbus.String("ApprovalPending"),
 
750
                                 dbus_bool)
 
751
 
 
752
    approvals_pending = property(_get_approvals_pending,
 
753
                                 _set_approvals_pending)
 
754
    del _get_approvals_pending, _set_approvals_pending
 
755
    
 
756
    @staticmethod
 
757
    def _datetime_to_dbus(dt, variant_level=0):
 
758
        """Convert a UTC datetime.datetime() to a D-Bus type."""
 
759
        return dbus.String(dt.isoformat(),
 
760
                           variant_level=variant_level)
 
761
    
 
762
    def enable(self):
 
763
        oldstate = getattr(self, "enabled", False)
 
764
        r = Client.enable(self)
 
765
        if oldstate != self.enabled:
 
766
            # Emit D-Bus signals
 
767
            self.PropertyChanged(dbus.String("Enabled"),
 
768
                                 dbus.Boolean(True, variant_level=1))
 
769
            self.PropertyChanged(
 
770
                dbus.String("LastEnabled"),
 
771
                self._datetime_to_dbus(self.last_enabled,
 
772
                                       variant_level=1))
 
773
        return r
 
774
    
 
775
    def disable(self, quiet = False):
 
776
        oldstate = getattr(self, "enabled", False)
 
777
        r = Client.disable(self, quiet=quiet)
 
778
        if not quiet and oldstate != self.enabled:
 
779
            # Emit D-Bus signal
 
780
            self.PropertyChanged(dbus.String("Enabled"),
 
781
                                 dbus.Boolean(False, variant_level=1))
 
782
        return r
842
783
    
843
784
    def __del__(self, *args, **kwargs):
844
785
        try:
853
794
                         *args, **kwargs):
854
795
        self.checker_callback_tag = None
855
796
        self.checker = None
 
797
        # Emit D-Bus signal
 
798
        self.PropertyChanged(dbus.String("CheckerRunning"),
 
799
                             dbus.Boolean(False, variant_level=1))
856
800
        if os.WIFEXITED(condition):
857
801
            exitstatus = os.WEXITSTATUS(condition)
858
802
            # Emit D-Bus signal
867
811
        
868
812
        return Client.checker_callback(self, pid, condition, command,
869
813
                                       *args, **kwargs)
870
 
 
 
814
    
 
815
    def checked_ok(self, *args, **kwargs):
 
816
        r = Client.checked_ok(self, *args, **kwargs)
 
817
        # Emit D-Bus signal
 
818
        self.PropertyChanged(
 
819
            dbus.String("LastCheckedOK"),
 
820
            (self._datetime_to_dbus(self.last_checked_ok,
 
821
                                    variant_level=1)))
 
822
        return r
 
823
    
 
824
    def need_approval(self, *args, **kwargs):
 
825
        r = Client.need_approval(self, *args, **kwargs)
 
826
        # Emit D-Bus signal
 
827
        self.PropertyChanged(
 
828
            dbus.String("LastApprovalRequest"),
 
829
            (self._datetime_to_dbus(self.last_approval_request,
 
830
                                    variant_level=1)))
 
831
        return r
 
832
    
871
833
    def start_checker(self, *args, **kwargs):
872
834
        old_checker = self.checker
873
835
        if self.checker is not None:
880
842
            and old_checker_pid != self.checker.pid):
881
843
            # Emit D-Bus signal
882
844
            self.CheckerStarted(self.current_checker_command)
 
845
            self.PropertyChanged(
 
846
                dbus.String("CheckerRunning"),
 
847
                dbus.Boolean(True, variant_level=1))
883
848
        return r
884
849
    
 
850
    def stop_checker(self, *args, **kwargs):
 
851
        old_checker = getattr(self, "checker", None)
 
852
        r = Client.stop_checker(self, *args, **kwargs)
 
853
        if (old_checker is not None
 
854
            and getattr(self, "checker", None) is None):
 
855
            self.PropertyChanged(dbus.String("CheckerRunning"),
 
856
                                 dbus.Boolean(False, variant_level=1))
 
857
        return r
 
858
 
885
859
    def _reset_approved(self):
886
860
        self._approved = None
887
861
        return False
889
863
    def approve(self, value=True):
890
864
        self.send_changedstate()
891
865
        self._approved = value
892
 
        gobject.timeout_add(_timedelta_to_milliseconds
 
866
        gobject.timeout_add(self._timedelta_to_milliseconds
893
867
                            (self.approval_duration),
894
868
                            self._reset_approved)
895
869
    
948
922
    # CheckedOK - method
949
923
    @dbus.service.method(_interface)
950
924
    def CheckedOK(self):
951
 
        self.checked_ok()
 
925
        return self.checked_ok()
952
926
    
953
927
    # Enable - method
954
928
    @dbus.service.method(_interface)
987
961
        if value is None:       # get
988
962
            return dbus.Boolean(self.approved_by_default)
989
963
        self.approved_by_default = bool(value)
 
964
        # Emit D-Bus signal
 
965
        self.PropertyChanged(dbus.String("ApprovedByDefault"),
 
966
                             dbus.Boolean(value, variant_level=1))
990
967
    
991
968
    # ApprovalDelay - property
992
969
    @dbus_service_property(_interface, signature="t",
995
972
        if value is None:       # get
996
973
            return dbus.UInt64(self.approval_delay_milliseconds())
997
974
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
 
975
        # Emit D-Bus signal
 
976
        self.PropertyChanged(dbus.String("ApprovalDelay"),
 
977
                             dbus.UInt64(value, variant_level=1))
998
978
    
999
979
    # ApprovalDuration - property
1000
980
    @dbus_service_property(_interface, signature="t",
1001
981
                           access="readwrite")
1002
982
    def ApprovalDuration_dbus_property(self, value=None):
1003
983
        if value is None:       # get
1004
 
            return dbus.UInt64(_timedelta_to_milliseconds(
 
984
            return dbus.UInt64(self._timedelta_to_milliseconds(
1005
985
                    self.approval_duration))
1006
986
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
 
987
        # Emit D-Bus signal
 
988
        self.PropertyChanged(dbus.String("ApprovalDuration"),
 
989
                             dbus.UInt64(value, variant_level=1))
1007
990
    
1008
991
    # Name - property
1009
992
    @dbus_service_property(_interface, signature="s", access="read")
1022
1005
        if value is None:       # get
1023
1006
            return dbus.String(self.host)
1024
1007
        self.host = value
 
1008
        # Emit D-Bus signal
 
1009
        self.PropertyChanged(dbus.String("Host"),
 
1010
                             dbus.String(value, variant_level=1))
1025
1011
    
1026
1012
    # Created - property
1027
1013
    @dbus_service_property(_interface, signature="s", access="read")
1028
1014
    def Created_dbus_property(self):
1029
 
        return dbus.String(datetime_to_dbus(self.created))
 
1015
        return dbus.String(self._datetime_to_dbus(self.created))
1030
1016
    
1031
1017
    # LastEnabled - property
1032
1018
    @dbus_service_property(_interface, signature="s", access="read")
1033
1019
    def LastEnabled_dbus_property(self):
1034
 
        return datetime_to_dbus(self.last_enabled)
 
1020
        if self.last_enabled is None:
 
1021
            return dbus.String("")
 
1022
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
1035
1023
    
1036
1024
    # Enabled - property
1037
1025
    @dbus_service_property(_interface, signature="b",
1051
1039
        if value is not None:
1052
1040
            self.checked_ok()
1053
1041
            return
1054
 
        return datetime_to_dbus(self.last_checked_ok)
1055
 
    
1056
 
    # Expires - property
1057
 
    @dbus_service_property(_interface, signature="s", access="read")
1058
 
    def Expires_dbus_property(self):
1059
 
        return datetime_to_dbus(self.expires)
 
1042
        if self.last_checked_ok is None:
 
1043
            return dbus.String("")
 
1044
        return dbus.String(self._datetime_to_dbus(self
 
1045
                                                  .last_checked_ok))
1060
1046
    
1061
1047
    # LastApprovalRequest - property
1062
1048
    @dbus_service_property(_interface, signature="s", access="read")
1063
1049
    def LastApprovalRequest_dbus_property(self):
1064
 
        return datetime_to_dbus(self.last_approval_request)
 
1050
        if self.last_approval_request is None:
 
1051
            return dbus.String("")
 
1052
        return dbus.String(self.
 
1053
                           _datetime_to_dbus(self
 
1054
                                             .last_approval_request))
1065
1055
    
1066
1056
    # Timeout - property
1067
1057
    @dbus_service_property(_interface, signature="t",
1070
1060
        if value is None:       # get
1071
1061
            return dbus.UInt64(self.timeout_milliseconds())
1072
1062
        self.timeout = datetime.timedelta(0, 0, 0, value)
 
1063
        # Emit D-Bus signal
 
1064
        self.PropertyChanged(dbus.String("Timeout"),
 
1065
                             dbus.UInt64(value, variant_level=1))
1073
1066
        if getattr(self, "disable_initiator_tag", None) is None:
1074
1067
            return
1075
1068
        # Reschedule timeout
1076
1069
        gobject.source_remove(self.disable_initiator_tag)
1077
1070
        self.disable_initiator_tag = None
1078
 
        self.expires = None
1079
1071
        time_to_die = (self.
1080
1072
                       _timedelta_to_milliseconds((self
1081
1073
                                                   .last_checked_ok
1086
1078
            # The timeout has passed
1087
1079
            self.disable()
1088
1080
        else:
1089
 
            self.expires = (datetime.datetime.utcnow()
1090
 
                            + datetime.timedelta(milliseconds = time_to_die))
1091
1081
            self.disable_initiator_tag = (gobject.timeout_add
1092
1082
                                          (time_to_die, self.disable))
1093
 
 
1094
 
    # ExtendedTimeout - property
1095
 
    @dbus_service_property(_interface, signature="t",
1096
 
                           access="readwrite")
1097
 
    def ExtendedTimeout_dbus_property(self, value=None):
1098
 
        if value is None:       # get
1099
 
            return dbus.UInt64(self.extended_timeout_milliseconds())
1100
 
        self.extended_timeout = datetime.timedelta(0, 0, 0, value)
1101
 
 
 
1083
    
1102
1084
    # Interval - property
1103
1085
    @dbus_service_property(_interface, signature="t",
1104
1086
                           access="readwrite")
1106
1088
        if value is None:       # get
1107
1089
            return dbus.UInt64(self.interval_milliseconds())
1108
1090
        self.interval = datetime.timedelta(0, 0, 0, value)
 
1091
        # Emit D-Bus signal
 
1092
        self.PropertyChanged(dbus.String("Interval"),
 
1093
                             dbus.UInt64(value, variant_level=1))
1109
1094
        if getattr(self, "checker_initiator_tag", None) is None:
1110
1095
            return
1111
1096
        # Reschedule checker run
1121
1106
        if value is None:       # get
1122
1107
            return dbus.String(self.checker_command)
1123
1108
        self.checker_command = value
 
1109
        # Emit D-Bus signal
 
1110
        self.PropertyChanged(dbus.String("Checker"),
 
1111
                             dbus.String(self.checker_command,
 
1112
                                         variant_level=1))
1124
1113
    
1125
1114
    # CheckerRunning - property
1126
1115
    @dbus_service_property(_interface, signature="b",
1215
1204
            try:
1216
1205
                if int(line.strip().split()[0]) > 1:
1217
1206
                    raise RuntimeError
1218
 
            except (ValueError, IndexError, RuntimeError) as error:
 
1207
            except (ValueError, IndexError, RuntimeError), error:
1219
1208
                logger.error("Unknown protocol version: %s", error)
1220
1209
                return
1221
1210
 
1222
1211
            # Start GnuTLS connection
1223
1212
            try:
1224
1213
                session.handshake()
1225
 
            except gnutls.errors.GNUTLSError as error:
 
1214
            except gnutls.errors.GNUTLSError, error:
1226
1215
                logger.warning("Handshake failed: %s", error)
1227
1216
                # Do not run session.bye() here: the session is not
1228
1217
                # established.  Just abandon the request.
1234
1223
                try:
1235
1224
                    fpr = self.fingerprint(self.peer_certificate
1236
1225
                                           (session))
1237
 
                except (TypeError,
1238
 
                        gnutls.errors.GNUTLSError) as error:
 
1226
                except (TypeError, gnutls.errors.GNUTLSError), error:
1239
1227
                    logger.warning("Bad certificate: %s", error)
1240
1228
                    return
1241
1229
                logger.debug("Fingerprint: %s", fpr)
1253
1241
                
1254
1242
                while True:
1255
1243
                    if not client.enabled:
1256
 
                        logger.info("Client %s is disabled",
 
1244
                        logger.warning("Client %s is disabled",
1257
1245
                                       client.name)
1258
1246
                        if self.server.use_dbus:
1259
1247
                            # Emit D-Bus signal
1304
1292
                while sent_size < len(client.secret):
1305
1293
                    try:
1306
1294
                        sent = session.send(client.secret[sent_size:])
1307
 
                    except gnutls.errors.GNUTLSError as error:
 
1295
                    except (gnutls.errors.GNUTLSError), error:
1308
1296
                        logger.warning("gnutls send failed")
1309
1297
                        return
1310
1298
                    logger.debug("Sent: %d, remaining: %d",
1314
1302
 
1315
1303
                logger.info("Sending secret to %s", client.name)
1316
1304
                # bump the timeout as if seen
1317
 
                client.checked_ok(client.extended_timeout)
 
1305
                client.checked_ok()
1318
1306
                if self.server.use_dbus:
1319
1307
                    # Emit D-Bus signal
1320
1308
                    client.GotSecret()
1324
1312
                    client.approvals_pending -= 1
1325
1313
                try:
1326
1314
                    session.bye()
1327
 
                except gnutls.errors.GNUTLSError as error:
 
1315
                except (gnutls.errors.GNUTLSError), error:
1328
1316
                    logger.warning("GnuTLS bye failed")
1329
1317
    
1330
1318
    @staticmethod
1454
1442
                                           SO_BINDTODEVICE,
1455
1443
                                           str(self.interface
1456
1444
                                               + '\0'))
1457
 
                except socket.error as error:
 
1445
                except socket.error, error:
1458
1446
                    if error[0] == errno.EPERM:
1459
1447
                        logger.error("No permission to"
1460
1448
                                     " bind to interface %s",
1554
1542
                    client = c
1555
1543
                    break
1556
1544
            else:
1557
 
                logger.info("Client not found for fingerprint: %s, ad"
1558
 
                            "dress: %s", fpr, address)
 
1545
                logger.warning("Client not found for fingerprint: %s, ad"
 
1546
                               "dress: %s", fpr, address)
1559
1547
                if self.use_dbus:
1560
1548
                    # Emit D-Bus signal
1561
1549
                    mandos_dbus_service.ClientNotFound(fpr, address[0])
1625
1613
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1626
1614
            else:
1627
1615
                raise ValueError("Unknown suffix %r" % suffix)
1628
 
        except (ValueError, IndexError) as e:
 
1616
        except (ValueError, IndexError), e:
1629
1617
            raise ValueError(*(e.args))
1630
1618
        timevalue += delta
1631
1619
    return timevalue
1685
1673
    ##################################################################
1686
1674
    # Parsing of options, both command line and config file
1687
1675
    
1688
 
    parser = argparse.ArgumentParser()
1689
 
    parser.add_argument("-v", "--version", action="version",
1690
 
                        version = "%%(prog)s %s" % version,
1691
 
                        help="show version number and exit")
1692
 
    parser.add_argument("-i", "--interface", metavar="IF",
1693
 
                        help="Bind to interface IF")
1694
 
    parser.add_argument("-a", "--address",
1695
 
                        help="Address to listen for requests on")
1696
 
    parser.add_argument("-p", "--port", type=int,
1697
 
                        help="Port number to receive requests on")
1698
 
    parser.add_argument("--check", action="store_true",
1699
 
                        help="Run self-test")
1700
 
    parser.add_argument("--debug", action="store_true",
1701
 
                        help="Debug mode; run in foreground and log"
1702
 
                        " to terminal")
1703
 
    parser.add_argument("--debuglevel", metavar="LEVEL",
1704
 
                        help="Debug level for stdout output")
1705
 
    parser.add_argument("--priority", help="GnuTLS"
1706
 
                        " priority string (see GnuTLS documentation)")
1707
 
    parser.add_argument("--servicename",
1708
 
                        metavar="NAME", help="Zeroconf service name")
1709
 
    parser.add_argument("--configdir",
1710
 
                        default="/etc/mandos", metavar="DIR",
1711
 
                        help="Directory to search for configuration"
1712
 
                        " files")
1713
 
    parser.add_argument("--no-dbus", action="store_false",
1714
 
                        dest="use_dbus", help="Do not provide D-Bus"
1715
 
                        " system bus interface")
1716
 
    parser.add_argument("--no-ipv6", action="store_false",
1717
 
                        dest="use_ipv6", help="Do not use IPv6")
1718
 
    options = parser.parse_args()
 
1676
    parser = optparse.OptionParser(version = "%%prog %s" % version)
 
1677
    parser.add_option("-i", "--interface", type="string",
 
1678
                      metavar="IF", help="Bind to interface IF")
 
1679
    parser.add_option("-a", "--address", type="string",
 
1680
                      help="Address to listen for requests on")
 
1681
    parser.add_option("-p", "--port", type="int",
 
1682
                      help="Port number to receive requests on")
 
1683
    parser.add_option("--check", action="store_true",
 
1684
                      help="Run self-test")
 
1685
    parser.add_option("--debug", action="store_true",
 
1686
                      help="Debug mode; run in foreground and log to"
 
1687
                      " terminal")
 
1688
    parser.add_option("--debuglevel", type="string", metavar="LEVEL",
 
1689
                      help="Debug level for stdout output")
 
1690
    parser.add_option("--priority", type="string", help="GnuTLS"
 
1691
                      " priority string (see GnuTLS documentation)")
 
1692
    parser.add_option("--servicename", type="string",
 
1693
                      metavar="NAME", help="Zeroconf service name")
 
1694
    parser.add_option("--configdir", type="string",
 
1695
                      default="/etc/mandos", metavar="DIR",
 
1696
                      help="Directory to search for configuration"
 
1697
                      " files")
 
1698
    parser.add_option("--no-dbus", action="store_false",
 
1699
                      dest="use_dbus", help="Do not provide D-Bus"
 
1700
                      " system bus interface")
 
1701
    parser.add_option("--no-ipv6", action="store_false",
 
1702
                      dest="use_ipv6", help="Do not use IPv6")
 
1703
    options = parser.parse_args()[0]
1719
1704
    
1720
1705
    if options.check:
1721
1706
        import doctest
1781
1766
                                % server_settings["servicename"]))
1782
1767
    
1783
1768
    # Parse config file with clients
1784
 
    client_defaults = { "timeout": "5m",
1785
 
                        "extended_timeout": "15m",
1786
 
                        "interval": "2m",
 
1769
    client_defaults = { "timeout": "1h",
 
1770
                        "interval": "5m",
1787
1771
                        "checker": "fping -q -- %%(host)s",
1788
1772
                        "host": "",
1789
1773
                        "approval_delay": "0s",
1829
1813
    try:
1830
1814
        os.setgid(gid)
1831
1815
        os.setuid(uid)
1832
 
    except OSError as error:
 
1816
    except OSError, error:
1833
1817
        if error[0] != errno.EPERM:
1834
1818
            raise error
1835
1819
    
1879
1863
        try:
1880
1864
            bus_name = dbus.service.BusName("se.bsnet.fukt.Mandos",
1881
1865
                                            bus, do_not_queue=True)
1882
 
        except dbus.exceptions.NameExistsException as e:
 
1866
        except dbus.exceptions.NameExistsException, e:
1883
1867
            logger.error(unicode(e) + ", disabling D-Bus")
1884
1868
            use_dbus = False
1885
1869
            server_settings["use_dbus"] = False
2035
2019
        # From the Avahi example code
2036
2020
        try:
2037
2021
            service.activate()
2038
 
        except dbus.exceptions.DBusException as error:
 
2022
        except dbus.exceptions.DBusException, error:
2039
2023
            logger.critical("DBusException: %s", error)
2040
2024
            cleanup()
2041
2025
            sys.exit(1)
2048
2032
        
2049
2033
        logger.debug("Starting main loop")
2050
2034
        main_loop.run()
2051
 
    except AvahiError as error:
 
2035
    except AvahiError, error:
2052
2036
        logger.critical("AvahiError: %s", error)
2053
2037
        cleanup()
2054
2038
        sys.exit(1)