/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-08-08 21:12:37 UTC
  • Revision ID: teddy@fukt.bsnet.se-20110808211237-jejsz5brjytrjot8
* Makefile (DOCS): Added "intro.8mandos".
  (intro.8mandos, intro.8mandos.xhtml): New.
* README: Replaced text with link, reference and short summary.
* intro.xml: New.
* mandos-clients.conf.xml (SEE ALSO): Added "intro(8mandos)".
* mandos-ctl.xml (SEE ALSO): - '' -
* mandos-keygen.xml (SEE ALSO): - '' -
* mandos-monitor.xml (SEE ALSO): - '' -
* mandos.conf.xml (SEE ALSO): - '' -
* mandos.xml (SEE ALSO): - '' -
* plugin-runner.xml (SEE ALSO): - '' -
* plugins.d/askpass-fifo.xml (SEE ALSO): - '' -
* plugins.d/mandos-client.xml (SEE ALSO): - '' -
* plugins.d/password-prompt.xml (SEE ALSO): - '' -
* plugins.d/plymouth.xml (SEE ALSO): - '' -
* plugins.d/splashy.xml (SEE ALSO): - '' -
* plugins.d/usplash.xml (SEE ALSO): - '' -

Show diffs side-by-side

added added

removed removed

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