/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos

* clients.conf ([DEFAULT]/timeout): Changed default value to "5m".
  ([DEFAULT]/interval): Changed default value to "2m".
  ([DEFAULT]/extenden_timeout): New.
  ([bar]/interval): Changed to "1m".

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
    
314
308
                          "host", "interval", "last_checked_ok",
315
309
                          "last_enabled", "name", "timeout")
316
310
    
 
311
    @staticmethod
 
312
    def _timedelta_to_milliseconds(td):
 
313
        "Convert a datetime.timedelta() to milliseconds"
 
314
        return ((td.days * 24 * 60 * 60 * 1000)
 
315
                + (td.seconds * 1000)
 
316
                + (td.microseconds // 1000))
 
317
    
317
318
    def timeout_milliseconds(self):
318
319
        "Return the 'timeout' attribute in milliseconds"
319
 
        return _timedelta_to_milliseconds(self.timeout)
320
 
    
 
320
        return self._timedelta_to_milliseconds(self.timeout)
 
321
 
321
322
    def extended_timeout_milliseconds(self):
322
323
        "Return the 'extended_timeout' attribute in milliseconds"
323
 
        return _timedelta_to_milliseconds(self.extended_timeout)    
 
324
        return self._timedelta_to_milliseconds(self.extended_timeout)    
324
325
    
325
326
    def interval_milliseconds(self):
326
327
        "Return the 'interval' attribute in milliseconds"
327
 
        return _timedelta_to_milliseconds(self.interval)
328
 
    
 
328
        return self._timedelta_to_milliseconds(self.interval)
 
329
 
329
330
    def approval_delay_milliseconds(self):
330
 
        return _timedelta_to_milliseconds(self.approval_delay)
 
331
        return self._timedelta_to_milliseconds(self.approval_delay)
331
332
    
332
333
    def __init__(self, name = None, disable_hook=None, config=None):
333
334
        """Note: the 'checker' key in 'config' sets the
392
393
            # Already enabled
393
394
            return
394
395
        self.send_changedstate()
 
396
        self.last_enabled = datetime.datetime.utcnow()
395
397
        # Schedule a new checker to be started an 'interval' from now,
396
398
        # and every interval from then on.
397
399
        self.checker_initiator_tag = (gobject.timeout_add
403
405
                                   (self.timeout_milliseconds(),
404
406
                                    self.disable))
405
407
        self.enabled = True
406
 
        self.last_enabled = datetime.datetime.utcnow()
407
408
        # Also start a new checker *right now*.
408
409
        self.start_checker()
409
410
    
462
463
        gobject.source_remove(self.disable_initiator_tag)
463
464
        self.expires = datetime.datetime.utcnow() + timeout
464
465
        self.disable_initiator_tag = (gobject.timeout_add
465
 
                                      (_timedelta_to_milliseconds(timeout),
 
466
                                      (self._timedelta_to_milliseconds(timeout),
466
467
                                       self.disable))
467
468
    
468
469
    def need_approval(self):
509
510
                                       'replace')))
510
511
                    for attr in
511
512
                    self.runtime_expansions)
512
 
                
 
513
 
513
514
                try:
514
515
                    command = self.checker_command % escaped_attrs
515
516
                except TypeError as error:
561
562
                raise
562
563
        self.checker = None
563
564
 
564
 
 
565
565
def dbus_service_property(dbus_interface, signature="v",
566
566
                          access="readwrite", byte_arrays=False):
567
567
    """Decorators for marking methods of a DBusObjectWithProperties to
613
613
 
614
614
class DBusObjectWithProperties(dbus.service.Object):
615
615
    """A D-Bus object with properties.
616
 
    
 
616
 
617
617
    Classes inheriting from this can use the dbus_service_property
618
618
    decorator to expose methods as D-Bus properties.  It exposes the
619
619
    standard Get(), Set(), and GetAll() methods on the D-Bus.
683
683
    def GetAll(self, interface_name):
684
684
        """Standard D-Bus property GetAll() method, see D-Bus
685
685
        standard.
686
 
        
 
686
 
687
687
        Note: Will not include properties with access="write".
688
688
        """
689
689
        all = {}
751
751
        return xmlstring
752
752
 
753
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
 
 
762
754
class ClientDBus(Client, DBusObjectWithProperties):
763
755
    """A Client class using D-Bus
764
756
    
785
777
                                 ("/clients/" + client_object_name))
786
778
        DBusObjectWithProperties.__init__(self, self.bus,
787
779
                                          self.dbus_object_path)
788
 
        
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
 
780
    def _set_expires(self, value):
 
781
        old_value = getattr(self, "_expires", None)
 
782
        self._expires = value
 
783
        if hasattr(self, "dbus_object_path") and old_value != value:
 
784
            dbus_time = (self._datetime_to_dbus(self._expires,
 
785
                                                variant_level=1))
 
786
            self.PropertyChanged(dbus.String("Expires"),
 
787
                                 dbus_time)
 
788
    expires = property(lambda self: self._expires, _set_expires)
 
789
    del _set_expires
 
790
        
 
791
    def _get_approvals_pending(self):
 
792
        return self._approvals_pending
 
793
    def _set_approvals_pending(self, value):
 
794
        old_value = self._approvals_pending
 
795
        self._approvals_pending = value
 
796
        bval = bool(value)
 
797
        if (hasattr(self, "dbus_object_path")
 
798
            and bval is not bool(old_value)):
 
799
            dbus_bool = dbus.Boolean(bval, variant_level=1)
 
800
            self.PropertyChanged(dbus.String("ApprovalPending"),
 
801
                                 dbus_bool)
 
802
 
 
803
    approvals_pending = property(_get_approvals_pending,
 
804
                                 _set_approvals_pending)
 
805
    del _get_approvals_pending, _set_approvals_pending
 
806
    
 
807
    @staticmethod
 
808
    def _datetime_to_dbus(dt, variant_level=0):
 
809
        """Convert a UTC datetime.datetime() to a D-Bus type."""
 
810
        if dt is None:
 
811
            return dbus.String("", variant_level = variant_level)
 
812
        return dbus.String(dt.isoformat(),
 
813
                           variant_level=variant_level)
 
814
    
 
815
    def enable(self):
 
816
        oldstate = getattr(self, "enabled", False)
 
817
        r = Client.enable(self)
 
818
        if oldstate != self.enabled:
 
819
            # Emit D-Bus signals
 
820
            self.PropertyChanged(dbus.String("Enabled"),
 
821
                                 dbus.Boolean(True, variant_level=1))
 
822
            self.PropertyChanged(
 
823
                dbus.String("LastEnabled"),
 
824
                self._datetime_to_dbus(self.last_enabled,
 
825
                                       variant_level=1))
 
826
        return r
 
827
    
 
828
    def disable(self, quiet = False):
 
829
        oldstate = getattr(self, "enabled", False)
 
830
        r = Client.disable(self, quiet=quiet)
 
831
        if not quiet and oldstate != self.enabled:
 
832
            # Emit D-Bus signal
 
833
            self.PropertyChanged(dbus.String("Enabled"),
 
834
                                 dbus.Boolean(False, variant_level=1))
 
835
        return r
844
836
    
845
837
    def __del__(self, *args, **kwargs):
846
838
        try:
855
847
                         *args, **kwargs):
856
848
        self.checker_callback_tag = None
857
849
        self.checker = None
 
850
        # Emit D-Bus signal
 
851
        self.PropertyChanged(dbus.String("CheckerRunning"),
 
852
                             dbus.Boolean(False, variant_level=1))
858
853
        if os.WIFEXITED(condition):
859
854
            exitstatus = os.WEXITSTATUS(condition)
860
855
            # Emit D-Bus signal
870
865
        return Client.checker_callback(self, pid, condition, command,
871
866
                                       *args, **kwargs)
872
867
    
 
868
    def checked_ok(self, *args, **kwargs):
 
869
        Client.checked_ok(self, *args, **kwargs)
 
870
        # Emit D-Bus signal
 
871
        self.PropertyChanged(
 
872
            dbus.String("LastCheckedOK"),
 
873
            (self._datetime_to_dbus(self.last_checked_ok,
 
874
                                    variant_level=1)))
 
875
    
 
876
    def need_approval(self, *args, **kwargs):
 
877
        r = Client.need_approval(self, *args, **kwargs)
 
878
        # Emit D-Bus signal
 
879
        self.PropertyChanged(
 
880
            dbus.String("LastApprovalRequest"),
 
881
            (self._datetime_to_dbus(self.last_approval_request,
 
882
                                    variant_level=1)))
 
883
        return r
 
884
    
873
885
    def start_checker(self, *args, **kwargs):
874
886
        old_checker = self.checker
875
887
        if self.checker is not None:
882
894
            and old_checker_pid != self.checker.pid):
883
895
            # Emit D-Bus signal
884
896
            self.CheckerStarted(self.current_checker_command)
 
897
            self.PropertyChanged(
 
898
                dbus.String("CheckerRunning"),
 
899
                dbus.Boolean(True, variant_level=1))
885
900
        return r
886
901
    
 
902
    def stop_checker(self, *args, **kwargs):
 
903
        old_checker = getattr(self, "checker", None)
 
904
        r = Client.stop_checker(self, *args, **kwargs)
 
905
        if (old_checker is not None
 
906
            and getattr(self, "checker", None) is None):
 
907
            self.PropertyChanged(dbus.String("CheckerRunning"),
 
908
                                 dbus.Boolean(False, variant_level=1))
 
909
        return r
 
910
 
887
911
    def _reset_approved(self):
888
912
        self._approved = None
889
913
        return False
891
915
    def approve(self, value=True):
892
916
        self.send_changedstate()
893
917
        self._approved = value
894
 
        gobject.timeout_add(_timedelta_to_milliseconds
 
918
        gobject.timeout_add(self._timedelta_to_milliseconds
895
919
                            (self.approval_duration),
896
920
                            self._reset_approved)
897
921
    
988
1012
    def ApprovedByDefault_dbus_property(self, value=None):
989
1013
        if value is None:       # get
990
1014
            return dbus.Boolean(self.approved_by_default)
 
1015
        old_value = self.approved_by_default
991
1016
        self.approved_by_default = bool(value)
 
1017
        # Emit D-Bus signal
 
1018
        if old_value != self.approved_by_default:
 
1019
            self.PropertyChanged(dbus.String("ApprovedByDefault"),
 
1020
                                 dbus.Boolean(value, variant_level=1))
992
1021
    
993
1022
    # ApprovalDelay - property
994
1023
    @dbus_service_property(_interface, signature="t",
996
1025
    def ApprovalDelay_dbus_property(self, value=None):
997
1026
        if value is None:       # get
998
1027
            return dbus.UInt64(self.approval_delay_milliseconds())
 
1028
        old_value = self.approval_delay
999
1029
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
 
1030
        # Emit D-Bus signal
 
1031
        if old_value != self.approval_delay:
 
1032
            self.PropertyChanged(dbus.String("ApprovalDelay"),
 
1033
                                 dbus.UInt64(value, variant_level=1))
1000
1034
    
1001
1035
    # ApprovalDuration - property
1002
1036
    @dbus_service_property(_interface, signature="t",
1003
1037
                           access="readwrite")
1004
1038
    def ApprovalDuration_dbus_property(self, value=None):
1005
1039
        if value is None:       # get
1006
 
            return dbus.UInt64(_timedelta_to_milliseconds(
 
1040
            return dbus.UInt64(self._timedelta_to_milliseconds(
1007
1041
                    self.approval_duration))
 
1042
        old_value = self.approval_duration
1008
1043
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
 
1044
        # Emit D-Bus signal
 
1045
        if old_value != self.approval_duration:
 
1046
            self.PropertyChanged(dbus.String("ApprovalDuration"),
 
1047
                                 dbus.UInt64(value, variant_level=1))
1009
1048
    
1010
1049
    # Name - property
1011
1050
    @dbus_service_property(_interface, signature="s", access="read")
1023
1062
    def Host_dbus_property(self, value=None):
1024
1063
        if value is None:       # get
1025
1064
            return dbus.String(self.host)
 
1065
        old_value = self.host
1026
1066
        self.host = value
 
1067
        # Emit D-Bus signal
 
1068
        if old_value != self.host:
 
1069
            self.PropertyChanged(dbus.String("Host"),
 
1070
                                 dbus.String(value, variant_level=1))
1027
1071
    
1028
1072
    # Created - property
1029
1073
    @dbus_service_property(_interface, signature="s", access="read")
1030
1074
    def Created_dbus_property(self):
1031
 
        return dbus.String(datetime_to_dbus(self.created))
 
1075
        return dbus.String(self._datetime_to_dbus(self.created))
1032
1076
    
1033
1077
    # LastEnabled - property
1034
1078
    @dbus_service_property(_interface, signature="s", access="read")
1035
1079
    def LastEnabled_dbus_property(self):
1036
 
        return datetime_to_dbus(self.last_enabled)
 
1080
        return self._datetime_to_dbus(self.last_enabled)
1037
1081
    
1038
1082
    # Enabled - property
1039
1083
    @dbus_service_property(_interface, signature="b",
1053
1097
        if value is not None:
1054
1098
            self.checked_ok()
1055
1099
            return
1056
 
        return datetime_to_dbus(self.last_checked_ok)
 
1100
        return self._datetime_to_dbus(self.last_checked_ok)
1057
1101
    
1058
1102
    # Expires - property
1059
1103
    @dbus_service_property(_interface, signature="s", access="read")
1060
1104
    def Expires_dbus_property(self):
1061
 
        return datetime_to_dbus(self.expires)
 
1105
        return self._datetime_to_dbus(self.expires)
1062
1106
    
1063
1107
    # LastApprovalRequest - property
1064
1108
    @dbus_service_property(_interface, signature="s", access="read")
1065
1109
    def LastApprovalRequest_dbus_property(self):
1066
 
        return datetime_to_dbus(self.last_approval_request)
 
1110
        return self._datetime_to_dbus(self.last_approval_request)
1067
1111
    
1068
1112
    # Timeout - property
1069
1113
    @dbus_service_property(_interface, signature="t",
1071
1115
    def Timeout_dbus_property(self, value=None):
1072
1116
        if value is None:       # get
1073
1117
            return dbus.UInt64(self.timeout_milliseconds())
 
1118
        old_value = self.timeout
1074
1119
        self.timeout = datetime.timedelta(0, 0, 0, value)
 
1120
        # Emit D-Bus signal
 
1121
        if old_value != self.timeout:
 
1122
            self.PropertyChanged(dbus.String("Timeout"),
 
1123
                                 dbus.UInt64(value, variant_level=1))
1075
1124
        if getattr(self, "disable_initiator_tag", None) is None:
1076
1125
            return
1077
1126
        # Reschedule timeout
1092
1141
                            + datetime.timedelta(milliseconds = time_to_die))
1093
1142
            self.disable_initiator_tag = (gobject.timeout_add
1094
1143
                                          (time_to_die, self.disable))
1095
 
    
 
1144
 
1096
1145
    # ExtendedTimeout - property
1097
1146
    @dbus_service_property(_interface, signature="t",
1098
1147
                           access="readwrite")
1099
1148
    def ExtendedTimeout_dbus_property(self, value=None):
1100
1149
        if value is None:       # get
1101
1150
            return dbus.UInt64(self.extended_timeout_milliseconds())
 
1151
        old_value = self.extended_timeout
1102
1152
        self.extended_timeout = datetime.timedelta(0, 0, 0, value)
1103
 
    
 
1153
        # Emit D-Bus signal
 
1154
        if old_value != self.extended_timeout:
 
1155
            self.PropertyChanged(dbus.String("ExtendedTimeout"),
 
1156
                                 dbus.UInt64(value, variant_level=1))
 
1157
 
1104
1158
    # Interval - property
1105
1159
    @dbus_service_property(_interface, signature="t",
1106
1160
                           access="readwrite")
1107
1161
    def Interval_dbus_property(self, value=None):
1108
1162
        if value is None:       # get
1109
1163
            return dbus.UInt64(self.interval_milliseconds())
 
1164
        old_value = self.interval
1110
1165
        self.interval = datetime.timedelta(0, 0, 0, value)
 
1166
        # Emit D-Bus signal
 
1167
        if old_value != self.interval:
 
1168
            self.PropertyChanged(dbus.String("Interval"),
 
1169
                                 dbus.UInt64(value, variant_level=1))
1111
1170
        if getattr(self, "checker_initiator_tag", None) is None:
1112
1171
            return
1113
1172
        # Reschedule checker run
1115
1174
        self.checker_initiator_tag = (gobject.timeout_add
1116
1175
                                      (value, self.start_checker))
1117
1176
        self.start_checker()    # Start one now, too
1118
 
    
 
1177
 
1119
1178
    # Checker - property
1120
1179
    @dbus_service_property(_interface, signature="s",
1121
1180
                           access="readwrite")
1122
1181
    def Checker_dbus_property(self, value=None):
1123
1182
        if value is None:       # get
1124
1183
            return dbus.String(self.checker_command)
 
1184
        old_value = self.checker_command
1125
1185
        self.checker_command = value
 
1186
        # Emit D-Bus signal
 
1187
        if old_value != self.checker_command:
 
1188
            self.PropertyChanged(dbus.String("Checker"),
 
1189
                                 dbus.String(self.checker_command,
 
1190
                                             variant_level=1))
1126
1191
    
1127
1192
    # CheckerRunning - property
1128
1193
    @dbus_service_property(_interface, signature="b",
1155
1220
        self._pipe.send(('init', fpr, address))
1156
1221
        if not self._pipe.recv():
1157
1222
            raise KeyError()
1158
 
    
 
1223
 
1159
1224
    def __getattribute__(self, name):
1160
1225
        if(name == '_pipe'):
1161
1226
            return super(ProxyClient, self).__getattribute__(name)
1168
1233
                self._pipe.send(('funcall', name, args, kwargs))
1169
1234
                return self._pipe.recv()[1]
1170
1235
            return func
1171
 
    
 
1236
 
1172
1237
    def __setattr__(self, name, value):
1173
1238
        if(name == '_pipe'):
1174
1239
            return super(ProxyClient, self).__setattr__(name, value)
1187
1252
                        unicode(self.client_address))
1188
1253
            logger.debug("Pipe FD: %d",
1189
1254
                         self.server.child_pipe.fileno())
1190
 
            
 
1255
 
1191
1256
            session = (gnutls.connection
1192
1257
                       .ClientSession(self.request,
1193
1258
                                      gnutls.connection
1194
1259
                                      .X509Credentials()))
1195
 
            
 
1260
 
1196
1261
            # Note: gnutls.connection.X509Credentials is really a
1197
1262
            # generic GnuTLS certificate credentials object so long as
1198
1263
            # no X.509 keys are added to it.  Therefore, we can use it
1199
1264
            # here despite using OpenPGP certificates.
1200
 
            
 
1265
 
1201
1266
            #priority = ':'.join(("NONE", "+VERS-TLS1.1",
1202
1267
            #                      "+AES-256-CBC", "+SHA1",
1203
1268
            #                      "+COMP-NULL", "+CTYPE-OPENPGP",
1209
1274
            (gnutls.library.functions
1210
1275
             .gnutls_priority_set_direct(session._c_object,
1211
1276
                                         priority, None))
1212
 
            
 
1277
 
1213
1278
            # Start communication using the Mandos protocol
1214
1279
            # Get protocol number
1215
1280
            line = self.request.makefile().readline()
1220
1285
            except (ValueError, IndexError, RuntimeError) as error:
1221
1286
                logger.error("Unknown protocol version: %s", error)
1222
1287
                return
1223
 
            
 
1288
 
1224
1289
            # Start GnuTLS connection
1225
1290
            try:
1226
1291
                session.handshake()
1230
1295
                # established.  Just abandon the request.
1231
1296
                return
1232
1297
            logger.debug("Handshake succeeded")
1233
 
            
 
1298
 
1234
1299
            approval_required = False
1235
1300
            try:
1236
1301
                try:
1241
1306
                    logger.warning("Bad certificate: %s", error)
1242
1307
                    return
1243
1308
                logger.debug("Fingerprint: %s", fpr)
1244
 
                
 
1309
 
1245
1310
                try:
1246
1311
                    client = ProxyClient(child_pipe, fpr,
1247
1312
                                         self.client_address)
1313
1378
                                 sent, len(client.secret)
1314
1379
                                 - (sent_size + sent))
1315
1380
                    sent_size += sent
1316
 
                
 
1381
 
1317
1382
                logger.info("Sending secret to %s", client.name)
1318
1383
                # bump the timeout as if seen
1319
1384
                client.checked_ok(client.extended_timeout)
1407
1472
        multiprocessing.Process(target = self.sub_process_main,
1408
1473
                                args = (request, address)).start()
1409
1474
 
1410
 
 
1411
1475
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
1412
1476
    """ adds a pipe to the MixIn """
1413
1477
    def process_request(self, request, client_address):
1416
1480
        This function creates a new pipe in self.pipe
1417
1481
        """
1418
1482
        parent_pipe, self.child_pipe = multiprocessing.Pipe()
1419
 
        
 
1483
 
1420
1484
        super(MultiprocessingMixInWithPipe,
1421
1485
              self).process_request(request, client_address)
1422
1486
        self.child_pipe.close()
1423
1487
        self.add_pipe(parent_pipe)
1424
 
    
 
1488
 
1425
1489
    def add_pipe(self, parent_pipe):
1426
1490
        """Dummy function; override as necessary"""
1427
1491
        raise NotImplementedError
1428
1492
 
1429
 
 
1430
1493
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
1431
1494
                     socketserver.TCPServer, object):
1432
1495
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
1580
1643
            kwargs = request[3]
1581
1644
            
1582
1645
            parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1583
 
        
 
1646
 
1584
1647
        if command == 'getattr':
1585
1648
            attrname = request[1]
1586
1649
            if callable(client_object.__getattribute__(attrname)):
1592
1655
            attrname = request[1]
1593
1656
            value = request[2]
1594
1657
            setattr(client_object, attrname, value)
1595
 
        
 
1658
 
1596
1659
        return True
1597
1660
 
1598
1661
 
1777
1840
    debuglevel = server_settings["debuglevel"]
1778
1841
    use_dbus = server_settings["use_dbus"]
1779
1842
    use_ipv6 = server_settings["use_ipv6"]
1780
 
    
 
1843
 
1781
1844
    if server_settings["servicename"] != "Mandos":
1782
1845
        syslogger.setFormatter(logging.Formatter
1783
1846
                               ('Mandos (%s) [%%(process)d]:'
1844
1907
        level = getattr(logging, debuglevel.upper())
1845
1908
        syslogger.setLevel(level)
1846
1909
        console.setLevel(level)
1847
 
    
 
1910
 
1848
1911
    if debug:
1849
1912
        # Enable all possible GnuTLS debugging
1850
1913
        
1937
2000
        del pidfilename
1938
2001
        
1939
2002
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1940
 
    
 
2003
 
1941
2004
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1942
2005
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())
1943
2006
    
2064
2127
    # Must run before the D-Bus bus name gets deregistered
2065
2128
    cleanup()
2066
2129
 
2067
 
 
2068
2130
if __name__ == '__main__':
2069
2131
    main()