/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-10-02 13:47:52 UTC
  • Revision ID: teddy@fukt.bsnet.se-20111002134752-c5g5ibcga4biz7ob
* plugins.d/plymouth.c (plymouth_pid): Changed to
                                       "/run/initramfs/plymouth.pid".
  (plymouth_old_pid): New; set to "/dev/.initramfs/plymouth.pid".
  (get_pid): Try both 'plymouth_pid' and 'plymouth_old_pid'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
82
82
        SO_BINDTODEVICE = None
83
83
 
84
84
 
85
 
version = "1.3.0"
 
85
version = "1.3.1"
86
86
 
87
87
#logger = logging.getLogger('mandos')
88
88
logger = logging.Logger('mandos')
264
264
        self.server_state_changed(self.server.GetState())
265
265
 
266
266
 
 
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
        
267
273
class Client(object):
268
274
    """A representation of a client host served by this server.
269
275
    
297
303
    secret:     bytestring; sent verbatim (over TLS) to client
298
304
    timeout:    datetime.timedelta(); How long from last_checked_ok
299
305
                                      until this client is disabled
 
306
    extended_timeout:   extra long timeout when password has been sent
300
307
    runtime_expansions: Allowed attributes for runtime expansion.
 
308
    expires:    datetime.datetime(); time (UTC) when a client will be
 
309
                disabled, or None
301
310
    """
302
311
    
303
312
    runtime_expansions = ("approval_delay", "approval_duration",
305
314
                          "host", "interval", "last_checked_ok",
306
315
                          "last_enabled", "name", "timeout")
307
316
    
308
 
    @staticmethod
309
 
    def _timedelta_to_milliseconds(td):
310
 
        "Convert a datetime.timedelta() to milliseconds"
311
 
        return ((td.days * 24 * 60 * 60 * 1000)
312
 
                + (td.seconds * 1000)
313
 
                + (td.microseconds // 1000))
314
 
    
315
317
    def timeout_milliseconds(self):
316
318
        "Return the 'timeout' attribute in milliseconds"
317
 
        return self._timedelta_to_milliseconds(self.timeout)
 
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)    
318
324
    
319
325
    def interval_milliseconds(self):
320
326
        "Return the 'interval' attribute in milliseconds"
321
 
        return self._timedelta_to_milliseconds(self.interval)
322
 
 
 
327
        return _timedelta_to_milliseconds(self.interval)
 
328
    
323
329
    def approval_delay_milliseconds(self):
324
 
        return self._timedelta_to_milliseconds(self.approval_delay)
 
330
        return _timedelta_to_milliseconds(self.approval_delay)
325
331
    
326
332
    def __init__(self, name = None, disable_hook=None, config=None):
327
333
        """Note: the 'checker' key in 'config' sets the
354
360
        self.last_enabled = None
355
361
        self.last_checked_ok = None
356
362
        self.timeout = string_to_delta(config["timeout"])
 
363
        self.extended_timeout = string_to_delta(config["extended_timeout"])
357
364
        self.interval = string_to_delta(config["interval"])
358
365
        self.disable_hook = disable_hook
359
366
        self.checker = None
360
367
        self.checker_initiator_tag = None
361
368
        self.disable_initiator_tag = None
 
369
        self.expires = None
362
370
        self.checker_callback_tag = None
363
371
        self.checker_command = config["checker"]
364
372
        self.current_checker_command = None
384
392
            # Already enabled
385
393
            return
386
394
        self.send_changedstate()
387
 
        self.last_enabled = datetime.datetime.utcnow()
388
395
        # Schedule a new checker to be started an 'interval' from now,
389
396
        # and every interval from then on.
390
397
        self.checker_initiator_tag = (gobject.timeout_add
391
398
                                      (self.interval_milliseconds(),
392
399
                                       self.start_checker))
393
400
        # Schedule a disable() when 'timeout' has passed
 
401
        self.expires = datetime.datetime.utcnow() + self.timeout
394
402
        self.disable_initiator_tag = (gobject.timeout_add
395
403
                                   (self.timeout_milliseconds(),
396
404
                                    self.disable))
397
405
        self.enabled = True
 
406
        self.last_enabled = datetime.datetime.utcnow()
398
407
        # Also start a new checker *right now*.
399
408
        self.start_checker()
400
409
    
409
418
        if getattr(self, "disable_initiator_tag", False):
410
419
            gobject.source_remove(self.disable_initiator_tag)
411
420
            self.disable_initiator_tag = None
 
421
        self.expires = None
412
422
        if getattr(self, "checker_initiator_tag", False):
413
423
            gobject.source_remove(self.checker_initiator_tag)
414
424
            self.checker_initiator_tag = None
440
450
            logger.warning("Checker for %(name)s crashed?",
441
451
                           vars(self))
442
452
    
443
 
    def checked_ok(self):
 
453
    def checked_ok(self, timeout=None):
444
454
        """Bump up the timeout for this client.
445
455
        
446
456
        This should only be called when the client has been seen,
447
457
        alive and well.
448
458
        """
 
459
        if timeout is None:
 
460
            timeout = self.timeout
449
461
        self.last_checked_ok = datetime.datetime.utcnow()
450
462
        gobject.source_remove(self.disable_initiator_tag)
 
463
        self.expires = datetime.datetime.utcnow() + timeout
451
464
        self.disable_initiator_tag = (gobject.timeout_add
452
 
                                      (self.timeout_milliseconds(),
 
465
                                      (_timedelta_to_milliseconds(timeout),
453
466
                                       self.disable))
454
467
    
455
468
    def need_approval(self):
496
509
                                       'replace')))
497
510
                    for attr in
498
511
                    self.runtime_expansions)
499
 
 
 
512
                
500
513
                try:
501
514
                    command = self.checker_command % escaped_attrs
502
515
                except TypeError as error:
548
561
                raise
549
562
        self.checker = None
550
563
 
 
564
 
551
565
def dbus_service_property(dbus_interface, signature="v",
552
566
                          access="readwrite", byte_arrays=False):
553
567
    """Decorators for marking methods of a DBusObjectWithProperties to
599
613
 
600
614
class DBusObjectWithProperties(dbus.service.Object):
601
615
    """A D-Bus object with properties.
602
 
 
 
616
    
603
617
    Classes inheriting from this can use the dbus_service_property
604
618
    decorator to expose methods as D-Bus properties.  It exposes the
605
619
    standard Get(), Set(), and GetAll() methods on the D-Bus.
669
683
    def GetAll(self, interface_name):
670
684
        """Standard D-Bus property GetAll() method, see D-Bus
671
685
        standard.
672
 
 
 
686
        
673
687
        Note: Will not include properties with access="write".
674
688
        """
675
689
        all = {}
737
751
        return xmlstring
738
752
 
739
753
 
 
754
def datetime_to_dbus (dt, variant_level=0):
 
755
    """Convert a UTC datetime.datetime() to a D-Bus type."""
 
756
    if dt is None:
 
757
        return dbus.String("", variant_level = variant_level)
 
758
    return dbus.String(dt.isoformat(),
 
759
                       variant_level=variant_level)
 
760
 
 
761
 
740
762
class ClientDBus(Client, DBusObjectWithProperties):
741
763
    """A Client class using D-Bus
742
764
    
764
786
        DBusObjectWithProperties.__init__(self, self.bus,
765
787
                                          self.dbus_object_path)
766
788
        
767
 
    def _get_approvals_pending(self):
768
 
        return self._approvals_pending
769
 
    def _set_approvals_pending(self, value):
770
 
        old_value = self._approvals_pending
771
 
        self._approvals_pending = value
772
 
        bval = bool(value)
773
 
        if (hasattr(self, "dbus_object_path")
774
 
            and bval is not bool(old_value)):
775
 
            dbus_bool = dbus.Boolean(bval, variant_level=1)
776
 
            self.PropertyChanged(dbus.String("ApprovalPending"),
777
 
                                 dbus_bool)
778
 
 
779
 
    approvals_pending = property(_get_approvals_pending,
780
 
                                 _set_approvals_pending)
781
 
    del _get_approvals_pending, _set_approvals_pending
782
 
    
783
 
    @staticmethod
784
 
    def _datetime_to_dbus(dt, variant_level=0):
785
 
        """Convert a UTC datetime.datetime() to a D-Bus type."""
786
 
        return dbus.String(dt.isoformat(),
787
 
                           variant_level=variant_level)
788
 
    
789
 
    def enable(self):
790
 
        oldstate = getattr(self, "enabled", False)
791
 
        r = Client.enable(self)
792
 
        if oldstate != self.enabled:
793
 
            # Emit D-Bus signals
794
 
            self.PropertyChanged(dbus.String("Enabled"),
795
 
                                 dbus.Boolean(True, variant_level=1))
796
 
            self.PropertyChanged(
797
 
                dbus.String("LastEnabled"),
798
 
                self._datetime_to_dbus(self.last_enabled,
799
 
                                       variant_level=1))
800
 
        return r
801
 
    
802
 
    def disable(self, quiet = False):
803
 
        oldstate = getattr(self, "enabled", False)
804
 
        r = Client.disable(self, quiet=quiet)
805
 
        if not quiet and oldstate != self.enabled:
806
 
            # Emit D-Bus signal
807
 
            self.PropertyChanged(dbus.String("Enabled"),
808
 
                                 dbus.Boolean(False, variant_level=1))
809
 
        return r
 
789
    def notifychangeproperty(transform_func,
 
790
                             dbus_name, type_func=lambda x: x,
 
791
                             variant_level=1):
 
792
        """ Modify a variable so that its a property that announce its
 
793
        changes to DBus.
 
794
        transform_fun: Function that takes a value and transform it to
 
795
                       DBus type.
 
796
        dbus_name: DBus name of the variable
 
797
        type_func: Function that transform the value before sending it
 
798
                   to DBus
 
799
        variant_level: DBus variant level. default: 1
 
800
        """
 
801
        real_value = [None,]
 
802
        def setter(self, value):
 
803
            old_value = real_value[0]
 
804
            real_value[0] = value
 
805
            if hasattr(self, "dbus_object_path"):
 
806
                if type_func(old_value) != type_func(real_value[0]):
 
807
                    dbus_value = transform_func(type_func(real_value[0]),
 
808
                                                variant_level)
 
809
                    self.PropertyChanged(dbus.String(dbus_name),
 
810
                                         dbus_value)
 
811
        
 
812
        return property(lambda self: real_value[0], setter)
 
813
    
 
814
    
 
815
    expires = notifychangeproperty(datetime_to_dbus, "Expires")
 
816
    approvals_pending = notifychangeproperty(dbus.Boolean,
 
817
                                             "ApprovalPending",
 
818
                                             type_func = bool)
 
819
    enabled = notifychangeproperty(dbus.Boolean, "Enabled")
 
820
    last_enabled = notifychangeproperty(datetime_to_dbus,
 
821
                                        "LastEnabled")
 
822
    checker = notifychangeproperty(dbus.Boolean, "CheckerRunning",
 
823
                                   type_func = lambda checker: checker is not None)
 
824
    last_checked_ok = notifychangeproperty(datetime_to_dbus,
 
825
                                           "LastCheckedOK")
 
826
    last_approval_request = notifychangeproperty(datetime_to_dbus,
 
827
                                                 "LastApprovalRequest")
 
828
    approved_by_default = notifychangeproperty(dbus.Boolean,
 
829
                                               "ApprovedByDefault")
 
830
    approval_delay = notifychangeproperty(dbus.UInt16, "ApprovalDelay",
 
831
                                          type_func = _timedelta_to_milliseconds)
 
832
    approval_duration = notifychangeproperty(dbus.UInt16, "ApprovalDuration",
 
833
                                             type_func = _timedelta_to_milliseconds)
 
834
    host = notifychangeproperty(dbus.String, "Host")
 
835
    timeout = notifychangeproperty(dbus.UInt16, "Timeout",
 
836
                                   type_func = _timedelta_to_milliseconds)
 
837
    extended_timeout = notifychangeproperty(dbus.UInt16, "ExtendedTimeout",
 
838
                                            type_func = _timedelta_to_milliseconds)
 
839
    interval = notifychangeproperty(dbus.UInt16, "Interval",
 
840
                                    type_func = _timedelta_to_milliseconds)
 
841
    checker_command = notifychangeproperty(dbus.String, "Checker")
 
842
    
 
843
    del notifychangeproperty
810
844
    
811
845
    def __del__(self, *args, **kwargs):
812
846
        try:
821
855
                         *args, **kwargs):
822
856
        self.checker_callback_tag = None
823
857
        self.checker = None
824
 
        # Emit D-Bus signal
825
 
        self.PropertyChanged(dbus.String("CheckerRunning"),
826
 
                             dbus.Boolean(False, variant_level=1))
827
858
        if os.WIFEXITED(condition):
828
859
            exitstatus = os.WEXITSTATUS(condition)
829
860
            # Emit D-Bus signal
839
870
        return Client.checker_callback(self, pid, condition, command,
840
871
                                       *args, **kwargs)
841
872
    
842
 
    def checked_ok(self, *args, **kwargs):
843
 
        Client.checked_ok(self, *args, **kwargs)
844
 
        # Emit D-Bus signal
845
 
        self.PropertyChanged(
846
 
            dbus.String("LastCheckedOK"),
847
 
            (self._datetime_to_dbus(self.last_checked_ok,
848
 
                                    variant_level=1)))
849
 
    
850
 
    def need_approval(self, *args, **kwargs):
851
 
        r = Client.need_approval(self, *args, **kwargs)
852
 
        # Emit D-Bus signal
853
 
        self.PropertyChanged(
854
 
            dbus.String("LastApprovalRequest"),
855
 
            (self._datetime_to_dbus(self.last_approval_request,
856
 
                                    variant_level=1)))
857
 
        return r
858
 
    
859
873
    def start_checker(self, *args, **kwargs):
860
874
        old_checker = self.checker
861
875
        if self.checker is not None:
868
882
            and old_checker_pid != self.checker.pid):
869
883
            # Emit D-Bus signal
870
884
            self.CheckerStarted(self.current_checker_command)
871
 
            self.PropertyChanged(
872
 
                dbus.String("CheckerRunning"),
873
 
                dbus.Boolean(True, variant_level=1))
874
885
        return r
875
886
    
876
 
    def stop_checker(self, *args, **kwargs):
877
 
        old_checker = getattr(self, "checker", None)
878
 
        r = Client.stop_checker(self, *args, **kwargs)
879
 
        if (old_checker is not None
880
 
            and getattr(self, "checker", None) is None):
881
 
            self.PropertyChanged(dbus.String("CheckerRunning"),
882
 
                                 dbus.Boolean(False, variant_level=1))
883
 
        return r
884
 
 
885
887
    def _reset_approved(self):
886
888
        self._approved = None
887
889
        return False
889
891
    def approve(self, value=True):
890
892
        self.send_changedstate()
891
893
        self._approved = value
892
 
        gobject.timeout_add(self._timedelta_to_milliseconds
 
894
        gobject.timeout_add(_timedelta_to_milliseconds
893
895
                            (self.approval_duration),
894
896
                            self._reset_approved)
895
897
    
987
989
        if value is None:       # get
988
990
            return dbus.Boolean(self.approved_by_default)
989
991
        self.approved_by_default = bool(value)
990
 
        # Emit D-Bus signal
991
 
        self.PropertyChanged(dbus.String("ApprovedByDefault"),
992
 
                             dbus.Boolean(value, variant_level=1))
993
992
    
994
993
    # ApprovalDelay - property
995
994
    @dbus_service_property(_interface, signature="t",
998
997
        if value is None:       # get
999
998
            return dbus.UInt64(self.approval_delay_milliseconds())
1000
999
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
1001
 
        # Emit D-Bus signal
1002
 
        self.PropertyChanged(dbus.String("ApprovalDelay"),
1003
 
                             dbus.UInt64(value, variant_level=1))
1004
1000
    
1005
1001
    # ApprovalDuration - property
1006
1002
    @dbus_service_property(_interface, signature="t",
1007
1003
                           access="readwrite")
1008
1004
    def ApprovalDuration_dbus_property(self, value=None):
1009
1005
        if value is None:       # get
1010
 
            return dbus.UInt64(self._timedelta_to_milliseconds(
 
1006
            return dbus.UInt64(_timedelta_to_milliseconds(
1011
1007
                    self.approval_duration))
1012
1008
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
1013
 
        # Emit D-Bus signal
1014
 
        self.PropertyChanged(dbus.String("ApprovalDuration"),
1015
 
                             dbus.UInt64(value, variant_level=1))
1016
1009
    
1017
1010
    # Name - property
1018
1011
    @dbus_service_property(_interface, signature="s", access="read")
1031
1024
        if value is None:       # get
1032
1025
            return dbus.String(self.host)
1033
1026
        self.host = value
1034
 
        # Emit D-Bus signal
1035
 
        self.PropertyChanged(dbus.String("Host"),
1036
 
                             dbus.String(value, variant_level=1))
1037
1027
    
1038
1028
    # Created - property
1039
1029
    @dbus_service_property(_interface, signature="s", access="read")
1040
1030
    def Created_dbus_property(self):
1041
 
        return dbus.String(self._datetime_to_dbus(self.created))
 
1031
        return dbus.String(datetime_to_dbus(self.created))
1042
1032
    
1043
1033
    # LastEnabled - property
1044
1034
    @dbus_service_property(_interface, signature="s", access="read")
1045
1035
    def LastEnabled_dbus_property(self):
1046
 
        if self.last_enabled is None:
1047
 
            return dbus.String("")
1048
 
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
 
1036
        return datetime_to_dbus(self.last_enabled)
1049
1037
    
1050
1038
    # Enabled - property
1051
1039
    @dbus_service_property(_interface, signature="b",
1065
1053
        if value is not None:
1066
1054
            self.checked_ok()
1067
1055
            return
1068
 
        if self.last_checked_ok is None:
1069
 
            return dbus.String("")
1070
 
        return dbus.String(self._datetime_to_dbus(self
1071
 
                                                  .last_checked_ok))
 
1056
        return datetime_to_dbus(self.last_checked_ok)
 
1057
    
 
1058
    # Expires - property
 
1059
    @dbus_service_property(_interface, signature="s", access="read")
 
1060
    def Expires_dbus_property(self):
 
1061
        return datetime_to_dbus(self.expires)
1072
1062
    
1073
1063
    # LastApprovalRequest - property
1074
1064
    @dbus_service_property(_interface, signature="s", access="read")
1075
1065
    def LastApprovalRequest_dbus_property(self):
1076
 
        if self.last_approval_request is None:
1077
 
            return dbus.String("")
1078
 
        return dbus.String(self.
1079
 
                           _datetime_to_dbus(self
1080
 
                                             .last_approval_request))
 
1066
        return datetime_to_dbus(self.last_approval_request)
1081
1067
    
1082
1068
    # Timeout - property
1083
1069
    @dbus_service_property(_interface, signature="t",
1086
1072
        if value is None:       # get
1087
1073
            return dbus.UInt64(self.timeout_milliseconds())
1088
1074
        self.timeout = datetime.timedelta(0, 0, 0, value)
1089
 
        # Emit D-Bus signal
1090
 
        self.PropertyChanged(dbus.String("Timeout"),
1091
 
                             dbus.UInt64(value, variant_level=1))
1092
1075
        if getattr(self, "disable_initiator_tag", None) is None:
1093
1076
            return
1094
1077
        # Reschedule timeout
1095
1078
        gobject.source_remove(self.disable_initiator_tag)
1096
1079
        self.disable_initiator_tag = None
 
1080
        self.expires = None
1097
1081
        time_to_die = (self.
1098
1082
                       _timedelta_to_milliseconds((self
1099
1083
                                                   .last_checked_ok
1104
1088
            # The timeout has passed
1105
1089
            self.disable()
1106
1090
        else:
 
1091
            self.expires = (datetime.datetime.utcnow()
 
1092
                            + datetime.timedelta(milliseconds = time_to_die))
1107
1093
            self.disable_initiator_tag = (gobject.timeout_add
1108
1094
                                          (time_to_die, self.disable))
1109
1095
    
 
1096
    # ExtendedTimeout - property
 
1097
    @dbus_service_property(_interface, signature="t",
 
1098
                           access="readwrite")
 
1099
    def ExtendedTimeout_dbus_property(self, value=None):
 
1100
        if value is None:       # get
 
1101
            return dbus.UInt64(self.extended_timeout_milliseconds())
 
1102
        self.extended_timeout = datetime.timedelta(0, 0, 0, value)
 
1103
    
1110
1104
    # Interval - property
1111
1105
    @dbus_service_property(_interface, signature="t",
1112
1106
                           access="readwrite")
1114
1108
        if value is None:       # get
1115
1109
            return dbus.UInt64(self.interval_milliseconds())
1116
1110
        self.interval = datetime.timedelta(0, 0, 0, value)
1117
 
        # Emit D-Bus signal
1118
 
        self.PropertyChanged(dbus.String("Interval"),
1119
 
                             dbus.UInt64(value, variant_level=1))
1120
1111
        if getattr(self, "checker_initiator_tag", None) is None:
1121
1112
            return
1122
1113
        # Reschedule checker run
1124
1115
        self.checker_initiator_tag = (gobject.timeout_add
1125
1116
                                      (value, self.start_checker))
1126
1117
        self.start_checker()    # Start one now, too
1127
 
 
 
1118
    
1128
1119
    # Checker - property
1129
1120
    @dbus_service_property(_interface, signature="s",
1130
1121
                           access="readwrite")
1132
1123
        if value is None:       # get
1133
1124
            return dbus.String(self.checker_command)
1134
1125
        self.checker_command = value
1135
 
        # Emit D-Bus signal
1136
 
        self.PropertyChanged(dbus.String("Checker"),
1137
 
                             dbus.String(self.checker_command,
1138
 
                                         variant_level=1))
1139
1126
    
1140
1127
    # CheckerRunning - property
1141
1128
    @dbus_service_property(_interface, signature="b",
1168
1155
        self._pipe.send(('init', fpr, address))
1169
1156
        if not self._pipe.recv():
1170
1157
            raise KeyError()
1171
 
 
 
1158
    
1172
1159
    def __getattribute__(self, name):
1173
1160
        if(name == '_pipe'):
1174
1161
            return super(ProxyClient, self).__getattribute__(name)
1181
1168
                self._pipe.send(('funcall', name, args, kwargs))
1182
1169
                return self._pipe.recv()[1]
1183
1170
            return func
1184
 
 
 
1171
    
1185
1172
    def __setattr__(self, name, value):
1186
1173
        if(name == '_pipe'):
1187
1174
            return super(ProxyClient, self).__setattr__(name, value)
1200
1187
                        unicode(self.client_address))
1201
1188
            logger.debug("Pipe FD: %d",
1202
1189
                         self.server.child_pipe.fileno())
1203
 
 
 
1190
            
1204
1191
            session = (gnutls.connection
1205
1192
                       .ClientSession(self.request,
1206
1193
                                      gnutls.connection
1207
1194
                                      .X509Credentials()))
1208
 
 
 
1195
            
1209
1196
            # Note: gnutls.connection.X509Credentials is really a
1210
1197
            # generic GnuTLS certificate credentials object so long as
1211
1198
            # no X.509 keys are added to it.  Therefore, we can use it
1212
1199
            # here despite using OpenPGP certificates.
1213
 
 
 
1200
            
1214
1201
            #priority = ':'.join(("NONE", "+VERS-TLS1.1",
1215
1202
            #                      "+AES-256-CBC", "+SHA1",
1216
1203
            #                      "+COMP-NULL", "+CTYPE-OPENPGP",
1222
1209
            (gnutls.library.functions
1223
1210
             .gnutls_priority_set_direct(session._c_object,
1224
1211
                                         priority, None))
1225
 
 
 
1212
            
1226
1213
            # Start communication using the Mandos protocol
1227
1214
            # Get protocol number
1228
1215
            line = self.request.makefile().readline()
1233
1220
            except (ValueError, IndexError, RuntimeError) as error:
1234
1221
                logger.error("Unknown protocol version: %s", error)
1235
1222
                return
1236
 
 
 
1223
            
1237
1224
            # Start GnuTLS connection
1238
1225
            try:
1239
1226
                session.handshake()
1243
1230
                # established.  Just abandon the request.
1244
1231
                return
1245
1232
            logger.debug("Handshake succeeded")
1246
 
 
 
1233
            
1247
1234
            approval_required = False
1248
1235
            try:
1249
1236
                try:
1254
1241
                    logger.warning("Bad certificate: %s", error)
1255
1242
                    return
1256
1243
                logger.debug("Fingerprint: %s", fpr)
1257
 
 
 
1244
                
1258
1245
                try:
1259
1246
                    client = ProxyClient(child_pipe, fpr,
1260
1247
                                         self.client_address)
1326
1313
                                 sent, len(client.secret)
1327
1314
                                 - (sent_size + sent))
1328
1315
                    sent_size += sent
1329
 
 
 
1316
                
1330
1317
                logger.info("Sending secret to %s", client.name)
1331
1318
                # bump the timeout as if seen
1332
 
                client.checked_ok()
 
1319
                client.checked_ok(client.extended_timeout)
1333
1320
                if self.server.use_dbus:
1334
1321
                    # Emit D-Bus signal
1335
1322
                    client.GotSecret()
1420
1407
        multiprocessing.Process(target = self.sub_process_main,
1421
1408
                                args = (request, address)).start()
1422
1409
 
 
1410
 
1423
1411
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
1424
1412
    """ adds a pipe to the MixIn """
1425
1413
    def process_request(self, request, client_address):
1428
1416
        This function creates a new pipe in self.pipe
1429
1417
        """
1430
1418
        parent_pipe, self.child_pipe = multiprocessing.Pipe()
1431
 
 
 
1419
        
1432
1420
        super(MultiprocessingMixInWithPipe,
1433
1421
              self).process_request(request, client_address)
1434
1422
        self.child_pipe.close()
1435
1423
        self.add_pipe(parent_pipe)
1436
 
 
 
1424
    
1437
1425
    def add_pipe(self, parent_pipe):
1438
1426
        """Dummy function; override as necessary"""
1439
1427
        raise NotImplementedError
1440
1428
 
 
1429
 
1441
1430
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
1442
1431
                     socketserver.TCPServer, object):
1443
1432
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
1591
1580
            kwargs = request[3]
1592
1581
            
1593
1582
            parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1594
 
 
 
1583
        
1595
1584
        if command == 'getattr':
1596
1585
            attrname = request[1]
1597
1586
            if callable(client_object.__getattribute__(attrname)):
1603
1592
            attrname = request[1]
1604
1593
            value = request[2]
1605
1594
            setattr(client_object, attrname, value)
1606
 
 
 
1595
        
1607
1596
        return True
1608
1597
 
1609
1598
 
1788
1777
    debuglevel = server_settings["debuglevel"]
1789
1778
    use_dbus = server_settings["use_dbus"]
1790
1779
    use_ipv6 = server_settings["use_ipv6"]
1791
 
 
 
1780
    
1792
1781
    if server_settings["servicename"] != "Mandos":
1793
1782
        syslogger.setFormatter(logging.Formatter
1794
1783
                               ('Mandos (%s) [%%(process)d]:'
1796
1785
                                % server_settings["servicename"]))
1797
1786
    
1798
1787
    # Parse config file with clients
1799
 
    client_defaults = { "timeout": "1h",
1800
 
                        "interval": "5m",
 
1788
    client_defaults = { "timeout": "5m",
 
1789
                        "extended_timeout": "15m",
 
1790
                        "interval": "2m",
1801
1791
                        "checker": "fping -q -- %%(host)s",
1802
1792
                        "host": "",
1803
1793
                        "approval_delay": "0s",
1854
1844
        level = getattr(logging, debuglevel.upper())
1855
1845
        syslogger.setLevel(level)
1856
1846
        console.setLevel(level)
1857
 
 
 
1847
    
1858
1848
    if debug:
1859
1849
        # Enable all possible GnuTLS debugging
1860
1850
        
1947
1937
        del pidfilename
1948
1938
        
1949
1939
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1950
 
 
 
1940
    
1951
1941
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1952
1942
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())
1953
1943
    
2074
2064
    # Must run before the D-Bus bus name gets deregistered
2075
2065
    cleanup()
2076
2066
 
 
2067
 
2077
2068
if __name__ == '__main__':
2078
2069
    main()